security: Try harder to run transactions

When a QEMU process dies in the middle of a hotplug, then we fail
to restore the seclabels on the device. The problem is that if
the thread doing hotplug locks the domain object first and thus
blocks the thread that wants to do qemuProcessStop(), the
seclabel cleanup code will see vm->pid still set and mount
namespace used and therefore try to enter the namespace
represented by the PID. But the PID is gone really and thus
entering will fail and no restore is done. What we can do is to
try enter the namespace (if requested to do so) but if entering
fails, fall back to no NS mode.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1814481

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Pavel Mores <pmores@redhat.com>
This commit is contained in:
Michal Privoznik 2020-03-18 10:18:46 +01:00
parent c799d150d5
commit ea903036fa
2 changed files with 24 additions and 8 deletions

View File

@ -640,15 +640,23 @@ virSecurityDACTransactionCommit(virSecurityManagerPtr mgr G_GNUC_UNUSED,
list->lock = lock; list->lock = lock;
if (pid != -1) {
rc = virProcessRunInMountNamespace(pid,
virSecurityDACTransactionRun,
list);
if (rc < 0) {
if (virGetLastErrorCode() == VIR_ERR_SYSTEM_ERROR)
pid = -1;
else
goto cleanup;
}
}
if (pid == -1) { if (pid == -1) {
if (lock) if (lock)
rc = virProcessRunInFork(virSecurityDACTransactionRun, list); rc = virProcessRunInFork(virSecurityDACTransactionRun, list);
else else
rc = virSecurityDACTransactionRun(pid, list); rc = virSecurityDACTransactionRun(pid, list);
} else {
rc = virProcessRunInMountNamespace(pid,
virSecurityDACTransactionRun,
list);
} }
if (rc < 0) if (rc < 0)

View File

@ -1163,15 +1163,23 @@ virSecuritySELinuxTransactionCommit(virSecurityManagerPtr mgr G_GNUC_UNUSED,
list->lock = lock; list->lock = lock;
if (pid != -1) {
rc = virProcessRunInMountNamespace(pid,
virSecuritySELinuxTransactionRun,
list);
if (rc < 0) {
if (virGetLastErrorCode() == VIR_ERR_SYSTEM_ERROR)
pid = -1;
else
goto cleanup;
}
}
if (pid == -1) { if (pid == -1) {
if (lock) if (lock)
rc = virProcessRunInFork(virSecuritySELinuxTransactionRun, list); rc = virProcessRunInFork(virSecuritySELinuxTransactionRun, list);
else else
rc = virSecuritySELinuxTransactionRun(pid, list); rc = virSecuritySELinuxTransactionRun(pid, list);
} else {
rc = virProcessRunInMountNamespace(pid,
virSecuritySELinuxTransactionRun,
list);
} }
if (rc < 0) if (rc < 0)