Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, 2014-02-20 at 18:17 +, Colin Walters wrote: I think both of these (particularly the second) are worse than my patch - we don't (to my knowledge) support putting policy in the initramfs now with Fedora or Red Hat Enterprise Linux, so attempting to find it there by default on every bootup is wrong. To turn it around, what is the possible value in also probing the initramfs? Does anyone out there load policy from it with systemd? Oof. I'm late, but: actually, yes. Fedup does this during upgrades. We ship the new system's policy in upgrade.img in an attempt to ensure that files written during the upgrade get the right labels. (For example: if you're upgrading F19-F20, we load F20 policy during initramfs, then switch_root to the F19 system to get disks mounted, then switch_root back to initramfs to run the upgrade.) Loading policy in initramfs seems to have some unfortunate side-effects, though. For example, every process runs with kernel_t, and all the files outside of /run and /dev are root_t. Also, something seems racy - sometimes /run/systemd/ask-password ends up init_var_run_t, which keeps us from unlocking /home later. Ugh. It'd probably be better to load F19 policy first, then load F20 policy after the second switch_root *back* to initramfs.. except systemd won't do that either. I'm open to any ideas about how to make sure that the upgrade runs with the right policy loaded (or, really, how to be sure that files written during the upgrade get the correct labels for the new system). Otherwise, this patch will probably interfere with upgrades to F21. -w ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
Currently on at least Fedora, SELinux policy does not come in the initramfs. systemd will attempt to load *both* in the initramfs and in the real root. Now, the selinux_init_load_policy() API has a regular error return value, as well as an enforcing boolean. To determine enforcing state, it looks for /etc/selinux/config as well as the presence of enforcing= on the kernel command line. Ordinarily, neither of those exist in the initramfs, so it will return unknown for enforcing, and systemd will simply ignore the failure to load policy. Then later after we switch to the real root, we have the config file, and all will work properly. Except...this all blows up if someone explicitly specifies enforcing=1 on the kernel command line. Then systemd will fail to load the nonexistent policy in the initramfs and freeze. What this patch does is quite simple - we add an internal API that says where we expect to find policy, and attempt to load it exactly from there. Right now since I'm not aware of anyone who does policy-in-initramfs, this function is hardcoded to return false. Lots-of-very-painful-debugging-by: Colin Walters walt...@verbum.org --- src/core/main.c | 6 -- src/core/selinux-setup.c | 10 ++ src/core/selinux-setup.h | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) From b109b6e0c1ea7509f08a09d66072c86bea279a06 Mon Sep 17 00:00:00 2001 From: Colin Walters walt...@verbum.org Date: Thu, 20 Feb 2014 10:15:10 -0500 Subject: [PATCH] selinux: Only attempt to load policy exactly once, in the real root Currently on at least Fedora, SELinux policy does not come in the initramfs. systemd will attempt to load *both* in the initramfs and in the real root. Now, the selinux_init_load_policy() API has a regular error return value, as well as an enforcing boolean. To determine enforcing state, it looks for /etc/selinux/config as well as the presence of enforcing= on the kernel command line. Ordinarily, neither of those exist in the initramfs, so it will return unknown for enforcing, and systemd will simply ignore the failure to load policy. Then later after we switch to the real root, we have the config file, and all will work properly. Except...this all blows up if someone explicitly specifies enforcing=1 on the kernel command line. Then systemd will fail to load the nonexistent policy in the initramfs and freeze. What this patch does is quite simple - we add an internal API that says where we expect to find policy, and attempt to load it exactly from there. Right now since I'm not aware of anyone who does policy-in-initramfs, this function is hardcoded to return false. Lots-of-very-painful-debugging-by: Colin Walters walt...@verbum.org --- src/core/main.c | 6 -- src/core/selinux-setup.c | 10 ++ src/core/selinux-setup.h | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 58c3a9e..8a13b54 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1296,8 +1296,10 @@ int main(int argc, char *argv[]) { if (!skip_setup) { mount_setup_early(); -if (selinux_setup(loaded_policy) 0) -goto finish; +if (in_initrd() == selinux_load_policy_in_initramfs()) { +if (selinux_setup(loaded_policy) 0) +goto finish; +} if (ima_setup() 0) goto finish; if (smack_setup() 0) diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c index 7a32ed5..f689149 100644 --- a/src/core/selinux-setup.c +++ b/src/core/selinux-setup.c @@ -37,6 +37,16 @@ #include util.h #include log.h +/** + * At present, I'm not aware of a SELinux user who loads the policy + * from the initramfs. If you are such a user, you can flip this + * define with a patch. Alternatively in the future, this information + * could come from the kernel command line. + */ +bool selinux_load_policy_in_initramfs(void) { +return false; +} + #ifdef HAVE_SELINUX static int null_log(int type, const char *fmt, ...) { return 0; diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h index 39e2bc2..d3f3bbc 100644 --- a/src/core/selinux-setup.h +++ b/src/core/selinux-setup.h @@ -23,4 +23,6 @@ #include stdbool.h +bool selinux_load_policy_in_initramfs(void); + int selinux_setup(bool *loaded_policy); -- 1.8.3.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On 02/20/2014 10:42 AM, Colin Walters wrote: Currently on at least Fedora, SELinux policy does not come in the initramfs. systemd will attempt to load *both* in the initramfs and in the real root. Now, the selinux_init_load_policy() API has a regular error return value, as well as an enforcing boolean. To determine enforcing state, it looks for /etc/selinux/config as well as the presence of enforcing= on the kernel command line. Ordinarily, neither of those exist in the initramfs, so it will return unknown for enforcing, and systemd will simply ignore the failure to load policy. Then later after we switch to the real root, we have the config file, and all will work properly. Except...this all blows up if someone explicitly specifies enforcing=1 on the kernel command line. Then systemd will fail to load the nonexistent policy in the initramfs and freeze. What this patch does is quite simple - we add an internal API that says where we expect to find policy, and attempt to load it exactly from there. Right now since I'm not aware of anyone who does policy-in-initramfs, this function is hardcoded to return false. Lots-of-very-painful-debugging-by: Colin Walters walt...@verbum.org --- src/core/main.c | 6 -- src/core/selinux-setup.c | 10 ++ src/core/selinux-setup.h | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) Wouldn't it be better (and more correct) to probe both the initramfs and the real root, and if neither one can load policy successfully and enforcing=1, then halt? ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, Feb 20, 2014 at 1:06 PM, Stephen Smalley s...@tycho.nsa.gov wrote: Wouldn't it be better (and more correct) to probe both the initramfs and the real root, and if neither one can load policy successfully and enforcing=1, then halt? So you're saying we should handle -ENOENT specially in the initramfs? Something like being sure we preserve errno and returning it to the caller of selinux_init_load_policy()? That would introduce a subtle version dependency. Or alternatively, just try in the initramfs, ignore any errors, and only abort if we also fail to load in the real root? I think both of these (particularly the second) are worse than my patch - we don't (to my knowledge) support putting policy in the initramfs now with Fedora or Red Hat Enterprise Linux, so attempting to find it there by default on every bootup is wrong. To turn it around, what is the possible value in also probing the initramfs? Does anyone out there load policy from it with systemd? ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, 20.02.14 18:17, Colin Walters (walt...@verbum.org) wrote: Hmm, maybe a simple check access(/etc/selinux/, F_OK) would be enough? There's no point in trying to initialized SELinux if that dir does not exist, right? Then we could simply bypass the whole thing... On Thu, Feb 20, 2014 at 1:06 PM, Stephen Smalley s...@tycho.nsa.gov wrote: Wouldn't it be better (and more correct) to probe both the initramfs and the real root, and if neither one can load policy successfully and enforcing=1, then halt? So you're saying we should handle -ENOENT specially in the initramfs? Something like being sure we preserve errno and returning it to the caller of selinux_init_load_policy()? That would introduce a subtle version dependency. Or alternatively, just try in the initramfs, ignore any errors, and only abort if we also fail to load in the real root? I think both of these (particularly the second) are worse than my patch - we don't (to my knowledge) support putting policy in the initramfs now with Fedora or Red Hat Enterprise Linux, so attempting to find it there by default on every bootup is wrong. To turn it around, what is the possible value in also probing the initramfs? Does anyone out there load policy from it with systemd? ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
Not really. If it doesn't exist on the final root fs and I put enforcing=1 on the command line, I expect the box to panic/fail/die/whatever On Thu, Feb 20, 2014 at 1:36 PM, Lennart Poettering lenn...@poettering.net wrote: On Thu, 20.02.14 18:17, Colin Walters (walt...@verbum.org) wrote: Hmm, maybe a simple check access(/etc/selinux/, F_OK) would be enough? There's no point in trying to initialized SELinux if that dir does not exist, right? Then we could simply bypass the whole thing... On Thu, Feb 20, 2014 at 1:06 PM, Stephen Smalley s...@tycho.nsa.gov wrote: Wouldn't it be better (and more correct) to probe both the initramfs and the real root, and if neither one can load policy successfully and enforcing=1, then halt? So you're saying we should handle -ENOENT specially in the initramfs? Something like being sure we preserve errno and returning it to the caller of selinux_init_load_policy()? That would introduce a subtle version dependency. Or alternatively, just try in the initramfs, ignore any errors, and only abort if we also fail to load in the real root? I think both of these (particularly the second) are worse than my patch - we don't (to my knowledge) support putting policy in the initramfs now with Fedora or Red Hat Enterprise Linux, so attempting to find it there by default on every bootup is wrong. To turn it around, what is the possible value in also probing the initramfs? Does anyone out there load policy from it with systemd? ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel Lennart -- Lennart Poettering, Red Hat ___ Selinux mailing list seli...@tycho.nsa.gov To unsubscribe, send email to selinux-le...@tycho.nsa.gov. To get help, send an email containing help to selinux-requ...@tycho.nsa.gov. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On 02/20/2014 01:17 PM, Colin Walters wrote: On Thu, Feb 20, 2014 at 1:06 PM, Stephen Smalley s...@tycho.nsa.gov wrote: Wouldn't it be better (and more correct) to probe both the initramfs and the real root, and if neither one can load policy successfully and enforcing=1, then halt? So you're saying we should handle -ENOENT specially in the initramfs? Something like being sure we preserve errno and returning it to the caller of selinux_init_load_policy()? That would introduce a subtle version dependency. Or alternatively, just try in the initramfs, ignore any errors, and only abort if we also fail to load in the real root? I think both of these (particularly the second) are worse than my patch - we don't (to my knowledge) support putting policy in the initramfs now with Fedora or Red Hat Enterprise Linux, so attempting to find it there by default on every bootup is wrong. To turn it around, what is the possible value in also probing the initramfs? Does anyone out there load policy from it with systemd? Ok, I guess when you put it that way... The only cases I know of where policy is loaded from initramfs are embedded Linux and Android, neither of which are using systemd to my knowledge, and both of which have custom policy loading logic anyway. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, Feb 20, 2014 at 1:36 PM, Lennart Poettering lenn...@poettering.net wrote: On Thu, 20.02.14 18:17, Colin Walters (walt...@verbum.org) wrote: Hmm, maybe a simple check access(/etc/selinux/, F_OK) would be enough? There's no point in trying to initialized SELinux if that dir does not exist, right? Then we could simply bypass the whole thing... Beyond what Eric said, I also think that libselinux should continue to contain all of the key logic for whether or not SELinux is enabled and how to behave. The current *API* seems OK in having the two return values of an error code and an enforcing flag. The only thing libselinux can't know is: 1) Whether we're inside an initramfs right now 2) Whether or not the OS vendor expects policy to be found in the real root or the initramfs So those bits of logic make sense to me in systemd, although there is an argument for #2 living in libselinux. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, 20.02.14 13:50, Eric Paris (epa...@parisplace.org) wrote: Not really. If it doesn't exist on the final root fs and I put enforcing=1 on the command line, I expect the box to panic/fail/die/whatever OK, then maybe check !in_initrd() || access(/etc/selinux/, F_OK) = 0? Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
I like it, if it's reasonable/possible On Thu, Feb 20, 2014 at 2:26 PM, Lennart Poettering lenn...@poettering.net wrote: On Thu, 20.02.14 13:50, Eric Paris (epa...@parisplace.org) wrote: Not really. If it doesn't exist on the final root fs and I put enforcing=1 on the command line, I expect the box to panic/fail/die/whatever OK, then maybe check !in_initrd() || access(/etc/selinux/, F_OK) = 0? Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 02/20/2014 02:27 PM, Eric Paris wrote: I like it, if it's reasonable/possible On Thu, Feb 20, 2014 at 2:26 PM, Lennart Poettering lenn...@poettering.net wrote: On Thu, 20.02.14 13:50, Eric Paris (epa...@parisplace.org) wrote: Not really. If it doesn't exist on the final root fs and I put enforcing=1 on the command line, I expect the box to panic/fail/die/whatever OK, then maybe check !in_initrd() || access(/etc/selinux/, F_OK) = 0? Lennart -- Lennart Poettering, Red Hat ___ Selinux mailing list seli...@tycho.nsa.gov To unsubscribe, send email to selinux-le...@tycho.nsa.gov. To get help, send an email containing help to selinux-requ...@tycho.nsa.gov. You mean !in_initrd() || access(selinux_path(), F_OK) = 0? -BEGIN PGP SIGNATURE- Version: GnuPG v1 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMGW1AACgkQrlYvE4MpobOeUgCg3YoRWatuabfOsAGLD4p09QVo PYMAn3hDTBy4ePCPy/jORYlE+KGotSxE =kkZx -END PGP SIGNATURE- ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, Feb 20, 2014 at 2:45 PM, Daniel J Walsh dwa...@redhat.com wrote: You mean !in_initrd() || access(selinux_path(), F_OK) = 0? I don't think so - that would mean we would silently continue if enforcing=1, but we happen to not find a policy on disk. Right? I think my patch is better than this - systemd will attempt to load policy from *only* the real root (not the initramfs), using the exact same logic as is in libselinux currently. For example, it would allow explicitly specifying enforcing=1 on the kernel command line, and that would continue to cause an explicit failure if policy is not found. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
I think the idea was if we are not in the initrd - try to load policy if we are in the initrd and we find selinux_path() - try to load policy Thus embeded/thin who put everything inside the initrd will work (and the kernel enforce=1 will mean what is should) And where we don't put anything inside the initrd will still be correct since we'll try to load no matter what in the real root On Thu, Feb 20, 2014 at 3:52 PM, Colin Walters walt...@verbum.org wrote: On Thu, Feb 20, 2014 at 2:45 PM, Daniel J Walsh dwa...@redhat.com wrote: You mean !in_initrd() || access(selinux_path(), F_OK) = 0? I don't think so - that would mean we would silently continue if enforcing=1, but we happen to not find a policy on disk. Right? I think my patch is better than this - systemd will attempt to load policy from *only* the real root (not the initramfs), using the exact same logic as is in libselinux currently. For example, it would allow explicitly specifying enforcing=1 on the kernel command line, and that would continue to cause an explicit failure if policy is not found. ___ Selinux mailing list seli...@tycho.nsa.gov To unsubscribe, send email to selinux-le...@tycho.nsa.gov. To get help, send an email containing help to selinux-requ...@tycho.nsa.gov. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, Feb 20, 2014 at 4:10 PM, Eric Paris epa...@parisplace.org wrote: I think the idea was if we are not in the initrd - try to load policy if we are in the initrd and we find selinux_path() - try to load policy Thus embeded/thin who put everything inside the initrd will work (and the kernel enforce=1 will mean what is should) And where we don't put anything inside the initrd will still be correct since we'll try to load no matter what in the real root I guess then as long as we don't attempt to load policy again if we already have done so in the initrd - and yes, systemd already has logic of this form inside selinux_setup(). I'm testing this suggested patch now. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] selinux: Only attempt to load policy exactly once, in the real root
On Thu, Feb 20, 2014 at 4:21 PM, Colin Walters walt...@verbum.org wrote: I'm testing this suggested patch now. I tweaked the suggestion a bit because the selinux_path() API call made the most sense inside selinux-setup.c. Attached patch works for me. From ae5f54b4d34320528db8fd1bb24ab7479d081594 Mon Sep 17 00:00:00 2001 From: Colin Walters walt...@verbum.org Date: Thu, 20 Feb 2014 10:15:10 -0500 Subject: [PATCH] selinux: Don't attempt to load policy in initramfs if it doesn't exist Currently on at least Fedora, SELinux policy does not come in the initramfs. systemd will attempt to load *both* in the initramfs and in the real root. Now, the selinux_init_load_policy() API has a regular error return value, as well as an enforcing boolean. To determine enforcing state, it looks for /etc/selinux/config as well as the presence of enforcing= on the kernel command line. Ordinarily, neither of those exist in the initramfs, so it will return unknown for enforcing, and systemd will simply ignore the failure to load policy. Then later after we switch to the real root, we have the config file, and all will work properly. Except...this all blows up if someone explicitly specifies enforcing=1 on the kernel command line. Then systemd will fail to load the nonexistent policy in the initramfs and freeze. This patch tweaks the logic so we attempt to load policy from the initramfs only if we see it exists. We always attempt to load from the real root - but selinux_setup() is a noop if policy is already loaded, so the case of policy successfully loaded in initramfs, not in the real root will work. Lots-of-very-painful-debugging-by: Colin Walters walt...@verbum.org --- src/core/main.c | 2 +- src/core/selinux-setup.c | 9 - src/core/selinux-setup.h | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 58c3a9e..49f237a 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1296,7 +1296,7 @@ int main(int argc, char *argv[]) { if (!skip_setup) { mount_setup_early(); -if (selinux_setup(loaded_policy) 0) +if (selinux_setup(in_initrd(), loaded_policy) 0) goto finish; if (ima_setup() 0) goto finish; diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c index 7a32ed5..ee0ac32 100644 --- a/src/core/selinux-setup.c +++ b/src/core/selinux-setup.c @@ -43,7 +43,7 @@ static int null_log(int type, const char *fmt, ...) { } #endif -int selinux_setup(bool *loaded_policy) { +int selinux_setup(bool in_initrd, bool *loaded_policy) { #ifdef HAVE_SELINUX int enforce = 0; @@ -54,6 +54,13 @@ int selinux_setup(bool *loaded_policy) { assert(loaded_policy); + /* Don't load policy in the initrd if we don't appear to have +* it. For the real root, we check below if we've already +* loaded policy, and return gracefully. +*/ + if (in_initrd access(selinux_path(), F_OK) == -1) + return 0; + /* Turn off all of SELinux' own logging, we want to do that */ cb.func_log = null_log; selinux_set_callback(SELINUX_CB_LOG, cb); diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h index 39e2bc2..9291144 100644 --- a/src/core/selinux-setup.h +++ b/src/core/selinux-setup.h @@ -23,4 +23,4 @@ #include stdbool.h -int selinux_setup(bool *loaded_policy); +int selinux_setup(bool in_initrd, bool *loaded_policy); -- 1.8.3.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel