public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Daniel Burgener <dburgener@linux.microsoft.com>
To: cgzones@googlemail.com, selinux@vger.kernel.org
Cc: Paul Moore <paul@paul-moore.com>,
	Stephen Smalley <stephen.smalley.work@gmail.com>,
	Ondrej Mosnacek <omosnace@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [RFC PATCH 22/22] selinux: restrict policy strings
Date: Fri, 13 Dec 2024 17:14:03 -0500	[thread overview]
Message-ID: <c4416dfa-ed1c-479d-9558-252775f3b8b6@linux.microsoft.com> (raw)
In-Reply-To: <20241115133619.114393-22-cgoettsche@seltendoof.de>

On 11/15/2024 8:35 AM, Christian Göttsche wrote:
> From: Christian Göttsche <cgzones@googlemail.com>
> 
> Validate the characters and the lengths of strings parsed from binary
> policies.
> 
>    * Disallow control characters
>    * Limit characters of identifiers to alphanumeric, underscore, dash,
>      and dot
>    * Limit identifiers in length to 128, expect types to 1024 and
>      categories to 32, characters (excluding NUL-terminator)
> 
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
> ---
>   security/selinux/ss/conditional.c |  2 +-
>   security/selinux/ss/policydb.c    | 60 ++++++++++++++++++++-----------
>   security/selinux/ss/policydb.h    |  5 ++-
>   3 files changed, 44 insertions(+), 23 deletions(-)
> 
> diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
> index d37b4bdf6ba9..346102417cbf 100644
> --- a/security/selinux/ss/conditional.c
> +++ b/security/selinux/ss/conditional.c
> @@ -280,7 +280,7 @@ int cond_read_bool(struct policydb *p, struct symtab *s, struct policy_file *fp)
>   
>   	len = le32_to_cpu(buf[2]);
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto err;
>

It would be nice if these limits were named constants instead of magic 
numbers.  Right now it's hard to tell if all the "128"s are essentially 
the same limit referenced in different places, or if they could (in 
theory) be changed independently.

> diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
> index 917b468c5144..d98dfa6c3f30 100644
> --- a/security/selinux/ss/policydb.c
> +++ b/security/selinux/ss/policydb.c
> @@ -1221,8 +1221,9 @@ static int context_read_and_validate(struct context *c, struct policydb *p,
>    * binary representation file.
>    */
>   
> -int str_read(char **strp, gfp_t flags, struct policy_file *fp, u32 len)
> +int str_read(char **strp, gfp_t flags, struct policy_file *fp, u32 len, int kind, u32 max_len)
>   {
> +	u32 i;
>   	int rc;
>   	char *str;
>   
> @@ -1232,19 +1233,35 @@ int str_read(char **strp, gfp_t flags, struct policy_file *fp, u32 len)
>   	if (oom_check(sizeof(char), len, fp))
>   		return -EINVAL;
>   
> +	if (max_len != 0 && len > max_len)
> +		return -EINVAL;
> +
>   	str = kmalloc(len + 1, flags | __GFP_NOWARN);
>   	if (!str)
>   		return -ENOMEM;
>   
>   	rc = next_entry(str, fp, len);
> -	if (rc) {
> -		kfree(str);
> -		return rc;
> +	if (rc)
> +		goto bad_str;
> +
> +	rc = -EINVAL;
> +	for (i = 0; i < len; i++) {
> +		if (iscntrl(str[i]))
> +			goto bad_str;
> +
> +		if (kind == STR_IDENTIFIER &&
> +		    !(isalnum(str[i]) || str[i] == '_' || str[i] == '-' || str[i] == '.'))
> +			goto bad_str;
> +
>   	}
>   
>   	str[len] = '\0';
>   	*strp = str;
>   	return 0;
> +
> +bad_str:
> +	kfree(str);
> +	return rc;
>   }
>   
>   static int perm_read(struct policydb *p, struct symtab *s, struct policy_file *fp)
> @@ -1269,7 +1286,7 @@ static int perm_read(struct policydb *p, struct symtab *s, struct policy_file *f
>   	if (perdatum->value < 1 || perdatum->value > 32)
>   		goto bad;
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto bad;
>   
> @@ -1315,7 +1332,7 @@ static int common_read(struct policydb *p, struct symtab *s, struct policy_file
>   		goto bad;
>   	comdatum->permissions.nprim = le32_to_cpu(buf[2]);
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto bad;
>   
> @@ -1552,12 +1569,12 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
>   
>   	ncons = le32_to_cpu(buf[5]);
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto bad;
>   
>   	if (len2) {
> -		rc = str_read(&cladatum->comkey, GFP_KERNEL, fp, len2);
> +		rc = str_read(&cladatum->comkey, GFP_KERNEL, fp, len2, STR_IDENTIFIER, 128);
>   		if (rc)
>   			goto bad;
>   
> @@ -1691,7 +1708,7 @@ static int role_read(struct policydb *p, struct symtab *s, struct policy_file *f
>   	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
>   		role->bounds = le32_to_cpu(buf[2]);
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto bad;
>   
> @@ -1758,7 +1775,7 @@ static int type_read(struct policydb *p, struct symtab *s, struct policy_file *f
>   		typdatum->primary = le32_to_cpu(buf[2]);
>   	}
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 1024);
>   	if (rc)
>   		goto bad;
>   
> @@ -1822,7 +1839,7 @@ static int user_read(struct policydb *p, struct symtab *s, struct policy_file *f
>   	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
>   		usrdatum->bounds = le32_to_cpu(buf[2]);
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto bad;
>   
> @@ -1871,7 +1888,7 @@ static int sens_read(struct policydb *p, struct symtab *s, struct policy_file *f
>   		goto bad;
>   	levdatum->isalias = val;
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 128);
>   	if (rc)
>   		goto bad;
>   
> @@ -1914,7 +1931,7 @@ static int cat_read(struct policydb *p, struct symtab *s, struct policy_file *fp
>   		goto bad;
>   	catdatum->isalias = val;
>   
> -	rc = str_read(&key, GFP_KERNEL, fp, len);
> +	rc = str_read(&key, GFP_KERNEL, fp, len, STR_IDENTIFIER, 32);
>   	if (rc)
>   		goto bad;

The category restriction is more tight than the sensitivity one because 
a context may have many categories?  I guess that makes sense, but it 
feels counterintuitive from a user perspective, because I feel like 
users tend to think of categories and sensitivities as essentially the 
same thing.  Would dropping the sensitivity limit to 32 to match the 
category limit make sense?

Is there a more strict limit on the number of categories a context can 
have than the U32_MAX from symtab.nprim?  Because that will allow 
exceeding the page size using too many categories regardless of length 
distinctions, which is a concern if the motivation here is about 
potential future untrusted policy loaders in a namespaced environment.

-Daniel


  reply	other threads:[~2024-12-13 22:14 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-15 13:35 [RFC PATCH 01/22] selinux: supply missing field initializers Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 02/22] selinux: avoid using types indicating user space interaction Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 03/22] selinux: align and constify functions Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 04/22] selinux: rework match_ipv6_addrmask() Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 05/22] selinux: avoid nontransitive comparison Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 06/22] selinux: rename comparison functions for clarity Christian Göttsche
2024-12-16 14:28   ` Daniel Burgener
2024-11-15 13:35 ` [RFC PATCH 07/22] selinux: use known type instead of void pointer Christian Göttsche
2024-12-16 14:36   ` Daniel Burgener
2024-11-15 13:35 ` [RFC PATCH 08/22] selinux: avoid unnecessary indirection in struct level_datum Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 09/22] selinux: make use of str_read() Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 10/22] selinux: use u16 for security classes Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 11/22] selinux: more strict policy parsing Christian Göttsche
2024-12-03  0:34   ` Thiébaud Weksteen
2024-11-15 13:35 ` [RFC PATCH 12/22] selinux: check length fields in policies Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 13/22] selinux: validate constraints Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 14/22] selinux: pre-validate conditional expressions Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 15/22] selinux: introduce ebitmap_highest_set_bit() Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 16/22] selinux: check type attr map overflows Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 17/22] selinux: reorder policydb_index() Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 18/22] selinux: beef up isvalid checks Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 19/22] selinux: validate symbols Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 20/22] selinux: more strict bounds check Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 21/22] selinux: check for simple types Christian Göttsche
2024-11-15 13:35 ` [RFC PATCH 22/22] selinux: restrict policy strings Christian Göttsche
2024-12-13 22:14   ` Daniel Burgener [this message]
2024-12-16 16:02     ` Christian Göttsche

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=c4416dfa-ed1c-479d-9558-252775f3b8b6@linux.microsoft.com \
    --to=dburgener@linux.microsoft.com \
    --cc=cgzones@googlemail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=omosnace@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=selinux@vger.kernel.org \
    --cc=stephen.smalley.work@gmail.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