selinux/stable-6.12 PR 20240911

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmbiGE0UHHBhdWxAcGF1
 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXMeZA/+KwrK8bHSm+y9USrYaI4S2biiomsb
 GxNS6j0yIvg6uogWI2q8uTLXDdKMuJy88i7DHAMze+k6sSg8w6yEpFngFKeSAFpa
 7X6iF/4EU2ZjwHnKRbL5r5DDGyGeKm+GxCmjkwx/Xo+Qfk85D0mzjcXYiXkwRa2h
 DGdL34XztCfJNhJpPnnHDwh6OvVTY/c20g684D/7RMAXCkOq5r5SCfRK4SX1SpaT
 ge9DEm1Oz7cC4zY0yUMby6ibBmCsfjIIO1aIXFgf1IHjKOIuMzESIG6YwphnU2zp
 mI+7Zy6vvMd3dWDTxeMKqSsu43R3jkaclUnxyORmRD2noe7ehTvgPsQp31C9mmu1
 JF+50TjkiONGkuWoYsCdRDAZnpA1GLU5cU0Y3ENDcXazV5xt9omXIek4En2MlV/S
 DsXznvyaEJrAlZUBHZcJQwao394ZsPd+4nAelBTrbu+Ok2YD1p/GIv0va+lHIgZp
 xUsRNbOs/24bxW0k6XXgv8nFhsiBuXctB4GF1x4Dw2rvUqYtSJEK7tpq5B3yWAPs
 R57xKyELZrNTkf/2jcoCRQb9EODmhefYxYvN0fVgAKrzBbtVlOLltncKu3PYD8Vl
 yQPLKlu2NaER3ipJqMIFMi+O945YWPB47pNbKFVQJmyneGgc7++It1fVmvnFqWlt
 xP+p81tIM5E++Gw=
 =VwaX
 -----END PGP SIGNATURE-----

Merge tag 'selinux-pr-20240911' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux updates from Paul Moore:

 - Ensure that both IPv4 and IPv6 connections are properly initialized

   While we always properly initialized IPv4 connections early in their
   life, we missed the necessary IPv6 change when we were adding IPv6
   support.

 - Annotate the SELinux inode revalidation function to quiet KCSAN

   KCSAN correctly identifies a race in __inode_security_revalidate()
   when we check to see if an inode's SELinux has been properly
   initialized. While KCSAN is correct, it is an intentional choice made
   for performance reasons; if necessary, we check the state a second
   time, this time with a lock held, before initializing the inode's
   state.

 - Code cleanups, simplification, etc.

   A handful of individual patches to simplify some SELinux kernel
   logic, improve return code granularity via ERR_PTR(), follow the
   guidance on using KMEM_CACHE(), and correct some minor style
   problems.

* tag 'selinux-pr-20240911' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: fix style problems in security/selinux/include/audit.h
  selinux: simplify avc_xperms_audit_required()
  selinux: mark both IPv4 and IPv6 accepted connection sockets as labeled
  selinux: replace kmem_cache_create() with KMEM_CACHE()
  selinux: annotate false positive data race to avoid KCSAN warnings
  selinux: refactor code to return ERR_PTR in selinux_netlbl_sock_genattr
  selinux: Streamline type determination in security_compute_sid
This commit is contained in:
Linus Torvalds 2024-09-16 16:55:42 +02:00
commit ad060dbbcf
8 changed files with 68 additions and 76 deletions

View File

@ -134,18 +134,10 @@ static inline u32 avc_hash(u32 ssid, u32 tsid, u16 tclass)
*/
void __init avc_init(void)
{
avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
0, SLAB_PANIC, NULL);
avc_xperms_cachep = kmem_cache_create("avc_xperms_node",
sizeof(struct avc_xperms_node),
0, SLAB_PANIC, NULL);
avc_xperms_decision_cachep = kmem_cache_create(
"avc_xperms_decision_node",
sizeof(struct avc_xperms_decision_node),
0, SLAB_PANIC, NULL);
avc_xperms_data_cachep = kmem_cache_create("avc_xperms_data",
sizeof(struct extended_perms_data),
0, SLAB_PANIC, NULL);
avc_node_cachep = KMEM_CACHE(avc_node, SLAB_PANIC);
avc_xperms_cachep = KMEM_CACHE(avc_xperms_node, SLAB_PANIC);
avc_xperms_decision_cachep = KMEM_CACHE(avc_xperms_decision_node, SLAB_PANIC);
avc_xperms_data_cachep = KMEM_CACHE(extended_perms_data, SLAB_PANIC);
}
int avc_get_hash_stats(char *page)
@ -396,7 +388,7 @@ static inline u32 avc_xperms_audit_required(u32 requested,
audited = denied & avd->auditdeny;
if (audited && xpd) {
if (avc_xperms_has_perm(xpd, perm, XPERMS_DONTAUDIT))
audited &= ~requested;
audited = 0;
}
} else if (result) {
audited = denied = requested;
@ -404,7 +396,7 @@ static inline u32 avc_xperms_audit_required(u32 requested,
audited = requested & avd->auditallow;
if (audited && xpd) {
if (!avc_xperms_has_perm(xpd, perm, XPERMS_AUDITALLOW))
audited &= ~requested;
audited = 0;
}
}

View File

@ -282,8 +282,13 @@ static int __inode_security_revalidate(struct inode *inode,
might_sleep_if(may_sleep);
/*
* The check of isec->initialized below is racy but
* inode_doinit_with_dentry() will recheck with
* isec->lock held.
*/
if (selinux_initialized() &&
isec->initialized != LABEL_INITIALIZED) {
data_race(isec->initialized != LABEL_INITIALIZED)) {
if (!may_sleep)
return -ECHILD;

View File

@ -16,45 +16,45 @@
#include <linux/types.h>
/**
* selinux_audit_rule_init - alloc/init an selinux audit rule structure.
* @field: the field this rule refers to
* @op: the operator the rule uses
* @rulestr: the text "target" of the rule
* @rule: pointer to the new rule structure returned via this
* @gfp: GFP flag used for kmalloc
* selinux_audit_rule_init - alloc/init an selinux audit rule structure.
* @field: the field this rule refers to
* @op: the operator the rule uses
* @rulestr: the text "target" of the rule
* @rule: pointer to the new rule structure returned via this
* @gfp: GFP flag used for kmalloc
*
* Returns 0 if successful, -errno if not. On success, the rule structure
* will be allocated internally. The caller must free this structure with
* selinux_audit_rule_free() after use.
* Returns 0 if successful, -errno if not. On success, the rule structure
* will be allocated internally. The caller must free this structure with
* selinux_audit_rule_free() after use.
*/
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule,
gfp_t gfp);
/**
* selinux_audit_rule_free - free an selinux audit rule structure.
* @rule: pointer to the audit rule to be freed
* selinux_audit_rule_free - free an selinux audit rule structure.
* @rule: pointer to the audit rule to be freed
*
* This will free all memory associated with the given rule.
* If @rule is NULL, no operation is performed.
* This will free all memory associated with the given rule.
* If @rule is NULL, no operation is performed.
*/
void selinux_audit_rule_free(void *rule);
/**
* selinux_audit_rule_match - determine if a context ID matches a rule.
* @sid: the context ID to check
* @field: the field this rule refers to
* @op: the operator the rule uses
* @rule: pointer to the audit rule to check against
* selinux_audit_rule_match - determine if a context ID matches a rule.
* @sid: the context ID to check
* @field: the field this rule refers to
* @op: the operator the rule uses
* @rule: pointer to the audit rule to check against
*
* Returns 1 if the context id matches the rule, 0 if it does not, and
* -errno on failure.
* Returns 1 if the context id matches the rule, 0 if it does not, and
* -errno on failure.
*/
int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule);
/**
* selinux_audit_rule_known - check to see if rule contains selinux fields.
* @rule: rule to be checked
* Returns 1 if there are selinux fields specified in the rule, 0 otherwise.
* selinux_audit_rule_known - check to see if rule contains selinux fields.
* @rule: rule to be checked
* Returns 1 if there are selinux fields specified in the rule, 0 otherwise.
*/
int selinux_audit_rule_known(struct audit_krule *rule);

View File

@ -62,7 +62,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
* Description:
* Generate the NetLabel security attributes for a socket, making full use of
* the socket's attribute cache. Returns a pointer to the security attributes
* on success, NULL on failure.
* on success, or an ERR_PTR on failure.
*
*/
static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
@ -76,11 +76,12 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
secattr = netlbl_secattr_alloc(GFP_ATOMIC);
if (secattr == NULL)
return NULL;
return ERR_PTR(-ENOMEM);
rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
if (rc != 0) {
netlbl_secattr_free(secattr);
return NULL;
return ERR_PTR(rc);
}
sksec->nlbl_secattr = secattr;
@ -358,7 +359,7 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
{
struct sk_security_struct *sksec = sk->sk_security;
if (family == PF_INET)
if (family == PF_INET || family == PF_INET6)
sksec->nlbl_state = NLBL_LABELED;
else
sksec->nlbl_state = NLBL_UNSET;
@ -400,8 +401,8 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
return 0;
secattr = selinux_netlbl_sock_genattr(sk);
if (secattr == NULL)
return -ENOMEM;
if (IS_ERR(secattr))
return PTR_ERR(secattr);
/* On socket creation, replacement of IP options is safe even if
* the caller does not hold the socket lock.
*/
@ -561,10 +562,9 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
return rc;
}
secattr = selinux_netlbl_sock_genattr(sk);
if (secattr == NULL) {
rc = -ENOMEM;
return rc;
}
if (IS_ERR(secattr))
return PTR_ERR(secattr);
rc = netlbl_conn_setattr(sk, addr, secattr);
if (rc == 0)
sksec->nlbl_state = NLBL_CONNLABELED;

View File

@ -604,9 +604,6 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
void __init avtab_cache_init(void)
{
avtab_node_cachep = kmem_cache_create(
"avtab_node", sizeof(struct avtab_node), 0, SLAB_PANIC, NULL);
avtab_xperms_cachep = kmem_cache_create(
"avtab_extended_perms", sizeof(struct avtab_extended_perms), 0,
SLAB_PANIC, NULL);
avtab_node_cachep = KMEM_CACHE(avtab_node, SLAB_PANIC);
avtab_xperms_cachep = KMEM_CACHE(avtab_extended_perms, SLAB_PANIC);
}

View File

@ -572,7 +572,5 @@ u32 ebitmap_hash(const struct ebitmap *e, u32 hash)
void __init ebitmap_cache_init(void)
{
ebitmap_node_cachep = kmem_cache_create("ebitmap_node",
sizeof(struct ebitmap_node), 0,
SLAB_PANIC, NULL);
ebitmap_node_cachep = KMEM_CACHE(ebitmap_node, SLAB_PANIC);
}

View File

@ -194,7 +194,5 @@ error:
void __init hashtab_cache_init(void)
{
hashtab_node_cachep = kmem_cache_create("hashtab_node",
sizeof(struct hashtab_node), 0,
SLAB_PANIC, NULL);
hashtab_node_cachep = KMEM_CACHE(hashtab_node, SLAB_PANIC);
}

View File

@ -1804,22 +1804,9 @@ retry:
newcontext.role = OBJECT_R_VAL;
}
/* Set the type to default values. */
if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
newcontext.type = scontext->type;
} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
newcontext.type = tcontext->type;
} else {
if ((tclass == policydb->process_class) || sock) {
/* Use the type of process. */
newcontext.type = scontext->type;
} else {
/* Use the type of the related object. */
newcontext.type = tcontext->type;
}
}
/* Look for a type transition/member/change rule. */
/* Set the type.
* Look for a type transition/member/change rule.
*/
avkey.source_type = scontext->type;
avkey.target_type = tcontext->type;
avkey.target_class = tclass;
@ -1837,9 +1824,24 @@ retry:
}
}
/* If a permanent rule is found, use the type from
* the type transition/member/change rule. Otherwise,
* set the type to its default values.
*/
if (avnode) {
/* Use the type from the type transition/member/change rule. */
newcontext.type = avnode->datum.u.data;
} else if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
newcontext.type = scontext->type;
} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
newcontext.type = tcontext->type;
} else {
if ((tclass == policydb->process_class) || sock) {
/* Use the type of process. */
newcontext.type = scontext->type;
} else {
/* Use the type of the related object. */
newcontext.type = tcontext->type;
}
}
/* if we have a objname this is a file trans check so check those rules */