diff options
-rw-r--r-- | security/selinux/include/security.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/context.h | 20 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 24 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 25 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 13 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 32 |
6 files changed, 109 insertions, 8 deletions
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index d871e8ad2103..ba53400195c0 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -31,13 +31,14 @@ | |||
31 | #define POLICYDB_VERSION_BOUNDARY 24 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 | 32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 |
33 | #define POLICYDB_VERSION_ROLETRANS 26 | 33 | #define POLICYDB_VERSION_ROLETRANS 26 |
34 | #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 | ||
34 | 35 | ||
35 | /* Range of policy versions we understand*/ | 36 | /* Range of policy versions we understand*/ |
36 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 37 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
37 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX | 38 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
38 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 39 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
39 | #else | 40 | #else |
40 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS | 41 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_NEW_OBJECT_DEFAULTS |
41 | #endif | 42 | #endif |
42 | 43 | ||
43 | /* Mask for just the mount related flags */ | 44 | /* Mask for just the mount related flags */ |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index 45e8fb0515f8..212e3479a0d9 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
@@ -74,6 +74,26 @@ out: | |||
74 | return rc; | 74 | return rc; |
75 | } | 75 | } |
76 | 76 | ||
77 | /* | ||
78 | * Sets both levels in the MLS range of 'dst' to the high level of 'src'. | ||
79 | */ | ||
80 | static inline int mls_context_cpy_high(struct context *dst, struct context *src) | ||
81 | { | ||
82 | int rc; | ||
83 | |||
84 | dst->range.level[0].sens = src->range.level[1].sens; | ||
85 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat); | ||
86 | if (rc) | ||
87 | goto out; | ||
88 | |||
89 | dst->range.level[1].sens = src->range.level[1].sens; | ||
90 | rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); | ||
91 | if (rc) | ||
92 | ebitmap_destroy(&dst->range.level[0].cat); | ||
93 | out: | ||
94 | return rc; | ||
95 | } | ||
96 | |||
77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 97 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
78 | { | 98 | { |
79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 99 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index fbf9c5816c71..40de8d3f208e 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext, | |||
517 | { | 517 | { |
518 | struct range_trans rtr; | 518 | struct range_trans rtr; |
519 | struct mls_range *r; | 519 | struct mls_range *r; |
520 | struct class_datum *cladatum; | ||
521 | int default_range = 0; | ||
520 | 522 | ||
521 | if (!policydb.mls_enabled) | 523 | if (!policydb.mls_enabled) |
522 | return 0; | 524 | return 0; |
@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext, | |||
530 | r = hashtab_search(policydb.range_tr, &rtr); | 532 | r = hashtab_search(policydb.range_tr, &rtr); |
531 | if (r) | 533 | if (r) |
532 | return mls_range_set(newcontext, r); | 534 | return mls_range_set(newcontext, r); |
535 | |||
536 | if (tclass && tclass <= policydb.p_classes.nprim) { | ||
537 | cladatum = policydb.class_val_to_struct[tclass - 1]; | ||
538 | if (cladatum) | ||
539 | default_range = cladatum->default_range; | ||
540 | } | ||
541 | |||
542 | switch (default_range) { | ||
543 | case DEFAULT_SOURCE_LOW: | ||
544 | return mls_context_cpy_low(newcontext, scontext); | ||
545 | case DEFAULT_SOURCE_HIGH: | ||
546 | return mls_context_cpy_high(newcontext, scontext); | ||
547 | case DEFAULT_SOURCE_LOW_HIGH: | ||
548 | return mls_context_cpy(newcontext, scontext); | ||
549 | case DEFAULT_TARGET_LOW: | ||
550 | return mls_context_cpy_low(newcontext, tcontext); | ||
551 | case DEFAULT_TARGET_HIGH: | ||
552 | return mls_context_cpy_high(newcontext, tcontext); | ||
553 | case DEFAULT_TARGET_LOW_HIGH: | ||
554 | return mls_context_cpy(newcontext, tcontext); | ||
555 | } | ||
556 | |||
533 | /* Fallthrough */ | 557 | /* Fallthrough */ |
534 | case AVTAB_CHANGE: | 558 | case AVTAB_CHANGE: |
535 | if ((tclass == policydb.process_class) || (sock == true)) | 559 | if ((tclass == policydb.process_class) || (sock == true)) |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index a7f61d52f05c..2bb9c2fd5f1a 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -133,6 +133,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
133 | .sym_num = SYM_NUM, | 133 | .sym_num = SYM_NUM, |
134 | .ocon_num = OCON_NUM, | 134 | .ocon_num = OCON_NUM, |
135 | }, | 135 | }, |
136 | { | ||
137 | .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, | ||
138 | .sym_num = SYM_NUM, | ||
139 | .ocon_num = OCON_NUM, | ||
140 | }, | ||
136 | }; | 141 | }; |
137 | 142 | ||
138 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 143 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -1306,6 +1311,16 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1306 | goto bad; | 1311 | goto bad; |
1307 | } | 1312 | } |
1308 | 1313 | ||
1314 | if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { | ||
1315 | rc = next_entry(buf, fp, sizeof(u32) * 3); | ||
1316 | if (rc) | ||
1317 | goto bad; | ||
1318 | |||
1319 | cladatum->default_user = le32_to_cpu(buf[0]); | ||
1320 | cladatum->default_role = le32_to_cpu(buf[1]); | ||
1321 | cladatum->default_range = le32_to_cpu(buf[2]); | ||
1322 | } | ||
1323 | |||
1309 | rc = hashtab_insert(h, key, cladatum); | 1324 | rc = hashtab_insert(h, key, cladatum); |
1310 | if (rc) | 1325 | if (rc) |
1311 | goto bad; | 1326 | goto bad; |
@@ -2832,6 +2847,16 @@ static int class_write(void *vkey, void *datum, void *ptr) | |||
2832 | if (rc) | 2847 | if (rc) |
2833 | return rc; | 2848 | return rc; |
2834 | 2849 | ||
2850 | if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { | ||
2851 | buf[0] = cpu_to_le32(cladatum->default_user); | ||
2852 | buf[1] = cpu_to_le32(cladatum->default_role); | ||
2853 | buf[2] = cpu_to_le32(cladatum->default_range); | ||
2854 | |||
2855 | rc = put_entry(buf, sizeof(uint32_t), 3, fp); | ||
2856 | if (rc) | ||
2857 | return rc; | ||
2858 | } | ||
2859 | |||
2835 | return 0; | 2860 | return 0; |
2836 | } | 2861 | } |
2837 | 2862 | ||
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index b846c0387180..a949f1ad43bb 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -60,6 +60,19 @@ struct class_datum { | |||
60 | struct symtab permissions; /* class-specific permission symbol table */ | 60 | struct symtab permissions; /* class-specific permission symbol table */ |
61 | struct constraint_node *constraints; /* constraints on class permissions */ | 61 | struct constraint_node *constraints; /* constraints on class permissions */ |
62 | struct constraint_node *validatetrans; /* special transition rules */ | 62 | struct constraint_node *validatetrans; /* special transition rules */ |
63 | /* Options how a new object user and role should be decided */ | ||
64 | #define DEFAULT_SOURCE 1 | ||
65 | #define DEFAULT_TARGET 2 | ||
66 | char default_user; | ||
67 | char default_role; | ||
68 | /* Options how a new object range should be decided */ | ||
69 | #define DEFAULT_SOURCE_LOW 1 | ||
70 | #define DEFAULT_SOURCE_HIGH 2 | ||
71 | #define DEFAULT_SOURCE_LOW_HIGH 3 | ||
72 | #define DEFAULT_TARGET_LOW 4 | ||
73 | #define DEFAULT_TARGET_HIGH 5 | ||
74 | #define DEFAULT_TARGET_LOW_HIGH 6 | ||
75 | char default_range; | ||
63 | }; | 76 | }; |
64 | 77 | ||
65 | /* Role attributes */ | 78 | /* Role attributes */ |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 185f849a26f6..2ea108c2c048 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1389,6 +1389,7 @@ static int security_compute_sid(u32 ssid, | |||
1389 | u32 *out_sid, | 1389 | u32 *out_sid, |
1390 | bool kern) | 1390 | bool kern) |
1391 | { | 1391 | { |
1392 | struct class_datum *cladatum = NULL; | ||
1392 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1393 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1393 | struct role_trans *roletr = NULL; | 1394 | struct role_trans *roletr = NULL; |
1394 | struct avtab_key avkey; | 1395 | struct avtab_key avkey; |
@@ -1437,12 +1438,20 @@ static int security_compute_sid(u32 ssid, | |||
1437 | goto out_unlock; | 1438 | goto out_unlock; |
1438 | } | 1439 | } |
1439 | 1440 | ||
1441 | if (tclass && tclass <= policydb.p_classes.nprim) | ||
1442 | cladatum = policydb.class_val_to_struct[tclass - 1]; | ||
1443 | |||
1440 | /* Set the user identity. */ | 1444 | /* Set the user identity. */ |
1441 | switch (specified) { | 1445 | switch (specified) { |
1442 | case AVTAB_TRANSITION: | 1446 | case AVTAB_TRANSITION: |
1443 | case AVTAB_CHANGE: | 1447 | case AVTAB_CHANGE: |
1444 | /* Use the process user identity. */ | 1448 | if (cladatum && cladatum->default_user == DEFAULT_TARGET) { |
1445 | newcontext.user = scontext->user; | 1449 | newcontext.user = tcontext->user; |
1450 | } else { | ||
1451 | /* notice this gets both DEFAULT_SOURCE and unset */ | ||
1452 | /* Use the process user identity. */ | ||
1453 | newcontext.user = scontext->user; | ||
1454 | } | ||
1446 | break; | 1455 | break; |
1447 | case AVTAB_MEMBER: | 1456 | case AVTAB_MEMBER: |
1448 | /* Use the related object owner. */ | 1457 | /* Use the related object owner. */ |
@@ -1450,14 +1459,23 @@ static int security_compute_sid(u32 ssid, | |||
1450 | break; | 1459 | break; |
1451 | } | 1460 | } |
1452 | 1461 | ||
1453 | /* Set the role and type to default values. */ | 1462 | /* Set the role to default values. */ |
1454 | if ((tclass == policydb.process_class) || (sock == true)) { | 1463 | if (cladatum && cladatum->default_role == DEFAULT_SOURCE) { |
1455 | /* Use the current role and type of process. */ | ||
1456 | newcontext.role = scontext->role; | 1464 | newcontext.role = scontext->role; |
1465 | } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { | ||
1466 | newcontext.role = tcontext->role; | ||
1467 | } else { | ||
1468 | if ((tclass == policydb.process_class) || (sock == true)) | ||
1469 | newcontext.role = scontext->role; | ||
1470 | else | ||
1471 | newcontext.role = OBJECT_R_VAL; | ||
1472 | } | ||
1473 | |||
1474 | /* Set the type to default values. */ | ||
1475 | if ((tclass == policydb.process_class) || (sock == true)) { | ||
1476 | /* Use the type of process. */ | ||
1457 | newcontext.type = scontext->type; | 1477 | newcontext.type = scontext->type; |
1458 | } else { | 1478 | } else { |
1459 | /* Use the well-defined object role. */ | ||
1460 | newcontext.role = OBJECT_R_VAL; | ||
1461 | /* Use the type of the related object. */ | 1479 | /* Use the type of the related object. */ |
1462 | newcontext.type = tcontext->type; | 1480 | newcontext.type = tcontext->type; |
1463 | } | 1481 | } |