qemu: Move pid file of virtiofsd to stateDir

Libvirt will put the pid file of virtiofsd 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
   virtiofsd process will never be cleared even if the VM is destroyed.

So, move the pid file of virtiofsd from per-domain directory to
stateDir.

Signed-off-by: Peng Liang <liangpeng10@huawei.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Peng Liang 2021-10-18 17:20:12 +08:00 committed by Michal Privoznik
parent 74e1ebee7f
commit e8b5c09a03

View File

@ -39,9 +39,9 @@
VIR_LOG_INIT("qemu.virtiofs");
char *
qemuVirtioFSCreatePidFilename(virDomainObj *vm,
const char *alias)
static char *
qemuVirtioFSCreatePidFilenameOld(virDomainObj *vm,
const char *alias)
{
qemuDomainObjPrivate *priv = vm->privateData;
g_autofree char *name = NULL;
@ -52,6 +52,19 @@ qemuVirtioFSCreatePidFilename(virDomainObj *vm,
}
char *
qemuVirtioFSCreatePidFilename(virDomainObj *vm,
const char *alias)
{
qemuDomainObjPrivate *priv = vm->privateData;
g_autofree char *domname = virDomainDefGetShortName(vm->def);
g_autofree char *name = g_strdup_printf("%s-%s-fs", domname, alias);
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver);
return virPidFileBuildPath(cfg->stateDir, name);
}
char *
qemuVirtioFSCreateSocketFilename(virDomainObj *vm,
const char *alias)
@ -283,6 +296,12 @@ qemuVirtioFSStop(virQEMUDriver *driver G_GNUC_UNUSED,
if (!(pidfile = qemuVirtioFSCreatePidFilename(vm, fs->info.alias)))
goto cleanup;
if (!virFileExists(pidfile)) {
g_free(pidfile);
if (!(pidfile = qemuVirtioFSCreatePidFilenameOld(vm, fs->info.alias)))
goto cleanup;
}
if (virPidFileForceCleanupPathFull(pidfile, true) < 0) {
VIR_WARN("Unable to kill virtiofsd process");
} else {