diff mbox series

selinux: pre-allocate the status page

Message ID 20240328192042.211948-1-cgoettsche@seltendoof.de (mailing list archive)
State Changes Requested
Delegated to: Paul Moore
Headers show
Series selinux: pre-allocate the status page | expand

Commit Message

Christian Göttsche March 28, 2024, 7:20 p.m. UTC
From: Christian Göttsche <cgzones@googlemail.com>

Since the status page is currently only allocated on first use, the
sequence number of the initial policyload (i.e. 1) is not stored,
leading to the observable sequence of 0, 2, 3, 4, ...

Pre-allocate the status page during the initialization of the selinuxfs,
so selinux_status_update_policyload() will set the sequence number.

This brings the status page to return the actual sequence number for the
initial policy load, which is also observable via the netlink socket.
I could not find any occurrence where userspace depends on the actual
value returned by selinux_status_policyload(3), thus the breakage should
be unnoticed.

Reported-by: Milos Malik
Closes: https://lore.kernel.org/selinux/87o7fmua12.fsf@redhat.com/
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 security/selinux/selinuxfs.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Paul Moore April 2, 2024, 2:15 a.m. UTC | #1
On Mar 28, 2024 =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgoettsche@seltendoof.de> wrote:
> 
> Since the status page is currently only allocated on first use, the
> sequence number of the initial policyload (i.e. 1) is not stored,
> leading to the observable sequence of 0, 2, 3, 4, ...
> 
> Pre-allocate the status page during the initialization of the selinuxfs,
> so selinux_status_update_policyload() will set the sequence number.
> 
> This brings the status page to return the actual sequence number for the
> initial policy load, which is also observable via the netlink socket.
> I could not find any occurrence where userspace depends on the actual
> value returned by selinux_status_policyload(3), thus the breakage should
> be unnoticed.
> 
> Reported-by: Milos Malik
> Closes: https://lore.kernel.org/selinux/87o7fmua12.fsf@redhat.com/
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
> ---
>  security/selinux/selinuxfs.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> index 7e9aa5d151b4..ad57b5ad5829 100644
> --- a/security/selinux/selinuxfs.c
> +++ b/security/selinux/selinuxfs.c
> @@ -2131,6 +2131,7 @@ static int __init init_sel_fs(void)
>  {
>  	struct qstr null_name = QSTR_INIT(NULL_FILE_NAME,
>  					  sizeof(NULL_FILE_NAME)-1);
> +	struct page *status;
>  	int err;
>  
>  	if (!selinux_enabled_boot)
> @@ -2163,6 +2164,14 @@ static int __init init_sel_fs(void)
>  		return err;
>  	}
>  
> +	/*
> +	 * Pre-allocate the status page, so the sequence number of the initial
> +	 * policy load can be stored.
> +	 */
> +	status = selinux_kernel_status_page();
> +	if (!status)
> +		return -ENOMEM;

Thanks Christian.

I'm not sure we need to fail here, do we?  In the case where we can't
allocate the status page we will simply fall back to allocating it on
the next page read request.  Yes, this will mean that we go back to
missing the initial policy load sequence number of one/1, but that is
hardly reason to take the system down, right?

>  	return err;
>  }
>  
> -- 
> 2.43.0

--
paul-moore.com
diff mbox series

Patch

diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 7e9aa5d151b4..ad57b5ad5829 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -2131,6 +2131,7 @@  static int __init init_sel_fs(void)
 {
 	struct qstr null_name = QSTR_INIT(NULL_FILE_NAME,
 					  sizeof(NULL_FILE_NAME)-1);
+	struct page *status;
 	int err;
 
 	if (!selinux_enabled_boot)
@@ -2163,6 +2164,14 @@  static int __init init_sel_fs(void)
 		return err;
 	}
 
+	/*
+	 * Pre-allocate the status page, so the sequence number of the initial
+	 * policy load can be stored.
+	 */
+	status = selinux_kernel_status_page();
+	if (!status)
+		return -ENOMEM;
+
 	return err;
 }