diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r-- | security/selinux/selinuxfs.c | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 397fd4955fe1..a85740530afc 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -2,6 +2,11 @@ | |||
2 | * | 2 | * |
3 | * Added conditional policy language extensions | 3 | * Added conditional policy language extensions |
4 | * | 4 | * |
5 | * Updated: Hewlett-Packard <paul.moore@hp.com> | ||
6 | * | ||
7 | * Added support for the policy capability bitmap | ||
8 | * | ||
9 | * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. | ||
5 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC | 10 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC |
6 | * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> | 11 | * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> |
7 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
@@ -35,6 +40,11 @@ | |||
35 | #include "objsec.h" | 40 | #include "objsec.h" |
36 | #include "conditional.h" | 41 | #include "conditional.h" |
37 | 42 | ||
43 | /* Policy capability filenames */ | ||
44 | static char *policycap_names[] = { | ||
45 | "network_peer_controls" | ||
46 | }; | ||
47 | |||
38 | unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; | 48 | unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; |
39 | 49 | ||
40 | #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT | 50 | #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT |
@@ -72,6 +82,9 @@ static int *bool_pending_values = NULL; | |||
72 | static struct dentry *class_dir = NULL; | 82 | static struct dentry *class_dir = NULL; |
73 | static unsigned long last_class_ino; | 83 | static unsigned long last_class_ino; |
74 | 84 | ||
85 | /* global data for policy capabilities */ | ||
86 | static struct dentry *policycap_dir = NULL; | ||
87 | |||
75 | extern void selnl_notify_setenforce(int val); | 88 | extern void selnl_notify_setenforce(int val); |
76 | 89 | ||
77 | /* Check whether a task is allowed to use a security operation. */ | 90 | /* Check whether a task is allowed to use a security operation. */ |
@@ -111,10 +124,11 @@ enum sel_inos { | |||
111 | 124 | ||
112 | static unsigned long sel_last_ino = SEL_INO_NEXT - 1; | 125 | static unsigned long sel_last_ino = SEL_INO_NEXT - 1; |
113 | 126 | ||
114 | #define SEL_INITCON_INO_OFFSET 0x01000000 | 127 | #define SEL_INITCON_INO_OFFSET 0x01000000 |
115 | #define SEL_BOOL_INO_OFFSET 0x02000000 | 128 | #define SEL_BOOL_INO_OFFSET 0x02000000 |
116 | #define SEL_CLASS_INO_OFFSET 0x04000000 | 129 | #define SEL_CLASS_INO_OFFSET 0x04000000 |
117 | #define SEL_INO_MASK 0x00ffffff | 130 | #define SEL_POLICYCAP_INO_OFFSET 0x08000000 |
131 | #define SEL_INO_MASK 0x00ffffff | ||
118 | 132 | ||
119 | #define TMPBUFLEN 12 | 133 | #define TMPBUFLEN 12 |
120 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, | 134 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, |
@@ -263,6 +277,7 @@ static const struct file_operations sel_policyvers_ops = { | |||
263 | /* declaration for sel_write_load */ | 277 | /* declaration for sel_write_load */ |
264 | static int sel_make_bools(void); | 278 | static int sel_make_bools(void); |
265 | static int sel_make_classes(void); | 279 | static int sel_make_classes(void); |
280 | static int sel_make_policycap(void); | ||
266 | 281 | ||
267 | /* declaration for sel_make_class_dirs */ | 282 | /* declaration for sel_make_class_dirs */ |
268 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, | 283 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, |
@@ -323,6 +338,12 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf, | |||
323 | } | 338 | } |
324 | 339 | ||
325 | ret = sel_make_classes(); | 340 | ret = sel_make_classes(); |
341 | if (ret) { | ||
342 | length = ret; | ||
343 | goto out1; | ||
344 | } | ||
345 | |||
346 | ret = sel_make_policycap(); | ||
326 | if (ret) | 347 | if (ret) |
327 | length = ret; | 348 | length = ret; |
328 | else | 349 | else |
@@ -1399,6 +1420,24 @@ static const struct file_operations sel_perm_ops = { | |||
1399 | .read = sel_read_perm, | 1420 | .read = sel_read_perm, |
1400 | }; | 1421 | }; |
1401 | 1422 | ||
1423 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, | ||
1424 | size_t count, loff_t *ppos) | ||
1425 | { | ||
1426 | int value; | ||
1427 | char tmpbuf[TMPBUFLEN]; | ||
1428 | ssize_t length; | ||
1429 | unsigned long i_ino = file->f_path.dentry->d_inode->i_ino; | ||
1430 | |||
1431 | value = security_policycap_supported(i_ino & SEL_INO_MASK); | ||
1432 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); | ||
1433 | |||
1434 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | ||
1435 | } | ||
1436 | |||
1437 | static const struct file_operations sel_policycap_ops = { | ||
1438 | .read = sel_read_policycap, | ||
1439 | }; | ||
1440 | |||
1402 | static int sel_make_perm_files(char *objclass, int classvalue, | 1441 | static int sel_make_perm_files(char *objclass, int classvalue, |
1403 | struct dentry *dir) | 1442 | struct dentry *dir) |
1404 | { | 1443 | { |
@@ -1545,6 +1584,36 @@ out: | |||
1545 | return rc; | 1584 | return rc; |
1546 | } | 1585 | } |
1547 | 1586 | ||
1587 | static int sel_make_policycap(void) | ||
1588 | { | ||
1589 | unsigned int iter; | ||
1590 | struct dentry *dentry = NULL; | ||
1591 | struct inode *inode = NULL; | ||
1592 | |||
1593 | sel_remove_entries(policycap_dir); | ||
1594 | |||
1595 | for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) { | ||
1596 | if (iter < ARRAY_SIZE(policycap_names)) | ||
1597 | dentry = d_alloc_name(policycap_dir, | ||
1598 | policycap_names[iter]); | ||
1599 | else | ||
1600 | dentry = d_alloc_name(policycap_dir, "unknown"); | ||
1601 | |||
1602 | if (dentry == NULL) | ||
1603 | return -ENOMEM; | ||
1604 | |||
1605 | inode = sel_make_inode(policycap_dir->d_sb, S_IFREG | S_IRUGO); | ||
1606 | if (inode == NULL) | ||
1607 | return -ENOMEM; | ||
1608 | |||
1609 | inode->i_fop = &sel_policycap_ops; | ||
1610 | inode->i_ino = iter | SEL_POLICYCAP_INO_OFFSET; | ||
1611 | d_add(dentry, inode); | ||
1612 | } | ||
1613 | |||
1614 | return 0; | ||
1615 | } | ||
1616 | |||
1548 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, | 1617 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, |
1549 | unsigned long *ino) | 1618 | unsigned long *ino) |
1550 | { | 1619 | { |
@@ -1673,6 +1742,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) | |||
1673 | 1742 | ||
1674 | class_dir = dentry; | 1743 | class_dir = dentry; |
1675 | 1744 | ||
1745 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); | ||
1746 | if (!dentry) { | ||
1747 | ret = -ENOMEM; | ||
1748 | goto err; | ||
1749 | } | ||
1750 | |||
1751 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | ||
1752 | if (ret) | ||
1753 | goto err; | ||
1754 | |||
1755 | policycap_dir = dentry; | ||
1756 | |||
1676 | out: | 1757 | out: |
1677 | return ret; | 1758 | return ret; |
1678 | err: | 1759 | err: |