aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/hooks.c15
-rw-r--r--security/selinux/include/security.h8
-rw-r--r--security/selinux/ss/avtab.h22
-rw-r--r--security/selinux/ss/policydb.c130
-rw-r--r--security/selinux/ss/policydb.h14
-rw-r--r--security/selinux/ss/services.c45
6 files changed, 197 insertions, 37 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 099bbd07732f..6ae19fd28be5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1301,10 +1301,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1301 1301
1302 /* Try to obtain a transition SID. */ 1302 /* Try to obtain a transition SID. */
1303 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1303 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1304 rc = security_transition_sid(isec->task_sid, 1304 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1305 sbsec->sid, 1305 isec->sclass, NULL, &sid);
1306 isec->sclass,
1307 &sid);
1308 if (rc) 1306 if (rc)
1309 goto out_unlock; 1307 goto out_unlock;
1310 isec->sid = sid; 1308 isec->sid = sid;
@@ -1579,7 +1577,7 @@ static int may_create(struct inode *dir,
1579 return rc; 1577 return rc;
1580 1578
1581 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { 1579 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
1582 rc = security_transition_sid(sid, dsec->sid, tclass, &newsid); 1580 rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid);
1583 if (rc) 1581 if (rc)
1584 return rc; 1582 return rc;
1585 } 1583 }
@@ -2061,7 +2059,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2061 } else { 2059 } else {
2062 /* Check for a default transition on this program. */ 2060 /* Check for a default transition on this program. */
2063 rc = security_transition_sid(old_tsec->sid, isec->sid, 2061 rc = security_transition_sid(old_tsec->sid, isec->sid,
2064 SECCLASS_PROCESS, &new_tsec->sid); 2062 SECCLASS_PROCESS, NULL,
2063 &new_tsec->sid);
2065 if (rc) 2064 if (rc)
2066 return rc; 2065 return rc;
2067 } 2066 }
@@ -2532,7 +2531,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2532 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { 2531 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
2533 rc = security_transition_sid(sid, dsec->sid, 2532 rc = security_transition_sid(sid, dsec->sid,
2534 inode_mode_to_security_class(inode->i_mode), 2533 inode_mode_to_security_class(inode->i_mode),
2535 &newsid); 2534 qstr, &newsid);
2536 if (rc) { 2535 if (rc) {
2537 printk(KERN_WARNING "%s: " 2536 printk(KERN_WARNING "%s: "
2538 "security_transition_sid failed, rc=%d (dev=%s " 2537 "security_transition_sid failed, rc=%d (dev=%s "
@@ -4845,7 +4844,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
4845 * message queue this message will be stored in 4844 * message queue this message will be stored in
4846 */ 4845 */
4847 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, 4846 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
4848 &msec->sid); 4847 NULL, &msec->sid);
4849 if (rc) 4848 if (rc)
4850 return rc; 4849 return rc;
4851 } 4850 }
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 671273eb1115..348eb00cb668 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -8,6 +8,7 @@
8#ifndef _SELINUX_SECURITY_H_ 8#ifndef _SELINUX_SECURITY_H_
9#define _SELINUX_SECURITY_H_ 9#define _SELINUX_SECURITY_H_
10 10
11#include <linux/dcache.h>
11#include <linux/magic.h> 12#include <linux/magic.h>
12#include <linux/types.h> 13#include <linux/types.h>
13#include "flask.h" 14#include "flask.h"
@@ -28,13 +29,14 @@
28#define POLICYDB_VERSION_POLCAP 22 29#define POLICYDB_VERSION_POLCAP 22
29#define POLICYDB_VERSION_PERMISSIVE 23 30#define POLICYDB_VERSION_PERMISSIVE 23
30#define POLICYDB_VERSION_BOUNDARY 24 31#define POLICYDB_VERSION_BOUNDARY 24
32#define POLICYDB_VERSION_FILENAME_TRANS 25
31 33
32/* Range of policy versions we understand*/ 34/* Range of policy versions we understand*/
33#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 35#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
34#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 36#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
35#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 37#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
36#else 38#else
37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY 39#define POLICYDB_VERSION_MAX POLICYDB_VERSION_FILENAME_TRANS
38#endif 40#endif
39 41
40/* Mask for just the mount related flags */ 42/* Mask for just the mount related flags */
@@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid,
106void security_compute_av_user(u32 ssid, u32 tsid, 108void security_compute_av_user(u32 ssid, u32 tsid,
107 u16 tclass, struct av_decision *avd); 109 u16 tclass, struct av_decision *avd);
108 110
109int security_transition_sid(u32 ssid, u32 tsid, 111int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
110 u16 tclass, u32 *out_sid); 112 const struct qstr *qstr, u32 *out_sid);
111 113
112int security_transition_sid_user(u32 ssid, u32 tsid, 114int security_transition_sid_user(u32 ssid, u32 tsid,
113 u16 tclass, u32 *out_sid); 115 u16 tclass, u32 *out_sid);
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/policydb.c b/security/selinux/ss/policydb.c
index be9de3872837..159c81806760 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..2e36e03c21f2 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1343,10 +1343,27 @@ out:
1343 return -EACCES; 1343 return -EACCES;
1344} 1344}
1345 1345
1346static void filename_compute_type(struct policydb *p, struct context *newcontext,
1347 u32 scon, u32 tcon, u16 tclass,
1348 const struct qstr *qstr)
1349{
1350 struct filename_trans *ft;
1351 for (ft = p->filename_trans; ft; ft = ft->next) {
1352 if (ft->stype == scon &&
1353 ft->ttype == tcon &&
1354 ft->tclass == tclass &&
1355 !strcmp(ft->name, qstr->name)) {
1356 newcontext->type = ft->otype;
1357 return;
1358 }
1359 }
1360}
1361
1346static int security_compute_sid(u32 ssid, 1362static int security_compute_sid(u32 ssid,
1347 u32 tsid, 1363 u32 tsid,
1348 u16 orig_tclass, 1364 u16 orig_tclass,
1349 u32 specified, 1365 u32 specified,
1366 const struct qstr *qstr,
1350 u32 *out_sid, 1367 u32 *out_sid,
1351 bool kern) 1368 bool kern)
1352{ 1369{
@@ -1442,6 +1459,11 @@ static int security_compute_sid(u32 ssid,
1442 newcontext.type = avdatum->data; 1459 newcontext.type = avdatum->data;
1443 } 1460 }
1444 1461
1462 /* if we have a qstr this is a file trans check so check those rules */
1463 if (qstr)
1464 filename_compute_type(&policydb, &newcontext, scontext->type,
1465 tcontext->type, tclass, qstr);
1466
1445 /* Check for class-specific changes. */ 1467 /* Check for class-specific changes. */
1446 if (tclass == policydb.process_class) { 1468 if (tclass == policydb.process_class) {
1447 if (specified & AVTAB_TRANSITION) { 1469 if (specified & AVTAB_TRANSITION) {
@@ -1495,22 +1517,17 @@ out:
1495 * if insufficient memory is available, or %0 if the new SID was 1517 * if insufficient memory is available, or %0 if the new SID was
1496 * computed successfully. 1518 * computed successfully.
1497 */ 1519 */
1498int security_transition_sid(u32 ssid, 1520int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
1499 u32 tsid, 1521 const struct qstr *qstr, u32 *out_sid)
1500 u16 tclass,
1501 u32 *out_sid)
1502{ 1522{
1503 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, 1523 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
1504 out_sid, true); 1524 qstr, out_sid, true);
1505} 1525}
1506 1526
1507int security_transition_sid_user(u32 ssid, 1527int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1508 u32 tsid,
1509 u16 tclass,
1510 u32 *out_sid)
1511{ 1528{
1512 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, 1529 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
1513 out_sid, false); 1530 NULL, out_sid, false);
1514} 1531}
1515 1532
1516/** 1533/**
@@ -1531,8 +1548,8 @@ int security_member_sid(u32 ssid,
1531 u16 tclass, 1548 u16 tclass,
1532 u32 *out_sid) 1549 u32 *out_sid)
1533{ 1550{
1534 return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, 1551 return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL,
1535 false); 1552 out_sid, false);
1536} 1553}
1537 1554
1538/** 1555/**
@@ -1553,8 +1570,8 @@ int security_change_sid(u32 ssid,
1553 u16 tclass, 1570 u16 tclass,
1554 u32 *out_sid) 1571 u32 *out_sid)
1555{ 1572{
1556 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, 1573 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
1557 false); 1574 out_sid, false);
1558} 1575}
1559 1576
1560/* Clone the SID into the new SID table. */ 1577/* Clone the SID into the new SID table. */