[PATCH 1/2] qemu: Move pid file of pr-helper to stateDir
Michal Prívozník
mprivozn at redhat.com
Sun Oct 17 13:53:55 UTC 2021
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 at huawei.com>
>>> ---
>>> 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
More information about the libvir-list
mailing list