From nobody Wed Oct 8 20:55:26 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 C10892D29BA; Tue, 24 Jun 2025 14:33:51 +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=1750775634; cv=none; b=QDiWrkDzBHOBbfhzNtKDvfMZ6LaZBf3Kn2lSFg83yJvsnZaZmOGfRlptvwCTs/Z7c8yFxXaI0dFVkxnT3O7bg9NYK8y4hXPVXZHMFqprO4OQUEh5bLEs8TyHYDbef/8iBmTso/5xrXPJ9eGBXl4G2c9bNlBec9qjq1VipGdAfh8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750775634; c=relaxed/simple; bh=8Ba/iUV8KxOwbPI5k+ksoH4gA6gnBCmY9MCf/lyBN3o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ahw1Ud5HPOG+YcgJa58C3Qa2ShqrP+zlU2msfIhlHVHB7U9wBUFdQDLQ2PuLkPaXaR/I5uv4+e1DpdVjm8+1pQr8Pcxn9lWSpK8AgQHzV+CrDVXNsbY9IZqwV532EFo2JcRZN8qxs5tA5fdk+HDmxjChIUOfHymKcawO8U2gYE4= 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 (2048-bit key) header.d=canonical.com header.i=@canonical.com header.b=MHZGFi5j; 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 (2048-bit key) header.d=canonical.com header.i=@canonical.com header.b="MHZGFi5j" Received: from sec2-plucky-amd64.. (lau06-h06-176-136-128-80.dsl.sta.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 65B52400E2; Tue, 24 Jun 2025 14:33:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1750775628; bh=gN5JUBqYStlK2RpnTIQjOj6RzVWh26VE7Kpa1MyH6GI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MHZGFi5jzDn50Qbna1xa/YJhJmBEDFb0UA8oQi/AXQymaQy/rZRy2Ju8usYWGxa07 WbbBNlwvUfvDML1EvupUI5hYo89YwGCEBoVFgiKI7Ph1xeUv3iJrAMD359LFIIn5A/ yETiVFq2N5IaBjhyiK4J0MPmF4igxRLFRCAUgwV3Qq2OaRYIati17f8B3qvUlDqVhH VK+F/4oZ+EbgVsC53bSfh7BVydH7chVVonZQjaGf8uFJ4pmC+v6ClxQDNAEI392Fs6 u8+ugBYgOV95L21S77TtWl5HjYgyMPTGcJWRxqxVrdWY/ocJiyN4fBepenrkQFV84t vg5Uva2uknBdQ== 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@infraread.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v3 1/3] Wire up lsm_config_self_policy and lsm_config_system_policy syscalls Date: Tue, 24 Jun 2025 16:30:40 +0200 Message-ID: <20250624143211.436045-2-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250624143211.436045-1-maxime.belair@canonical.com> References: <20250624143211.436045-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..15b0f35c42fe 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 flags); +asmlinkage long sys_lsm_config_system_policy(u32 lsm_id, u32 op, void __us= er *buf, + u32 __user *size, 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..34278cc6a476 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, lsm_config_self_policy) +#define __NR_lsm_config_system_policy 469 +__SYSCALL(__NR_lsm_config_system_policy, 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..a3cb6dab8102 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_DEFINE5(lsm_config_self_policy, u32, lsm_id, u32, op, void __user = *, + buf, u32 __user *, size, u32, flags) +{ + return 0; +} + +SYSCALL_DEFINE5(lsm_config_system_policy, u32, lsm_id, u32, op, void __use= r *, + buf, u32 __user *, size, 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..34278cc6a476 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, lsm_config_self_policy) +#define __NR_lsm_config_system_policy 469 +__SYSCALL(__NR_lsm_config_system_policy, 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 Oct 8 20:55:26 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 3135B2E3398; Tue, 24 Jun 2025 14:33:51 +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=1750775634; cv=none; b=lnglvI7IZZT1uhVLL8ld6yidPBM8yKbh19gmnhoOiHkLsRG5AKATNvr6vGvehQ2C2AGP9oMHf3wlXvLX1PO07W3GvjtsaVAXp6QTNCCfLaje6qICTZxnSiSuVzqnJiUO6uNEcsYkDx5ZLEzGEj5wiJGydLFdlKkcxHYOYA5x0n8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750775634; c=relaxed/simple; bh=vY5ovfAgtX7+swDE0wtBdjUWUGzqIRLCJ0cI9h4JQv4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZtHs9NskTBY8bsLm/vbSmQu98cXolHSFuOyFRX9+WtydlhzsLdPtb8d17/o2m75p506hySQtJeobOjCdIehwimVg2sjBrYGfOukY5N6RQccTtUycPQwSAhqx12GQcT/rLj+1+zE77LCSOaYJU6nC8ywt7c5B+Xj70RAVkiOApds= 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 (2048-bit key) header.d=canonical.com header.i=@canonical.com header.b=BJf48FMF; 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 (2048-bit key) header.d=canonical.com header.i=@canonical.com header.b="BJf48FMF" Received: from sec2-plucky-amd64.. (lau06-h06-176-136-128-80.dsl.sta.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 F07874015F; Tue, 24 Jun 2025 14:33:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1750775629; bh=SpzfyRyqdHLaDUOnzKNlq2XzE75XwsARN6pvtR5yy7Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BJf48FMFMMxMiqJwkHhcdbnfr+xsQjrBAXLUjxiEJ7D7SlP++GWRX6WrJY8yRukzH j2mgf6Pl2UE6jZllqa1eS248Kc628VMEZVIkuhG5zeUDFeP6rbbkDFtlkTsueKZ3NP qZR0ufi1+xWSJiTPpt2KBAfDdmVzbCJl5GlIG8R8yjUoQq2VOrYubwrm9bedaUkbep aDK9A7DaeuZyGLOj86SYuO6Sg7cqiN09ySnOySSwuu1tmoN2XatnuUzo2q3ruNkyZ3 /hgzmh+cpwa5VU4PL5ks4Ayp0JbO6OSxSGNZDm/SzMsF7H6mBBGp5IoPNWqFNpqjXw xO5lliuU8OJHA== 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@infraread.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v3 2/3] lsm: introduce security_lsm_config_*_policy hooks Date: Tue, 24 Jun 2025 16:30:41 +0200 Message-ID: <20250624143211.436045-3-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250624143211.436045-1-maxime.belair@canonical.com> References: <20250624143211.436045-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 | 18 +++++++++ include/uapi/linux/lsm.h | 8 ++++ security/Kconfig | 22 +++++++++++ security/lsm_syscalls.c | 17 ++++++++- security/security.c | 69 +++++++++++++++++++++++++++++++++++ 6 files changed, 136 insertions(+), 2 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index bf3bbac4e02a..fca490444643 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 lsm_id, u32 op, + void __user *buf, size_t size, u32 flags) +LSM_HOOK(int, -EINVAL, lsm_config_system_policy, u32 lsm_id, u32 op, + void __user *buf, size_t size, u32 flags) diff --git a/include/linux/security.h b/include/linux/security.h index cc9b54d95d22..8ad988b87be4 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,19 @@ static inline int security_bdev_setintegrity(struct = block_device *bdev, return 0; } =20 +static int security_lsm_config_self_policy(u32 lsm_id, u32 op, void __user= *buf, + size_t size, u32 flags) +{ + + return -EOPNOTSUPP; +} + +static int security_lsm_config_system_policy(u32 lsm_id, u32 op, void __us= er *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..844279f819ce 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 + * configure lsm policies + */ + +#define LSM_POLICY_UNDEF 0 +#define LSM_POLICY_LOAD 100 + #endif /* _UAPI_LINUX_LSM_H */ diff --git a/security/Kconfig b/security/Kconfig index 4816fc74f81e..b194f7f7a7c2 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -220,6 +220,28 @@ config STATIC_USERMODEHELPER_PATH If you wish for all usermode helper programs to be disabled, specify an empty string here (i.e. ""). =20 +config LSM_CONFIG_SELF_POLICY_MAX_BUFFER_SIZE + int "Maximum buffer size for lsm_config_self_policy" + range 16384 1073741824 + depends on SECURITY + default 4194304 + help + The maximum size of the buffer argument of lsm_config_self_policy. + + The default value of 4194304 (4MiB) is reasonable and should be large + enough to fit policies in for most cases. + +config LSM_CONFIG_SYSTEM_POLICY_MAX_BUFFER_SIZE + int "Maximum buffer size for lsm_config_system_policy" + range 16384 1073741824 + depends on SECURITY + default 4194304 + help + The maximum size of the buffer argument of lsm_config_system_policy. + + The default value of 4194304 (4MiB) is reasonable and should be large + enough to fit policies in for most cases + source "security/selinux/Kconfig" source "security/smack/Kconfig" source "security/tomoyo/Kconfig" diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c index a3cb6dab8102..dd016ba6976c 100644 --- a/security/lsm_syscalls.c +++ b/security/lsm_syscalls.c @@ -122,11 +122,24 @@ SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, = u32 __user *, size, SYSCALL_DEFINE5(lsm_config_self_policy, u32, lsm_id, u32, op, void __user = *, buf, u32 __user *, size, u32, flags) { - return 0; + size_t usize; + + if (get_user(usize, size)) + return -EFAULT; + + return security_lsm_config_self_policy(lsm_id, op, buf, usize, flags); } =20 SYSCALL_DEFINE5(lsm_config_system_policy, u32, lsm_id, u32, op, void __use= r *, buf, u32 __user *, size, u32, flags) { - return 0; + size_t usize; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(usize, size)) + return -EFAULT; + + return security_lsm_config_system_policy(lsm_id, op, buf, usize, flags); } diff --git a/security/security.c b/security/security.c index fb57e8fddd91..15bf3dab7892 100644 --- a/security/security.c +++ b/security/security.c @@ -5883,6 +5883,75 @@ 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; + + if (size > (CONFIG_LSM_CONFIG_SELF_POLICY_MAX_BUFFER_SIZE)) + return -E2BIG; + + 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(lsm_id, op, buf, size, fl= ags); + break; + } + } + + return rc; +} +EXPORT_SYMBOL(security_lsm_config_self_policy); + +/** + * 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; + + if (size > (CONFIG_LSM_CONFIG_SYSTEM_POLICY_MAX_BUFFER_SIZE)) + return -E2BIG; + + 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(lsm_id, op, buf, size, = flags); + break; + } + } + + return rc; +} +EXPORT_SYMBOL(security_lsm_config_system_policy); + + #ifdef CONFIG_PERF_EVENTS /** * security_perf_event_open() - Check if a perf event open is allowed --=20 2.48.1 From nobody Wed Oct 8 20:55:26 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 B95932E6D0F; Tue, 24 Jun 2025 14:33:54 +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=1750775637; cv=none; b=ZIAXYYYotg7Csk7ceTllTNfgujWttAVOkfaU2AFRDT/egs4ry0Wl9V7zLKiIXgb5NmALwyfR3kQWiqkEomaTou+CJ701fOwsHrXVrU1r6fKF1oHZPsjX78TbfPwKqmoRp+oTl+EubktBtn8O4HKSXz5RJDzVO5R2TiaVuWgB04s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750775637; c=relaxed/simple; bh=d5M/Hk14yChGkT7tf/L/6oDfqdz4CsH3WSwtJxG4I+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mhN8jfWjAZ9ZsB7l4i5Ch/qLIzzrre8CXbqq9FIxQ9vcCT/znLb2NBaIPE6H013s5WSJCw0EtFsO0be7h4/DVaFuwkns8dH3ZZB4/QPexc/zObma8sFGU/pejiEazqSjDVNXxj9oi6c90RyPuhCB8depLDQL7PJMjYQp+mQ6Psw= 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 (2048-bit key) header.d=canonical.com header.i=@canonical.com header.b=WNsqZBDE; 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 (2048-bit key) header.d=canonical.com header.i=@canonical.com header.b="WNsqZBDE" Received: from sec2-plucky-amd64.. (lau06-h06-176-136-128-80.dsl.sta.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 7A4BD4018F; Tue, 24 Jun 2025 14:33:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1750775629; bh=X3yVcB/5qVhKayZUa41FaUh8FIUjAjD/QoJab4XolZw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WNsqZBDEdQ49baJVa2zBQXXd77lSSOW1kTOl4Rm5hknAVwup7AwSx1eR6no8KGF8c vA04/0hHt9mUrvgsGBjHmOsnz677LX/nJ5I4Os7wyOX9/tpG2cAPggiEZMR5WGrEpk 9qlhuhKtQYPtHVg4Q+CIynLrulYwLW6kqagQa/k86hwJVzU9g6fdFeWwYmbW2x5Y4E meLRs/6jeLetM6BZsDA65Zd+dRLqhgBvKaGZHKDOaOV33bxdCPVwe32Y8H9YQlq+ko 9OTgkxOMHaiPVJ4TNRcmfiNqh9RQevXlff1WhT+3q5YmcUFQso5IXJHf2fe015KY5W LY01HJdtwXg/Q== 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@infraread.org, linux-api@vger.kernel.org, apparmor@lists.ubuntu.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Maxime=20B=C3=A9lair?= Subject: [PATCH v3 3/3] AppArmor: add support for lsm_config_self_policy and lsm_config_system_policy Date: Tue, 24 Jun 2025 16:30:42 +0200 Message-ID: <20250624143211.436045-4-maxime.belair@canonical.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250624143211.436045-1-maxime.belair@canonical.com> References: <20250624143211.436045-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. Signed-off-by: Maxime B=C3=A9lair --- security/apparmor/apparmorfs.c | 31 +++++++++++ security/apparmor/include/apparmorfs.h | 3 ++ security/apparmor/lsm.c | 71 ++++++++++++++++++++++++++ 3 files changed, 105 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/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..7ca2eb8c0981 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1275,6 +1275,73 @@ 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 + * @lsm_id: AppArmor ID (LSM_ID_APPARMOR). Unused here + * @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 lsm_id, u32 op, void __user= *buf, + size_t size, u32 flags) +{ + char *name =3D kvmalloc(size, GFP_KERNEL); + long name_size; + int ret; + + if (!name) + return -ENOMEM; + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + name_size =3D strncpy_from_user(name, buf, size); + if (name_size < 0) + return name_size; + + ret =3D aa_change_profile(name, AA_CHANGE_STACK); + + kvfree(name); + + return ret; +} + +/** + * apparmor_lsm_config_system_policy - Load or replace a system policy + * @lsm_id: AppArmor ID (LSM_ID_APPARMOR). Unused here + * @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 lsm_id, u32 op, void __us= er *buf, + size_t size, u32 flags) +{ + loff_t pos =3D 0; // Partial writing is not currently supported + char name[256]; + long name_size; + + if (op !=3D LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + name_size =3D strncpy_from_user(name, buf, 256); + if (name_size < 0) + return name_size; + else if (name_size =3D=3D 256) + return -E2BIG; + + return aa_profile_load_ns_name(name, name_size, buf + name_size + 1, + size - name_size - 1, &pos); +} + + #ifdef CONFIG_NETWORK_SECMARK /** * apparmor_socket_sock_rcv_skb - check perms before associating skb to sk @@ -1483,6 +1550,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