mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serge@hallyn.com>
To: Cai Xinchen <caixinchen1@huawei.com>
Cc: nicolas.bouchinet@oss.cyber.gouv.fr, xiujianfeng@huawei.com,
	paul@paul-moore.com, jmorris@namei.org, shuah@kernel.org,
	kalevi@kolttonen.fi, linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	bpf@vger.kernel.org, lujialin4@huawei.com
Subject: Re: [PATCH -next -v2 6/8] lockdown: bound the status string with scnprintf
Date: Tue, 10 Nov 2026 07:42:10 -0600	[thread overview]
Message-ID: <avMfMnoJUb9bIYbG@hallyn.com> (raw)
In-Reply-To: <20261110132818.2231593-7-caixinchen1@huawei.com>

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
> 

  reply	other threads:[~2026-11-10 13:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=avMfMnoJUb9bIYbG@hallyn.com \
    --to=serge@hallyn.com \
    --cc=bpf@vger.kernel.org \
    --cc=caixinchen1@huawei.com \
    --cc=jmorris@namei.org \
    --cc=kalevi@kolttonen.fi \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=lujialin4@huawei.com \
    --cc=nicolas.bouchinet@oss.cyber.gouv.fr \
    --cc=paul@paul-moore.com \
    --cc=shuah@kernel.org \
    --cc=xiujianfeng@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®