On 1/13/22 13:42, Vasiliy Ulyanov wrote: > Access to /proc/[pid]/exe may be restricted in certain environments (e.g. > in containers) and any attempt to stat(2) or readlink(2) the file will > result in 'permission denied' error if the calling process does not have > CAP_SYS_PTRACE capability. According to proc(5) manpage: > > Permission to dereference or read (readlink(2)) this symbolic link is > governed by a ptrace access mode PTRACE_MODE_READ_FSCREDS check; see > ptrace(2). > > The binary validation in virPidFileReadPathIfAlive may fail with EACCES. > Therefore instead do only the check that the pidfile is locked by the > correct process. To ensure this is always the case the daemonization and > pidfile handling of the swtpm command is now controlled by libvirt. > > Signed-off-by: Vasiliy Ulyanov <vulyanov@xxxxxxx> > --- > src/qemu/qemu_tpm.c | 26 +++++++++++--------------- > 1 file changed, 11 insertions(+), 15 deletions(-) > > diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c > index 7e7b01768e..792ee19bbd 100644 > --- a/src/qemu/qemu_tpm.c > +++ b/src/qemu/qemu_tpm.c > @@ -258,13 +258,12 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir, > const char *shortName, > pid_t *pid) > { > - g_autofree char *swtpm = virTPMGetSwtpm(); > g_autofree char *pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, > shortName); > if (!pidfile) > return -1; > > - if (virPidFileReadPathIfAlive(pidfile, pid, swtpm) < 0) > + if (virPidFileReadPathIfAlive(pidfile, pid, NULL) < 0) > return -1; > > return 0; > @@ -721,7 +720,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, > > virCommandClearCaps(cmd); > > - virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL); > + virCommandAddArgList(cmd, "socket", "--ctrl", NULL); > virCommandAddArgFormat(cmd, "type=unixio,path=%s,mode=0600", > tpm->data.emulator.source->data.nix.path); > > @@ -751,8 +750,8 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, > if (!(pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, shortName))) > goto error; > > - virCommandAddArg(cmd, "--pid"); > - virCommandAddArgFormat(cmd, "file=%s", pidfile); > + virCommandSetPidFile(cmd, pidfile); > + virCommandDaemonize(cmd); > > if (tpm->data.emulator.hassecretuuid) { > if (!virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD)) { > @@ -905,7 +904,6 @@ qemuExtTPMStartEmulator(virQEMUDriver *driver, > { > g_autoptr(virCommand) cmd = NULL; > int exitstatus = 0; > - g_autofree char *errbuf = NULL; > g_autoptr(virQEMUDriverConfig) cfg = NULL; > g_autofree char *shortName = virDomainDefGetShortName(vm->def); > int cmdret = 0, timeout, rc; > @@ -930,8 +928,6 @@ qemuExtTPMStartEmulator(virQEMUDriver *driver, > if (qemuExtDeviceLogCommand(driver, vm, cmd, "TPM Emulator") < 0) > return -1; > > - virCommandSetErrorBuffer(cmd, &errbuf); > - We can use virCommandSetErrorFD(), which ... > if (qemuSecurityStartTPMEmulator(driver, vm, cmd, > cfg->swtpm_user, cfg->swtpm_group, > &exitstatus, &cmdret) < 0) > @@ -939,22 +935,22 @@ qemuExtTPMStartEmulator(virQEMUDriver *driver, > > if (cmdret < 0 || exitstatus != 0) { > virReportError(VIR_ERR_INTERNAL_ERROR, > - _("Could not start 'swtpm'. exitstatus: %d, " > - "error: %s"), exitstatus, errbuf); > + _("Could not start 'swtpm'. exitstatus: %d"), exitstatus); > return -1; > } > > - /* check that the swtpm has written its pid into the file */ > + /* check that the swtpm has written its pid into the file and the control > + * socket has been created. */ > + rc = qemuTPMEmulatorGetPid(cfg->swtpmStateDir, shortName, &pid); > + if ((rc == 0 && pid == (pid_t)-1) || rc < 0) > + goto error; > timeout = 1000; /* ms */ > while (timeout > 0) { > - rc = qemuTPMEmulatorGetPid(cfg->swtpmStateDir, shortName, &pid); > - if (rc < 0) { > + if (!virFileExists(tpm->data.emulator.source->data.nix.path)) { > timeout -= 50; > g_usleep(50 * 1000); > continue; > } > - if (rc == 0 && pid == (pid_t)-1) > - goto error; Can then be used here to report error message that swtpm printed onto its stderr. Look at qemuProcessStartManagedPRDaemon() which does that. > break; > } > if (timeout <= 0) Michal