-
Bug
-
Resolution: Unresolved
-
Undefined
-
rhel-10.2
-
None
-
None
-
Low
-
1
-
rhel-virt-core-libvirt-1
-
None
-
False
-
False
-
-
No
-
Libvirt Bugs already in Sprint
-
None
-
None
-
Unspecified Release Note Type - Unknown
-
Unspecified
-
Unspecified
-
Unspecified
-
-
11.10.0
-
None
Until recently, libguestfs was accidentally disabling svirt for VMs quite often. We recently fixed that but then noticed that running `make -j8 check` with selinux enforcing would cause random failures.
Setup to reproduce:
+ qemu:///session (qemu:///system with remember=on is unaffected)
+ selinux enforcing
+ vm1 and vm2 using kernel+initrd boot
+ put the kernel in $HOME/kernel
+ apply this patch to simulate a race condition
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index fa5d1568eb..d1665d3efe 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -3383,10 +3383,18 @@ virSecuritySELinuxSetAllLabel(virSecurityManager *mgr,
return -1;
}
- if (def->os.kernel &&
- virSecuritySELinuxSetFilecon(mgr, def->os.kernel,
- data->content_context, true) < 0)
- return -1;
+ if (def->os.kernel) {
+ if (virSecuritySELinuxSetFilecon(mgr, def->os.kernel,
+ data->content_context, true) < 0)
+ return -1;
+ printf("kernel label set for vm=%s\n", def->name);
+
+ if STREQ(def->name, "v2") {
+ printf("doing startup sleep for dom=v2\n");
+ sleep(15);
+ printf("sleep done\n");
+ }
+ }
if (def->os.initrd &&
virSecuritySELinuxSetFilecon(mgr, def->os.initrd,
+ build, run virtqemud
+ start vm1. confirm that kernel has expected label virt_content_t
+ start vm2 but it will hit the sleep
+ in another terminal, stop vm1 during the sleep. vm1 startup will actually hang until the sleep is over
+ when sleep expires, vm2 will fail to start, because the disk label changed underneath it to user_home_t, which qemu svirt can't access
There's a bit of subtlety here. If you put the kernel in /tmp, things work, because the label restore step doesn't find any default label for /tmp/kernel (basically, `matchpathcon /tmp/kernel` returns `<<none>>`) so libvirt leaves the label untouched as virt_content_t. If you put the kernel in /var/lib/libvirt/images/, the label will be restored to svirt_image_t, which also works. But $HOME and some other locations have blanket policies to label everything unknown as user_home_t, which svirt policy rejects. libguestfs test suite is storing test kernel+initrd in tree in $HOME, so that's why we are seeing this.
Note, this doesn't impact libguestfs in practice because where libguestfs stores its kernel/initrd is not affected by a blanket selinux file content policy like $HOME. But in some future scenario where selinux policy changes, suddenly real world libguestfs usage is susceptible.
Some ideas after looking at the code:
+ Consider broadening the VM startup locking to protect the security driver until the VM has launched. Might be totally impractical, but it would eliminate the race condition entirely.
+ For the particular case of kernel/initrd and anything that is considered 'shared' and gets virt_content_t, we could skip label restore entirely. this is what is already done for disks marked as shared (grep for src->shared in security_selinux.c).
- is blocked by
-
RHEL-104238 Rebase libvirt in RHEL-10.2
-
- In Progress
-
- links to