aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2011-03-07 19:38:10 -0500
committerJames Morris <jmorris@namei.org>2011-03-07 19:38:10 -0500
commitfe3fa43039d47ee4e22caf460b79b62a14937f79 (patch)
tree9eab8d00f1227b9fe0959f32a62d892ed35803ba /security/selinux/ss
parentee009e4a0d4555ed522a631bae9896399674f064 (diff)
parent026eb167ae77244458fa4b4b9fc171209c079ba7 (diff)
Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next
Diffstat (limited to 'security/selinux/ss')
-rw-r--r--security/selinux/ss/avtab.h22
-rw-r--r--security/selinux/ss/mls.c5
-rw-r--r--security/selinux/ss/mls.h3
-rw-r--r--security/selinux/ss/policydb.c130
-rw-r--r--security/selinux/ss/policydb.h14
-rw-r--r--security/selinux/ss/services.c73
6 files changed, 214 insertions, 33 deletions
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 3417f9cc1cbd..63ce2f9e441d 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -14,7 +14,7 @@
14 * 14 *
15 * Copyright (C) 2003 Tresys Technology, LLC 15 * Copyright (C) 2003 Tresys Technology, LLC
16 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, version 2. 18 * the Free Software Foundation, version 2.
19 * 19 *
20 * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> 20 * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
@@ -27,16 +27,16 @@ struct avtab_key {
27 u16 source_type; /* source type */ 27 u16 source_type; /* source type */
28 u16 target_type; /* target type */ 28 u16 target_type; /* target type */
29 u16 target_class; /* target object class */ 29 u16 target_class; /* target object class */
30#define AVTAB_ALLOWED 1 30#define AVTAB_ALLOWED 0x0001
31#define AVTAB_AUDITALLOW 2 31#define AVTAB_AUDITALLOW 0x0002
32#define AVTAB_AUDITDENY 4 32#define AVTAB_AUDITDENY 0x0004
33#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) 33#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
34#define AVTAB_TRANSITION 16 34#define AVTAB_TRANSITION 0x0010
35#define AVTAB_MEMBER 32 35#define AVTAB_MEMBER 0x0020
36#define AVTAB_CHANGE 64 36#define AVTAB_CHANGE 0x0040
37#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) 37#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
38#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ 38#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
39#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ 39#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
40 u16 specified; /* what field is specified */ 40 u16 specified; /* what field is specified */
41}; 41};
42 42
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 1ef8e4e89880..e96174216bc9 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -512,7 +512,8 @@ int mls_compute_sid(struct context *scontext,
512 struct context *tcontext, 512 struct context *tcontext,
513 u16 tclass, 513 u16 tclass,
514 u32 specified, 514 u32 specified,
515 struct context *newcontext) 515 struct context *newcontext,
516 bool sock)
516{ 517{
517 struct range_trans rtr; 518 struct range_trans rtr;
518 struct mls_range *r; 519 struct mls_range *r;
@@ -531,7 +532,7 @@ int mls_compute_sid(struct context *scontext,
531 return mls_range_set(newcontext, r); 532 return mls_range_set(newcontext, r);
532 /* Fallthrough */ 533 /* Fallthrough */
533 case AVTAB_CHANGE: 534 case AVTAB_CHANGE:
534 if (tclass == policydb.process_class) 535 if ((tclass == policydb.process_class) || (sock == true))
535 /* Use the process MLS attributes. */ 536 /* Use the process MLS attributes. */
536 return mls_context_cpy(newcontext, scontext); 537 return mls_context_cpy(newcontext, scontext);
537 else 538 else
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index cd9152632e54..037bf9d82d41 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -49,7 +49,8 @@ int mls_compute_sid(struct context *scontext,
49 struct context *tcontext, 49 struct context *tcontext,
50 u16 tclass, 50 u16 tclass,
51 u32 specified, 51 u32 specified,
52 struct context *newcontext); 52 struct context *newcontext,
53 bool sock);
53 54
54int mls_setup_user_range(struct context *fromcon, struct user_datum *user, 55int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
55 struct context *usercon); 56 struct context *usercon);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 57363562f0f8..e7b850ad57ee 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = {
123 .sym_num = SYM_NUM, 123 .sym_num = SYM_NUM,
124 .ocon_num = OCON_NUM, 124 .ocon_num = OCON_NUM,
125 }, 125 },
126 {
127 .version = POLICYDB_VERSION_FILENAME_TRANS,
128 .sym_num = SYM_NUM,
129 .ocon_num = OCON_NUM,
130 },
126}; 131};
127 132
128static struct policydb_compat_info *policydb_lookup_compat(int version) 133static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p)
704 int i; 709 int i;
705 struct role_allow *ra, *lra = NULL; 710 struct role_allow *ra, *lra = NULL;
706 struct role_trans *tr, *ltr = NULL; 711 struct role_trans *tr, *ltr = NULL;
712 struct filename_trans *ft, *nft;
707 713
708 for (i = 0; i < SYM_NUM; i++) { 714 for (i = 0; i < SYM_NUM; i++) {
709 cond_resched(); 715 cond_resched();
@@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p)
781 } 787 }
782 flex_array_free(p->type_attr_map_array); 788 flex_array_free(p->type_attr_map_array);
783 } 789 }
790
791 ft = p->filename_trans;
792 while (ft) {
793 nft = ft->next;
794 kfree(ft->name);
795 kfree(ft);
796 ft = nft;
797 }
798
784 ebitmap_destroy(&p->policycaps); 799 ebitmap_destroy(&p->policycaps);
785 ebitmap_destroy(&p->permissive_map); 800 ebitmap_destroy(&p->permissive_map);
786 801
@@ -1788,6 +1803,76 @@ out:
1788 return rc; 1803 return rc;
1789} 1804}
1790 1805
1806static int filename_trans_read(struct policydb *p, void *fp)
1807{
1808 struct filename_trans *ft, *last;
1809 u32 nel, len;
1810 char *name;
1811 __le32 buf[4];
1812 int rc, i;
1813
1814 if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
1815 return 0;
1816
1817 rc = next_entry(buf, fp, sizeof(u32));
1818 if (rc)
1819 goto out;
1820 nel = le32_to_cpu(buf[0]);
1821
1822 printk(KERN_ERR "%s: nel=%d\n", __func__, nel);
1823
1824 last = p->filename_trans;
1825 while (last && last->next)
1826 last = last->next;
1827
1828 for (i = 0; i < nel; i++) {
1829 rc = -ENOMEM;
1830 ft = kzalloc(sizeof(*ft), GFP_KERNEL);
1831 if (!ft)
1832 goto out;
1833
1834 /* add it to the tail of the list */
1835 if (!last)
1836 p->filename_trans = ft;
1837 else
1838 last->next = ft;
1839 last = ft;
1840
1841 /* length of the path component string */
1842 rc = next_entry(buf, fp, sizeof(u32));
1843 if (rc)
1844 goto out;
1845 len = le32_to_cpu(buf[0]);
1846
1847 rc = -ENOMEM;
1848 name = kmalloc(len + 1, GFP_KERNEL);
1849 if (!name)
1850 goto out;
1851
1852 ft->name = name;
1853
1854 /* path component string */
1855 rc = next_entry(name, fp, len);
1856 if (rc)
1857 goto out;
1858 name[len] = 0;
1859
1860 printk(KERN_ERR "%s: ft=%p ft->name=%p ft->name=%s\n", __func__, ft, ft->name, ft->name);
1861
1862 rc = next_entry(buf, fp, sizeof(u32) * 4);
1863 if (rc)
1864 goto out;
1865
1866 ft->stype = le32_to_cpu(buf[0]);
1867 ft->ttype = le32_to_cpu(buf[1]);
1868 ft->tclass = le32_to_cpu(buf[2]);
1869 ft->otype = le32_to_cpu(buf[3]);
1870 }
1871 rc = 0;
1872out:
1873 return rc;
1874}
1875
1791static int genfs_read(struct policydb *p, void *fp) 1876static int genfs_read(struct policydb *p, void *fp)
1792{ 1877{
1793 int i, j, rc; 1878 int i, j, rc;
@@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp)
2251 lra = ra; 2336 lra = ra;
2252 } 2337 }
2253 2338
2339 rc = filename_trans_read(p, fp);
2340 if (rc)
2341 goto bad;
2342
2254 rc = policydb_index(p); 2343 rc = policydb_index(p);
2255 if (rc) 2344 if (rc)
2256 goto bad; 2345 goto bad;
@@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp)
3025 return 0; 3114 return 0;
3026} 3115}
3027 3116
3117static int filename_trans_write(struct policydb *p, void *fp)
3118{
3119 struct filename_trans *ft;
3120 u32 len, nel = 0;
3121 __le32 buf[4];
3122 int rc;
3123
3124 for (ft = p->filename_trans; ft; ft = ft->next)
3125 nel++;
3126
3127 buf[0] = cpu_to_le32(nel);
3128 rc = put_entry(buf, sizeof(u32), 1, fp);
3129 if (rc)
3130 return rc;
3131
3132 for (ft = p->filename_trans; ft; ft = ft->next) {
3133 len = strlen(ft->name);
3134 buf[0] = cpu_to_le32(len);
3135 rc = put_entry(buf, sizeof(u32), 1, fp);
3136 if (rc)
3137 return rc;
3138
3139 rc = put_entry(ft->name, sizeof(char), len, fp);
3140 if (rc)
3141 return rc;
3142
3143 buf[0] = ft->stype;
3144 buf[1] = ft->ttype;
3145 buf[2] = ft->tclass;
3146 buf[3] = ft->otype;
3147
3148 rc = put_entry(buf, sizeof(u32), 4, fp);
3149 if (rc)
3150 return rc;
3151 }
3152 return 0;
3153}
3028/* 3154/*
3029 * Write the configuration data in a policy database 3155 * Write the configuration data in a policy database
3030 * structure to a policy database binary representation 3156 * structure to a policy database binary representation
@@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp)
3135 if (rc) 3261 if (rc)
3136 return rc; 3262 return rc;
3137 3263
3264 rc = filename_trans_write(p, fp);
3265 if (rc)
3266 return rc;
3267
3138 rc = ocontext_write(p, info, fp); 3268 rc = ocontext_write(p, info, fp);
3139 if (rc) 3269 if (rc)
3140 return rc; 3270 return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 4e3ab9d0b315..732ea4a68682 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -77,6 +77,15 @@ struct role_trans {
77 struct role_trans *next; 77 struct role_trans *next;
78}; 78};
79 79
80struct filename_trans {
81 struct filename_trans *next;
82 u32 stype; /* current process */
83 u32 ttype; /* parent dir context */
84 u16 tclass; /* class of new object */
85 const char *name; /* last path component */
86 u32 otype; /* expected of new object */
87};
88
80struct role_allow { 89struct role_allow {
81 u32 role; /* current role */ 90 u32 role; /* current role */
82 u32 new_role; /* new role */ 91 u32 new_role; /* new role */
@@ -217,6 +226,9 @@ struct policydb {
217 /* role transitions */ 226 /* role transitions */
218 struct role_trans *role_tr; 227 struct role_trans *role_tr;
219 228
229 /* file transitions with the last path component */
230 struct filename_trans *filename_trans;
231
220 /* bools indexed by (value - 1) */ 232 /* bools indexed by (value - 1) */
221 struct cond_bool_datum **bool_val_to_struct; 233 struct cond_bool_datum **bool_val_to_struct;
222 /* type enforcement conditional access vectors and transitions */ 234 /* type enforcement conditional access vectors and transitions */
@@ -302,7 +314,7 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
302 return 0; 314 return 0;
303} 315}
304 316
305static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp) 317static inline int put_entry(const void *buf, size_t bytes, int num, struct policy_file *fp)
306{ 318{
307 size_t len = bytes * num; 319 size_t len = bytes * num;
308 320
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index a03cfaf0ee07..3e7544d2a07b 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass)
201 return tclass; 201 return tclass;
202} 202}
203 203
204/*
205 * Get kernel value for class from its policy value
206 */
207static u16 map_class(u16 pol_value)
208{
209 u16 i;
210
211 for (i = 1; i < current_mapping_size; i++) {
212 if (current_mapping[i].value == pol_value)
213 return i;
214 }
215
216 return pol_value;
217}
218
204static void map_decision(u16 tclass, struct av_decision *avd, 219static void map_decision(u16 tclass, struct av_decision *avd,
205 int allow_unknown) 220 int allow_unknown)
206{ 221{
@@ -1343,10 +1358,27 @@ out:
1343 return -EACCES; 1358 return -EACCES;
1344} 1359}
1345 1360
1361static void filename_compute_type(struct policydb *p, struct context *newcontext,
1362 u32 scon, u32 tcon, u16 tclass,
1363 const struct qstr *qstr)
1364{
1365 struct filename_trans *ft;
1366 for (ft = p->filename_trans; ft; ft = ft->next) {
1367 if (ft->stype == scon &&
1368 ft->ttype == tcon &&
1369 ft->tclass == tclass &&
1370 !strcmp(ft->name, qstr->name)) {
1371 newcontext->type = ft->otype;
1372 return;
1373 }
1374 }
1375}
1376
1346static int security_compute_sid(u32 ssid, 1377static int security_compute_sid(u32 ssid,
1347 u32 tsid, 1378 u32 tsid,
1348 u16 orig_tclass, 1379 u16 orig_tclass,
1349 u32 specified, 1380 u32 specified,
1381 const struct qstr *qstr,
1350 u32 *out_sid, 1382 u32 *out_sid,
1351 bool kern) 1383 bool kern)
1352{ 1384{
@@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid,
1357 struct avtab_node *node; 1389 struct avtab_node *node;
1358 u16 tclass; 1390 u16 tclass;
1359 int rc = 0; 1391 int rc = 0;
1392 bool sock;
1360 1393
1361 if (!ss_initialized) { 1394 if (!ss_initialized) {
1362 switch (orig_tclass) { 1395 switch (orig_tclass) {
@@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid,
1374 1407
1375 read_lock(&policy_rwlock); 1408 read_lock(&policy_rwlock);
1376 1409
1377 if (kern) 1410 if (kern) {
1378 tclass = unmap_class(orig_tclass); 1411 tclass = unmap_class(orig_tclass);
1379 else 1412 sock = security_is_socket_class(orig_tclass);
1413 } else {
1380 tclass = orig_tclass; 1414 tclass = orig_tclass;
1415 sock = security_is_socket_class(map_class(tclass));
1416 }
1381 1417
1382 scontext = sidtab_search(&sidtab, ssid); 1418 scontext = sidtab_search(&sidtab, ssid);
1383 if (!scontext) { 1419 if (!scontext) {
@@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid,
1408 } 1444 }
1409 1445
1410 /* Set the role and type to default values. */ 1446 /* Set the role and type to default values. */
1411 if (tclass == policydb.process_class) { 1447 if ((tclass == policydb.process_class) || (sock == true)) {
1412 /* Use the current role and type of process. */ 1448 /* Use the current role and type of process. */
1413 newcontext.role = scontext->role; 1449 newcontext.role = scontext->role;
1414 newcontext.type = scontext->type; 1450 newcontext.type = scontext->type;
@@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid,
1442 newcontext.type = avdatum->data; 1478 newcontext.type = avdatum->data;
1443 } 1479 }
1444 1480
1481 /* if we have a qstr this is a file trans check so check those rules */
1482 if (qstr)
1483 filename_compute_type(&policydb, &newcontext, scontext->type,
1484 tcontext->type, tclass, qstr);
1485
1445 /* Check for class-specific changes. */ 1486 /* Check for class-specific changes. */
1446 if (tclass == policydb.process_class) { 1487 if (tclass == policydb.process_class) {
1447 if (specified & AVTAB_TRANSITION) { 1488 if (specified & AVTAB_TRANSITION) {
@@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid,
1460 1501
1461 /* Set the MLS attributes. 1502 /* Set the MLS attributes.
1462 This is done last because it may allocate memory. */ 1503 This is done last because it may allocate memory. */
1463 rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext); 1504 rc = mls_compute_sid(scontext, tcontext, tclass, specified,
1505 &newcontext, sock);
1464 if (rc) 1506 if (rc)
1465 goto out_unlock; 1507 goto out_unlock;
1466 1508
@@ -1495,22 +1537,17 @@ out:
1495 * if insufficient memory is available, or %0 if the new SID was 1537 * if insufficient memory is available, or %0 if the new SID was
1496 * computed successfully. 1538 * computed successfully.
1497 */ 1539 */
1498int security_transition_sid(u32 ssid, 1540int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
1499 u32 tsid, 1541 const struct qstr *qstr, u32 *out_sid)
1500 u16 tclass,
1501 u32 *out_sid)
1502{ 1542{
1503 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, 1543 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
1504 out_sid, true); 1544 qstr, out_sid, true);
1505} 1545}
1506 1546
1507int security_transition_sid_user(u32 ssid, 1547int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1508 u32 tsid,
1509 u16 tclass,
1510 u32 *out_sid)
1511{ 1548{
1512 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, 1549 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
1513 out_sid, false); 1550 NULL, out_sid, false);
1514} 1551}
1515 1552
1516/** 1553/**
@@ -1531,8 +1568,8 @@ int security_member_sid(u32 ssid,
1531 u16 tclass, 1568 u16 tclass,
1532 u32 *out_sid) 1569 u32 *out_sid)
1533{ 1570{
1534 return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, 1571 return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL,
1535 false); 1572 out_sid, false);
1536} 1573}
1537 1574
1538/** 1575/**
@@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid,
1553 u16 tclass, 1590 u16 tclass,
1554 u32 *out_sid) 1591 u32 *out_sid)
1555{ 1592{
1556 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, 1593 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
1557 false); 1594 out_sid, false);
1558} 1595}
1559 1596
1560/* Clone the SID into the new SID table. */ 1597/* Clone the SID into the new SID table. */