* [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests
@ 2026-11-10 13:28 Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 1/8] lockdown: Add break in lockdown_write Cai Xinchen
` (7 more replies)
0 siblings, 8 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
The lockdown LSM provides /sys/kernel/security/lockdown, but the file is
neither documented nor covered by a selftest. While reviewing the
interface, we also found a Kconfig bug and a few accumulated cleanups.
The series is organized as follows:
- patches 1-2 are small cleanups in lockdown_write(): stop scanning
after the matching level, and drop an update to a length variable
that is not used afterwards.
- patch 3 makes the LSM select SECURITYFS. Without it, a kernel built
with CONFIG_SECURITYFS=n logs "failed LSM lockdown core initcall with
errno -19" and does not create the file advertised by the Kconfig
help text.
- patch 4 removes LSM_AUDIT_DATA_LOCKDOWN and its formatting code,
which became dead when the SELinux lockdown implementation was
removed by commit f5d0e5e9d72d.
- patch 5 drops an unused include and moves lockdown_reasons[] next to
its only user.
- patch 6 replaces sprintf() with scnprintf() so that the status
buffer
is bounded explicitly if more levels are added later, and adds a
BUILD_BUG_ON() that checks at compile time that all level labels,
their separators, and the terminating NUL still fit.
- patch 7 documents the ABI and adds the new file to the LOCKDOWN
SECURITY MODULE entry in MAINTAINERS.
- patch 8 adds a kselftest covering the read format, invalid levels,
the rejection of the current or a lower level, and an upgrade to the
next level.
The only functional change is patch 3; the rest are cleanups,
documentation, or test coverage.
Changes since v1:
- The scnprintf()/BUILD_BUG_ON() patch now comes after the audit and
cleanup patches.
- The lockdown_reasons move patch has a corrected commit message: the
enum comment already pointed at security/lockdown/lockdown.c.
- The ABI documentation now mentions CONFIG_LSM as a way to order
lockdown in, and states that the FORCE_* options only take effect
when the lockdown LSM is active.
- The selftest patch moves the read-format string checks before the
active-level checks, corrects the no-downgrade skip message, and adds
an upgrade test. Because that test irreversibly raises the lockdown
level, the test is kept out of the default run
(TEST_GEN_PROGS_EXTENDED and run_lockdown_test),
CONFIG_SECURITY_LOCKDOWN_LSM is enabled in the selftest config
fragment, and non-ENOENT read failures now fail instead of being
skipped.
- The break, decrement, SECURITYFS, and audit patches are unchanged.
The upgrade test irreversibly raises the lockdown level, so lockdown_test
is built but not run by default. Use "make run_lockdown_test" to run it
explicitly, preferably on a disposable test system. The shared
selftests/lsm config fragment now enables CONFIG_SECURITY_LOCKDOWN_LSM so
that the test has something to exercise.
Cai Xinchen (7):
lockdown: Add break in lockdown_write
lockdown: select SECURITYFS
lsm: remove unused lockdown audit data
lockdown: drop an unused include and move lockdown_reasons
lockdown: bound the status string with scnprintf
Documentation/ABI: document the lockdown securityfs file
selftests/lsm: add lockdown securityfs test
Kalevi Kolttonen (1):
lockdown: remove useless decrement operation
Documentation/ABI/testing/securityfs-lockdown | 43 ++++
MAINTAINERS | 1 +
include/linux/lsm_audit.h | 2 -
include/linux/security.h | 2 -
security/lockdown/Kconfig | 1 +
security/lockdown/lockdown.c | 70 +++++-
security/lsm_audit.c | 4 -
security/security.c | 40 ---
tools/testing/selftests/lsm/Makefile | 8 +
tools/testing/selftests/lsm/common.c | 35 ++-
tools/testing/selftests/lsm/common.h | 2 +
tools/testing/selftests/lsm/config | 1 +
tools/testing/selftests/lsm/lockdown_test.c | 230 ++++++++++++++++++
13 files changed, 375 insertions(+), 64 deletions(-)
create mode 100644 Documentation/ABI/testing/securityfs-lockdown
create mode 100644 tools/testing/selftests/lsm/lockdown_test.c
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 1/8] lockdown: Add break in lockdown_write
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 2/8] lockdown: remove useless decrement operation Cai Xinchen
` (6 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
After the label is matched successful, any other levels judgements
are meaningless. Therefore, add break to return early
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
security/lockdown/lockdown.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 8d46886d2cca..263dcc80d839 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -139,8 +139,10 @@ static ssize_t lockdown_write(struct file *file, const char __user *buf,
enum lockdown_reason level = lockdown_levels[i];
const char *label = lockdown_reasons[level];
- if (label && !strcmp(state, label))
+ if (label && !strcmp(state, label)) {
err = lock_kernel_down("securityfs", level);
+ break;
+ }
}
kfree(state);
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 2/8] lockdown: remove useless decrement operation
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 1/8] lockdown: Add break in lockdown_write Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 3/8] lockdown: select SECURITYFS Cai Xinchen
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
From: Kalevi Kolttonen <kalevi@kolttonen.fi>
Signed-off-by: Kalevi Kolttonen <kalevi@kolttonen.fi>
---
security/lockdown/lockdown.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 263dcc80d839..8648508d49b2 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -130,10 +130,8 @@ static ssize_t lockdown_write(struct file *file, const char __user *buf,
return PTR_ERR(state);
len = strlen(state);
- if (len && state[len-1] == '\n') {
+ if (len && state[len-1] == '\n')
state[len-1] = '\0';
- len--;
- }
for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
enum lockdown_reason level = lockdown_levels[i];
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 3/8] lockdown: select SECURITYFS
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 1/8] lockdown: Add break in lockdown_write Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 2/8] lockdown: remove useless decrement operation Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 4/8] lsm: remove unused lockdown audit data Cai Xinchen
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
The lockdown LSM exposes /sys/kernel/security/lockdown, but it does not
select SECURITYFS. If SECURITYFS is disabled, securityfs_create_file()
returns -ENODEV, lockdown_secfs_init() fails and the LSM framework logs:
failed LSM lockdown core initcall with errno -19
while the sysfs interface advertised by the Kconfig help text is missing.
Select SECURITYFS like the other LSMs that create securityfs entries
(AppArmor, SafeSetID, TOMOYO and IMA) already do.
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
security/lockdown/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig
index e84ddf484010..82b69d8253bd 100644
--- a/security/lockdown/Kconfig
+++ b/security/lockdown/Kconfig
@@ -2,6 +2,7 @@ config SECURITY_LOCKDOWN_LSM
bool "Basic module for enforcing kernel lockdown"
depends on SECURITY
select MODULE_SIG if MODULES
+ select SECURITYFS
help
Build support for an LSM that enforces a coarse kernel lockdown
behaviour.
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 4/8] lsm: remove unused lockdown audit data
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
` (2 preceding siblings ...)
2026-11-10 13:28 ` [PATCH -next -v2 3/8] lockdown: select SECURITYFS Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 5/8] lockdown: drop an unused include and move lockdown_reasons Cai Xinchen
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
Commit f5d0e5e9d72d ("selinux: remove the SELinux lockdown
implementation") removed the only producer of LSM_AUDIT_DATA_LOCKDOWN.
The type, the u.reason union member and the audit formatting case are now
dead, so drop them.
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
include/linux/lsm_audit.h | 2 --
security/lsm_audit.c | 4 ----
2 files changed, 6 deletions(-)
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 5cf0b4795065..51b498c0ec74 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -74,7 +74,6 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_FILE 12
#define LSM_AUDIT_DATA_IBPKEY 13
#define LSM_AUDIT_DATA_IBENDPORT 14
-#define LSM_AUDIT_DATA_LOCKDOWN 15
#define LSM_AUDIT_DATA_NOTIFICATION 16
#define LSM_AUDIT_DATA_ANONINODE 17
#define LSM_AUDIT_DATA_NLMSGTYPE 18
@@ -98,7 +97,6 @@ struct common_audit_data {
const struct file *file;
struct lsm_ibpkey_audit *ibpkey;
struct lsm_ibendport_audit *ibendport;
- int reason;
const char *anonclass;
u16 nlmsg_type;
struct {
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 955b2e7b2c8e..4b653edcb77e 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -393,10 +393,6 @@ void audit_log_lsm_data(struct audit_buffer *ab,
a->u.ibendport->dev_name,
a->u.ibendport->port);
break;
- case LSM_AUDIT_DATA_LOCKDOWN:
- audit_log_format(ab, " lockdown_reason=\"%s\"",
- lockdown_reasons[a->u.reason]);
- break;
case LSM_AUDIT_DATA_ANONINODE:
audit_log_format(ab, " anonclass=%s", a->u.anonclass);
break;
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 5/8] lockdown: drop an unused include and move lockdown_reasons
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
` (3 preceding siblings ...)
2026-11-10 13:28 ` [PATCH -next -v2 4/8] lsm: remove unused lockdown audit data Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf Cai Xinchen
` (2 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
linux/export.h is not needed since the file has no EXPORT_SYMBOL() usage.
lockdown_reasons[] is only used by the lockdown LSM after the audit data
was removed from lsm_audit. Move it into security/lockdown/lockdown.c,
make it static, and drop the now stale extern declaration. The existing
enum comment in include/linux/security.h already pointed at
security/lockdown/lockdown.c and becomes accurate now that the array has
moved there.
No functional change.
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
include/linux/security.h | 2 --
security/lockdown/lockdown.c | 40 +++++++++++++++++++++++++++++++++++-
security/security.c | 40 ------------------------------------
3 files changed, 39 insertions(+), 43 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 40831fab5470..9d3a1eaa90ff 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -170,8 +170,6 @@ struct lsm_prop {
struct lsm_prop_bpf bpf;
};
-extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
-
/* These functions are in security/commoncap.c */
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
int cap, unsigned int opts);
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 8648508d49b2..84efd533fe5a 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -11,10 +11,48 @@
*/
#include <linux/security.h>
-#include <linux/export.h>
#include <linux/lsm_hooks.h>
#include <uapi/linux/lsm.h>
+/*
+ * These are descriptions of the reasons that can be passed to the
+ * security_locked_down() LSM hook, used for the denial message and the
+ * securityfs status file.
+ */
+static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
+ [LOCKDOWN_NONE] = "none",
+ [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
+ [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",
+ [LOCKDOWN_EFI_TEST] = "/dev/efi_test access",
+ [LOCKDOWN_KEXEC] = "kexec of unsigned images",
+ [LOCKDOWN_HIBERNATION] = "hibernation",
+ [LOCKDOWN_PCI_ACCESS] = "direct PCI access",
+ [LOCKDOWN_IOPORT] = "raw io port access",
+ [LOCKDOWN_MSR] = "raw MSR access",
+ [LOCKDOWN_ACPI_TABLES] = "modifying ACPI tables",
+ [LOCKDOWN_DEVICE_TREE] = "modifying device tree contents",
+ [LOCKDOWN_PCMCIA_CIS] = "direct PCMCIA CIS storage",
+ [LOCKDOWN_TIOCSSERIAL] = "reconfiguration of serial port IO",
+ [LOCKDOWN_MODULE_PARAMETERS] = "unsafe module parameters",
+ [LOCKDOWN_MMIOTRACE] = "unsafe mmio",
+ [LOCKDOWN_DEBUGFS] = "debugfs access",
+ [LOCKDOWN_XMON_WR] = "xmon write access",
+ [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
+ [LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
+ [LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",
+ [LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",
+ [LOCKDOWN_INTEGRITY_MAX] = "integrity",
+ [LOCKDOWN_KCORE] = "/proc/kcore access",
+ [LOCKDOWN_KPROBES] = "use of kprobes",
+ [LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
+ [LOCKDOWN_DBG_READ_KERNEL] = "use of kgdb/kdb to read kernel RAM",
+ [LOCKDOWN_PERF] = "unsafe use of perf",
+ [LOCKDOWN_TRACEFS] = "use of tracefs",
+ [LOCKDOWN_XMON_RW] = "xmon read and write access",
+ [LOCKDOWN_XFRM_SECRET] = "xfrm SA secret",
+ [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
+};
+
static enum lockdown_reason kernel_locked_down;
static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
diff --git a/security/security.c b/security/security.c
index 4727b8347fc4..68cf2ab9174f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -35,46 +35,6 @@
#include "lsm.h"
-/*
- * These are descriptions of the reasons that can be passed to the
- * security_locked_down() LSM hook. Placing this array here allows
- * all security modules to use the same descriptions for auditing
- * purposes.
- */
-const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
- [LOCKDOWN_NONE] = "none",
- [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
- [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",
- [LOCKDOWN_EFI_TEST] = "/dev/efi_test access",
- [LOCKDOWN_KEXEC] = "kexec of unsigned images",
- [LOCKDOWN_HIBERNATION] = "hibernation",
- [LOCKDOWN_PCI_ACCESS] = "direct PCI access",
- [LOCKDOWN_IOPORT] = "raw io port access",
- [LOCKDOWN_MSR] = "raw MSR access",
- [LOCKDOWN_ACPI_TABLES] = "modifying ACPI tables",
- [LOCKDOWN_DEVICE_TREE] = "modifying device tree contents",
- [LOCKDOWN_PCMCIA_CIS] = "direct PCMCIA CIS storage",
- [LOCKDOWN_TIOCSSERIAL] = "reconfiguration of serial port IO",
- [LOCKDOWN_MODULE_PARAMETERS] = "unsafe module parameters",
- [LOCKDOWN_MMIOTRACE] = "unsafe mmio",
- [LOCKDOWN_DEBUGFS] = "debugfs access",
- [LOCKDOWN_XMON_WR] = "xmon write access",
- [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
- [LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
- [LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",
- [LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",
- [LOCKDOWN_INTEGRITY_MAX] = "integrity",
- [LOCKDOWN_KCORE] = "/proc/kcore access",
- [LOCKDOWN_KPROBES] = "use of kprobes",
- [LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
- [LOCKDOWN_DBG_READ_KERNEL] = "use of kgdb/kdb to read kernel RAM",
- [LOCKDOWN_PERF] = "unsafe use of perf",
- [LOCKDOWN_TRACEFS] = "use of tracefs",
- [LOCKDOWN_XMON_RW] = "xmon read and write access",
- [LOCKDOWN_XFRM_SECRET] = "xfrm SA secret",
- [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
-};
-
bool lsm_debug __ro_after_init;
unsigned int lsm_active_cnt __ro_after_init;
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
` (4 preceding siblings ...)
2026-11-10 13:28 ` [PATCH -next -v2 5/8] lockdown: drop an unused include and move lockdown_reasons Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:42 ` Serge E. Hallyn
2026-11-10 13:28 ` [PATCH -next -v2 7/8] Documentation/ABI: document the lockdown securityfs file Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 8/8] selftests/lsm: add lockdown securityfs test Cai Xinchen
7 siblings, 1 reply; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
Use scnprintf() instead of sprintf() when composing the lockdown status
string in lockdown_read(). The current set of levels fits well within the
80 byte buffer, but sprintf() provides no protection if more or longer
labels are added later. scnprintf() makes the buffer bounds explicit.
Store the level label strings in named arrays and point the matching
lockdown_reasons[] entries at them. Their sizes are compile-time
constants, so a BUILD_BUG_ON() can verify that the status buffer is large
enough for all level labels, their trailing spaces, and the brackets
around the active one.
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
security/lockdown/lockdown.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 84efd533fe5a..26cac7628a48 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -14,13 +14,17 @@
#include <linux/lsm_hooks.h>
#include <uapi/linux/lsm.h>
+static const char lockdown_label_none[] = "none";
+static const char lockdown_label_integrity[] = "integrity";
+static const char lockdown_label_confidentiality[] = "confidentiality";
+
/*
* These are descriptions of the reasons that can be passed to the
* security_locked_down() LSM hook, used for the denial message and the
* securityfs status file.
*/
static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
- [LOCKDOWN_NONE] = "none",
+ [LOCKDOWN_NONE] = lockdown_label_none,
[LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
[LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",
[LOCKDOWN_EFI_TEST] = "/dev/efi_test access",
@@ -41,7 +45,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
[LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
[LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",
[LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",
- [LOCKDOWN_INTEGRITY_MAX] = "integrity",
+ [LOCKDOWN_INTEGRITY_MAX] = lockdown_label_integrity,
[LOCKDOWN_KCORE] = "/proc/kcore access",
[LOCKDOWN_KPROBES] = "use of kprobes",
[LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
@@ -50,7 +54,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
[LOCKDOWN_TRACEFS] = "use of tracefs",
[LOCKDOWN_XMON_RW] = "xmon read and write access",
[LOCKDOWN_XFRM_SECRET] = "xfrm SA secret",
- [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
+ [LOCKDOWN_CONFIDENTIALITY_MAX] = lockdown_label_confidentiality,
};
static enum lockdown_reason kernel_locked_down;
@@ -137,6 +141,16 @@ static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
char temp[80] = "";
int i, offset = 0;
+ /*
+ * Size the buffer for the worst case: the active level is
+ * confidentiality, with brackets and trailing spaces, plus the
+ * terminating NUL. The label sizeof() values include their own
+ * NULs, so only three more bytes are needed.
+ */
+ BUILD_BUG_ON(sizeof(temp) < sizeof(lockdown_label_none) +
+ sizeof(lockdown_label_integrity) +
+ sizeof(lockdown_label_confidentiality) + 3);
+
for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
enum lockdown_reason level = lockdown_levels[i];
@@ -144,9 +158,13 @@ static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
const char *label = lockdown_reasons[level];
if (kernel_locked_down == level)
- offset += sprintf(temp+offset, "[%s] ", label);
+ offset += scnprintf(temp + offset,
+ sizeof(temp) - offset,
+ "[%s] ", label);
else
- offset += sprintf(temp+offset, "%s ", label);
+ offset += scnprintf(temp + offset,
+ sizeof(temp) - offset,
+ "%s ", label);
}
}
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 7/8] Documentation/ABI: document the lockdown securityfs file
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
` (5 preceding siblings ...)
2026-11-10 13:28 ` [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 8/8] selftests/lsm: add lockdown securityfs test Cai Xinchen
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
Describe the /sys/kernel/security/lockdown interface: the levels it
reports, how the active level is marked, when the file is present, and
the write semantics (escalation only, EPERM for the current or a lower
level, EINVAL for an unknown level).
Also add the new ABI file to the LOCKDOWN SECURITY MODULE entry in
MAINTAINERS.
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
Documentation/ABI/testing/securityfs-lockdown | 43 +++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 44 insertions(+)
create mode 100644 Documentation/ABI/testing/securityfs-lockdown
diff --git a/Documentation/ABI/testing/securityfs-lockdown b/Documentation/ABI/testing/securityfs-lockdown
new file mode 100644
index 000000000000..2967a07df97c
--- /dev/null
+++ b/Documentation/ABI/testing/securityfs-lockdown
@@ -0,0 +1,43 @@
+What: /sys/kernel/security/lockdown
+Date: August 2019
+KernelVersion: 5.4
+Contact: linux-security-module@vger.kernel.org
+Description:
+ The lockdown securityfs file reports and controls the
+ lockdown state of the running kernel. It is provided by
+ the lockdown LSM and is located at
+ /sys/kernel/security/lockdown.
+
+ The file is present only when CONFIG_SECURITY_LOCKDOWN_LSM is
+ enabled and the lockdown LSM is active, either because
+ CONFIG_SECURITY_LOCKDOWN_LSM_EARLY is set, or because it is
+ ordered in through CONFIG_LSM or the "lsm=" kernel
+ parameter. Otherwise the node is absent, and userspace must
+ handle its absence.
+
+ Reading the file returns the supported lockdown levels,
+ with the currently active level enclosed in square
+ brackets. For example, when the kernel is not locked
+ down::
+
+ [none] integrity confidentiality
+
+ and when the kernel is in integrity mode::
+
+ none [integrity] confidentiality
+
+ The file may be written with the name of a level to lock
+ the kernel down further. Lockdown can only be escalated,
+ never relaxed, so writing the currently active level or a
+ lower level fails with EPERM. Writing an unrecognized
+ level fails with EINVAL. Successful writes return the
+ number of bytes written.
+
+ The kernel can also be locked down at boot time with the
+ "lockdown=" kernel parameter, or at build time via
+ CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY or
+ CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY when the
+ lockdown LSM is active.
+
+Users: fwupd and other userspace tools that query or manage
+ kernel lockdown state
diff --git a/MAINTAINERS b/MAINTAINERS
index c57be10c8729..0ba942dfe4c0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15652,6 +15652,7 @@ M: Xiu Jianfeng <xiujianfeng@huawei.com>
L: linux-security-module@vger.kernel.org
S: Maintained
T: git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
+F: Documentation/ABI/testing/securityfs-lockdown
F: security/lockdown/
LOCKING PRIMITIVES
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH -next -v2 8/8] selftests/lsm: add lockdown securityfs test
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
` (6 preceding siblings ...)
2026-11-10 13:28 ` [PATCH -next -v2 7/8] Documentation/ABI: document the lockdown securityfs file Cai Xinchen
@ 2026-11-10 13:28 ` Cai Xinchen
7 siblings, 0 replies; 10+ messages in thread
From: Cai Xinchen @ 2026-11-10 13:28 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge, shuah,
kalevi, caixinchen1
Cc: linux-security-module, linux-kernel, linux-kselftest, bpf, lujialin4
Add a kselftest for the lockdown securityfs interface. It checks the
read format, rejects unknown levels, verifies that an already locked
down kernel neither accepts the current level nor a lower one, and
checks that the level can be upgraded. The test skips itself when
lockdown is not enabled, when not run as root, or when the file cannot
be opened for writing.
The upgrade test irreversibly raises the lockdown level, so the test is
built but not run by default; run "make run_lockdown_test" to execute
it, preferably on a disposable test system.
Enable CONFIG_SECURITY_LOCKDOWN_LSM in the selftest config fragment so
that the test has something to exercise.
Use the shared file read helper from common.c instead of duplicating it.
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
tools/testing/selftests/lsm/Makefile | 8 +
tools/testing/selftests/lsm/common.c | 35 ++-
tools/testing/selftests/lsm/common.h | 2 +
tools/testing/selftests/lsm/config | 1 +
tools/testing/selftests/lsm/lockdown_test.c | 230 ++++++++++++++++++++
5 files changed, 267 insertions(+), 9 deletions(-)
create mode 100644 tools/testing/selftests/lsm/lockdown_test.c
diff --git a/tools/testing/selftests/lsm/Makefile b/tools/testing/selftests/lsm/Makefile
index 3f80c0bc093d..3be7aa42761c 100644
--- a/tools/testing/selftests/lsm/Makefile
+++ b/tools/testing/selftests/lsm/Makefile
@@ -8,10 +8,18 @@ LOCAL_HDRS += common.h
TEST_GEN_PROGS := lsm_get_self_attr_test lsm_list_modules_test \
lsm_set_self_attr_test
+# lockdown_test changes the machine's lockdown level, so do not run it
+# by default.
+TEST_GEN_PROGS_EXTENDED := lockdown_test
+
include ../lib.mk
$(OUTPUT)/lsm_get_self_attr_test: lsm_get_self_attr_test.c common.c
$(OUTPUT)/lsm_set_self_attr_test: lsm_set_self_attr_test.c common.c
$(OUTPUT)/lsm_list_modules_test: lsm_list_modules_test.c common.c
+$(OUTPUT)/lockdown_test: lockdown_test.c common.c
+
+run_lockdown_test: all
+ $(call RUN_TESTS, lockdown_test)
EXTRA_CLEAN = $(OUTPUT)/common.o
diff --git a/tools/testing/selftests/lsm/common.c b/tools/testing/selftests/lsm/common.c
index 927dce4f04cb..e7d5cdb10137 100644
--- a/tools/testing/selftests/lsm/common.c
+++ b/tools/testing/selftests/lsm/common.c
@@ -7,6 +7,7 @@
#define _GNU_SOURCE
#include <linux/lsm.h>
+#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
@@ -50,23 +51,39 @@ int read_proc_attr(const char *attr, char *value, size_t size)
return 0;
}
-int read_sysfs_lsms(char *lsms, size_t size)
+int read_file(const char *path, char *buf, size_t size)
{
- FILE *fp;
- size_t red;
+ ssize_t len;
+ int fd;
- fp = fopen("/sys/kernel/security/lsm", "r");
- if (fp == NULL)
+ if (!size) {
+ errno = EINVAL;
return -1;
- red = fread(lsms, 1, size, fp);
- fclose(fp);
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ len = read(fd, buf, size - 1);
+ if (len < 0) {
+ int err = errno;
- if (red <= 0 || red == size)
+ close(fd);
+ errno = err;
return -1;
- lsms[red] = '\0';
+ }
+
+ close(fd);
+ buf[len] = '\0';
return 0;
}
+int read_sysfs_lsms(char *lsms, size_t size)
+{
+ return read_file("/sys/kernel/security/lsm", lsms, size);
+}
+
int attr_lsm_count(void)
{
char *names = calloc(sysconf(_SC_PAGESIZE), 1);
diff --git a/tools/testing/selftests/lsm/common.h b/tools/testing/selftests/lsm/common.h
index 06d12110d241..2f824de2d1ad 100644
--- a/tools/testing/selftests/lsm/common.h
+++ b/tools/testing/selftests/lsm/common.h
@@ -31,3 +31,5 @@ static inline int lsm_list_modules(__u64 *ids, __u32 *size, __u32 flags)
extern int read_proc_attr(const char *attr, char *value, size_t size);
extern int read_sysfs_lsms(char *lsms, size_t size);
int attr_lsm_count(void);
+
+extern int read_file(const char *path, char *buf, size_t size);
diff --git a/tools/testing/selftests/lsm/config b/tools/testing/selftests/lsm/config
index 1c0c4c020f9c..f8704a4c58ad 100644
--- a/tools/testing/selftests/lsm/config
+++ b/tools/testing/selftests/lsm/config
@@ -1,3 +1,4 @@
CONFIG_SYSFS=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
+CONFIG_SECURITY_LOCKDOWN_LSM=y
diff --git a/tools/testing/selftests/lsm/lockdown_test.c b/tools/testing/selftests/lsm/lockdown_test.c
new file mode 100644
index 000000000000..fed050551cff
--- /dev/null
+++ b/tools/testing/selftests/lsm/lockdown_test.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Linux Security Module infrastructure tests
+ * Tests for the lockdown securityfs interface
+ */
+
+#define _GNU_SOURCE
+#include <linux/lsm.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "kselftest_harness.h"
+#include "common.h"
+
+#define LOCKDOWN_PATH "/sys/kernel/security/lockdown"
+
+static int write_status(const char *value)
+{
+ ssize_t len;
+ int fd, err;
+
+ fd = open(LOCKDOWN_PATH, O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ len = write(fd, value, strlen(value));
+ err = errno;
+ close(fd);
+ if (len < 0) {
+ errno = err;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int status_writable(void)
+{
+ int fd;
+
+ fd = open(LOCKDOWN_PATH, O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ close(fd);
+ return 0;
+}
+
+static int get_active_level(const char *buf, char *level, size_t size)
+{
+ const char *start, *end;
+ size_t len;
+
+ start = strchr(buf, '[');
+ if (!start)
+ return -1;
+ end = strchr(start, ']');
+ if (!end)
+ return -1;
+
+ len = end - start - 1;
+ if (len == 0 || len >= size)
+ return -1;
+
+ memcpy(level, start + 1, len);
+ level[len] = '\0';
+ return 0;
+}
+
+static int read_lockdown_status(char *buf, size_t size)
+{
+ if (!read_file(LOCKDOWN_PATH, buf, size))
+ return 0;
+
+ return errno == ENOENT ? 1 : -1;
+}
+
+TEST(lockdown_read_format)
+{
+ char buf[128], level[32];
+ int ret;
+
+ ret = read_lockdown_status(buf, sizeof(buf));
+ if (ret) {
+ if (ret > 0)
+ SKIP(return, "%s is not present", LOCKDOWN_PATH);
+ TH_LOG("cannot read %s: %s", LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, ret);
+ }
+
+ ASSERT_NE(NULL, strstr(buf, "none"));
+ ASSERT_NE(NULL, strstr(buf, "integrity"));
+ ASSERT_NE(NULL, strstr(buf, "confidentiality"));
+
+ ASSERT_EQ(0, get_active_level(buf, level, sizeof(level)));
+ ASSERT_TRUE(!strcmp(level, "none") ||
+ !strcmp(level, "integrity") ||
+ !strcmp(level, "confidentiality"));
+}
+
+TEST(lockdown_invalid_write)
+{
+ char before[128], after[128];
+ int ret;
+
+ ret = read_lockdown_status(before, sizeof(before));
+ if (ret) {
+ if (ret > 0)
+ SKIP(return, "%s is not present", LOCKDOWN_PATH);
+ TH_LOG("cannot read %s: %s", LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, ret);
+ }
+ if (geteuid() != 0)
+ SKIP(return, "requires root");
+ if (status_writable())
+ SKIP(return, "cannot open %s for writing: %s",
+ LOCKDOWN_PATH, strerror(errno));
+
+ errno = 0;
+ ASSERT_EQ(-1, write_status("invalid-level"));
+ ASSERT_EQ(EINVAL, errno);
+
+ ASSERT_EQ(0, read_file(LOCKDOWN_PATH, after, sizeof(after)));
+ ASSERT_STREQ(before, after);
+}
+
+TEST(lockdown_no_downgrade)
+{
+ char before[128], after[128], level[32];
+ const char *lower;
+ int ret;
+
+ ret = read_lockdown_status(before, sizeof(before));
+ if (ret) {
+ if (ret > 0)
+ SKIP(return, "%s is not present", LOCKDOWN_PATH);
+ TH_LOG("cannot read %s: %s", LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, ret);
+ }
+ if (geteuid() != 0)
+ SKIP(return, "requires root");
+ if (status_writable())
+ SKIP(return, "cannot open %s for writing: %s",
+ LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, get_active_level(before, level, sizeof(level)));
+
+ if (!strcmp(level, "confidentiality"))
+ lower = "integrity";
+ else if (!strcmp(level, "integrity"))
+ lower = "none";
+ else
+ SKIP(return, "kernel is not locked down, nothing to downgrade");
+
+ errno = 0;
+ ASSERT_EQ(-1, write_status(lower));
+ ASSERT_EQ(EPERM, errno);
+
+ ASSERT_EQ(0, read_file(LOCKDOWN_PATH, after, sizeof(after)));
+ ASSERT_STREQ(before, after);
+}
+
+TEST(lockdown_same_level_rejected)
+{
+ char before[128], after[128], level[32];
+ int ret;
+
+ ret = read_lockdown_status(before, sizeof(before));
+ if (ret) {
+ if (ret > 0)
+ SKIP(return, "%s is not present", LOCKDOWN_PATH);
+ TH_LOG("cannot read %s: %s", LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, ret);
+ }
+ if (geteuid() != 0)
+ SKIP(return, "requires root");
+ if (status_writable())
+ SKIP(return, "cannot open %s for writing: %s",
+ LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, get_active_level(before, level, sizeof(level)));
+
+ errno = 0;
+ ASSERT_EQ(-1, write_status(level));
+ ASSERT_EQ(EPERM, errno);
+
+ ASSERT_EQ(0, read_file(LOCKDOWN_PATH, after, sizeof(after)));
+ ASSERT_STREQ(before, after);
+}
+
+/*
+ * This test raises the lockdown level and cannot undo it, so run it last.
+ */
+TEST(lockdown_upgrade)
+{
+ char before[128], after[128], level[32];
+ const char *next;
+ int ret;
+
+ ret = read_lockdown_status(before, sizeof(before));
+ if (ret) {
+ if (ret > 0)
+ SKIP(return, "%s is not present", LOCKDOWN_PATH);
+ TH_LOG("cannot read %s: %s", LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, ret);
+ }
+ if (geteuid() != 0)
+ SKIP(return, "requires root");
+ if (status_writable())
+ SKIP(return, "cannot open %s for writing: %s",
+ LOCKDOWN_PATH, strerror(errno));
+ ASSERT_EQ(0, get_active_level(before, level, sizeof(level)));
+
+ if (!strcmp(level, "none"))
+ next = "integrity";
+ else if (!strcmp(level, "integrity"))
+ next = "confidentiality";
+ else
+ SKIP(return, "kernel is already at the highest level");
+
+ errno = 0;
+ ASSERT_EQ(0, write_status(next));
+
+ ASSERT_EQ(0, read_file(LOCKDOWN_PATH, after, sizeof(after)));
+ ASSERT_EQ(0, get_active_level(after, level, sizeof(level)));
+ ASSERT_STREQ(next, level);
+}
+
+TEST_HARNESS_MAIN
--
2.18.0.huawei.25
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf
2026-11-10 13:28 ` [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf Cai Xinchen
@ 2026-11-10 13:42 ` Serge E. Hallyn
0 siblings, 0 replies; 10+ messages in thread
From: Serge E. Hallyn @ 2026-11-10 13:42 UTC (permalink / raw)
To: Cai Xinchen
Cc: nicolas.bouchinet, xiujianfeng, paul, jmorris, shuah, kalevi,
linux-security-module, linux-kernel, linux-kselftest, bpf,
lujialin4
On Tue, Nov 10, 2026 at 09:28:16PM +0800, Cai Xinchen wrote:
> Use scnprintf() instead of sprintf() when composing the lockdown status
> string in lockdown_read(). The current set of levels fits well within the
> 80 byte buffer, but sprintf() provides no protection if more or longer
> labels are added later. scnprintf() makes the buffer bounds explicit.
>
> Store the level label strings in named arrays and point the matching
> lockdown_reasons[] entries at them. Their sizes are compile-time
> constants, so a BUILD_BUG_ON() can verify that the status buffer is large
> enough for all level labels, their trailing spaces, and the brackets
> around the active one.
>
> Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
> ---
> security/lockdown/lockdown.c | 28 +++++++++++++++++++++++-----
> 1 file changed, 23 insertions(+), 5 deletions(-)
>
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> index 84efd533fe5a..26cac7628a48 100644
> --- a/security/lockdown/lockdown.c
> +++ b/security/lockdown/lockdown.c
> @@ -14,13 +14,17 @@
> #include <linux/lsm_hooks.h>
> #include <uapi/linux/lsm.h>
>
> +static const char lockdown_label_none[] = "none";
> +static const char lockdown_label_integrity[] = "integrity";
> +static const char lockdown_label_confidentiality[] = "confidentiality";
> +
> /*
> * These are descriptions of the reasons that can be passed to the
> * security_locked_down() LSM hook, used for the denial message and the
> * securityfs status file.
> */
> static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
> - [LOCKDOWN_NONE] = "none",
> + [LOCKDOWN_NONE] = lockdown_label_none,
> [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
> [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",
> [LOCKDOWN_EFI_TEST] = "/dev/efi_test access",
> @@ -41,7 +45,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
> [LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
> [LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",
> [LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",
> - [LOCKDOWN_INTEGRITY_MAX] = "integrity",
> + [LOCKDOWN_INTEGRITY_MAX] = lockdown_label_integrity,
> [LOCKDOWN_KCORE] = "/proc/kcore access",
> [LOCKDOWN_KPROBES] = "use of kprobes",
> [LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
> @@ -50,7 +54,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
> [LOCKDOWN_TRACEFS] = "use of tracefs",
> [LOCKDOWN_XMON_RW] = "xmon read and write access",
> [LOCKDOWN_XFRM_SECRET] = "xfrm SA secret",
> - [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
> + [LOCKDOWN_CONFIDENTIALITY_MAX] = lockdown_label_confidentiality,
> };
>
> static enum lockdown_reason kernel_locked_down;
> @@ -137,6 +141,16 @@ static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
> char temp[80] = "";
> int i, offset = 0;
>
> + /*
> + * Size the buffer for the worst case: the active level is
> + * confidentiality, with brackets and trailing spaces, plus the
> + * terminating NUL. The label sizeof() values include their own
> + * NULs, so only three more bytes are needed.
> + */
> + BUILD_BUG_ON(sizeof(temp) < sizeof(lockdown_label_none) +
> + sizeof(lockdown_label_integrity) +
> + sizeof(lockdown_label_confidentiality) + 3);
Awesome, thanks. It also might be worth it to replace the 80 in temp[80]
with the calculated size, but this is safe enough.
> +
> for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
> enum lockdown_reason level = lockdown_levels[i];
>
> @@ -144,9 +158,13 @@ static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
> const char *label = lockdown_reasons[level];
>
> if (kernel_locked_down == level)
> - offset += sprintf(temp+offset, "[%s] ", label);
> + offset += scnprintf(temp + offset,
> + sizeof(temp) - offset,
> + "[%s] ", label);
> else
> - offset += sprintf(temp+offset, "%s ", label);
> + offset += scnprintf(temp + offset,
> + sizeof(temp) - offset,
> + "%s ", label);
> }
> }
>
> --
> 2.18.0.huawei.25
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-11-10 13:42 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10 13:28 [PATCH -next -v2 0/8] lockdown: fix the securityfs interface and add tests Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 1/8] lockdown: Add break in lockdown_write Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 2/8] lockdown: remove useless decrement operation Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 3/8] lockdown: select SECURITYFS Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 4/8] lsm: remove unused lockdown audit data Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 5/8] lockdown: drop an unused include and move lockdown_reasons Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf Cai Xinchen
2026-11-10 13:42 ` Serge E. Hallyn
2026-11-10 13:28 ` [PATCH -next -v2 7/8] Documentation/ABI: document the lockdown securityfs file Cai Xinchen
2026-11-10 13:28 ` [PATCH -next -v2 8/8] selftests/lsm: add lockdown securityfs test Cai Xinchen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®