diff mbox series

[OpenWrt-Devel,procd] initd/init: add minimal SELinux policy loading support

Message ID 20191113151241.752720-1-thomas.petazzoni@bootlin.com
State Changes Requested
Headers show
Series [OpenWrt-Devel,procd] initd/init: add minimal SELinux policy loading support | expand

Commit Message

Thomas Petazzoni Nov. 13, 2019, 3:12 p.m. UTC
In order to support SELinux in OpenWRT, this commit introduces minimal
support for loading the SELinux policy in the init code. The logic is
very much inspired from what Busybox is doing: call
selinux_init_load_policy() from libselinux, and then re-execute init
so that it runs with the SELinux policy in place and enforced.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
---
I have patches ready to add some minimal SELinux support to OpenWRT,
which I intend to send in the near future.
---
 CMakeLists.txt |  9 ++++++++-
 initd/init.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

Comments

Petr Štetiar Nov. 15, 2019, 5:29 a.m. UTC | #1
Thomas Petazzoni <thomas.petazzoni@bootlin.com> [2019-11-13 16:12:41]:

Hi,

is this some kind of RFC/idea probe? I like the idea, additional hardening is
needed and welcome I would say.

> I have patches ready to add some minimal SELinux support to OpenWRT,
> which I intend to send in the near future.

It would probably make more sense to send somehow minimal but complete working
SELinux support so one could see what it would mean in terms of flash space,
RAM, CPU overhead etc. Maybe adding one of the default services exposed to the
network as initial example?

> +  pkg_search_module(SELINUX REQUIRED libselinux)

This looks like a missing dependency.

> fprintf(stderr, "Cannot load SELinux policy, but system in enforcing mode. Halting.\n");

Just a side note, halting in the context of running on the router means
flashing of factory image. Halting doesn't provide any feedback to the user,
if we don't consider stuck-in-the-bootlop as a proper feedback.  Probably
entering failsafe(has LED feedback) or such would make more sense here?

I'm not implying, that this needs to be solved from the beginning, halting
during development is alright, just something to think about.

-- ynezz
Thomas Petazzoni Nov. 15, 2019, 8:16 a.m. UTC | #2
Hello Petr,

Thanks for your feedback!

On Fri, 15 Nov 2019 06:29:49 +0100
Petr Štetiar <ynezz@true.cz> wrote:

> is this some kind of RFC/idea probe? I like the idea, additional hardening is
> needed and welcome I would say.

No, this patch is not RFC, it should be ready for merging, I'm already
using it in some devices.

> > I have patches ready to add some minimal SELinux support to OpenWRT,
> > which I intend to send in the near future.  
> 
> It would probably make more sense to send somehow minimal but complete working
> SELinux support so one could see what it would mean in terms of flash space,
> RAM, CPU overhead etc. Maybe adding one of the default services exposed to the
> network as initial example?

The thing is that the SELinux support in OpenWRT needs this improvement
in procd, otherwise it won't work at runtime as nothing will be loading
the SELinux policy.

Regarding the flash space, RAM and CPU overhead, I'm not sure it's that
relevant: the SELinux packaging I've done makes it completely optional,
so you only have an impact of flash space, RAM and CPU if you enable
SELinux support. If you don't, then your OpenWRT system is exactly like
it was before.

> > +  pkg_search_module(SELINUX REQUIRED libselinux)  
> 
> This looks like a missing dependency.

Sorry, but I don't understand what you mean here. Or maybe you're
saying that there is no libselinux package in OpenWRT ? That is true,
and will be part of my patch series to OpenWRT adding all the packages
related to OpenWRT support.

> > fprintf(stderr, "Cannot load SELinux policy, but system in enforcing mode. Halting.\n");  
> 
> Just a side note, halting in the context of running on the router means
> flashing of factory image. Halting doesn't provide any feedback to the user,
> if we don't consider stuck-in-the-bootlop as a proper feedback.  Probably
> entering failsafe(has LED feedback) or such would make more sense here?

Do you have more details about entering failsafe mode ? How do you do
that ?

Thanks,

Thomas
Petr Štetiar Nov. 16, 2019, 1:22 p.m. UTC | #3
Thomas Petazzoni <thomas.petazzoni@bootlin.com> [2019-11-15 09:16:32]:

(nitpick, it's OpenWrt, not OpenWRT)

> No, this patch is not RFC, it should be ready for merging, I'm already
> using it in some devices.

Ok, this patch is good enough for your limited use case, but in order to
include SELinux support in OpenWrt, then the first patch series should be more
comprehensive, minimal yet complete.

> The thing is that the SELinux support in OpenWRT needs this improvement
> in procd, otherwise it won't work at runtime as nothing will be loading
> the SELinux policy.

Where is that policy? What about kernel part? What about userspace part? What
about filesystem image? And so on.

> Regarding the flash space, RAM and CPU overhead, I'm not sure it's that
> relevant: the SELinux packaging I've done makes it completely optional,
> so you only have an impact of flash space, RAM and CPU if you enable
> SELinux support.

Once its merged, we basically say, that its more or less supported, even if
it's optional.

It's pretty much crystal clear, that some additional hardening layer would be
very welcome. I think, that OpenWrt should aim for something, which could be
usable on most of modern devices today and enabled by default. Security
shouldn't be an option, it should be default.

SELinux is just one of the LSMs in Linux.  Is SELinux the right one for
OpenWrt project? Are we going to support all of them? I doubt that, so
decision needs to be made.

> Do you have more details about entering failsafe mode ? How do you do that ?

It's usually triggered by the button during the boot process[1], but it should
be possible to force it from procd as well.

1. https://openwrt.org/docs/guide-user/troubleshooting/failsafe_and_factory_reset

-- ynezz
Thomas Petazzoni Nov. 18, 2019, 1:32 p.m. UTC | #4
Hello Petr,

Thanks for your feedback again.

On Sat, 16 Nov 2019 14:22:13 +0100
Petr Štetiar <ynezz@true.cz> wrote:

> (nitpick, it's OpenWrt, not OpenWRT)

Thanks for this clarification, it's always good to use the proper
capitalization for project names. I'll try to use OpenWrt in the
future, but please bear with me if I sometimes forget.

> > No, this patch is not RFC, it should be ready for merging, I'm already
> > using it in some devices.  
> 
> Ok, this patch is good enough for your limited use case, but in order to
> include SELinux support in OpenWrt, then the first patch series should be more
> comprehensive, minimal yet complete.

I guess I'll send the patch series itself, so we can have the
discussion on the actual proposal. I sent this procd patch separately,
just because it is a requirement for the rest of the series to work
(right now I was working with this procd patch in the OpenWrt procd
package).

> > The thing is that the SELinux support in OpenWRT needs this improvement
> > in procd, otherwise it won't work at runtime as nothing will be loading
> > the SELinux policy.  
> 
> Where is that policy? What about kernel part? What about userspace part? What
> about filesystem image? And so on.

In terms of policy, I'm simply using the reference policy provided by
the SELinux project itself, with no specific customization for OpenWrt.
Of course, additional tuning may be required, but for my use case, it
was sufficient. In terms of kernel part, it of course requires some
kernel options to be enabled. In terms of user-space parts, this is
where my patch series is the most interesting: it packages all the
user-space components that are necessary to be able to work with
SELinux.

> > Regarding the flash space, RAM and CPU overhead, I'm not sure it's that
> > relevant: the SELinux packaging I've done makes it completely optional,
> > so you only have an impact of flash space, RAM and CPU if you enable
> > SELinux support.  
> 
> Once its merged, we basically say, that its more or less supported, even if
> it's optional.
> 
> It's pretty much crystal clear, that some additional hardening layer would be
> very welcome. I think, that OpenWrt should aim for something, which could be
> usable on most of modern devices today and enabled by default. Security
> shouldn't be an option, it should be default.
> 
> SELinux is just one of the LSMs in Linux.  Is SELinux the right one for
> OpenWrt project? Are we going to support all of them? I doubt that, so
> decision needs to be made.

I guess here I don't have the OpenWrt mindset, as I come from a
Buildroot background. Buildroot supports multiple solutions for the
same "problem", and let users decide which solution they want to use
(so the users have some integration work to do), while it seems that
OpenWrt wants to make a decision on one solution to use, but provide
something that is seamlessly integrated for users.

> > Do you have more details about entering failsafe mode ? How do you do that ?  
> 
> It's usually triggered by the button during the boot process[1], but it should
> be possible to force it from procd as well.
> 
> 1. https://openwrt.org/docs/guide-user/troubleshooting/failsafe_and_factory_reset

OK, thanks.

Thomas
Etienne Champetier Nov. 18, 2019, 3:14 p.m. UTC | #5
Hello Thomas,

Le lun. 18 nov. 2019 à 05:33, Thomas Petazzoni
<thomas.petazzoni@bootlin.com> a écrit :
>
> Hello Petr,
>
> Thanks for your feedback again.
>
> On Sat, 16 Nov 2019 14:22:13 +0100
> Petr Štetiar <ynezz@true.cz> wrote:
>
> > (nitpick, it's OpenWrt, not OpenWRT)
>
> Thanks for this clarification, it's always good to use the proper
> capitalization for project names. I'll try to use OpenWrt in the
> future, but please bear with me if I sometimes forget.
>
> > > No, this patch is not RFC, it should be ready for merging, I'm already
> > > using it in some devices.
> >
> > Ok, this patch is good enough for your limited use case, but in order to
> > include SELinux support in OpenWrt, then the first patch series should be more
> > comprehensive, minimal yet complete.
>
> I guess I'll send the patch series itself, so we can have the
> discussion on the actual proposal. I sent this procd patch separately,
> just because it is a requirement for the rest of the series to work
> (right now I was working with this procd patch in the OpenWrt procd
> package).
>
> > > The thing is that the SELinux support in OpenWRT needs this improvement
> > > in procd, otherwise it won't work at runtime as nothing will be loading
> > > the SELinux policy.
> >
> > Where is that policy? What about kernel part? What about userspace part? What
> > about filesystem image? And so on.
>
> In terms of policy, I'm simply using the reference policy provided by
> the SELinux project itself, with no specific customization for OpenWrt.
> Of course, additional tuning may be required, but for my use case, it
> was sufficient. In terms of kernel part, it of course requires some
> kernel options to be enabled. In terms of user-space parts, this is
> where my patch series is the most interesting: it packages all the
> user-space components that are necessary to be able to work with
> SELinux.

If you can include the compressed size of each part, this is also
important for the discussion I think
I know part of the debug tools on regular distro, like audit2why, are
python scripts, so pretty huge dependency

Regards
Etienne

>
> > > Regarding the flash space, RAM and CPU overhead, I'm not sure it's that
> > > relevant: the SELinux packaging I've done makes it completely optional,
> > > so you only have an impact of flash space, RAM and CPU if you enable
> > > SELinux support.
> >
> > Once its merged, we basically say, that its more or less supported, even if
> > it's optional.
> >
> > It's pretty much crystal clear, that some additional hardening layer would be
> > very welcome. I think, that OpenWrt should aim for something, which could be
> > usable on most of modern devices today and enabled by default. Security
> > shouldn't be an option, it should be default.
> >
> > SELinux is just one of the LSMs in Linux.  Is SELinux the right one for
> > OpenWrt project? Are we going to support all of them? I doubt that, so
> > decision needs to be made.
>
> I guess here I don't have the OpenWrt mindset, as I come from a
> Buildroot background. Buildroot supports multiple solutions for the
> same "problem", and let users decide which solution they want to use
> (so the users have some integration work to do), while it seems that
> OpenWrt wants to make a decision on one solution to use, but provide
> something that is seamlessly integrated for users.
>
> > > Do you have more details about entering failsafe mode ? How do you do that ?
> >
> > It's usually triggered by the button during the boot process[1], but it should
> > be possible to force it from procd as well.
> >
> > 1. https://openwrt.org/docs/guide-user/troubleshooting/failsafe_and_factory_reset
>
> OK, thanks.
>
> Thomas
> --
> Thomas Petazzoni, CTO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
diff mbox series

Patch

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4b3eebd..865e43c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,12 @@  IF(ZRAM_TMPFS)
   SET(SOURCES_ZRAM initd/zram.c)
 ENDIF()
 
+IF(SELINUX)
+  include(FindPkgConfig)
+  pkg_search_module(SELINUX REQUIRED libselinux)
+  add_compile_definitions(WITH_SELINUX)
+ENDIF()
+
 add_subdirectory(upgraded)
 
 ADD_EXECUTABLE(procd ${SOURCES})
@@ -56,7 +62,8 @@  ADD_DEFINITIONS(-DDISABLE_INIT)
 ELSE()
 ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c sysupgrade.c watchdog.c
 	utils/utils.c ${SOURCES_ZRAM})
-TARGET_LINK_LIBRARIES(init ${LIBS})
+TARGET_INCLUDE_DIRECTORIES(init PUBLIC ${SELINUX_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(init ${LIBS} ${SELINUX_LIBRARIES})
 INSTALL(TARGETS init
 	RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
 )
diff --git a/initd/init.c b/initd/init.c
index 9b47826..f765b60 100644
--- a/initd/init.c
+++ b/initd/init.c
@@ -29,6 +29,10 @@ 
 #include <unistd.h>
 #include <stdio.h>
 
+#if defined(WITH_SELINUX)
+#include <selinux/selinux.h>
+#endif
+
 #include "../utils/utils.h"
 #include "init.h"
 #include "../watchdog.h"
@@ -67,6 +71,41 @@  cmdline(void)
 	}
 }
 
+#if defined(WITH_SELINUX)
+static int
+selinux(char **argv)
+{
+	int enforce = 0;
+	int ret;
+
+	/* SELinux already initialized */
+	if (getenv("SELINUX_INIT"))
+		return 0;
+
+	putenv("SELINUX_INIT=1");
+
+	printf("Loading SELinux policy...\n");
+
+	ret = selinux_init_load_policy(&enforce);
+	printf("selinux_init_load_policy returned %d\n", ret);
+	if (ret == 0)
+		execv(argv[0], argv);
+
+	if (enforce > 0) {
+		fprintf(stderr, "Cannot load SELinux policy, but system in enforcing mode. Halting.\n");
+		return 1;
+	}
+
+	return 0;
+}
+#else
+static int
+selinux(char **argv)
+{
+	return 0;
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
@@ -79,6 +118,8 @@  main(int argc, char **argv)
 	sigaction(SIGUSR2, &sa_shutdown, NULL);
 	sigaction(SIGPWR, &sa_shutdown, NULL);
 
+	if (selinux(argv))
+		exit(-1);
 	early();
 	cmdline();
 	watchdog_init(1);