diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
| -rw-r--r-- | security/selinux/selinuxfs.c | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 93b3177c7585..aca099aa2ed3 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -96,12 +96,18 @@ enum sel_inos { | |||
| 96 | SEL_COMMIT_BOOLS, /* commit new boolean values */ | 96 | SEL_COMMIT_BOOLS, /* commit new boolean values */ |
| 97 | SEL_MLS, /* return if MLS policy is enabled */ | 97 | SEL_MLS, /* return if MLS policy is enabled */ |
| 98 | SEL_DISABLE, /* disable SELinux until next reboot */ | 98 | SEL_DISABLE, /* disable SELinux until next reboot */ |
| 99 | SEL_AVC, /* AVC management directory */ | ||
| 100 | SEL_MEMBER, /* compute polyinstantiation membership decision */ | 99 | SEL_MEMBER, /* compute polyinstantiation membership decision */ |
| 101 | SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */ | 100 | SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */ |
| 102 | SEL_COMPAT_NET, /* whether to use old compat network packet controls */ | 101 | SEL_COMPAT_NET, /* whether to use old compat network packet controls */ |
| 102 | SEL_INO_NEXT, /* The next inode number to use */ | ||
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | static unsigned long sel_last_ino = SEL_INO_NEXT - 1; | ||
| 106 | |||
| 107 | #define SEL_INITCON_INO_OFFSET 0x01000000 | ||
| 108 | #define SEL_BOOL_INO_OFFSET 0x02000000 | ||
| 109 | #define SEL_INO_MASK 0x00ffffff | ||
| 110 | |||
| 105 | #define TMPBUFLEN 12 | 111 | #define TMPBUFLEN 12 |
| 106 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, | 112 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, |
| 107 | size_t count, loff_t *ppos) | 113 | size_t count, loff_t *ppos) |
| @@ -777,8 +783,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) | |||
| 777 | return ret; | 783 | return ret; |
| 778 | } | 784 | } |
| 779 | 785 | ||
| 780 | #define BOOL_INO_OFFSET 30 | ||
| 781 | |||
| 782 | static ssize_t sel_read_bool(struct file *filep, char __user *buf, | 786 | static ssize_t sel_read_bool(struct file *filep, char __user *buf, |
| 783 | size_t count, loff_t *ppos) | 787 | size_t count, loff_t *ppos) |
| 784 | { | 788 | { |
| @@ -806,14 +810,14 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
| 806 | } | 810 | } |
| 807 | 811 | ||
| 808 | inode = filep->f_path.dentry->d_inode; | 812 | inode = filep->f_path.dentry->d_inode; |
| 809 | cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET); | 813 | cur_enforcing = security_get_bool_value(inode->i_ino&SEL_INO_MASK); |
| 810 | if (cur_enforcing < 0) { | 814 | if (cur_enforcing < 0) { |
| 811 | ret = cur_enforcing; | 815 | ret = cur_enforcing; |
| 812 | goto out; | 816 | goto out; |
| 813 | } | 817 | } |
| 814 | 818 | ||
| 815 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, | 819 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, |
| 816 | bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); | 820 | bool_pending_values[inode->i_ino&SEL_INO_MASK]); |
| 817 | ret = simple_read_from_buffer(buf, count, ppos, page, length); | 821 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
| 818 | out: | 822 | out: |
| 819 | mutex_unlock(&sel_mutex); | 823 | mutex_unlock(&sel_mutex); |
| @@ -865,7 +869,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
| 865 | new_value = 1; | 869 | new_value = 1; |
| 866 | 870 | ||
| 867 | inode = filep->f_path.dentry->d_inode; | 871 | inode = filep->f_path.dentry->d_inode; |
| 868 | bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value; | 872 | bool_pending_values[inode->i_ino&SEL_INO_MASK] = new_value; |
| 869 | length = count; | 873 | length = count; |
| 870 | 874 | ||
| 871 | out: | 875 | out: |
| @@ -1029,7 +1033,7 @@ static int sel_make_bools(void) | |||
| 1029 | isec->sid = sid; | 1033 | isec->sid = sid; |
| 1030 | isec->initialized = 1; | 1034 | isec->initialized = 1; |
| 1031 | inode->i_fop = &sel_bool_ops; | 1035 | inode->i_fop = &sel_bool_ops; |
| 1032 | inode->i_ino = i + BOOL_INO_OFFSET; | 1036 | inode->i_ino = i|SEL_BOOL_INO_OFFSET; |
| 1033 | d_add(dentry, inode); | 1037 | d_add(dentry, inode); |
| 1034 | } | 1038 | } |
| 1035 | bool_num = num; | 1039 | bool_num = num; |
| @@ -1234,6 +1238,56 @@ static int sel_make_avc_files(struct dentry *dir) | |||
| 1234 | goto out; | 1238 | goto out; |
| 1235 | } | 1239 | } |
| 1236 | inode->i_fop = files[i].ops; | 1240 | inode->i_fop = files[i].ops; |
| 1241 | inode->i_ino = ++sel_last_ino; | ||
| 1242 | d_add(dentry, inode); | ||
| 1243 | } | ||
| 1244 | out: | ||
| 1245 | return ret; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | static ssize_t sel_read_initcon(struct file * file, char __user *buf, | ||
| 1249 | size_t count, loff_t *ppos) | ||
| 1250 | { | ||
| 1251 | struct inode *inode; | ||
| 1252 | char *con; | ||
| 1253 | u32 sid, len; | ||
| 1254 | ssize_t ret; | ||
| 1255 | |||
| 1256 | inode = file->f_path.dentry->d_inode; | ||
| 1257 | sid = inode->i_ino&SEL_INO_MASK; | ||
| 1258 | ret = security_sid_to_context(sid, &con, &len); | ||
| 1259 | if (ret < 0) | ||
| 1260 | return ret; | ||
| 1261 | |||
| 1262 | ret = simple_read_from_buffer(buf, count, ppos, con, len); | ||
| 1263 | kfree(con); | ||
| 1264 | return ret; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | static const struct file_operations sel_initcon_ops = { | ||
| 1268 | .read = sel_read_initcon, | ||
| 1269 | }; | ||
| 1270 | |||
| 1271 | static int sel_make_initcon_files(struct dentry *dir) | ||
| 1272 | { | ||
| 1273 | int i, ret = 0; | ||
| 1274 | |||
| 1275 | for (i = 1; i <= SECINITSID_NUM; i++) { | ||
| 1276 | struct inode *inode; | ||
| 1277 | struct dentry *dentry; | ||
| 1278 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); | ||
| 1279 | if (!dentry) { | ||
| 1280 | ret = -ENOMEM; | ||
| 1281 | goto out; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | ||
| 1285 | if (!inode) { | ||
| 1286 | ret = -ENOMEM; | ||
| 1287 | goto out; | ||
| 1288 | } | ||
| 1289 | inode->i_fop = &sel_initcon_ops; | ||
| 1290 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; | ||
| 1237 | d_add(dentry, inode); | 1291 | d_add(dentry, inode); |
| 1238 | } | 1292 | } |
| 1239 | out: | 1293 | out: |
| @@ -1252,6 +1306,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry) | |||
| 1252 | } | 1306 | } |
| 1253 | inode->i_op = &simple_dir_inode_operations; | 1307 | inode->i_op = &simple_dir_inode_operations; |
| 1254 | inode->i_fop = &simple_dir_operations; | 1308 | inode->i_fop = &simple_dir_operations; |
| 1309 | inode->i_ino = ++sel_last_ino; | ||
| 1255 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 1310 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
| 1256 | inc_nlink(inode); | 1311 | inc_nlink(inode); |
| 1257 | d_add(dentry, inode); | 1312 | d_add(dentry, inode); |
| @@ -1314,6 +1369,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) | |||
| 1314 | ret = -ENOMEM; | 1369 | ret = -ENOMEM; |
| 1315 | goto err; | 1370 | goto err; |
| 1316 | } | 1371 | } |
| 1372 | inode->i_ino = ++sel_last_ino; | ||
| 1317 | isec = (struct inode_security_struct*)inode->i_security; | 1373 | isec = (struct inode_security_struct*)inode->i_security; |
| 1318 | isec->sid = SECINITSID_DEVNULL; | 1374 | isec->sid = SECINITSID_DEVNULL; |
| 1319 | isec->sclass = SECCLASS_CHR_FILE; | 1375 | isec->sclass = SECCLASS_CHR_FILE; |
| @@ -1336,6 +1392,21 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) | |||
| 1336 | ret = sel_make_avc_files(dentry); | 1392 | ret = sel_make_avc_files(dentry); |
| 1337 | if (ret) | 1393 | if (ret) |
| 1338 | goto err; | 1394 | goto err; |
| 1395 | |||
| 1396 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); | ||
| 1397 | if (!dentry) { | ||
| 1398 | ret = -ENOMEM; | ||
| 1399 | goto err; | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | ret = sel_make_dir(root_inode, dentry); | ||
| 1403 | if (ret) | ||
| 1404 | goto err; | ||
| 1405 | |||
| 1406 | ret = sel_make_initcon_files(dentry); | ||
| 1407 | if (ret) | ||
| 1408 | goto err; | ||
| 1409 | |||
| 1339 | out: | 1410 | out: |
| 1340 | return ret; | 1411 | return ret; |
| 1341 | err: | 1412 | err: |
