Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+68 -76
+6 -14
security/selinux/avc.c
··· 134 134 */ 135 135 void __init avc_init(void) 136 136 { 137 - avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), 138 - 0, SLAB_PANIC, NULL); 139 - avc_xperms_cachep = kmem_cache_create("avc_xperms_node", 140 - sizeof(struct avc_xperms_node), 141 - 0, SLAB_PANIC, NULL); 142 - avc_xperms_decision_cachep = kmem_cache_create( 143 - "avc_xperms_decision_node", 144 - sizeof(struct avc_xperms_decision_node), 145 - 0, SLAB_PANIC, NULL); 146 - avc_xperms_data_cachep = kmem_cache_create("avc_xperms_data", 147 - sizeof(struct extended_perms_data), 148 - 0, SLAB_PANIC, NULL); 137 + avc_node_cachep = KMEM_CACHE(avc_node, SLAB_PANIC); 138 + avc_xperms_cachep = KMEM_CACHE(avc_xperms_node, SLAB_PANIC); 139 + avc_xperms_decision_cachep = KMEM_CACHE(avc_xperms_decision_node, SLAB_PANIC); 140 + avc_xperms_data_cachep = KMEM_CACHE(extended_perms_data, SLAB_PANIC); 149 141 } 150 142 151 143 int avc_get_hash_stats(char *page) ··· 388 396 audited = denied & avd->auditdeny; 389 397 if (audited && xpd) { 390 398 if (avc_xperms_has_perm(xpd, perm, XPERMS_DONTAUDIT)) 391 - audited &= ~requested; 399 + audited = 0; 392 400 } 393 401 } else if (result) { 394 402 audited = denied = requested; ··· 396 404 audited = requested & avd->auditallow; 397 405 if (audited && xpd) { 398 406 if (!avc_xperms_has_perm(xpd, perm, XPERMS_AUDITALLOW)) 399 - audited &= ~requested; 407 + audited = 0; 400 408 } 401 409 } 402 410
+6 -1
security/selinux/hooks.c
··· 282 282 283 283 might_sleep_if(may_sleep); 284 284 285 + /* 286 + * The check of isec->initialized below is racy but 287 + * inode_doinit_with_dentry() will recheck with 288 + * isec->lock held. 289 + */ 285 290 if (selinux_initialized() && 286 - isec->initialized != LABEL_INITIALIZED) { 291 + data_race(isec->initialized != LABEL_INITIALIZED)) { 287 292 if (!may_sleep) 288 293 return -ECHILD; 289 294
+23 -23
security/selinux/include/audit.h
··· 16 16 #include <linux/types.h> 17 17 18 18 /** 19 - * selinux_audit_rule_init - alloc/init an selinux audit rule structure. 20 - * @field: the field this rule refers to 21 - * @op: the operator the rule uses 22 - * @rulestr: the text "target" of the rule 23 - * @rule: pointer to the new rule structure returned via this 24 - * @gfp: GFP flag used for kmalloc 19 + * selinux_audit_rule_init - alloc/init an selinux audit rule structure. 20 + * @field: the field this rule refers to 21 + * @op: the operator the rule uses 22 + * @rulestr: the text "target" of the rule 23 + * @rule: pointer to the new rule structure returned via this 24 + * @gfp: GFP flag used for kmalloc 25 25 * 26 - * Returns 0 if successful, -errno if not. On success, the rule structure 27 - * will be allocated internally. The caller must free this structure with 28 - * selinux_audit_rule_free() after use. 26 + * Returns 0 if successful, -errno if not. On success, the rule structure 27 + * will be allocated internally. The caller must free this structure with 28 + * selinux_audit_rule_free() after use. 29 29 */ 30 30 int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule, 31 31 gfp_t gfp); 32 32 33 33 /** 34 - * selinux_audit_rule_free - free an selinux audit rule structure. 35 - * @rule: pointer to the audit rule to be freed 34 + * selinux_audit_rule_free - free an selinux audit rule structure. 35 + * @rule: pointer to the audit rule to be freed 36 36 * 37 - * This will free all memory associated with the given rule. 38 - * If @rule is NULL, no operation is performed. 37 + * This will free all memory associated with the given rule. 38 + * If @rule is NULL, no operation is performed. 39 39 */ 40 40 void selinux_audit_rule_free(void *rule); 41 41 42 42 /** 43 - * selinux_audit_rule_match - determine if a context ID matches a rule. 44 - * @sid: the context ID to check 45 - * @field: the field this rule refers to 46 - * @op: the operator the rule uses 47 - * @rule: pointer to the audit rule to check against 43 + * selinux_audit_rule_match - determine if a context ID matches a rule. 44 + * @sid: the context ID to check 45 + * @field: the field this rule refers to 46 + * @op: the operator the rule uses 47 + * @rule: pointer to the audit rule to check against 48 48 * 49 - * Returns 1 if the context id matches the rule, 0 if it does not, and 50 - * -errno on failure. 49 + * Returns 1 if the context id matches the rule, 0 if it does not, and 50 + * -errno on failure. 51 51 */ 52 52 int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule); 53 53 54 54 /** 55 - * selinux_audit_rule_known - check to see if rule contains selinux fields. 56 - * @rule: rule to be checked 57 - * Returns 1 if there are selinux fields specified in the rule, 0 otherwise. 55 + * selinux_audit_rule_known - check to see if rule contains selinux fields. 56 + * @rule: rule to be checked 57 + * Returns 1 if there are selinux fields specified in the rule, 0 otherwise. 58 58 */ 59 59 int selinux_audit_rule_known(struct audit_krule *rule); 60 60
+10 -10
security/selinux/netlabel.c
··· 62 62 * Description: 63 63 * Generate the NetLabel security attributes for a socket, making full use of 64 64 * the socket's attribute cache. Returns a pointer to the security attributes 65 - * on success, NULL on failure. 65 + * on success, or an ERR_PTR on failure. 66 66 * 67 67 */ 68 68 static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) ··· 76 76 77 77 secattr = netlbl_secattr_alloc(GFP_ATOMIC); 78 78 if (secattr == NULL) 79 - return NULL; 79 + return ERR_PTR(-ENOMEM); 80 + 80 81 rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); 81 82 if (rc != 0) { 82 83 netlbl_secattr_free(secattr); 83 - return NULL; 84 + return ERR_PTR(rc); 84 85 } 85 86 sksec->nlbl_secattr = secattr; 86 87 ··· 359 358 { 360 359 struct sk_security_struct *sksec = sk->sk_security; 361 360 362 - if (family == PF_INET) 361 + if (family == PF_INET || family == PF_INET6) 363 362 sksec->nlbl_state = NLBL_LABELED; 364 363 else 365 364 sksec->nlbl_state = NLBL_UNSET; ··· 401 400 return 0; 402 401 403 402 secattr = selinux_netlbl_sock_genattr(sk); 404 - if (secattr == NULL) 405 - return -ENOMEM; 403 + if (IS_ERR(secattr)) 404 + return PTR_ERR(secattr); 406 405 /* On socket creation, replacement of IP options is safe even if 407 406 * the caller does not hold the socket lock. 408 407 */ ··· 562 561 return rc; 563 562 } 564 563 secattr = selinux_netlbl_sock_genattr(sk); 565 - if (secattr == NULL) { 566 - rc = -ENOMEM; 567 - return rc; 568 - } 564 + if (IS_ERR(secattr)) 565 + return PTR_ERR(secattr); 566 + 569 567 rc = netlbl_conn_setattr(sk, addr, secattr); 570 568 if (rc == 0) 571 569 sksec->nlbl_state = NLBL_CONNLABELED;
+2 -5
security/selinux/ss/avtab.c
··· 604 604 605 605 void __init avtab_cache_init(void) 606 606 { 607 - avtab_node_cachep = kmem_cache_create( 608 - "avtab_node", sizeof(struct avtab_node), 0, SLAB_PANIC, NULL); 609 - avtab_xperms_cachep = kmem_cache_create( 610 - "avtab_extended_perms", sizeof(struct avtab_extended_perms), 0, 611 - SLAB_PANIC, NULL); 607 + avtab_node_cachep = KMEM_CACHE(avtab_node, SLAB_PANIC); 608 + avtab_xperms_cachep = KMEM_CACHE(avtab_extended_perms, SLAB_PANIC); 612 609 }
+1 -3
security/selinux/ss/ebitmap.c
··· 572 572 573 573 void __init ebitmap_cache_init(void) 574 574 { 575 - ebitmap_node_cachep = kmem_cache_create("ebitmap_node", 576 - sizeof(struct ebitmap_node), 0, 577 - SLAB_PANIC, NULL); 575 + ebitmap_node_cachep = KMEM_CACHE(ebitmap_node, SLAB_PANIC); 578 576 }
+1 -3
security/selinux/ss/hashtab.c
··· 194 194 195 195 void __init hashtab_cache_init(void) 196 196 { 197 - hashtab_node_cachep = kmem_cache_create("hashtab_node", 198 - sizeof(struct hashtab_node), 0, 199 - SLAB_PANIC, NULL); 197 + hashtab_node_cachep = KMEM_CACHE(hashtab_node, SLAB_PANIC); 200 198 }
+19 -17
security/selinux/ss/services.c
··· 1804 1804 newcontext.role = OBJECT_R_VAL; 1805 1805 } 1806 1806 1807 - /* Set the type to default values. */ 1808 - if (cladatum && cladatum->default_type == DEFAULT_SOURCE) { 1809 - newcontext.type = scontext->type; 1810 - } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { 1811 - newcontext.type = tcontext->type; 1812 - } else { 1813 - if ((tclass == policydb->process_class) || sock) { 1814 - /* Use the type of process. */ 1815 - newcontext.type = scontext->type; 1816 - } else { 1817 - /* Use the type of the related object. */ 1818 - newcontext.type = tcontext->type; 1819 - } 1820 - } 1821 - 1822 - /* Look for a type transition/member/change rule. */ 1807 + /* Set the type. 1808 + * Look for a type transition/member/change rule. 1809 + */ 1823 1810 avkey.source_type = scontext->type; 1824 1811 avkey.target_type = tcontext->type; 1825 1812 avkey.target_class = tclass; ··· 1824 1837 } 1825 1838 } 1826 1839 1840 + /* If a permanent rule is found, use the type from 1841 + * the type transition/member/change rule. Otherwise, 1842 + * set the type to its default values. 1843 + */ 1827 1844 if (avnode) { 1828 - /* Use the type from the type transition/member/change rule. */ 1829 1845 newcontext.type = avnode->datum.u.data; 1846 + } else if (cladatum && cladatum->default_type == DEFAULT_SOURCE) { 1847 + newcontext.type = scontext->type; 1848 + } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { 1849 + newcontext.type = tcontext->type; 1850 + } else { 1851 + if ((tclass == policydb->process_class) || sock) { 1852 + /* Use the type of process. */ 1853 + newcontext.type = scontext->type; 1854 + } else { 1855 + /* Use the type of the related object. */ 1856 + newcontext.type = tcontext->type; 1857 + } 1830 1858 } 1831 1859 1832 1860 /* if we have a objname this is a file trans check so check those rules */