Add a simple tool to set SECBIT_SHOULD_EXEC_CHECK,
SECBIT_SHOULD_EXEC_RESTRICT, and their lock counterparts before
executing a command. This should be useful to easily test against
script interpreters.
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Paul Moore <paul@paul-moore.com>
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Link: https://lore.kernel.org/r/20240704190137.696169-6-mic@digikod.net
---
samples/Kconfig | 7 +++
samples/Makefile | 1 +
samples/should-exec/.gitignore | 1 +
samples/should-exec/Makefile | 13 ++++
samples/should-exec/set-should-exec.c | 88 +++++++++++++++++++++++++++
5 files changed, 110 insertions(+)
create mode 100644 samples/should-exec/.gitignore
create mode 100644 samples/should-exec/Makefile
create mode 100644 samples/should-exec/set-should-exec.c
diff --git a/samples/Kconfig b/samples/Kconfig
index b288d9991d27..d8f2639bc830 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -180,6 +180,13 @@ config SAMPLE_SECCOMP
Build samples of seccomp filters using various methods of
BPF filter construction.
+config SAMPLE_SHOULD_EXEC
+ bool "Should-exec secure bits examples"
+ depends on CC_CAN_LINK && HEADERS_INSTALL
+ help
+ Build a tool to easily configure SECBIT_SHOULD_EXEC_CHECK,
+ SECBIT_SHOULD_EXEC_RESTRICT and their lock counterparts.
+
config SAMPLE_TIMER
bool "Timer sample"
depends on CC_CAN_LINK && HEADERS_INSTALL
diff --git a/samples/Makefile b/samples/Makefile
index b85fa64390c5..0e7a97fb222d 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -19,6 +19,7 @@ subdir-$(CONFIG_SAMPLE_PIDFD) += pidfd
obj-$(CONFIG_SAMPLE_QMI_CLIENT) += qmi/
obj-$(CONFIG_SAMPLE_RPMSG_CLIENT) += rpmsg/
subdir-$(CONFIG_SAMPLE_SECCOMP) += seccomp
+subdir-$(CONFIG_SAMPLE_SHOULD_EXEC) += should-exec
subdir-$(CONFIG_SAMPLE_TIMER) += timers
obj-$(CONFIG_SAMPLE_TRACE_EVENTS) += trace_events/
obj-$(CONFIG_SAMPLE_TRACE_CUSTOM_EVENTS) += trace_events/
diff --git a/samples/should-exec/.gitignore b/samples/should-exec/.gitignore
new file mode 100644
index 000000000000..ac46c614ec80
--- /dev/null
+++ b/samples/should-exec/.gitignore
@@ -0,0 +1 @@
+/set-should-exec
diff --git a/samples/should-exec/Makefile b/samples/should-exec/Makefile
new file mode 100644
index 000000000000..c4294278dd07
--- /dev/null
+++ b/samples/should-exec/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+userprogs-always-y := set-should-exec
+
+userccflags += -I usr/include
+
+.PHONY: all clean
+
+all:
+ $(MAKE) -C ../.. samples/should-exec/
+
+clean:
+ $(MAKE) -C ../.. M=samples/should-exec/ clean
diff --git a/samples/should-exec/set-should-exec.c b/samples/should-exec/set-should-exec.c
new file mode 100644
index 000000000000..b3c31106d916
--- /dev/null
+++ b/samples/should-exec/set-should-exec.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Simple tool to set SECBIT_SHOULD_EXEC_CHECK, SECBIT_SHOULD_EXEC_RESTRICT,
+ * and their lock counterparts before executing a command.
+ *
+ * Copyright © 2024 Microsoft Corporation
+ */
+
+#define _GNU_SOURCE
+#define __SANE_USERSPACE_TYPES__
+#include <errno.h>
+#include <linux/prctl.h>
+#include <linux/securebits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+static void print_usage(const char *argv0)
+{
+ fprintf(stderr, "usage: %s -c|-r [-l] -- <cmd> [args]...\n\n", argv0);
+ fprintf(stderr, "Execute a command with\n");
+ fprintf(stderr, "- SECBIT_SHOULD_EXEC_CHECK set: -c\n");
+ fprintf(stderr, "- SECBIT_SHOULD_EXEC_RESTRICT set: -r\n");
+ fprintf(stderr, "- SECBIT_SHOULD_EXEC_*_LOCKED set: -l\n");
+}
+
+int main(const int argc, char *const argv[], char *const *const envp)
+{
+ const char *cmd_path;
+ char *const *cmd_argv;
+ int opt, secbits, err;
+ bool has_policy = false;
+
+ secbits = prctl(PR_GET_SECUREBITS);
+
+ while ((opt = getopt(argc, argv, "crl")) != -1) {
+ switch (opt) {
+ case 'c':
+ secbits |= SECBIT_SHOULD_EXEC_CHECK;
+ has_policy = true;
+ break;
+ case 'r':
+ secbits |= SECBIT_SHOULD_EXEC_RESTRICT;
+ has_policy = true;
+ break;
+ case 'l':
+ secbits |= SECBIT_SHOULD_EXEC_CHECK_LOCKED;
+ secbits |= SECBIT_SHOULD_EXEC_RESTRICT_LOCKED;
+ break;
+ default:
+ print_usage(argv[0]);
+ return 1;
+ }
+ }
+
+ if (!argv[optind] || !has_policy) {
+ print_usage(argv[0]);
+ return 1;
+ }
+
+ err = prctl(PR_SET_SECUREBITS, secbits);
+ if (err) {
+ perror("Failed to set secure bit(s).");
+ fprintf(stderr,
+ "Hint: The running kernel may not support this feature.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "SECBIT_SHOULD_EXEC_CHECK: %d\n",
+ !!(secbits & SECBIT_SHOULD_EXEC_CHECK));
+ fprintf(stderr, "SECBIT_SHOULD_EXEC_CHECK_LOCKED: %d\n",
+ !!(secbits & SECBIT_SHOULD_EXEC_CHECK_LOCKED));
+ fprintf(stderr, "SECBIT_SHOULD_EXEC_RESTRICT: %d\n",
+ !!(secbits & SECBIT_SHOULD_EXEC_RESTRICT));
+ fprintf(stderr, "SECBIT_SHOULD_EXEC_RESTRICT_LOCKED: %d\n",
+ !!(secbits & SECBIT_SHOULD_EXEC_RESTRICT_LOCKED));
+
+ cmd_path = argv[optind];
+ cmd_argv = argv + optind;
+ fprintf(stderr, "Executing command...\n");
+ execvpe(cmd_path, cmd_argv, envp);
+ fprintf(stderr, "Failed to execute \"%s\": %s\n", cmd_path,
+ strerror(errno));
+ return 1;
+}
--
2.45.2
Hi Mickaël, On Thu, 2024-07-04 at 21:01 +0200, Mickaël Salaün wrote: > Add a simple tool to set SECBIT_SHOULD_EXEC_CHECK, > SECBIT_SHOULD_EXEC_RESTRICT, and their lock counterparts before > executing a command. This should be useful to easily test against > script interpreters. The print_usage() provides the calling syntax. Could you provide an example of how to use it and what to expect? thanks, Mimi
On Mon, Jul 08, 2024 at 03:40:42PM -0400, Mimi Zohar wrote: > Hi Mickaël, > > On Thu, 2024-07-04 at 21:01 +0200, Mickaël Salaün wrote: > > Add a simple tool to set SECBIT_SHOULD_EXEC_CHECK, > > SECBIT_SHOULD_EXEC_RESTRICT, and their lock counterparts before > > executing a command. This should be useful to easily test against > > script interpreters. > > The print_usage() provides the calling syntax. Could you provide an example of > how to use it and what to expect? To set SECBIT_SHOULD_EXEC_CHECK, SECBIT_SHOULD_EXEC_RESTRICT, and lock them on a new shell (session) we can use this: ./set-should-exec -crl -- bash -i This would have no impact unless Bash, ld.so, or one of its child code is patched to restrict execution (e.g. with execveat+AT_CHECK check). Script interpreters and dynamic linkers need to be patch on a secure sysetm. Steve is enlightening Python, and we'll need more similar changes for common user space code. This can be an incremental work and only enforced on some user sessions or containers for instance. > > thanks, > > Mimi > >
© 2016 - 2026 Red Hat, Inc.