Skip to contentSkip to conversation

make ip vrf exec SELinux-aware

PATCH Applied Andrea Claudi 2 participants 6 messages Aug 23, 2023 – Aug 25, 2023

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover make ip vrf exec SELinux-aware

In order to execute a service with VRF, a user should start it using "ip vrf exec". For example, using systemd, the user can encapsulate the ExecStart command in ip vrf exec as shown below:

ExecStart=/usr/sbin/ip vrf exec vrf1 /usr/sbin/httpd $OPTIONS -DFOREGROUND

Assuming SELinux is in permissive mode, starting the service with the current ip vrf implementation results in:

# systemctl start httpd
# ps -eafZ | grep httpd
system_u:system_r:ifconfig_t:s0 root      597448       1  1 19:22 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:ifconfig_t:s0 apache    597452  597448  0 19:22 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
[snip]

This is incorrect, as the context for httpd should be httpd_t, not ifconfig_t.

This happens because ipvrf_exec invokes cmd_exec without setting the correct SELinux context before. Without the correct setting, the process is executed using ip's SELinux context.

This patch series makes "ip vrf exec" SELinux-aware using the setexecfilecon functions, which retrieves the correct context to be used on the next execvp() call.

After this series:

# systemctl start httpd
# ps -eafZ | grep httpd
system_u:system_r:httpd_t:s0    root      595805       1  0 19:01 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0    apache    595809  595805  0 19:01 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND

Patch series description:
- 1/4 and 2/4 are preliminary changes to make SELinux helper functions used in ss conformant to the SELinux API definitions;
- 3/4 makes SELinux helper functions into a library, so they can be used in other iproute tools - such as ip - when iproute is compiled without SELinux support;
- 4/4, finally, add setexecfilecon to the SELinux stubs, and uses it to actually set the correct file context for the command to be executed.

Andrea Claudi (4):
ss: make is_selinux_enabled stub work like in SELinux
ss: make SELinux stub functions conformant to API definitions
lib: add SELinux include and stub functions
ip vrf: make ipvrf_exec SELinux-aware

 include/selinux.h | 10 ++++++++++
 ip/ipvrf.c        |  6 ++++++
 lib/Makefile      |  4 ++++
 lib/selinux.c     | 37 +++++++++++++++++++++++++++++++++++++
 misc/ss.c         | 36 ++----------------------------------
 5 files changed, 59 insertions(+), 34 deletions(-)
 create mode 100644 include/selinux.h
 create mode 100644 lib/selinux.c
Signature · 1 line
2.41.0
#1 lore raw

PATCH 1/4 ss: make is_selinux_enabled stub work like in SELinux

From the is_selinux_enabled() manpage:

is_selinux_enabled() returns 1 if SELinux is running or 0 if it is not.

This makes the is_selinux_enabled() stub functions works exactly like the SELinux function it is supposed to replace.

---
 misc/ss.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
misc/ss.c +2 -2
index 6d34ad0e..007cb349 100644
@@ -77,7 +77,7 @@
 /* Stubs for SELinux functions */
 static int is_selinux_enabled(void)
 {
-	return -1;
+	return 0;
 }
 
 static int getpidcon(pid_t pid, char **context)
@@ -5682,7 +5682,7 @@ int main(int argc, char *argv[])
 			show_sock_ctx++;
 			/* fall through */
 		case 'Z':
-			if (is_selinux_enabled() <= 0) {
+			if (!is_selinux_enabled()) {
 				fprintf(stderr, "ss: SELinux is not enabled.\n");
 				exit(1);
 			}
Signature · 1 line
2.41.0
#2 lore raw

PATCH 2/4 ss: make SELinux stub functions conformant to API definitions

In reply to Andrea Claudi

getfilecon() and security_get_initial_context() use the const qualifier for their first paramater in SELinux APIs.

This commit adds the const qualifier to these functions, making them conformant to API definitions.

---
 misc/ss.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
misc/ss.c +2 -2
index 007cb349..b3183630 100644
@@ -86,13 +86,13 @@ static int getpidcon(pid_t pid, char **context)
 	return -1;
 }
 
-static int getfilecon(char *path, char **context)
+static int getfilecon(const char *path, char **context)
 {
 	*context = NULL;
 	return -1;
 }
 
-static int security_get_initial_context(char *name,  char **context)
+static int security_get_initial_context(const char *name,  char **context)
 {
 	*context = NULL;
 	return -1;
Signature · 1 line
2.41.0
#3 lore raw

PATCH 3/4 lib: add SELinux include and stub functions

In reply to Andrea Claudi

ss provides some selinux stub functions, useful when iproute2 is compiled without selinux support.

Move them to lib/ so we can use them in other iproute2 tools.

---
 include/selinux.h |  9 +++++++++
 lib/Makefile      |  4 ++++
 lib/selinux.c     | 32 ++++++++++++++++++++++++++++++++
 misc/ss.c         | 34 +---------------------------------
 4 files changed, 46 insertions(+), 33 deletions(-)
 create mode 100644 include/selinux.h
 create mode 100644 lib/selinux.c
include/selinux.h new file +9 -0
new file mode 100644
index 00000000..499aa966
@@ -0,0 +1,9 @@
+#if HAVE_SELINUX
+#include <selinux/selinux.h>
+#else
+int is_selinux_enabled(void);
+void freecon(char *context);
+int getpidcon(pid_t pid, char **context);
+int getfilecon(const char *path, char **context);
+int security_get_initial_context(const char *name,  char **context);
+#endif
lib/Makefile +4 -0
index ddedd37f..aa7bbd2e 100644
@@ -13,6 +13,10 @@ UTILOBJ += bpf_libbpf.o
 endif
 endif
 
+ifneq ($(HAVE_SELINUX),y)
+UTILOBJ += selinux.o
+endif
+
 NLOBJ=libgenl.o libnetlink.o
 ifeq ($(HAVE_MNL),y)
 NLOBJ += mnl_utils.o
lib/selinux.c new file +32 -0
new file mode 100644
index 00000000..4e6805fc
@@ -0,0 +1,32 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include "selinux.h"
+
+/* Stubs for SELinux functions */
+int is_selinux_enabled(void)
+{
+	return 0;
+}
+
+void freecon(char *context)
+{
+	free(context);
+}
+
+int getpidcon(pid_t pid, char **context)
+{
+	*context = NULL;
+	return -1;
+}
+
+int getfilecon(const char *path, char **context)
+{
+	*context = NULL;
+	return -1;
+}
+
+int security_get_initial_context(const char *name,  char **context)
+{
+	*context = NULL;
+	return -1;
+}
misc/ss.c +1 -33
index b3183630..2ef19039 100644
@@ -33,6 +33,7 @@
 #include "version.h"
 #include "rt_names.h"
 #include "cg_map.h"
+#include "selinux.h"
 
 #include <linux/tcp.h>
 #include <linux/unix_diag.h>
@@ -71,39 +72,6 @@
 #define BUF_CHUNKS_MAX 5	/* Maximum number of allocated buffer chunks */
 #define LEN_ALIGN(x) (((x) + 1) & ~1)
 
-#if HAVE_SELINUX
-#include <selinux/selinux.h>
-#else
-/* Stubs for SELinux functions */
-static int is_selinux_enabled(void)
-{
-	return 0;
-}
-
-static int getpidcon(pid_t pid, char **context)
-{
-	*context = NULL;
-	return -1;
-}
-
-static int getfilecon(const char *path, char **context)
-{
-	*context = NULL;
-	return -1;
-}
-
-static int security_get_initial_context(const char *name,  char **context)
-{
-	*context = NULL;
-	return -1;
-}
-
-static void freecon(char *context)
-{
-	free(context);
-}
-#endif
-
 int preferred_family = AF_UNSPEC;
 static int show_options;
 int show_details;
Signature · 1 line
2.41.0
#4 lore raw

PATCH 4/4 ip vrf: make ipvrf_exec SELinux-aware

In reply to Andrea Claudi

When using ip vrf and SELinux is enabled, make sure to set the exec file context before calling cmd_exec.

This ensures that the command is executed with the right context, falling back to the ifconfig_t context when needed.

---
 include/selinux.h | 1 +
 ip/ipvrf.c        | 6 ++++++
 lib/selinux.c     | 5 +++++
 3 files changed, 12 insertions(+)
include/selinux.h +1 -0
index 499aa966..592c7680 100644
@@ -6,4 +6,5 @@ void freecon(char *context);
 int getpidcon(pid_t pid, char **context);
 int getfilecon(const char *path, char **context);
 int security_get_initial_context(const char *name,  char **context);
+int setexecfilecon(const char *filename, const char *fallback_type);
 #endif
ip/ipvrf.c +6 -0
index d6b59adb..12beaec3 100644
@@ -24,6 +24,7 @@
 #include "utils.h"
 #include "ip_common.h"
 #include "bpf_util.h"
+#include "selinux.h"
 
 #define CGRP_PROC_FILE  "/cgroup.procs"
 
@@ -455,6 +456,11 @@ static int ipvrf_exec(int argc, char **argv)
 		return -1;
 	}
 
+	if (is_selinux_enabled() && setexecfilecon(argv[1], "ifconfig_t")) {
+		fprintf(stderr, "setexecfilecon for \"%s\" failed\n", argv[1]);
+		return -1;
+	}
+
 	return -cmd_exec(argv[1], argv + 1, !!batch_mode, do_switch, argv[0]);
 }
 
lib/selinux.c +5 -0
index 4e6805fc..7e5dd16d 100644
@@ -30,3 +30,8 @@ int security_get_initial_context(const char *name,  char **context)
 	*context = NULL;
 	return -1;
 }
+
+int setexecfilecon(const char *filename, const char *fallback_type)
+{
+	return -1;
+}
Signature · 1 line
2.41.0
#5 lore raw
In reply to Andrea Claudi
This series was applied to iproute2/iproute2-next.git (main) by David Ahern <[email protected]>:

Hello:

This series was applied to iproute2/iproute2-next.git (main) by David Ahern <[email protected]>:

Quoted 10 lines · On Wed, 23 Aug 2023 19:29:58 +0200 you wrote:

In order to execute a service with VRF, a user should start it using "ip vrf exec". For example, using systemd, the user can encapsulate the ExecStart command in ip vrf exec as shown below:

ExecStart=/usr/sbin/ip vrf exec vrf1 /usr/sbin/httpd $OPTIONS -DFOREGROUND

Assuming SELinux is in permissive mode, starting the service with the current ip vrf implementation results in:

[...]

Here is the summary with links:
- [iproute2-next,1/4] ss: make is_selinux_enabled stub work like in SELinux

    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=c8970828b650
  - [iproute2-next,2/4] ss: make SELinux stub functions conformant to API definitions
    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=61c6882ce21c
  - [iproute2-next,3/4] lib: add SELinux include and stub functions
    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=e246ebc3b7f1
  - [iproute2-next,4/4] ip vrf: make ipvrf_exec SELinux-aware
    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=0d0eeaa6cb92

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html