From nobody Wed Dec 17 10:22:48 2025 Received: from smtp-relay-canonical-0.canonical.com (smtp-relay-canonical-0.canonical.com [185.125.188.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64E81283145; Fri, 10 Oct 2025 13:35:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.125.188.120 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103306; cv=none; b=PnE8Db2aYCauKkP75oKM9sZxcKe2BCuAZ3o/NOhAQknDg6VyBqD1b8x1ypn8e9HTNV0nWfIxYY6c5WDBljT4fbleoDyxIW/QTnEUdohoW+5aPE/kqUGbbcmyNG6DfXGBoe8RyMMV4Wp5TwtNmrxUB6nK4+rsps77yVVrF0ErZ+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103306; c=relaxed/simple; bh=KXep7NVOwTKVzewOBLfq2vUJFjiHHnxI+Vd/5ay7Scs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iX/7nY0uZtEzY9fwdFpIMkXPkV01dNqqN54MaI0Gxi19fn/Ic5KpGlP4Qg84RdpEd4q/t0q5+TZX0KZek8KWXVl2IcC+afxPHtUvNqV8myGnkQSoiMU47qom+EJ+mUrJKh10P7STgWMinxjZXDnbJBWCqlf/RIgCJRqOEmPb898= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com; spf=pass smtp.mailfrom=canonical.com; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b=l1x0o9E+; arc=none smtp.client-ip=185.125.188.120 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=canonical.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b="l1x0o9E+" Received: from sec2-plucky-amd64.. (176-136-128-80.abo.bbox.fr [176.136.128.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id 1641342AC4; Fri, 10 Oct 2025 13:26:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20251003; t=1760102818; bh=i0z0hp01nkDNYMe/66Eoqju2NbR4cKF9bq5emxh6Jwk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=l1x0o9E+btRuZYotYPTgT0+f6Sr/gCLcLuLFLUHA5qBwg+86+AvZks2k0eDlXVsWe LIJshGMEXvG22790lARwbQxNJpMSWYaitY/jjRBpLLFMZrlzrhQgFQGV/BxsXIDt7M osb+6FpdUNCOwithJnQl1jRYNqTU3Vmp4WNj2z9TXacjbSL4Hqp6yfnmNZDxPYjOte dhvx6xDgOSzDvC0RVuLlxyBayd9j4dLqKep0kmD3433/jksri/YeL/Sp3HfSCWp6R2 4hKvvN8D3lCaOpGj1rg7ZgYN6KVALyHnvIN17SSenrQnl5eRklYaCgVvujGGBnM6Kz mSiwEj5IfbR+vuy/HGo3uwHkI68sPG6hrmOpdNnbUUXH38utFgDnEHTAK8CaJcI2wP 6cmYX54PjHsUelwdvzQpZoZhWYF+2dY6qbF2yUa1ebCxToY1jKz0+Nsc4BdHUWaSJN zBSNHW8SLwYxHiock5Fw8yu9cl9pB4epRDqW9noLJ3lRmBENz1wCMde8mkf2qQ6PmB 6QGSj+UqLD5OvvH6WPBYU1E+ZsaRQWUDGJGYGRJmSmJiPMcEXzxLkZQvQpDVfznCrL SOrXCC/+ZHe6Npe1Sg2LWsEKujGWQwgD3aXspohVNAtuHmfpaGdsfEPrwrIDA8wgQ3 LdAjdxuIg2s/SvQXW5otTNMw= From: =?UTF-8?q?Maxime=20B=C3=A9lair?= To: linux-security-module@vger.kernel.org Cc: john.johansen@canonical.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, mic@digikod.net, kees@kernel.org, stephen.smalley.work@gmail.com, casey@schaufler-ca.com, takedakn@nttdata.co.jp, penguin-kernel@I-love.SAKURA.ne.jp, song@kernel.org, rdunlap@infradead.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v6 1/5] Wire up lsm_config_self_policy and lsm_config_system_policy syscalls Date: Fri, 10 Oct 2025 15:25:28 +0200 Message-ID: <20251010132610.12001-2-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251010132610.12001-1-maxime.belair@canonical.com> References: <20251010132610.12001-1-maxime.belair@canonical.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add support for the new lsm_config_self_policy and lsm_config_system_policy syscalls, providing a unified API for loading and modifying LSM policies, for the current user and for the entire system, respectively without requiring the LSM=E2=80=99s pseudo-filesystems. Benefits: - Works even if the LSM pseudo-filesystem isn=E2=80=99t mounted or availa= ble (e.g. in containers) - Offers a logical and unified interface rather than multiple heterogeneous pseudo-filesystems - Avoids the overhead of other kernel interfaces for better efficiency Signed-off-by: Maxime B=C3=A9lair --- arch/alpha/kernel/syscalls/syscall.tbl | 2 ++ arch/arm/tools/syscall.tbl | 2 ++ arch/m68k/kernel/syscalls/syscall.tbl | 2 ++ arch/microblaze/kernel/syscalls/syscall.tbl | 2 ++ arch/mips/kernel/syscalls/syscall_n32.tbl | 2 ++ arch/mips/kernel/syscalls/syscall_n64.tbl | 2 ++ arch/mips/kernel/syscalls/syscall_o32.tbl | 2 ++ arch/parisc/kernel/syscalls/syscall.tbl | 2 ++ arch/powerpc/kernel/syscalls/syscall.tbl | 2 ++ arch/s390/kernel/syscalls/syscall.tbl | 2 ++ arch/sh/kernel/syscalls/syscall.tbl | 2 ++ arch/sparc/kernel/syscalls/syscall.tbl | 2 ++ arch/x86/entry/syscalls/syscall_32.tbl | 2 ++ arch/x86/entry/syscalls/syscall_64.tbl | 2 ++ arch/xtensa/kernel/syscalls/syscall.tbl | 2 ++ include/linux/syscalls.h | 5 +++++ include/uapi/asm-generic/unistd.h | 6 +++++- kernel/sys_ni.c | 2 ++ security/lsm_syscalls.c | 12 ++++++++++++ tools/include/uapi/asm-generic/unistd.h | 6 +++++- tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 2 ++ 21 files changed, 61 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/sys= calls/syscall.tbl index 2dd6340de6b4..4fc75352220d 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -507,3 +507,5 @@ 575 common listxattrat sys_listxattrat 576 common removexattrat sys_removexattrat 577 common open_tree_attr sys_open_tree_attr +578 common lsm_config_self_policy sys_lsm_config_self_policy +579 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 27c1d5ebcd91..326483cb94a4 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -482,3 +482,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/sysca= lls/syscall.tbl index 9fe47112c586..d37364df1cd7 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -467,3 +467,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/= kernel/syscalls/syscall.tbl index 7b6e97828e55..9d58ebfcf967 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -473,3 +473,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/s= yscalls/syscall_n32.tbl index aa70e371bb54..8627b5f56280 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -406,3 +406,5 @@ 465 n32 listxattrat sys_listxattrat 466 n32 removexattrat sys_removexattrat 467 n32 open_tree_attr sys_open_tree_attr +468 n32 lsm_config_self_policy sys_lsm_config_self_policy +469 n32 lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/s= yscalls/syscall_n64.tbl index 1e8c44c7b614..813207b61f58 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -382,3 +382,5 @@ 465 n64 listxattrat sys_listxattrat 466 n64 removexattrat sys_removexattrat 467 n64 open_tree_attr sys_open_tree_attr +468 n64 lsm_config_self_policy sys_lsm_config_self_policy +469 n64 lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/s= yscalls/syscall_o32.tbl index 114a5a1a6230..9cd0946b4370 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -455,3 +455,5 @@ 465 o32 listxattrat sys_listxattrat 466 o32 removexattrat sys_removexattrat 467 o32 open_tree_attr sys_open_tree_attr +468 o32 lsm_config_self_policy sys_lsm_config_self_policy +469 o32 lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/s= yscalls/syscall.tbl index 94df3cb957e9..9db01dd55793 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -466,3 +466,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel= /syscalls/syscall.tbl index 9a084bdb8926..97714acb39ab 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -558,3 +558,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/sysca= lls/syscall.tbl index a4569b96ef06..d2b0f14fb516 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -470,3 +470,5 @@ 465 common listxattrat sys_listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy sys_lsm_con= fig_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy sys_lsm_= config_system_policy diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/= syscall.tbl index 52a7652fcff6..210d7118ce16 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -471,3 +471,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/sys= calls/syscall.tbl index 83e45eb6c095..494417d80680 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -513,3 +513,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscal= ls/syscall_32.tbl index ac007ea00979..36c2c538e04f 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -473,3 +473,5 @@ 465 i386 listxattrat sys_listxattrat 466 i386 removexattrat sys_removexattrat 467 i386 open_tree_attr sys_open_tree_attr +468 i386 lsm_config_self_policy sys_lsm_config_self_policy +469 i386 lsm_config_system_policy sys_lsm_config_system_policy diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscal= ls/syscall_64.tbl index cfb5ca41e30d..7eefbccfe531 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -391,6 +391,8 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy =20 # # Due to a historical design error, certain syscalls are numbered differen= tly diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/s= yscalls/syscall.tbl index f657a77314f8..90d86a54a952 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -438,3 +438,5 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index e5603cc91963..43b53fbd44be 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -988,6 +988,11 @@ asmlinkage long sys_lsm_get_self_attr(unsigned int att= r, struct lsm_ctx __user * asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __= user *ctx, u32 size, u32 flags); asmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u3= 2 flags); +asmlinkage long sys_lsm_config_self_policy(u32 lsm_id, u32 op, void __user= *buf, + u32 __user size, u32 common_flags, u32 flags); +asmlinkage long sys_lsm_config_system_policy(u32 lsm_id, u32 op, void __us= er *buf, + u32 __user size, u32 common_flags u32 flags); + =20 /* * Architecture-specific system calls diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/u= nistd.h index 2892a45023af..021d0689c929 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -851,9 +851,13 @@ __SYSCALL(__NR_listxattrat, sys_listxattrat) __SYSCALL(__NR_removexattrat, sys_removexattrat) #define __NR_open_tree_attr 467 __SYSCALL(__NR_open_tree_attr, sys_open_tree_attr) +#define __NR_lsm_config_self_policy 468 +__SYSCALL(__NR_lsm_config_self_policy, sys_lsm_config_self_policy) +#define __NR_lsm_config_system_policy 469 +__SYSCALL(__NR_lsm_config_system_policy, sys_lsm_config_system_policy) =20 #undef __NR_syscalls -#define __NR_syscalls 468 +#define __NR_syscalls 470 =20 /* * 32 bit systems traditionally used different diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index c00a86931f8c..3ecebcd3fbe0 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -172,6 +172,8 @@ COND_SYSCALL_COMPAT(fadvise64_64); COND_SYSCALL(lsm_get_self_attr); COND_SYSCALL(lsm_set_self_attr); COND_SYSCALL(lsm_list_modules); +COND_SYSCALL(lsm_config_self_policy); +COND_SYSCALL(lsm_config_system_policy); =20 /* CONFIG_MMU only */ COND_SYSCALL(swapon); diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c index 8440948a690c..b02a7623dea6 100644 --- a/security/lsm_syscalls.c +++ b/security/lsm_syscalls.c @@ -118,3 +118,15 @@ SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, u= 32 __user *, size, =20 return lsm_active_cnt; } + +SYSCALL_DEFINE6(lsm_config_self_policy, u32, lsm_id, u32, op, void __user = *, + buf, u32 __user, size, u32, common_flags, u32, flags) +{ + return 0; +} + +SYSCALL_DEFINE6(lsm_config_system_policy, u32, lsm_id, u32, op, void __use= r *, + buf, u32 __user, size, u32, common_flags, u32, flags) +{ + return 0; +} diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/a= sm-generic/unistd.h index 2892a45023af..021d0689c929 100644 --- a/tools/include/uapi/asm-generic/unistd.h +++ b/tools/include/uapi/asm-generic/unistd.h @@ -851,9 +851,13 @@ __SYSCALL(__NR_listxattrat, sys_listxattrat) __SYSCALL(__NR_removexattrat, sys_removexattrat) #define __NR_open_tree_attr 467 __SYSCALL(__NR_open_tree_attr, sys_open_tree_attr) +#define __NR_lsm_config_self_policy 468 +__SYSCALL(__NR_lsm_config_self_policy, sys_lsm_config_self_policy) +#define __NR_lsm_config_system_policy 469 +__SYSCALL(__NR_lsm_config_system_policy, sys_lsm_config_system_policy) =20 #undef __NR_syscalls -#define __NR_syscalls 468 +#define __NR_syscalls 470 =20 /* * 32 bit systems traditionally used different diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf= /arch/x86/entry/syscalls/syscall_64.tbl index cfb5ca41e30d..7eefbccfe531 100644 --- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl @@ -391,6 +391,8 @@ 465 common listxattrat sys_listxattrat 466 common removexattrat sys_removexattrat 467 common open_tree_attr sys_open_tree_attr +468 common lsm_config_self_policy sys_lsm_config_self_policy +469 common lsm_config_system_policy sys_lsm_config_system_policy =20 # # Due to a historical design error, certain syscalls are numbered differen= tly --=20 2.48.1 From nobody Wed Dec 17 10:22:48 2025 Received: from smtp-relay-canonical-0.canonical.com (smtp-relay-canonical-0.canonical.com [185.125.188.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6ED402F25EC; Fri, 10 Oct 2025 13:35:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.125.188.120 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103307; cv=none; b=kHnzmktKDGFEA/7r/N9LFj1Yue9iQmPzcXnzPylvrKj9YSo6ez7yQ97PGcePagq9CR6Yh0lHttDA0NCHaN2z00WWtgsD9Qek5g1gLiz3/9tmpN0MUEcK/2aKCqHX581ngcnFWHFGElzckdVVpcvuUbLgSOzc8Tzo6TnVDR0BkTw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103307; c=relaxed/simple; bh=SQXc1K0Z1VZW3ROHzyxH21tIQGWnboXgdIyPoPiCp1A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IAf41nQjz6MY5yuel3x1ol5W7B+0YN5mqBI9488BgN+cKR7QqU8ZcPR3T3p5aTFVJB+gOv/h4BPKNEzcyE9+fJ/gpmGyPnfm8yE1dXzYDhpRlPKRCYylKpbTtddfE0X3XAfiTYqCJnB0t2TPcI8kb/CxN6l/6sKzNtSptIBZk80= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com; spf=pass smtp.mailfrom=canonical.com; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b=m3WE9POt; arc=none smtp.client-ip=185.125.188.120 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=canonical.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b="m3WE9POt" Received: from sec2-plucky-amd64.. (176-136-128-80.abo.bbox.fr [176.136.128.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id A486842AC7; Fri, 10 Oct 2025 13:26:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20251003; t=1760102818; bh=7SW7X9yzS5dQaxg3ulKbD2ZXQwm+YDMDeeVSp63vB6Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m3WE9POtoKg+e501gTdMyJmeVBmxk0yBwuC1aiF15yUoQtczMg8a9fPw7iChuzdzM wk0Rozy25trmNKb3ZEg8JTpaNfp+DvtQgp0zDbVZfgzoXhEMR0PJVxdQ1Q2MhTOSkl ihQgdMs/TzMkkPebCrgtV7L6Hq5M2pXJiCOv90IV2Sw2lTOGHPuPutipldVimUa2mB vW1KqUQw22SCSDthLTA5g5L28hvwS/hGYJ0piId+Z+MvGTDtVzWbKMnxbw5iAVBXne b3m+WLi5eT32Gf0KoqnqMoGXCQq1qMC6n0HoMOx6zHC3ce6C4403SMZLJk0puN9TYf cObzX5K/SatbBw3OXkD0HxKhyKU4B7L78bGONRj1YnAmg0RbsMWxQflOGEuolVucBW cYTcHSVdW4bijeEohZJzGfpsWAHFiFYBv34jw7FrU9InJohuID1ih0Y0Vp9MYDlySY DWcQptHPiZsPTZo7urRUtpFduZFuLAXmNJUmfbJUadQdWgpXH3OmL5S6Zx7DshU3aZ p84HwR25NVBInI/pLyzudQqSj9Fy3ZwPNjK+lLFgkx8O6wuSvtdn384a5PsAI+yXsE 68McBHXXrM3LvyTWCCWbE6frtrkqMGIC1eJV+QMr3DSKaGdlDkP5XzbDkqhSQVTq0g 2M8UrKEbB7F8KMZgO5Ab/Ct4= From: =?UTF-8?q?Maxime=20B=C3=A9lair?= To: linux-security-module@vger.kernel.org Cc: john.johansen@canonical.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, mic@digikod.net, kees@kernel.org, stephen.smalley.work@gmail.com, casey@schaufler-ca.com, takedakn@nttdata.co.jp, penguin-kernel@I-love.SAKURA.ne.jp, song@kernel.org, rdunlap@infradead.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v6 2/5] lsm: introduce security_lsm_config_*_policy hooks Date: Fri, 10 Oct 2025 15:25:29 +0200 Message-ID: <20251010132610.12001-3-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251010132610.12001-1-maxime.belair@canonical.com> References: <20251010132610.12001-1-maxime.belair@canonical.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Define two new LSM hooks: security_lsm_config_self_policy and security_lsm_config_system_policy and wire them into the corresponding lsm_config_*_policy() syscalls so that LSMs can register a unified interface for policy management. This initial, minimal implementation only supports the LSM_POLICY_LOAD operation to limit changes. Signed-off-by: Maxime B=C3=A9lair --- include/linux/lsm_hook_defs.h | 4 +++ include/linux/security.h | 20 ++++++++++++ include/uapi/linux/lsm.h | 8 +++++ security/lsm_syscalls.c | 13 ++++++-- security/security.c | 60 +++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index bf3bbac4e02a..50b6e8aed787 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -464,3 +464,7 @@ LSM_HOOK(int, 0, bdev_alloc_security, struct block_devi= ce *bdev) LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev) LSM_HOOK(int, 0, bdev_setintegrity, struct block_device *bdev, enum lsm_integrity_type type, const void *value, size_t size) +LSM_HOOK(int, -EINVAL, lsm_config_self_policy, u32 op, void __user *buf, + size_t size, u32 flags) +LSM_HOOK(int, -EINVAL, lsm_config_system_policy, u32 op, + void __user *buf, size_t size, u32 flags) diff --git a/include/linux/security.h b/include/linux/security.h index cc9b54d95d22..54acaee4a994 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -581,6 +581,11 @@ void security_bdev_free(struct block_device *bdev); int security_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type, const void *value, size_t size); +int security_lsm_config_self_policy(u32 lsm_id, u32 op, void __user *buf, + size_t size, u32 flags); +int security_lsm_config_system_policy(u32 lsm_id, u32 op, void __user *buf, + size_t size, u32 flags); + #else /* CONFIG_SECURITY */ =20 /** @@ -1603,6 +1608,21 @@ static inline int security_bdev_setintegrity(struct = block_device *bdev, return 0; } =20 +static inline int security_lsm_config_self_policy(u32 lsm_id, u32 op, + void __user *buf, + size_t size, u32 flags) +{ + + return -EOPNOTSUPP; +} + +static inline int security_lsm_config_system_policy(u32 lsm_id, u32 op, + void __user *buf, + size_t size, u32 flags) +{ + + return -EOPNOTSUPP; +} #endif /* CONFIG_SECURITY */ =20 #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h index 938593dfd5da..2b9432a30cdc 100644 --- a/include/uapi/linux/lsm.h +++ b/include/uapi/linux/lsm.h @@ -90,4 +90,12 @@ struct lsm_ctx { */ #define LSM_FLAG_SINGLE 0x0001 =20 +/* + * LSM_POLICY_XXX definitions identify the different operations + * to configure LSM policies + */ + +#define LSM_POLICY_UNDEF 0 +#define LSM_POLICY_LOAD 100 + #endif /* _UAPI_LINUX_LSM_H */ diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c index b02a7623dea6..0796673b6f19 100644 --- a/security/lsm_syscalls.c +++ b/security/lsm_syscalls.c @@ -122,11 +122,20 @@ SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, = u32 __user *, size, SYSCALL_DEFINE6(lsm_config_self_policy, u32, lsm_id, u32, op, void __user = *, buf, u32 __user, size, u32, common_flags, u32, flags) { - return 0; + if (common_flags) // Reserved for future use + return -EINVAL; + + return security_lsm_config_self_policy(lsm_id, op, buf, size, flags); } =20 SYSCALL_DEFINE6(lsm_config_system_policy, u32, lsm_id, u32, op, void __use= r *, buf, u32 __user, size, u32, common_flags, u32, flags) { - return 0; + if (common_flags) // Reserved for future use + return -EINVAL; + + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + + return security_lsm_config_system_policy(lsm_id, op, buf, size, flags); } diff --git a/security/security.c b/security/security.c index fb57e8fddd91..eeb61b27cd56 100644 --- a/security/security.c +++ b/security/security.c @@ -5883,6 +5883,66 @@ int security_bdev_setintegrity(struct block_device *= bdev, } EXPORT_SYMBOL(security_bdev_setintegrity); =20 +/** + * security_lsm_config_self_policy() - Configure caller's LSM policies + * @lsm_id: id of the LSM to target + * @op: Operation to perform (one of the LSM_POLICY_XXX values) + * @buf: userspace pointer to policy data + * @size: size of @buf + * @flags: lsm policy configuration flags + * + * Configure the policies of a LSM for the current domain/user. This notab= ly + * allows to update them even when the lsmfs is unavailable or restricted. + * Currently, only LSM_POLICY_LOAD is supported. + * + * Return: Returns 0 on success, error on failure. + */ +int security_lsm_config_self_policy(u32 lsm_id, u32 op, void __user *buf, + size_t size, u32 flags) +{ + int rc =3D LSM_RET_DEFAULT(lsm_config_self_policy); + struct lsm_static_call *scall; + + lsm_for_each_hook(scall, lsm_config_self_policy) { + if ((scall->hl->lsmid->id) =3D=3D lsm_id) { + rc =3D scall->hl->hook.lsm_config_self_policy(op, buf, size, flags); + break; + } + } + + return rc; +} + +/** + * security_lsm_config_system_policy() - Configure system LSM policies + * @lsm_id: id of the lsm to target + * @op: Operation to perform (one of the LSM_POLICY_XXX values) + * @buf: userspace pointer to policy data + * @size: size of @buf + * @flags: lsm policy configuration flags + * + * Configure the policies of a LSM for the whole system. This notably allo= ws + * to update them even when the lsmfs is unavailable or restricted. Curren= tly, + * only LSM_POLICY_LOAD is supported. + * + * Return: Returns 0 on success, error on failure. + */ +int security_lsm_config_system_policy(u32 lsm_id, u32 op, void __user *buf, + size_t size, u32 flags) +{ + int rc =3D LSM_RET_DEFAULT(lsm_config_system_policy); + struct lsm_static_call *scall; + + lsm_for_each_hook(scall, lsm_config_system_policy) { + if ((scall->hl->lsmid->id) =3D=3D lsm_id) { + rc =3D scall->hl->hook.lsm_config_system_policy(op, buf, size, flags); + break; + } + } + + return rc; +} + #ifdef CONFIG_PERF_EVENTS /** * security_perf_event_open() - Check if a perf event open is allowed --=20 2.48.1 From nobody Wed Dec 17 10:22:48 2025 Received: from smtp-relay-canonical-0.canonical.com (smtp-relay-canonical-0.canonical.com [185.125.188.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C1682F25FC; Fri, 10 Oct 2025 13:35:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.125.188.120 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103307; cv=none; b=ozUbW1tmWUlK/scYGeuB3h+87Jmj8T+LKsRw8FSuLvDzSbQy5pE0IAVE67vKMPV2VXRLl23HWOM0RY181YRW5ReWcMbtHFE/XJQKHHXpL5D2536cha+O4OCj5Nsr/4EGtgQTaHrPRuH5oN5/QA0BHVt4JkMeCBKLTx0XB25xMq4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103307; c=relaxed/simple; bh=X/GsXdBWdfXXRt0ghFFsLgydBhQw5P0myg0jE0q0b4A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=J1aFz3V4kXXcTtP25z+BaDq6gENuhHfYRYuDOs38dHQ6G+euiJ/R6z8ZTOYkpQrOSaS9BeFS9ShIXodRJxwLHwid9MEtewowni/yMRVbIykfDJf32PmXgwNGRQaRgosv8HpuNGpdan/3O7K4fbj94lRRnl5k9joBUT6Zq9C06BY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com; spf=pass smtp.mailfrom=canonical.com; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b=RIcPvBsA; arc=none smtp.client-ip=185.125.188.120 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=canonical.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b="RIcPvBsA" Received: from sec2-plucky-amd64.. (176-136-128-80.abo.bbox.fr [176.136.128.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id 1A5BC42ABB; Fri, 10 Oct 2025 13:26:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20251003; t=1760102819; bh=jGPNpKS2szpuz35ek8898VMWMnvPCq4+dTJnd8sl6wI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RIcPvBsAQSzqoH30fHLjfpRcOHQecTxM1khAYi/usNZnnVWgRvLHXCcbpEcBSUajg 2ZFfnnbS8LYj52kQE4nqf634rSuGnhltRWrZtlbciZrlPH1kRdYlG22XKbHYiZPilw DXkMJI3UKpODl1J+7bCBnhhrEQ41ypcUvzBsDIlz+xf10INJB2FS2K4enOlGMXSOVS x+AWW4HWvvA+uL/tH6CTCqdeZHRb5odcpLErZxziZWOPgHss0xdRogdBF0vhkqOsjf EoZlmxykPr0YjZpzr8B2fs14oDZmxR4LnOfImALxOrpwbQdnRugz1JKaTPlFk7U77H /FdHIYZ1x5/LZ/XrnNzKOxraCl550+4tFvaPdwdO2vK0CbCsGI4686rmPitn0h1I/L XEz9bdvWT7krQM6m4wpfyrGYs1efkHCinyg/p+TB0IGEEFHFEzO5fHWpPliYNYx/+B Gh38n9wQso5j5e2eCNCeelbwXJacmhuhqvLf2xMweyypYUEmhdWH8gK581Gv9fcN3t zirt+Kw8TLCqJsILJxL/0uYKpMPEjJZUU63mSGHISe+hHJPUA0AOIGy3+UGbIjiexO qqOmv2YMHL+w4AqO4jWO2fCiw0neMJwmUL9btPl7uGjJYifxwBACjeqidc3cjk81rg gm1itOkj1UYHEQNd3D/qiTbc= From: =?UTF-8?q?Maxime=20B=C3=A9lair?= To: linux-security-module@vger.kernel.org Cc: john.johansen@canonical.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, mic@digikod.net, kees@kernel.org, stephen.smalley.work@gmail.com, casey@schaufler-ca.com, takedakn@nttdata.co.jp, penguin-kernel@I-love.SAKURA.ne.jp, song@kernel.org, rdunlap@infradead.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v6 3/5] AppArmor: add support for lsm_config_self_policy and lsm_config_system_policy Date: Fri, 10 Oct 2025 15:25:30 +0200 Message-ID: <20251010132610.12001-4-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251010132610.12001-1-maxime.belair@canonical.com> References: <20251010132610.12001-1-maxime.belair@canonical.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Enable users to manage AppArmor policies through the new hooks lsm_config_self_policy and lsm_config_system_policy. lsm_config_self_policy allows stacking existing policies in the kernel. This ensures that it can only further restrict the caller and can never be used to gain new privileges. lsm_config_system_policy allows loading or replacing AppArmor policies in any AppArmor namespace and is restricted to CAP_MAC_ADMIN. Signed-off-by: Maxime B=C3=A9lair --- security/apparmor/apparmorfs.c | 31 ++++++++++ security/apparmor/include/apparmor.h | 4 ++ security/apparmor/include/apparmorfs.h | 3 + security/apparmor/lsm.c | 84 ++++++++++++++++++++++++++ 4 files changed, 122 insertions(+) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 6039afae4bfc..6df43299b045 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -439,6 +439,37 @@ static ssize_t policy_update(u32 mask, const char __us= er *buf, size_t size, return error; } =20 +/** + * aa_profile_load_ns_name - load a profile into the current namespace ide= ntified by name + * @name: The name of the namesapce to load the policy in. "" for root_ns + * @name_size: size of @name. 0 For root ns + * @buf: buffer containing the user-provided policy + * @size: size of @buf + * @ppos: position pointer in the file + * + * Returns: 0 on success, negative value on error + */ +ssize_t aa_profile_load_ns_name(char *name, size_t name_size, const void _= _user *buf, + size_t size, loff_t *ppos) +{ + struct aa_ns *ns; + + if (name_size =3D=3D 0) + ns =3D aa_get_ns(root_ns); + else + ns =3D aa_lookupn_ns(root_ns, name, name_size); + + if (!ns) + return -EINVAL; + + int error =3D policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY, + buf, size, ppos, ns); + + aa_put_ns(ns); + + return error >=3D 0 ? 0 : error; +} + /* .load file hook fn to load policy */ static ssize_t profile_load(struct file *f, const char __user *buf, size_t= size, loff_t *pos) diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/inclu= de/apparmor.h index f83934913b0f..1d9a2881a8b9 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -62,5 +62,9 @@ extern unsigned int aa_g_path_max; #define AA_DEFAULT_CLEVEL 0 #endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ =20 +/* Syscall-related buffer size limits */ + +#define AA_PROFILE_NAME_MAX_SIZE (1 << 9) +#define AA_PROFILE_MAX_SIZE (1 << 28) =20 #endif /* __APPARMOR_H */ diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/inc= lude/apparmorfs.h index 1e94904f68d9..fd415afb7659 100644 --- a/security/apparmor/include/apparmorfs.h +++ b/security/apparmor/include/apparmorfs.h @@ -112,6 +112,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, st= ruct dentry *parent); void __aafs_ns_rmdir(struct aa_ns *ns); int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *n= ame, struct dentry *dent); +ssize_t aa_profile_load_ns_name(char *name, size_t name_len, const void __= user *buf, + size_t size, loff_t *ppos); + =20 struct aa_loaddata; =20 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 9b6c2f157f83..0c127f9dae19 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1275,6 +1275,86 @@ static int apparmor_socket_shutdown(struct socket *s= ock, int how) return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); } =20 +/** + * apparmor_lsm_config_self_policy - Stack a profile + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: buffer containing the user-provided name of the profile to stack + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: 0 on success, negative value on error + */ +static int apparmor_lsm_config_self_policy(u32 op, void __user *buf, + size_t size, u32 flags) +{ + char *name; + long name_size; + int ret; + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + if (size =3D=3D 0) + return -EINVAL; + if (size > AA_PROFILE_NAME_MAX_SIZE) + return -E2BIG; + + name =3D kmalloc(size, GFP_KERNEL); + if (!name) + return -ENOMEM; + + name_size =3D strncpy_from_user(name, buf, size); + if (name_size <=3D 0) { + kfree(name); + return name_size; + } else if (name_size =3D=3D size) { + kfree(name); + return -E2BIG; + } + + ret =3D aa_change_profile(name, AA_CHANGE_STACK); + + kfree(name); + + return ret; +} + +/** + * apparmor_lsm_config_system_policy - Load or replace a system policy + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: user-supplied buffer in the form "\0" + * is the namespace to load the policy into (empty string for = root) + * is the policy to load + * @size: size of @buf + * @flags: reserved for future uses; must be zero + * + * Returns: 0 on success, negative value on error + */ +static int apparmor_lsm_config_system_policy(u32 op, void __user *buf, + size_t size, u32 flags) +{ + loff_t pos =3D 0; // Partial writing is not currently supported + char ns_name[AA_PROFILE_NAME_MAX_SIZE]; + size_t ns_size; + size_t max_ns_size =3D min(size, AA_PROFILE_NAME_MAX_SIZE); + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + if (size < 2) + return -EINVAL; + if (size > AA_PROFILE_MAX_SIZE) + return -E2BIG; + + ns_size =3D strncpy_from_user(ns_name, buf, max_ns_size); + if (ns_size < 0) + return ns_size; + if (ns_size =3D=3D max_ns_size) + return -E2BIG; + + return aa_profile_load_ns_name(ns_name, ns_size, buf + ns_size + 1, + size - ns_size - 1, &pos); +} + + #ifdef CONFIG_NETWORK_SECMARK /** * apparmor_socket_sock_rcv_skb - check perms before associating skb to sk @@ -1483,6 +1563,10 @@ static struct security_hook_list apparmor_hooks[] __= ro_after_init =3D { LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), + + LSM_HOOK_INIT(lsm_config_self_policy, apparmor_lsm_config_self_policy), + LSM_HOOK_INIT(lsm_config_system_policy, + apparmor_lsm_config_system_policy), #ifdef CONFIG_NETWORK_SECMARK LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), #endif --=20 2.48.1 From nobody Wed Dec 17 10:22:48 2025 Received: from smtp-relay-canonical-0.canonical.com (smtp-relay-canonical-0.canonical.com [185.125.188.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EDC92F25F6; Fri, 10 Oct 2025 13:35:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.125.188.120 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103306; cv=none; b=bPdq8a5Rcb2TYw/MHOTsRaX4KLC1ppan87B29FV0QUIHvaI/URN/FGhxZ0alZrcvzN0eYqpRgy28WKh75TO3RMNaZfGZPK58vkt+NityktBsohMFoJDypJVbXhP8POIWscfCtzRV7QwuDnBNEILgZeph3AwUaBUdfIS3g0ZBTPk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760103306; c=relaxed/simple; bh=86IupXS7vJybzKeEqcu/apTr9ZsblsOH7kVcn69OVmk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eic0vHa3x7ehr3k5QapfDDPeeuNM7oA5573ho76QjZFk3Qs5Tfq5fyfXwBAMjgga+HJ/mnIWnbI2qg47kOTx31d3C+hC4zAsk8JjOcRgg0RR4K0sNAu2fVSYDRjqcbWkxqkZjzi1ZFCUHfH+LNyXV8Mi8fseDQOv6TwRqOUhIF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com; spf=pass smtp.mailfrom=canonical.com; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b=ArKy1PzE; arc=none smtp.client-ip=185.125.188.120 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=canonical.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b="ArKy1PzE" Received: from sec2-plucky-amd64.. (176-136-128-80.abo.bbox.fr [176.136.128.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id 7B78142ABC; Fri, 10 Oct 2025 13:26:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20251003; t=1760102819; bh=M2m06O/92yzIbKYKZQJQNk7bnRhXFzF181i5f3dRy1I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ArKy1PzETyeScQJJzKJyen23qk0N1d1UxX6gCuL1Z6SfQ9xAepj+LzfMLzMsGIoGZ NTzbR1evH4BO43kzTXVTKphtuON1hU9d0KEe2sEy+ROAOOhtidmEaayAn4f+O3coZs 6gLXpUZdxlEwg+dU9wDdFuLr3wg+CW4ITFKO+FUVbbowGBzYJLlsFDd6Y++cLn1Gtl vHaV6HHyvAZc2zWbCtPP79cgdzfO9FC7X7QSMstSLuC6dZi0xuoLOWTuJFfND5vKFv IcwZ5I0EfnifurlCsODXltkiw2QG6imvjQrZx2nKfU2ikW/IFfRfL59kyl1HO2wrIB LjWcOoEYokpItnkr1eocttDWvX8UacM2Ydo/bY2orKKHX3unPR4ZkG8UigF4nxqfKB Pzhvg+we92xYBlHEbRCF9Nx4LgNJQ2HmctdI2sV5pZjTy/05RmPhn3EsP9rK3emP9h nmNT5q4fGxp+bU6nW/iLKyDxusf1krY6iTj/bYkBK0pW0e3NTUDlzEnym5Sanz3ykT ktCjwAYkbt6i/Rpx8NypYWokBo+MUe1ZR9vV9bJnDgRLylMF0CNtWeFjUKoegbLuTE vxdesh9D1QuzGL5IeO7R6aJSb/eYVMIBF5rlZAaUm3fkDiGj/CZSe+EqSZM4P7K051 7wSKv/qqwUlE6GUXmUrZf3HY= From: =?UTF-8?q?Maxime=20B=C3=A9lair?= To: linux-security-module@vger.kernel.org Cc: john.johansen@canonical.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, mic@digikod.net, kees@kernel.org, stephen.smalley.work@gmail.com, casey@schaufler-ca.com, takedakn@nttdata.co.jp, penguin-kernel@I-love.SAKURA.ne.jp, song@kernel.org, rdunlap@infradead.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v6 4/5] SELinux: add support for lsm_config_system_policy Date: Fri, 10 Oct 2025 15:25:31 +0200 Message-ID: <20251010132610.12001-5-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251010132610.12001-1-maxime.belair@canonical.com> References: <20251010132610.12001-1-maxime.belair@canonical.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Enable users to manage SELinux policies through the new hook lsm_config_system_policy. This feature is restricted to CAP_MAC_ADMIN. Signed-off-by: Maxime B=C3=A9lair --- security/selinux/hooks.c | 27 +++++++++++++++++++++++++++ security/selinux/include/security.h | 7 +++++++ security/selinux/selinuxfs.c | 16 ++++++++++++---- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e7a7dcab81db..3d14d4e47937 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -7196,6 +7196,31 @@ static int selinux_uring_allowed(void) } #endif /* CONFIG_IO_URING */ =20 +/** + * selinux_lsm_config_system_policy - Manage a LSM policy + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: User-supplied buffer + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: number of written rules on success, negative value on error + */ +static int selinux_lsm_config_system_policy(u32 op, void __user *buf, + size_t size, u32 flags) +{ + loff_t pos =3D 0; + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + if (!selinux_null.dentry || !selinux_null.dentry->d_sb || + !selinux_null.dentry->d_sb->s_fs_info) + return -ENODEV; + + return __sel_write_load(selinux_null.dentry->d_sb->s_fs_info, buf, size, + &pos); +} + static const struct lsm_id selinux_lsmid =3D { .name =3D "selinux", .id =3D LSM_ID_SELINUX, @@ -7499,6 +7524,8 @@ static struct security_hook_list selinux_hooks[] __ro= _after_init =3D { #ifdef CONFIG_PERF_EVENTS LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc), #endif + LSM_HOOK_INIT(lsm_config_system_policy, selinux_lsm_config_system_policy), + }; =20 static __init int selinux_init(void) diff --git a/security/selinux/include/security.h b/security/selinux/include= /security.h index e7827ed7be5f..7b779ea43cc3 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -389,7 +389,14 @@ struct selinux_kernel_status { extern void selinux_status_update_setenforce(bool enforcing); extern void selinux_status_update_policyload(u32 seqno); extern void selinux_complete_init(void); + +struct selinux_fs_info; + extern struct path selinux_null; +extern ssize_t __sel_write_load(struct selinux_fs_info *fsi, + const char __user *buf, size_t count, + loff_t *ppos); + extern void selnl_notify_setenforce(int val); extern void selnl_notify_policyload(u32 seqno); extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 47480eb2189b..1f7e611d8300 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -567,11 +567,11 @@ static int sel_make_policy_nodes(struct selinux_fs_in= fo *fsi, return ret; } =20 -static ssize_t sel_write_load(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +ssize_t __sel_write_load(struct selinux_fs_info *fsi, + const char __user *buf, size_t count, + loff_t *ppos) =20 { - struct selinux_fs_info *fsi; struct selinux_load_state load_state; ssize_t length; void *data =3D NULL; @@ -605,7 +605,6 @@ static ssize_t sel_write_load(struct file *file, const = char __user *buf, pr_warn_ratelimited("SELinux: failed to load policy\n"); goto out; } - fsi =3D file_inode(file)->i_sb->s_fs_info; length =3D sel_make_policy_nodes(fsi, load_state.policy); if (length) { pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n"); @@ -626,6 +625,15 @@ static ssize_t sel_write_load(struct file *file, const= char __user *buf, return length; } =20 +static ssize_t sel_write_load(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct selinux_fs_info *fsi =3D file_inode(file)->i_sb->s_fs_info; + + return __sel_write_load(fsi, buf, count, ppos); +} + + static const struct file_operations sel_load_ops =3D { .write =3D sel_write_load, .llseek =3D generic_file_llseek, --=20 2.48.1 From nobody Wed Dec 17 10:22:48 2025 Received: from smtp-relay-canonical-0.canonical.com (smtp-relay-canonical-0.canonical.com [185.125.188.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99EE9284893; Fri, 10 Oct 2025 13:27:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.125.188.120 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760102829; cv=none; b=byOPyRhip8MWwIk8EcNIBTT6ENLcZtf6ApR3JmNqcVQYgWd+7eXNYAM51ofWnazmMqk8iUK57fwkw8CqhdhIFbJ9Fc1zvObzjeTLuUtm3ofy39XSrHawXEWZoJM4Iv83mZZF2CTocIu8fe9h4jsqrL+lZQ2sSqjJrQN+CKy2qrc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760102829; c=relaxed/simple; bh=Sqju36u31Al8dusP1hKtjOry3JIoKP8tolpuNZ+8w6M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QWfVCHqH1qXuUN4tNR2otObbC4UVlOussPrcdW/pGAsHo7GO7nO363I73RuCFz/iH9I0C5OKCZx8JX8WLFgvFDptc6oydfzOyPhOtrdG7gXlQywmyTJ46Nbj/91QN2gk0a/k6n/c/fPMePfcXHuqTtReEbrYLIrB65+Pa9m3CQE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com; spf=pass smtp.mailfrom=canonical.com; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b=L4o+0sYf; arc=none smtp.client-ip=185.125.188.120 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=canonical.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (4096-bit key) header.d=canonical.com header.i=@canonical.com header.b="L4o+0sYf" Received: from sec2-plucky-amd64.. (176-136-128-80.abo.bbox.fr [176.136.128.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id E53B542ABE; Fri, 10 Oct 2025 13:26:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20251003; t=1760102820; bh=21Ej0bxpFACoQIzpnvpszcLFxcd87MwXCKY1pXAfvF4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=L4o+0sYfURLqDWp6TBlMuUndaln4B9ioTdQ0F8OHohmz8C0MBMkaYEKv5rs4jIZMo w6R3yHNzapTLKmqYey8oj1VouJwpTbSZS+U1bUp+4a1raDaWu5GXleT22sneLBV86Y DQerpmnTTbfPVKP7HEI+mEg6Rlppb7bwh/YUeo5uEzr6xr0ym20AKw4MdigGtI96od A75SxEhX2BKeFjpHzrEvo1HvVnwRA+BBRF7u13HD+YXRWBSyfh7xmURgZI5PT6YHBZ wtFQ1vdvjkTQer4HqpQdCQyxm9NNjhneq92KuQ90cQs6B0CoHKEYkNxgTELSdKp48h Pp/QAZScv8q8poHxZT489hjSfdWC4DdrSH/9aA0dhYqE3d+u/vzTYFRzknqCGlYh30 IWrDKvIhoL1FpE77XLdKQPrNxhwUu/upXA0MB3Dq8pHx2q3E/vY2uOG967OtlieNWJ U9hqTtrm8VxKtz94PwjvOYyM3qAyIV1KU7Te9qCWwlskUiqSFzuSBdIeYdQvN3V9Jc AOTTka5yZcvgMqKnH6kTA1fkU8rXqMCVmAqm8r8ranbZgnHOk/7+nN2SgZA2L0Iulk EiUit8hRLwZr53X/hJWZMB0AkpGYCP/gOn/36sZRtRDMTYF8EEKnc4L9eonzlOQC/e YfB/vM2BvHbt7nslsEIhRoZ0= From: =?UTF-8?q?Maxime=20B=C3=A9lair?= To: linux-security-module@vger.kernel.org Cc: john.johansen@canonical.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, mic@digikod.net, kees@kernel.org, stephen.smalley.work@gmail.com, casey@schaufler-ca.com, takedakn@nttdata.co.jp, penguin-kernel@I-love.SAKURA.ne.jp, song@kernel.org, rdunlap@infradead.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v6 5/5] Smack: add support for lsm_config_self_policy and lsm_config_system_policy Date: Fri, 10 Oct 2025 15:25:32 +0200 Message-ID: <20251010132610.12001-6-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251010132610.12001-1-maxime.belair@canonical.com> References: <20251010132610.12001-1-maxime.belair@canonical.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Enable users to manage Smack policies through the new hooks lsm_config_self_policy and lsm_config_system_policy. lsm_config_self_policy allows adding Smack policies for the current cred. For now it remains restricted to CAP_MAC_ADMIN. lsm_config_system_policy allows adding globabl Smack policies. This is restricted to CAP_MAC_ADMIN. Signed-off-by: Maxime B=C3=A9lair --- security/smack/smack.h | 8 +++++ security/smack/smack_lsm.c | 73 ++++++++++++++++++++++++++++++++++++++ security/smack/smackfs.c | 2 +- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index bf6a6ed3946c..3e3d30dfdcf7 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -275,6 +275,14 @@ struct smk_audit_info { #endif }; =20 +/* + * This function is in smackfs.c + */ +ssize_t smk_write_rules_list(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, + struct list_head *rule_list, + struct mutex *rule_lock, int format); + /* * These functions are in smack_access.c */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 99833168604e..bf4bb2242768 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -5027,6 +5027,76 @@ static int smack_uring_cmd(struct io_uring_cmd *iouc= md) =20 #endif /* CONFIG_IO_URING */ =20 +/** + * smack_lsm_config_system_policy - Configure a system smack policy + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: User-supplied buffer in the form "" + * is the 1-byte format of + * is the policy to load + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: number of written rules on success, negative value on error + */ +static int smack_lsm_config_system_policy(u32 op, void __user *buf, size_t= size, + u32 flags) +{ + loff_t pos =3D 0; + u8 fmt; + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + if (size < 2) + return -EINVAL; + + if (get_user(fmt, (uint8_t *)buf)) + return -EFAULT; + + return smk_write_rules_list(NULL, buf + 1, size - 1, &pos, NULL, NULL, fm= t); +} + +/** + * smack_lsm_config_self_policy - Configure a smack policy for the current= cred + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: User-supplied buffer in the form "" + * is the 1-byte format of + * is the policy to load + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: number of written rules on success, negative value on error + */ +static int smack_lsm_config_self_policy(u32 op, void __user *buf, size_t s= ize, + u32 flags) +{ + loff_t pos =3D 0; + u8 fmt; + struct task_smack *tsp; + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + if (size < 2) + return -EINVAL; + + if (get_user(fmt, (uint8_t *)buf)) + return -EFAULT; + /** + * smk_write_rules_list could be used to gain privileges. + * This function is thus restricted to CAP_MAC_ADMIN. + * TODO: Ensure that the new rule does not give extra privileges + * before dropping this CAP_MAC_ADMIN check. + */ + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + + + tsp =3D smack_cred(current_cred()); + return smk_write_rules_list(NULL, buf + 1, size - 1, &pos, &tsp->smk_rule= s, + &tsp->smk_rules_lock, fmt); +} + struct lsm_blob_sizes smack_blob_sizes __ro_after_init =3D { .lbs_cred =3D sizeof(struct task_smack), .lbs_file =3D sizeof(struct smack_known *), @@ -5203,6 +5273,9 @@ static struct security_hook_list smack_hooks[] __ro_a= fter_init =3D { LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll), LSM_HOOK_INIT(uring_cmd, smack_uring_cmd), #endif + LSM_HOOK_INIT(lsm_config_self_policy, smack_lsm_config_self_policy), + LSM_HOOK_INIT(lsm_config_system_policy, smack_lsm_config_system_policy), + }; =20 =20 diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 90a67e410808..ed1814588d56 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -441,7 +441,7 @@ static ssize_t smk_parse_long_rule(char *data, struct s= mack_parsed_rule *rule, * "subjectobject * acc_enableacc_disable[...]" */ -static ssize_t smk_write_rules_list(struct file *file, const char __user *= buf, +ssize_t smk_write_rules_list(struct file *file, const char __user *buf, size_t count, loff_t *ppos, struct list_head *rule_list, struct mutex *rule_lock, int format) --=20 2.48.1