Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The --chroot option doesn't work well with SELinux off in-chroot #940

Open
praiskup opened this issue Feb 7, 2024 · 5 comments
Open

The --chroot option doesn't work well with SELinux off in-chroot #940

praiskup opened this issue Feb 7, 2024 · 5 comments

Comments

@praiskup
Copy link

praiskup commented Feb 7, 2024

Consider installing a separate minimal chroot, and then running useradd --root (other shadow-utils utility):

$ sudo dnf5 -y --use-host-config --installroot /tmp/newroot install /bin/sh
$ sudo useradd jdoe --root /tmp/newroot
useradd: failure while writing changes to /etc/passwd

I used GDB to detect what was going on. It is the call to set_selinux_file_context () at file-descriptor-closing-time.

The thing is that set_selinux_file_context() is called non-conditionally every time, and it asks for is_selinux_enabled() - which provides the info about SELinux on-host, not in-chroot:

shadow/lib/selinux.c

Lines 47 to 52 in 3e59e96

int set_selinux_file_context (const char *dst_name, mode_t mode)
{
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}

A further assumption that the selabel_open(), selabel_lookup_raw(), etc. in-chroot will work, is wrong.

There are further checks for permissive mode that make shadow utils not fail (in theory):

shadow/lib/selinux.c

Lines 66 to 68 in e367d11

if (security_getenforce () != 0) {
return 1;
}

But one would have to make sure that the /tmp/newroot/sys/fs/selinux/enforce file exists first, and contains 0.

This problem is causing problems to Mock (RPM chrooted builds). We could fake the /sys/fs/selinux/enforce file for sure in Mock (we do other hacks to make things work), though this isn't the ideal solution; the mode in-chroot isn't really "permissive", it is supposed to be "disabled". So we should ideally not even attempt to call selabel_open(), etc.

While I see this probably isn't a mistake of shadow-utils (but rather chroot-unfriendly linbselinux API), I'm curious what is the best way out of this. Could we have a new --no-selinux option?

Also, note that the manual pages are a bit misleading:

       -P, --prefix PREFIX_DIR
           Apply changes to configuration files under the root filesystem
           found under the directory PREFIX_DIR. This option does not chroot
           and is intended for preparing a cross-compilation target. Some
           limitations: NIS and LDAP users/groups are not verified. PAM
           authentication is using the host files. No SELINUX support.

Note the note No SELinux support. This seems wrong. The set_selinux_file_context() is called with --prefix exactly the same way as with --root. It makes people think that --root works better with SELinux, but that's not truth either.

@pmatilai
Copy link

We (== rpm upstream) ran into this too: we'd like to use useradd/groupadd to create users into an otherwise practically empty chroot during the initial system install, but this selinux related logic prevents it. As @praiskup notes, just creating a fake enforcing file is enough to work around it:

[root@localhost]# rm -rf /srv/test/*
[root@localhost]# mkdir -p /srv/test/etc
[root@localhost]# groupadd -r -R /srv/test mumble
groupadd: failure while writing changes to /etc/group

[root@localhost]# mkdir -p /srv/test/sys/fs/selinux
[root@localhost]# echo 0 > /srv/test/sys/fs/selinux/enforce
[root@localhost]# groupadd -r -R /srv/test mumble
[root@localhost]#

This seems kinda counterproductive. Been there enough to know that SELinux and chroot aren't the best of friends, but few very few things are designed with a totally empty chroot in mind. In that case there are exactly two options: either use the info from the host, or disable. Disable is non-ambiguous, but obviously has other downsides.

I wouldn't mind working on a patch if we can agree on the desireable way to handle it. FWIW the rpm sysusers issue would be sufficiently handled with an explicit flag of some sort (cli switch, env variable).

@ikerexxe
Copy link
Collaborator

I'm not a SELinux expert, am I to assume that sys/fs/selinux/enforce is the file that indicates whether a system (or chroot) has SELinux activated?

@ffesti
Copy link

ffesti commented Aug 27, 2024

Yes.

@ikerexxe
Copy link
Collaborator

In that case, my preferred option would be for SELinux to take this into account and provide an interface that we can use to see if SELinux is enabled in the chroot environment. This would also allow other projects to use the same interface to do the same thing.

In case this is not possible shadow should check the sys/fs/selinux/enforce file manually in the chroot environment and act accordingly.

@praiskup
Copy link
Author

Adding a new SELinux API (I assume you mean within the /sys/fs/selinux path) would be a long-shot 🤷 Then, before we invent a new interface there, IMO we should answer a basic question: Does it ever make sense to operate with SELinux if shadow utils are used with --root? It probably makes sense with --prefix.

@pmatilai I observe that dnf --installroot / rpm --root correctly sets SELinux labels on installed files. Is this done by implicit SELinux support of underlying utilities (like shadow-utils), or does RPM handle this post install via restorecon?

I also missed the comment in SELinuxProject/selinux#419 before, where @cgzones suggests calling fini_selinuxmnt. Could we call it when we detect that the --root option is used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants