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 ---