services.c (cdd5b5a9761fd66d17586e4f4ba6588c70e640ea) | services.c (ae254858ce0745aba25d107159b580ab5fdada5b) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Implementation of the security services. 4 * | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Implementation of the security services. 4 * |
5 * Authors : Stephen Smalley, <sds@tycho.nsa.gov> | 5 * Authors : Stephen Smalley, <stephen.smalley.work@gmail.com> |
6 * James Morris <jmorris@redhat.com> 7 * 8 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 9 * 10 * Support for enhanced MLS infrastructure. 11 * Support for context based audit filters. 12 * 13 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> --- 78 unchanged lines hidden (view full) --- 92 struct av_decision *avd, 93 struct extended_perms *xperms); 94 95static int selinux_set_mapping(struct policydb *pol, 96 const struct security_class_mapping *map, 97 struct selinux_map *out_map) 98{ 99 u16 i, j; | 6 * James Morris <jmorris@redhat.com> 7 * 8 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 9 * 10 * Support for enhanced MLS infrastructure. 11 * Support for context based audit filters. 12 * 13 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> --- 78 unchanged lines hidden (view full) --- 92 struct av_decision *avd, 93 struct extended_perms *xperms); 94 95static int selinux_set_mapping(struct policydb *pol, 96 const struct security_class_mapping *map, 97 struct selinux_map *out_map) 98{ 99 u16 i, j; |
100 unsigned k; | |
101 bool print_unknown_handle = false; 102 103 /* Find number of classes in the input mapping */ 104 if (!map) 105 return -EINVAL; 106 i = 0; 107 while (map[i].name) 108 i++; 109 110 /* Allocate space for the class records, plus one for class zero */ 111 out_map->mapping = kcalloc(++i, sizeof(*out_map->mapping), GFP_ATOMIC); 112 if (!out_map->mapping) 113 return -ENOMEM; 114 115 /* Store the raw class and permission values */ 116 j = 0; 117 while (map[j].name) { 118 const struct security_class_mapping *p_in = map + (j++); 119 struct selinux_mapping *p_out = out_map->mapping + j; | 100 bool print_unknown_handle = false; 101 102 /* Find number of classes in the input mapping */ 103 if (!map) 104 return -EINVAL; 105 i = 0; 106 while (map[i].name) 107 i++; 108 109 /* Allocate space for the class records, plus one for class zero */ 110 out_map->mapping = kcalloc(++i, sizeof(*out_map->mapping), GFP_ATOMIC); 111 if (!out_map->mapping) 112 return -ENOMEM; 113 114 /* Store the raw class and permission values */ 115 j = 0; 116 while (map[j].name) { 117 const struct security_class_mapping *p_in = map + (j++); 118 struct selinux_mapping *p_out = out_map->mapping + j; |
119 u16 k; |
|
120 121 /* An empty class string skips ahead */ 122 if (!strcmp(p_in->name, "")) { 123 p_out->num_perms = 0; 124 continue; 125 } 126 127 p_out->value = string_to_security_class(pol, p_in->name); --- 74 unchanged lines hidden (view full) --- 202{ 203 if (tclass < map->size) { 204 struct selinux_mapping *mapping = &map->mapping[tclass]; 205 unsigned int i, n = mapping->num_perms; 206 u32 result; 207 208 for (i = 0, result = 0; i < n; i++) { 209 if (avd->allowed & mapping->perms[i]) | 120 121 /* An empty class string skips ahead */ 122 if (!strcmp(p_in->name, "")) { 123 p_out->num_perms = 0; 124 continue; 125 } 126 127 p_out->value = string_to_security_class(pol, p_in->name); --- 74 unchanged lines hidden (view full) --- 202{ 203 if (tclass < map->size) { 204 struct selinux_mapping *mapping = &map->mapping[tclass]; 205 unsigned int i, n = mapping->num_perms; 206 u32 result; 207 208 for (i = 0, result = 0; i < n; i++) { 209 if (avd->allowed & mapping->perms[i]) |
210 result |= 1<<i; | 210 result |= (u32)1<<i; |
211 if (allow_unknown && !mapping->perms[i]) | 211 if (allow_unknown && !mapping->perms[i]) |
212 result |= 1<<i; | 212 result |= (u32)1<<i; |
213 } 214 avd->allowed = result; 215 216 for (i = 0, result = 0; i < n; i++) 217 if (avd->auditallow & mapping->perms[i]) | 213 } 214 avd->allowed = result; 215 216 for (i = 0, result = 0; i < n; i++) 217 if (avd->auditallow & mapping->perms[i]) |
218 result |= 1<<i; | 218 result |= (u32)1<<i; |
219 avd->auditallow = result; 220 221 for (i = 0, result = 0; i < n; i++) { 222 if (avd->auditdeny & mapping->perms[i]) | 219 avd->auditallow = result; 220 221 for (i = 0, result = 0; i < n; i++) { 222 if (avd->auditdeny & mapping->perms[i]) |
223 result |= 1<<i; | 223 result |= (u32)1<<i; |
224 if (!allow_unknown && !mapping->perms[i]) | 224 if (!allow_unknown && !mapping->perms[i]) |
225 result |= 1<<i; | 225 result |= (u32)1<<i; |
226 } 227 /* 228 * In case the kernel has a bug and requests a permission 229 * between num_perms and the maximum permission number, we 230 * should audit that denial 231 */ 232 for (; i < (sizeof(u32)*8); i++) | 226 } 227 /* 228 * In case the kernel has a bug and requests a permission 229 * between num_perms and the maximum permission number, we 230 * should audit that denial 231 */ 232 for (; i < (sizeof(u32)*8); i++) |
233 result |= 1<<i; | 233 result |= (u32)1<<i; |
234 avd->auditdeny = result; 235 } 236} 237 238int security_mls_enabled(void) 239{ 240 int mls_enabled; 241 struct selinux_policy *policy; --- 609 unchanged lines hidden (view full) --- 851 */ 852int security_bounded_transition(u32 old_sid, u32 new_sid) 853{ 854 struct selinux_policy *policy; 855 struct policydb *policydb; 856 struct sidtab *sidtab; 857 struct sidtab_entry *old_entry, *new_entry; 858 struct type_datum *type; | 234 avd->auditdeny = result; 235 } 236} 237 238int security_mls_enabled(void) 239{ 240 int mls_enabled; 241 struct selinux_policy *policy; --- 609 unchanged lines hidden (view full) --- 851 */ 852int security_bounded_transition(u32 old_sid, u32 new_sid) 853{ 854 struct selinux_policy *policy; 855 struct policydb *policydb; 856 struct sidtab *sidtab; 857 struct sidtab_entry *old_entry, *new_entry; 858 struct type_datum *type; |
859 int index; | 859 u32 index; |
860 int rc; 861 862 if (!selinux_initialized()) 863 return 0; 864 865 rcu_read_lock(); 866 policy = rcu_dereference(selinux_state.policy); 867 policydb = &policy->policydb; --- 449 unchanged lines hidden (view full) --- 1317 1318 if (scontext) 1319 *scontext = NULL; 1320 *scontext_len = 0; 1321 1322 if (!selinux_initialized()) { 1323 if (sid <= SECINITSID_NUM) { 1324 char *scontextp; | 860 int rc; 861 862 if (!selinux_initialized()) 863 return 0; 864 865 rcu_read_lock(); 866 policy = rcu_dereference(selinux_state.policy); 867 policydb = &policy->policydb; --- 449 unchanged lines hidden (view full) --- 1317 1318 if (scontext) 1319 *scontext = NULL; 1320 *scontext_len = 0; 1321 1322 if (!selinux_initialized()) { 1323 if (sid <= SECINITSID_NUM) { 1324 char *scontextp; |
1325 const char *s = initial_sid_to_string[sid]; | 1325 const char *s; |
1326 | 1326 |
1327 /* 1328 * Before the policy is loaded, translate 1329 * SECINITSID_INIT to "kernel", because systemd and 1330 * libselinux < 2.6 take a getcon_raw() result that is 1331 * both non-null and not "kernel" to mean that a policy 1332 * is already loaded. 1333 */ 1334 if (sid == SECINITSID_INIT) 1335 sid = SECINITSID_KERNEL; 1336 1337 s = initial_sid_to_string[sid]; |
|
1327 if (!s) 1328 return -EINVAL; 1329 *scontext_len = strlen(s) + 1; 1330 if (!scontext) 1331 return 0; 1332 scontextp = kmemdup(s, *scontext_len, GFP_ATOMIC); 1333 if (!scontextp) 1334 return -ENOMEM; --- 171 unchanged lines hidden (view full) --- 1506 return -EINVAL; 1507 1508 /* Copy the string to allow changes and ensure a NUL terminator */ 1509 scontext2 = kmemdup_nul(scontext, scontext_len, gfp_flags); 1510 if (!scontext2) 1511 return -ENOMEM; 1512 1513 if (!selinux_initialized()) { | 1338 if (!s) 1339 return -EINVAL; 1340 *scontext_len = strlen(s) + 1; 1341 if (!scontext) 1342 return 0; 1343 scontextp = kmemdup(s, *scontext_len, GFP_ATOMIC); 1344 if (!scontextp) 1345 return -ENOMEM; --- 171 unchanged lines hidden (view full) --- 1517 return -EINVAL; 1518 1519 /* Copy the string to allow changes and ensure a NUL terminator */ 1520 scontext2 = kmemdup_nul(scontext, scontext_len, gfp_flags); 1521 if (!scontext2) 1522 return -ENOMEM; 1523 1524 if (!selinux_initialized()) { |
1514 int i; | 1525 u32 i; |
1515 1516 for (i = 1; i < SECINITSID_NUM; i++) { 1517 const char *s = initial_sid_to_string[i]; 1518 1519 if (s && !strcmp(s, scontext2)) { 1520 *sid = i; 1521 goto out; 1522 } --- 166 unchanged lines hidden (view full) --- 1689 } 1690 datum = datum->next; 1691 } 1692} 1693 1694static int security_compute_sid(u32 ssid, 1695 u32 tsid, 1696 u16 orig_tclass, | 1526 1527 for (i = 1; i < SECINITSID_NUM; i++) { 1528 const char *s = initial_sid_to_string[i]; 1529 1530 if (s && !strcmp(s, scontext2)) { 1531 *sid = i; 1532 goto out; 1533 } --- 166 unchanged lines hidden (view full) --- 1700 } 1701 datum = datum->next; 1702 } 1703} 1704 1705static int security_compute_sid(u32 ssid, 1706 u32 tsid, 1707 u16 orig_tclass, |
1697 u32 specified, | 1708 u16 specified, |
1698 const char *objname, 1699 u32 *out_sid, 1700 bool kern) 1701{ 1702 struct selinux_policy *policy; 1703 struct policydb *policydb; 1704 struct sidtab *sidtab; 1705 struct class_datum *cladatum; 1706 struct context *scontext, *tcontext, newcontext; 1707 struct sidtab_entry *sentry, *tentry; 1708 struct avtab_key avkey; | 1709 const char *objname, 1710 u32 *out_sid, 1711 bool kern) 1712{ 1713 struct selinux_policy *policy; 1714 struct policydb *policydb; 1715 struct sidtab *sidtab; 1716 struct class_datum *cladatum; 1717 struct context *scontext, *tcontext, newcontext; 1718 struct sidtab_entry *sentry, *tentry; 1719 struct avtab_key avkey; |
1709 struct avtab_datum *avdatum; 1710 struct avtab_node *node; | 1720 struct avtab_node *avnode, *node; |
1711 u16 tclass; 1712 int rc = 0; 1713 bool sock; 1714 1715 if (!selinux_initialized()) { 1716 switch (orig_tclass) { 1717 case SECCLASS_PROCESS: /* kernel value */ 1718 *out_sid = ssid; --- 91 unchanged lines hidden (view full) --- 1810 } 1811 } 1812 1813 /* Look for a type transition/member/change rule. */ 1814 avkey.source_type = scontext->type; 1815 avkey.target_type = tcontext->type; 1816 avkey.target_class = tclass; 1817 avkey.specified = specified; | 1721 u16 tclass; 1722 int rc = 0; 1723 bool sock; 1724 1725 if (!selinux_initialized()) { 1726 switch (orig_tclass) { 1727 case SECCLASS_PROCESS: /* kernel value */ 1728 *out_sid = ssid; --- 91 unchanged lines hidden (view full) --- 1820 } 1821 } 1822 1823 /* Look for a type transition/member/change rule. */ 1824 avkey.source_type = scontext->type; 1825 avkey.target_type = tcontext->type; 1826 avkey.target_class = tclass; 1827 avkey.specified = specified; |
1818 avdatum = avtab_search(&policydb->te_avtab, &avkey); | 1828 avnode = avtab_search_node(&policydb->te_avtab, &avkey); |
1819 1820 /* If no permanent rule, also check for enabled conditional rules */ | 1829 1830 /* If no permanent rule, also check for enabled conditional rules */ |
1821 if (!avdatum) { | 1831 if (!avnode) { |
1822 node = avtab_search_node(&policydb->te_cond_avtab, &avkey); 1823 for (; node; node = avtab_search_node_next(node, specified)) { 1824 if (node->key.specified & AVTAB_ENABLED) { | 1832 node = avtab_search_node(&policydb->te_cond_avtab, &avkey); 1833 for (; node; node = avtab_search_node_next(node, specified)) { 1834 if (node->key.specified & AVTAB_ENABLED) { |
1825 avdatum = &node->datum; | 1835 avnode = node; |
1826 break; 1827 } 1828 } 1829 } 1830 | 1836 break; 1837 } 1838 } 1839 } 1840 |
1831 if (avdatum) { | 1841 if (avnode) { |
1832 /* Use the type from the type transition/member/change rule. */ | 1842 /* Use the type from the type transition/member/change rule. */ |
1833 newcontext.type = avdatum->u.data; | 1843 newcontext.type = avnode->datum.u.data; |
1834 } 1835 1836 /* if we have a objname this is a file trans check so check those rules */ 1837 if (objname) 1838 filename_compute_type(policydb, &newcontext, scontext->type, 1839 tcontext->type, tclass, objname); 1840 1841 /* Check for class-specific changes. */ --- 975 unchanged lines hidden (view full) --- 2817static inline int __security_genfs_sid(struct selinux_policy *policy, 2818 const char *fstype, 2819 const char *path, 2820 u16 orig_sclass, 2821 u32 *sid) 2822{ 2823 struct policydb *policydb = &policy->policydb; 2824 struct sidtab *sidtab = policy->sidtab; | 1844 } 1845 1846 /* if we have a objname this is a file trans check so check those rules */ 1847 if (objname) 1848 filename_compute_type(policydb, &newcontext, scontext->type, 1849 tcontext->type, tclass, objname); 1850 1851 /* Check for class-specific changes. */ --- 975 unchanged lines hidden (view full) --- 2827static inline int __security_genfs_sid(struct selinux_policy *policy, 2828 const char *fstype, 2829 const char *path, 2830 u16 orig_sclass, 2831 u32 *sid) 2832{ 2833 struct policydb *policydb = &policy->policydb; 2834 struct sidtab *sidtab = policy->sidtab; |
2825 int len; | |
2826 u16 sclass; 2827 struct genfs *genfs; 2828 struct ocontext *c; 2829 int cmp = 0; 2830 2831 while (path[0] == '/' && path[1] == '/') 2832 path++; 2833 --- 5 unchanged lines hidden (view full) --- 2839 if (cmp <= 0) 2840 break; 2841 } 2842 2843 if (!genfs || cmp) 2844 return -ENOENT; 2845 2846 for (c = genfs->head; c; c = c->next) { | 2835 u16 sclass; 2836 struct genfs *genfs; 2837 struct ocontext *c; 2838 int cmp = 0; 2839 2840 while (path[0] == '/' && path[1] == '/') 2841 path++; 2842 --- 5 unchanged lines hidden (view full) --- 2848 if (cmp <= 0) 2849 break; 2850 } 2851 2852 if (!genfs || cmp) 2853 return -ENOENT; 2854 2855 for (c = genfs->head; c; c = c->next) { |
2847 len = strlen(c->u.name); | 2856 size_t len = strlen(c->u.name); |
2848 if ((!c->v.sclass || sclass == c->v.sclass) && 2849 (strncmp(c->u.name, path, len) == 0)) 2850 break; 2851 } 2852 2853 if (!c) 2854 return -ENOENT; 2855 --- 471 unchanged lines hidden (view full) --- 3327 rcu_read_unlock(); 3328 return rc; 3329} 3330 3331static int get_classes_callback(void *k, void *d, void *args) 3332{ 3333 struct class_datum *datum = d; 3334 char *name = k, **classes = args; | 2857 if ((!c->v.sclass || sclass == c->v.sclass) && 2858 (strncmp(c->u.name, path, len) == 0)) 2859 break; 2860 } 2861 2862 if (!c) 2863 return -ENOENT; 2864 --- 471 unchanged lines hidden (view full) --- 3336 rcu_read_unlock(); 3337 return rc; 3338} 3339 3340static int get_classes_callback(void *k, void *d, void *args) 3341{ 3342 struct class_datum *datum = d; 3343 char *name = k, **classes = args; |
3335 int value = datum->value - 1; | 3344 u32 value = datum->value - 1; |
3336 3337 classes[value] = kstrdup(name, GFP_ATOMIC); 3338 if (!classes[value]) 3339 return -ENOMEM; 3340 3341 return 0; 3342} 3343 3344int security_get_classes(struct selinux_policy *policy, | 3345 3346 classes[value] = kstrdup(name, GFP_ATOMIC); 3347 if (!classes[value]) 3348 return -ENOMEM; 3349 3350 return 0; 3351} 3352 3353int security_get_classes(struct selinux_policy *policy, |
3345 char ***classes, int *nclasses) | 3354 char ***classes, u32 *nclasses) |
3346{ 3347 struct policydb *policydb; 3348 int rc; 3349 3350 policydb = &policy->policydb; 3351 3352 rc = -ENOMEM; 3353 *nclasses = policydb->p_classes.nprim; 3354 *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); 3355 if (!*classes) 3356 goto out; 3357 3358 rc = hashtab_map(&policydb->p_classes.table, get_classes_callback, 3359 *classes); 3360 if (rc) { | 3355{ 3356 struct policydb *policydb; 3357 int rc; 3358 3359 policydb = &policy->policydb; 3360 3361 rc = -ENOMEM; 3362 *nclasses = policydb->p_classes.nprim; 3363 *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); 3364 if (!*classes) 3365 goto out; 3366 3367 rc = hashtab_map(&policydb->p_classes.table, get_classes_callback, 3368 *classes); 3369 if (rc) { |
3361 int i; | 3370 u32 i; 3371 |
3362 for (i = 0; i < *nclasses; i++) 3363 kfree((*classes)[i]); 3364 kfree(*classes); 3365 } 3366 3367out: 3368 return rc; 3369} 3370 3371static int get_permissions_callback(void *k, void *d, void *args) 3372{ 3373 struct perm_datum *datum = d; 3374 char *name = k, **perms = args; | 3372 for (i = 0; i < *nclasses; i++) 3373 kfree((*classes)[i]); 3374 kfree(*classes); 3375 } 3376 3377out: 3378 return rc; 3379} 3380 3381static int get_permissions_callback(void *k, void *d, void *args) 3382{ 3383 struct perm_datum *datum = d; 3384 char *name = k, **perms = args; |
3375 int value = datum->value - 1; | 3385 u32 value = datum->value - 1; |
3376 3377 perms[value] = kstrdup(name, GFP_ATOMIC); 3378 if (!perms[value]) 3379 return -ENOMEM; 3380 3381 return 0; 3382} 3383 3384int security_get_permissions(struct selinux_policy *policy, | 3386 3387 perms[value] = kstrdup(name, GFP_ATOMIC); 3388 if (!perms[value]) 3389 return -ENOMEM; 3390 3391 return 0; 3392} 3393 3394int security_get_permissions(struct selinux_policy *policy, |
3385 char *class, char ***perms, int *nperms) | 3395 const char *class, char ***perms, u32 *nperms) |
3386{ 3387 struct policydb *policydb; | 3396{ 3397 struct policydb *policydb; |
3388 int rc, i; | 3398 u32 i; 3399 int rc; |
3389 struct class_datum *match; 3390 3391 policydb = &policy->policydb; 3392 3393 rc = -EINVAL; 3394 match = symtab_search(&policydb->p_classes, class); 3395 if (!match) { 3396 pr_err("SELinux: %s: unrecognized class %s\n", --- 198 unchanged lines hidden (view full) --- 3595 selinux_audit_rule_free(tmprule); 3596 *rule = NULL; 3597 return rc; 3598} 3599 3600/* Check to see if the rule contains any selinux fields */ 3601int selinux_audit_rule_known(struct audit_krule *rule) 3602{ | 3400 struct class_datum *match; 3401 3402 policydb = &policy->policydb; 3403 3404 rc = -EINVAL; 3405 match = symtab_search(&policydb->p_classes, class); 3406 if (!match) { 3407 pr_err("SELinux: %s: unrecognized class %s\n", --- 198 unchanged lines hidden (view full) --- 3606 selinux_audit_rule_free(tmprule); 3607 *rule = NULL; 3608 return rc; 3609} 3610 3611/* Check to see if the rule contains any selinux fields */ 3612int selinux_audit_rule_known(struct audit_krule *rule) 3613{ |
3603 int i; | 3614 u32 i; |
3604 3605 for (i = 0; i < rule->field_count; i++) { 3606 struct audit_field *f = &rule->fields[i]; 3607 switch (f->type) { 3608 case AUDIT_SUBJ_USER: 3609 case AUDIT_SUBJ_ROLE: 3610 case AUDIT_SUBJ_TYPE: 3611 case AUDIT_SUBJ_SEN: --- 387 unchanged lines hidden --- | 3615 3616 for (i = 0; i < rule->field_count; i++) { 3617 struct audit_field *f = &rule->fields[i]; 3618 switch (f->type) { 3619 case AUDIT_SUBJ_USER: 3620 case AUDIT_SUBJ_ROLE: 3621 case AUDIT_SUBJ_TYPE: 3622 case AUDIT_SUBJ_SEN: --- 387 unchanged lines hidden --- |