Skip to content

install: Add final SELinux relabel of the physical root filesystem#2035

Open
jeckersb wants to merge 1 commit intobootc-dev:mainfrom
jeckersb:relabel-root
Open

install: Add final SELinux relabel of the physical root filesystem#2035
jeckersb wants to merge 1 commit intobootc-dev:mainfrom
jeckersb:relabel-root

Conversation

@jeckersb
Copy link
Collaborator

@jeckersb jeckersb commented Mar 3, 2026

Perform a full SELinux relabel pass over the physical root filesystem as
the very last step before filesystem finalization. This ensures all files
on the physical root have correct SELinux labels.

The ostree/deploy directory is skipped since its contents are already
correctly labeled as part of the container image deployment. If
ostree/deploy doesn't exist (e.g. composefs backend), the entire tree is
relabeled.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: John Eckersberg jeckersb@redhat.com

@github-actions github-actions bot added the area/install Issues related to `bootc install` label Mar 3, 2026
@bootc-bot bootc-bot bot requested a review from gursewak1997 March 3, 2026 01:12
@jeckersb
Copy link
Collaborator Author

jeckersb commented Mar 3, 2026

Assuming this actually works properly (seems to work for me locally but we'll see what the matrix says), we should be able to revert the install parts of #2025, keeping the booted system part as well as the test re-enablement.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a final, comprehensive SELinux relabeling pass on the physical root filesystem just before finalization. This is a robust approach to ensure all files have correct SELinux labels. The logic correctly handles different installation backends by skipping the ostree/deploy directory for ostree-based installs (where its contents are already labeled) and relabeling the entire tree for other scenarios like composefs. The implementation is clean, well-commented, and correctly placed within the installation flow. The changes look solid and improve the reliability of the installation process regarding SELinux contexts.

Perform a full SELinux relabel pass over the physical root filesystem as
the very last step before filesystem finalization. This ensures all files
on the physical root have correct SELinux labels.

The ostree/deploy directory is skipped since its contents are already
correctly labeled as part of the container image deployment. If
ostree/deploy doesn't exist (e.g. composefs backend), the entire tree is
relabeled.

Assisted-by: OpenCode (claude-opus-4-6)
Signed-off-by: John Eckersberg <jeckersb@redhat.com>
Copy link
Collaborator

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the goal here to prove this works by dropping the enforcing=0 in the composefs case? If this does fix it we should of course do that, if it doesn't...I think we should just keep trying until it does right?

}

// As the very last step before filesystem finalization, do a full SELinux
// relabel of the physical root filesystem. We skip ostree/deploy because
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think (but there's $details here) we actually need to precisely skip deployment roots not just all of ostree/deploy.

However...can't we also drop the current ostree-only relabeling step with this? That would really prove things out.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a difference in the labeling between ostree-with-composefs vs ostree-without-composefs? In the composefs case I don't think it matters too much how accurate the labels are since the source of truth ends up in the erofs (but does it populate the erofs from the underlying files? I admit I haven't looked too much into that before now...).

But in the non-composefs case (do we even use that anywhere?) the labels are the final labels.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a difference in the labeling between ostree-with-composefs vs ostree-without-composefs? In the composefs case I don't think it matters too much how accurate the labels are since the source of truth ends up in the erofs (but does it populate the erofs from the underlying files? I admit I haven't looked too much into that before now...).

There's not a difference AFAIK no, but a problem is that in the ostree code path we still sometimes for legacy reasons operate directly on a deployment root without the EROFS (running semodule e.g.) and so the labels need to be correct on the underlying files still too.


Anyways though what we're trying to solve here is the labeling of everything else; ostree should be getting labels of the deployment root correct.

@jeckersb
Copy link
Collaborator Author

jeckersb commented Mar 3, 2026

Looks like CI mostly worked, except:

error: Installing to filesystem: Final SELinux relabeling of physical root: No label found in policy 'Some("99a67cf6f12f746505cc0fdc62ddf3ac8fca59ed19f2eb227c17d0667aa68043")' for /sys/fs/cgroup/io.prio.class)

And yes I realized later in the evening after I had walked away from this that I forgot to remove the enforcing=0 bit here 🙄

@cgwalters
Copy link
Collaborator

/sys/fs/cgroup/io.prio.class

The relabeling code should probably be changed to use https://docs.rs/cap-std-ext/latest/cap_std_ext/dirext/trait.CapStdExtDirExt.html#tymethod.walk with noxdev

@jeckersb
Copy link
Collaborator Author

jeckersb commented Mar 3, 2026

Doesn't seem enough for the files to get just any label, because default_t on the underlying storage is getting denied:

[  178.773356] systemd[1]: Starting ssh-host-keys-migration.service - Update OpenSSH host key permissions...
[  178.774513] audit: type=1400 audit(1772558678.864:100): avc:  denied  { read } for  pid=838 comm="9" path="/39/556cc67f965f16554cb7d0f115a486ad86971eaf7ea804daa445ca3488596f28601a2762ef3115f2bc2ef2faae14e50b1f46f72499a869d561d8209c092b5f" dev="vda3" ino=1064524 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0
[  178.777454] systemd[1]: Starting sshd-keygen@ecdsa.service - OpenSSH ecdsa Server Key Generation...
[  178.779754] audit: type=1400 audit(1772558678.868:101): avc:  denied  { read } for  pid=839 comm="9" path="/39/556cc67f965f16554cb7d0f115a486ad86971eaf7ea804daa445ca3488596f28601a2762ef3115f2bc2ef2faae14e50b1f46f72499a869d561d8209c092b5f" dev="vda3" ino=1064524 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0
[  178.781967] systemd[1]: Starting sshd-keygen@ed25519.service - OpenSSH ed25519 Server Key Generation...
[  178.785205] audit: type=1400 audit(1772558678.872:102): avc:  denied  { read } for  pid=840 comm="9" path="/39/556cc67f965f16554cb7d0f115a486ad86971eaf7ea804daa445ca3488596f28601a2762ef3115f2bc2ef2faae14e50b1f46f72499a869d561d8209c092b5f" dev="vda3" ino=1064524 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0
[  178.787198] systemd[1]: Starting sshd-keygen@rsa.service - OpenSSH rsa Server Key Generation...
[  178.790744] audit: type=1400 audit(1772558678.878:103): avc:  denied  { read } for  pid=841 comm="9" path="/39/556cc67f965f16554cb7d0f115a486ad86971eaf7ea804daa445ca3488596f28601a2762ef3115f2bc2ef2faae14e50b1f46f72499a869d561d8209c092b5f" dev="vda3" ino=1064524 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0
[  178.791656] systemd[1]: sshd-keygen@ecdsa.service: Main process exited, code=exited, status=127/n/a
[  178.797668] systemd[1]: sshd-keygen@ecdsa.service: Failed with result 'exit-code'.

@cgwalters
Copy link
Collaborator

Ah right I think that's because this code needs to pass an override path of /usr like the ostree one does.

@jeckersb
Copy link
Collaborator Author

jeckersb commented Mar 3, 2026

Circling back to this comment it feels like the most correct approach here would be to label all of the composefs objects with some custom type along with some policy glue (via https://fedoraproject.org/wiki/SELinux/IndependentPolicy ?) to make it function similarly to usr_t. I guess initially we could use usr_t directly although that feels incorrect somehow.

@cgwalters
Copy link
Collaborator

I agree it'd be better to have a dedicated type for composefs objects. In theory we could ship custom policy addition to add it now without blocking on upstream. There's a variety of examples of this, e.g. https://github.com/cockpit-project/cockpit/tree/main/selinux

I personally would say it seems way easier to just use usr_t and avoid that complexity, but I have no opposition to trying to add it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install Issues related to `bootc install`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants