On 10/14/21 12:51 PM, Peng Liang wrote: > On 10/14/2021 6:10 PM, Michal Prívozník wrote: >> On 10/11/21 2:11 PM, Peng Liang wrote: >>> Libvirt will put the pid file of pr-helper to per-domain directory. >>> However, the ownership of the per-domain directory is the user to run >>> the QEMU process and the user has the write permission of the directory. >>> If VM escape occurs, the attacker can >>> 1. write arbitrary content to the pid file (if running QEMU using root), >>> then the attacker can kill any process by writing appropriate pid to >>> the pid file; >>> 2. spoof the pid file (if running QEMU using a regular user), then the >>> pr-helper process will never be cleared even if the VM is destroyed. >>> >>> So, move the pid file of pr-helper from per-domain directory to >>> stateDir just like the pid file of the domain. >>> >>> Signed-off-by: Peng Liang <liangpeng10@xxxxxxxxxx> >>> --- >>> src/qemu/qemu_process.c | 6 ++++-- >>> 1 file changed, 4 insertions(+), 2 deletions(-) >>> >>> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c >>> index 1d0165af6daa..583f3ec76c7b 100644 >>> --- a/src/qemu/qemu_process.c >>> +++ b/src/qemu/qemu_process.c >>> @@ -2859,9 +2859,11 @@ static char * >>> qemuProcessBuildPRHelperPidfilePath(virDomainObj *vm) >>> { >>> qemuDomainObjPrivate *priv = vm->privateData; >>> - const char *prdAlias = qemuDomainGetManagedPRAlias(); >>> + g_autofree char *domname = virDomainDefGetShortName(vm->def); >>> + g_autofree char *prdName = g_strdup_printf("%s-%s", domname, qemuDomainGetManagedPRAlias()); >>> + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver); >>> >>> - return virPidFileBuildPath(priv->libDir, prdAlias); >>> + return virPidFileBuildPath(cfg->stateDir, prdName); >>> } >> >> I don't think it is this simple. The pidfile path is not stored in >> status XML but generated when starting/stopping PR helper process. >> Therefore, if there is PR helper that was started with older libvirt its >> pidfile is /var/lib/libvirt/qemu/domain-1-fedora/pr-helper0.pid but >> after your change a different path is generated >> /var/run/libvirt/qemu/1-fedora-pr-helper0.pid and thus >> qemuProcessKillManagedPRDaemon() does not kill the PR helper process and >> leaves it behind. >> >> One solution would be to start recording the pidfile path in status XML >> and then when no path is found during parse we know that the old path >> was used. > > Can we just change to use old path if the path returned by > qemuProcessBuildPRHelperPidfilePath does not exist? For example: > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index f95ed80fac43..0ee1a97f5571 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -2877,6 +2877,14 @@ qemuProcessKillManagedPRDaemon(virDomainObj *vm) > return; > } > > + if (!virFileExists(pidfile)) { > + g_free(pidfile); > + if (!(pidfile = qemuProcessBuildPRHelperPidfilePathOld(vm))) { > + VIR_WARN("Unable to construct pr-helper pidfile path"); > + return; > + } > + } > + > virErrorPreserveLast(&orig_err); > if (virPidFileForceCleanupPath(pidfile) < 0) { > VIR_WARN("Unable to kill pr-helper process"); > > qemuProcessBuildPRHelperPidfilePathOld will build the old path (e.g., > /var/lib/libvirt/qemu/domain-1-fedora/pr-helper0.pid). Yes, I think this may help. Michal