aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/selinuxfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r--security/selinux/selinuxfs.c269
1 files changed, 259 insertions, 10 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index aca099aa2ed3..c9e92daedee2 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -67,6 +67,10 @@ static struct dentry *bool_dir = NULL;
67static int bool_num = 0; 67static int bool_num = 0;
68static int *bool_pending_values = NULL; 68static int *bool_pending_values = NULL;
69 69
70/* global data for classes */
71static struct dentry *class_dir = NULL;
72static unsigned long last_class_ino;
73
70extern void selnl_notify_setenforce(int val); 74extern void selnl_notify_setenforce(int val);
71 75
72/* Check whether a task is allowed to use a security operation. */ 76/* Check whether a task is allowed to use a security operation. */
@@ -106,6 +110,7 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
106 110
107#define SEL_INITCON_INO_OFFSET 0x01000000 111#define SEL_INITCON_INO_OFFSET 0x01000000
108#define SEL_BOOL_INO_OFFSET 0x02000000 112#define SEL_BOOL_INO_OFFSET 0x02000000
113#define SEL_CLASS_INO_OFFSET 0x04000000
109#define SEL_INO_MASK 0x00ffffff 114#define SEL_INO_MASK 0x00ffffff
110 115
111#define TMPBUFLEN 12 116#define TMPBUFLEN 12
@@ -237,6 +242,11 @@ static const struct file_operations sel_policyvers_ops = {
237 242
238/* declaration for sel_write_load */ 243/* declaration for sel_write_load */
239static int sel_make_bools(void); 244static int sel_make_bools(void);
245static int sel_make_classes(void);
246
247/* declaration for sel_make_class_dirs */
248static int sel_make_dir(struct inode *dir, struct dentry *dentry,
249 unsigned long *ino);
240 250
241static ssize_t sel_read_mls(struct file *filp, char __user *buf, 251static ssize_t sel_read_mls(struct file *filp, char __user *buf,
242 size_t count, loff_t *ppos) 252 size_t count, loff_t *ppos)
@@ -287,10 +297,18 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
287 goto out; 297 goto out;
288 298
289 ret = sel_make_bools(); 299 ret = sel_make_bools();
300 if (ret) {
301 length = ret;
302 goto out1;
303 }
304
305 ret = sel_make_classes();
290 if (ret) 306 if (ret)
291 length = ret; 307 length = ret;
292 else 308 else
293 length = count; 309 length = count;
310
311out1:
294 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, 312 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
295 "policy loaded auid=%u", 313 "policy loaded auid=%u",
296 audit_get_loginuid(current->audit_context)); 314 audit_get_loginuid(current->audit_context));
@@ -940,9 +958,8 @@ static const struct file_operations sel_commit_bools_ops = {
940 .write = sel_commit_bools_write, 958 .write = sel_commit_bools_write,
941}; 959};
942 960
943/* delete booleans - partial revoke() from 961/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
944 * fs/proc/generic.c proc_kill_inodes */ 962static void sel_remove_entries(struct dentry *de)
945static void sel_remove_bools(struct dentry *de)
946{ 963{
947 struct list_head *p, *node; 964 struct list_head *p, *node;
948 struct super_block *sb = de->d_sb; 965 struct super_block *sb = de->d_sb;
@@ -998,7 +1015,7 @@ static int sel_make_bools(void)
998 kfree(bool_pending_values); 1015 kfree(bool_pending_values);
999 bool_pending_values = NULL; 1016 bool_pending_values = NULL;
1000 1017
1001 sel_remove_bools(dir); 1018 sel_remove_entries(dir);
1002 1019
1003 if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) 1020 if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
1004 return -ENOMEM; 1021 return -ENOMEM;
@@ -1048,7 +1065,7 @@ out:
1048 return ret; 1065 return ret;
1049err: 1066err:
1050 kfree(values); 1067 kfree(values);
1051 sel_remove_bools(dir); 1068 sel_remove_entries(dir);
1052 ret = -ENOMEM; 1069 ret = -ENOMEM;
1053 goto out; 1070 goto out;
1054} 1071}
@@ -1294,7 +1311,227 @@ out:
1294 return ret; 1311 return ret;
1295} 1312}
1296 1313
1297static int sel_make_dir(struct inode *dir, struct dentry *dentry) 1314static inline unsigned int sel_div(unsigned long a, unsigned long b)
1315{
1316 return a / b - (a % b < 0);
1317}
1318
1319static inline unsigned long sel_class_to_ino(u16 class)
1320{
1321 return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
1322}
1323
1324static inline u16 sel_ino_to_class(unsigned long ino)
1325{
1326 return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
1327}
1328
1329static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
1330{
1331 return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
1332}
1333
1334static inline u32 sel_ino_to_perm(unsigned long ino)
1335{
1336 return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
1337}
1338
1339static ssize_t sel_read_class(struct file * file, char __user *buf,
1340 size_t count, loff_t *ppos)
1341{
1342 ssize_t rc, len;
1343 char *page;
1344 unsigned long ino = file->f_path.dentry->d_inode->i_ino;
1345
1346 page = (char *)__get_free_page(GFP_KERNEL);
1347 if (!page) {
1348 rc = -ENOMEM;
1349 goto out;
1350 }
1351
1352 len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
1353 rc = simple_read_from_buffer(buf, count, ppos, page, len);
1354 free_page((unsigned long)page);
1355out:
1356 return rc;
1357}
1358
1359static const struct file_operations sel_class_ops = {
1360 .read = sel_read_class,
1361};
1362
1363static ssize_t sel_read_perm(struct file * file, char __user *buf,
1364 size_t count, loff_t *ppos)
1365{
1366 ssize_t rc, len;
1367 char *page;
1368 unsigned long ino = file->f_path.dentry->d_inode->i_ino;
1369
1370 page = (char *)__get_free_page(GFP_KERNEL);
1371 if (!page) {
1372 rc = -ENOMEM;
1373 goto out;
1374 }
1375
1376 len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
1377 rc = simple_read_from_buffer(buf, count, ppos, page, len);
1378 free_page((unsigned long)page);
1379out:
1380 return rc;
1381}
1382
1383static const struct file_operations sel_perm_ops = {
1384 .read = sel_read_perm,
1385};
1386
1387static int sel_make_perm_files(char *objclass, int classvalue,
1388 struct dentry *dir)
1389{
1390 int i, rc = 0, nperms;
1391 char **perms;
1392
1393 rc = security_get_permissions(objclass, &perms, &nperms);
1394 if (rc)
1395 goto out;
1396
1397 for (i = 0; i < nperms; i++) {
1398 struct inode *inode;
1399 struct dentry *dentry;
1400
1401 dentry = d_alloc_name(dir, perms[i]);
1402 if (!dentry) {
1403 rc = -ENOMEM;
1404 goto out1;
1405 }
1406
1407 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
1408 if (!inode) {
1409 rc = -ENOMEM;
1410 goto out1;
1411 }
1412 inode->i_fop = &sel_perm_ops;
1413 /* i+1 since perm values are 1-indexed */
1414 inode->i_ino = sel_perm_to_ino(classvalue, i+1);
1415 d_add(dentry, inode);
1416 }
1417
1418out1:
1419 for (i = 0; i < nperms; i++)
1420 kfree(perms[i]);
1421 kfree(perms);
1422out:
1423 return rc;
1424}
1425
1426static int sel_make_class_dir_entries(char *classname, int index,
1427 struct dentry *dir)
1428{
1429 struct dentry *dentry = NULL;
1430 struct inode *inode = NULL;
1431 int rc;
1432
1433 dentry = d_alloc_name(dir, "index");
1434 if (!dentry) {
1435 rc = -ENOMEM;
1436 goto out;
1437 }
1438
1439 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
1440 if (!inode) {
1441 rc = -ENOMEM;
1442 goto out;
1443 }
1444
1445 inode->i_fop = &sel_class_ops;
1446 inode->i_ino = sel_class_to_ino(index);
1447 d_add(dentry, inode);
1448
1449 dentry = d_alloc_name(dir, "perms");
1450 if (!dentry) {
1451 rc = -ENOMEM;
1452 goto out;
1453 }
1454
1455 rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
1456 if (rc)
1457 goto out;
1458
1459 rc = sel_make_perm_files(classname, index, dentry);
1460
1461out:
1462 return rc;
1463}
1464
1465static void sel_remove_classes(void)
1466{
1467 struct list_head *class_node;
1468
1469 list_for_each(class_node, &class_dir->d_subdirs) {
1470 struct dentry *class_subdir = list_entry(class_node,
1471 struct dentry, d_u.d_child);
1472 struct list_head *class_subdir_node;
1473
1474 list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
1475 struct dentry *d = list_entry(class_subdir_node,
1476 struct dentry, d_u.d_child);
1477
1478 if (d->d_inode)
1479 if (d->d_inode->i_mode & S_IFDIR)
1480 sel_remove_entries(d);
1481 }
1482
1483 sel_remove_entries(class_subdir);
1484 }
1485
1486 sel_remove_entries(class_dir);
1487}
1488
1489static int sel_make_classes(void)
1490{
1491 int rc = 0, nclasses, i;
1492 char **classes;
1493
1494 /* delete any existing entries */
1495 sel_remove_classes();
1496
1497 rc = security_get_classes(&classes, &nclasses);
1498 if (rc < 0)
1499 goto out;
1500
1501 /* +2 since classes are 1-indexed */
1502 last_class_ino = sel_class_to_ino(nclasses+2);
1503
1504 for (i = 0; i < nclasses; i++) {
1505 struct dentry *class_name_dir;
1506
1507 class_name_dir = d_alloc_name(class_dir, classes[i]);
1508 if (!class_name_dir) {
1509 rc = -ENOMEM;
1510 goto out1;
1511 }
1512
1513 rc = sel_make_dir(class_dir->d_inode, class_name_dir,
1514 &last_class_ino);
1515 if (rc)
1516 goto out1;
1517
1518 /* i+1 since class values are 1-indexed */
1519 rc = sel_make_class_dir_entries(classes[i], i+1,
1520 class_name_dir);
1521 if (rc)
1522 goto out1;
1523 }
1524
1525out1:
1526 for (i = 0; i < nclasses; i++)
1527 kfree(classes[i]);
1528 kfree(classes);
1529out:
1530 return rc;
1531}
1532
1533static int sel_make_dir(struct inode *dir, struct dentry *dentry,
1534 unsigned long *ino)
1298{ 1535{
1299 int ret = 0; 1536 int ret = 0;
1300 struct inode *inode; 1537 struct inode *inode;
@@ -1306,7 +1543,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
1306 } 1543 }
1307 inode->i_op = &simple_dir_inode_operations; 1544 inode->i_op = &simple_dir_inode_operations;
1308 inode->i_fop = &simple_dir_operations; 1545 inode->i_fop = &simple_dir_operations;
1309 inode->i_ino = ++sel_last_ino; 1546 inode->i_ino = ++(*ino);
1310 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 1547 /* directory inodes start off with i_nlink == 2 (for "." entry) */
1311 inc_nlink(inode); 1548 inc_nlink(inode);
1312 d_add(dentry, inode); 1549 d_add(dentry, inode);
@@ -1352,7 +1589,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1352 goto err; 1589 goto err;
1353 } 1590 }
1354 1591
1355 ret = sel_make_dir(root_inode, dentry); 1592 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1356 if (ret) 1593 if (ret)
1357 goto err; 1594 goto err;
1358 1595
@@ -1385,7 +1622,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1385 goto err; 1622 goto err;
1386 } 1623 }
1387 1624
1388 ret = sel_make_dir(root_inode, dentry); 1625 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1389 if (ret) 1626 if (ret)
1390 goto err; 1627 goto err;
1391 1628
@@ -1399,7 +1636,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1399 goto err; 1636 goto err;
1400 } 1637 }
1401 1638
1402 ret = sel_make_dir(root_inode, dentry); 1639 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1403 if (ret) 1640 if (ret)
1404 goto err; 1641 goto err;
1405 1642
@@ -1407,6 +1644,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1407 if (ret) 1644 if (ret)
1408 goto err; 1645 goto err;
1409 1646
1647 dentry = d_alloc_name(sb->s_root, "class");
1648 if (!dentry) {
1649 ret = -ENOMEM;
1650 goto err;
1651 }
1652
1653 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1654 if (ret)
1655 goto err;
1656
1657 class_dir = dentry;
1658
1410out: 1659out:
1411 return ret; 1660 return ret;
1412err: 1661err: