summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-10-26 21:53:29 +0100
committerChristian Brauner <brauner@kernel.org>2026-10-29 14:35:13 +0100
commitbf5ba73c9bdd5e872eb35e801e429a3b526f8f04 (patch)
treecf3af62a7930916dfb813c004fd6447b9ef5dba5 /tools/testing
parent948e604aca8af30490accf7d46d44814ffa26f80 (diff)
userns: don't drop the exec securebits
SECBIT_EXEC_RESTRICT_FILE and SECBIT_EXEC_DENY_INTERACTIVE tell script interpreters to only run what AT_EXECVE_CHECK allows and to refuse interactive input. A service manager sets them together with their lock bits so that nothing below it can turn them off again. But set_cred_user_ns() resets all securebits to SECUREBITS_DEFAULT. So any task that can create a user namespace sheds the locked exec bits with a single unshare(CLONE_NEWUSER) and joining one with setns() does the same. The lock is pointless if anyone who may create a user namespace can drop it, and that is pretty much everyone. Resetting the other bits is fine. They are about how capabilities are computed and a new user namespace starts out with a full set of capabilities anyway. The exec bits grant nothing though. They are restrictions a task placed on itself, just like no_new_privs which a user namespace doesn't touch either. So keep them and their locks. Reproducer: // SPDX-License-Identifier: GPL-2.0 /* Lock the exec securebits, then create a user namespace and look at them again. */ #define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <sys/prctl.h> #define SECBIT_EXEC_RESTRICT_FILE (1 << 8) #define SECBIT_EXEC_RESTRICT_FILE_LOCKED (1 << 9) #define SECBIT_EXEC_DENY_INTERACTIVE (1 << 10) #define SECBIT_EXEC_DENY_INTERACTIVE_LOCKED (1 << 11) int main(void) { int bits = SECBIT_EXEC_RESTRICT_FILE | SECBIT_EXEC_RESTRICT_FILE_LOCKED | SECBIT_EXEC_DENY_INTERACTIVE | SECBIT_EXEC_DENY_INTERACTIVE_LOCKED; if (prctl(PR_SET_SECUREBITS, bits, 0, 0, 0)) { perror("PR_SET_SECUREBITS"); return 1; } printf("before: 0x%x\n", prctl(PR_GET_SECUREBITS, 0, 0, 0, 0)); printf("clear locked bits: %s\n", prctl(PR_SET_SECUREBITS, 0, 0, 0, 0) ? "refused" : "ALLOWED"); if (unshare(CLONE_NEWUSER)) { perror("unshare(CLONE_NEWUSER)"); return 1; } printf("after unshare(CLONE_NEWUSER): 0x%x\n", prctl(PR_GET_SECUREBITS, 0, 0, 0, 0)); return 0; } On v7.1 this prints "before: 0xf00", "clear locked bits: refused" and "after unshare(CLONE_NEWUSER): 0x0". With this patch the last line reads 0xf00 as well. Fixes: a0623b2a1d59 ("security: Add EXEC_RESTRICT_FILE and EXEC_DENY_INTERACTIVE securebits") Cc: stable@vger.kernel.org # v6.14+ Link: https://patch.msgid.link/20261026-work-securebits-userns-v1-1-b35473fa1a34@kernel.org Reviewed-by: Mickaël Salaün <mic@digikod.net> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'tools/testing')
0 files changed, 0 insertions, 0 deletions