initramfs: Inherit SELinux label on transient root tmpfs#2071
initramfs: Inherit SELinux label on transient root tmpfs#2071andrewdunndev wants to merge 1 commit intobootc-dev:mainfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request correctly addresses an issue with SELinux labels on transient root filesystems by inheriting the label from the base filesystem. The implementation is well-structured, introducing a new function mount_tmpfs_for_overlay to handle the logic. My review includes a suggestion to refactor the extended attribute reading logic to be more robust and idiomatic by avoiding hardcoded buffer sizes.
25092c4 to
0c64f52
Compare
cgwalters
left a comment
There was a problem hiding this comment.
I think this is all OK, however...and this is not something you need to fix as part of this PR, but we are missing testing transient root at all I believe as part of gating CI here by default.
It's tricky because it would be another entry in our ever-growing matrix, I'll try to write something up for this.
crates/initramfs/src/lib.rs
Outdated
| let tmpfs = FsHandle::open("tmpfs")?; | ||
|
|
||
| if let Some(base_fd) = base { | ||
| // Read the SELinux label from the base filesystem root using the |
There was a problem hiding this comment.
There was a problem hiding this comment.
Switched to cap-std-ext::getxattr via Dir::reopen_dir. Force-pushed.
crates/initramfs/src/lib.rs
Outdated
| // Construct a CString for fsconfig_set_string. This avoids | ||
| // requiring the label to be valid UTF-8 (per maintainer feedback). |
There was a problem hiding this comment.
To me this is a perfect example of a "very obvious" LLM generated (I'm sure) comment that's just unnecessary. I'll try to update our AGENTS.md and such to try to suppress some of this, I have it in my personal one.
There was a problem hiding this comment.
Noted, will keep replies terse going forward (and we adjusted our harness, you're detecting LLM assist correctly).
crates/initramfs/src/lib.rs
Outdated
| }; | ||
|
|
||
| /// The SELinux extended attribute name. | ||
| const SELINUX_XATTR: &str = "security.selinux"; |
There was a problem hiding this comment.
We also have this const elsewhere
There was a problem hiding this comment.
Removed. Using the string literal inline since the existing consts in lsm.rs aren't reachable from initramfs.
crates/initramfs/src/lib.rs
Outdated
| // The kernel may return a null-terminated byte string; strip it | ||
| // before constructing a CString (which adds its own terminator). | ||
| if label.last() == Some(&0) { | ||
| label.pop(); | ||
| } |
There was a problem hiding this comment.
Yeah, here be some 🐉 - we messed something up like this in ostree IIRC
There was a problem hiding this comment.
cap-std-ext::getxattr handles the buffer management now, so the manual null-terminator stripping is gone.
When root.transient is enabled, the tmpfs used as the overlay upper layer has no SELinux context set, so its root directory gets the default tmpfs_t label. This propagates to the overlay mountpoint at /, causing services like systemd-networkd to refuse to start because they expect root_t. Fix this by reading the SELinux label from the composefs lower layer via fgetxattr(security.selinux) and setting it as rootcontext on the tmpfs before creating the overlay. This ensures the overlay root inherits the correct label from the base filesystem. The rootcontext mount option sets only the root inode's label, preserving per-file labeling from SELinux policy via type_transition rules. This is preferable to context= which would force a uniform label on all inodes. When SELinux is not enabled, fgetxattr returns an error and no context is set, preserving the existing behavior. Note: the ostree backend (otcore-prepare-root.c in ostreedev/ostree) has the same issue but uses /run as the tmpfs backing store rather than creating its own tmpfs. That fix would need to go through libcomposefs mount options or the ostree repo directly. Closes: bootc-dev#1992 AI-Assisted: yes AI-Tools: GitLab Duo, OpenCode Signed-off-by: Andrew Dunn <andrew@dunn.dev>
0c64f52 to
9607e46
Compare
|
Happy to help wire up a transient-root test or file an issue to track. |
Summary
When
root.transientis enabled, the overlay root at/gets SELinux labeltmpfs_tinstead ofroot_t, causing services like systemd-networkd to crash.This PR fixes the composefs backend by reading the SELinux label from the lower
(composefs) filesystem and setting it as
rootcontexton the tmpfs used forthe overlay upper layer.
What changed
mount_tmpfs_for_overlay()that readssecurity.selinuxxattr from thebase filesystem and sets
rootcontexton the tmpfs before overlay creationfgetxattrpattern (query size → allocate → read) forcorrect handling of arbitrarily long MLS/MCS contexts
CString(notstr) to avoid requiring UTF-8 labelsoverlay_transient()passes the base fd through to inherit the correct labelmount_tmpfs()wrapperDesign decisions
rootcontext=overcontext=:rootcontextsets only the root inode'slabel, letting new files inherit labels from SELinux policy.
context=wouldforce a uniform label on all inodes in the tmpfs, which is too broad.
(systemd uses
context=in nspawn and has had issues with it — seenspawn volatile=overlay tmpfs labeled with "selinux-context" instead of "selinux-apifs-context" systemd/systemd#12292.)
Read from lower layer, not hardcode: The label is read from the composefs
base filesystem rather than hardcoding
root_t. This works regardless of theSELinux policy in use.
Silent fallback: If SELinux is not enabled or the xattr read fails, no
context is set and behavior is unchanged from before this patch.
Related issues
ostree backend: The ostree backend (
otcore-prepare-root.c) has the sameissue but uses
/runas the tmpfs backing store. That fix would go throughlcfs_mount_options_sin libcomposefs or the ostree repo. Happy to file afollow-up issue on ostreedev/ostree.
systemd:
systemd.volatile=overlayhas the same unfixed bug(nspawn volatile=overlay tmpfs labeled with "selinux-context" instead of "selinux-apifs-context" systemd/systemd#12292). Dan Walsh's fix attempt (Fix the labeling within an nspawn container systemd/systemd#26141) has
been stalled since 2023.
Testing
This runs in the initramfs before the real root is mounted, so testing requires
a VM with SELinux enforcing and
root.transientenabled. Verification:Closes #1992
Signed-off-by: Andrew Dunn andrew@dunn.dev