aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2012-03-20 14:35:12 -0400
committerEric Paris <eparis@redhat.com>2012-04-09 12:22:47 -0400
commitaa893269de6277b44be88e25dcd5331c934c29c4 (patch)
treef994e023f787c1665b65725f2c009a9f5a021be7 /security/selinux/ss
parent6ce74ec75ca690c4fb3a3c5f8b7767d094d93215 (diff)
SELinux: allow default source/target selectors for user/role/range
When new objects are created we have great and flexible rules to determine the type of the new object. We aren't quite as flexible or mature when it comes to determining the user, role, and range. This patch adds a new ability to specify the place a new objects user, role, and range should come from. For users and roles it can come from either the source or the target of the operation. aka for files the user can either come from the source (the running process and todays default) or it can come from the target (aka the parent directory of the new file) examples always are done with directory context: system_u:object_r:mnt_t:s0-s0:c0.c512 process context: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 [no rule] unconfined_u:object_r:mnt_t:s0 test_none [default user source] unconfined_u:object_r:mnt_t:s0 test_user_source [default user target] system_u:object_r:mnt_t:s0 test_user_target [default role source] unconfined_u:unconfined_r:mnt_t:s0 test_role_source [default role target] unconfined_u:object_r:mnt_t:s0 test_role_target [default range source low] unconfined_u:object_r:mnt_t:s0 test_range_source_low [default range source high] unconfined_u:object_r:mnt_t:s0:c0.c1023 test_range_source_high [default range source low-high] unconfined_u:object_r:mnt_t:s0-s0:c0.c1023 test_range_source_low-high [default range target low] unconfined_u:object_r:mnt_t:s0 test_range_target_low [default range target high] unconfined_u:object_r:mnt_t:s0:c0.c512 test_range_target_high [default range target low-high] unconfined_u:object_r:mnt_t:s0-s0:c0.c512 test_range_target_low-high Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux/ss')
-rw-r--r--security/selinux/ss/context.h20
-rw-r--r--security/selinux/ss/mls.c24
-rw-r--r--security/selinux/ss/policydb.c25
-rw-r--r--security/selinux/ss/policydb.h13
-rw-r--r--security/selinux/ss/services.c32
5 files changed, 107 insertions, 7 deletions
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 */
80static 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);
93out:
94 return rc;
95}
96
77static inline int mls_context_cmp(struct context *c1, struct context *c2) 97static 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
138static struct policydb_compat_info *policydb_lookup_compat(int version) 143static 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 }