diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
| -rw-r--r-- | security/selinux/selinuxfs.c | 225 |
1 files changed, 92 insertions, 133 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 48a7d0014b4..c71737f6d1c 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -44,7 +44,9 @@ /* Policy capability filenames */ static char *policycap_names[] = { "network_peer_controls", - "open_perms" + "open_perms", + "redhat1", + "always_check_network" }; unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; @@ -52,7 +54,7 @@ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; static int __init checkreqprot_setup(char *str) { unsigned long checkreqprot; - if (!strict_strtoul(str, 0, &checkreqprot)) + if (!kstrtoul(str, 0, &checkreqprot)) selinux_checkreqprot = checkreqprot ? 1 : 0; return 1; } @@ -174,7 +176,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "enforcing=%d old_enforcing=%d auid=%u ses=%u", new_value, selinux_enforcing, - audit_get_loginuid(current), + from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); selinux_enforcing = new_value; if (selinux_enforcing) @@ -202,7 +204,7 @@ static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, { char tmpbuf[TMPBUFLEN]; ssize_t length; - ino_t ino = filp->f_path.dentry->d_inode->i_ino; + ino_t ino = file_inode(filp)->i_ino; int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ? security_get_reject_unknown() : !security_get_allow_unknown(); @@ -305,7 +307,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "selinux=0 auid=%u ses=%u", - audit_get_loginuid(current), + from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); } @@ -344,7 +346,7 @@ static int sel_make_classes(void); static int sel_make_policycap(void); /* declaration for sel_make_class_dirs */ -static int sel_make_dir(struct inode *dir, struct dentry *dentry, +static struct dentry *sel_make_dir(struct dentry *dir, const char *name, unsigned long *ino); static ssize_t sel_read_mls(struct file *filp, char __user *buf, @@ -485,7 +487,7 @@ static int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma) return -EACCES; } - vma->vm_flags |= VM_RESERVED; + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; vma->vm_ops = &sel_mmap_policy_ops; return 0; @@ -496,6 +498,7 @@ static const struct file_operations sel_policy_ops = { .read = sel_read_policy, .mmap = sel_mmap_policy, .release = sel_release_policy, + .llseek = generic_file_llseek, }; static ssize_t sel_write_load(struct file *file, const char __user *buf, @@ -550,7 +553,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, out1: audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, "policy loaded auid=%u ses=%u", - audit_get_loginuid(current), + from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); out: mutex_unlock(&sel_mutex); @@ -573,7 +576,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) if (length) goto out; - length = security_context_to_sid(buf, size, &sid); + length = security_context_to_sid(buf, size, &sid, GFP_KERNEL); if (length) goto out; @@ -670,7 +673,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { - ino_t ino = file->f_path.dentry->d_inode->i_ino; + ino_t ino = file_inode(file)->i_ino; char *data; ssize_t rv; @@ -728,11 +731,13 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, + GFP_KERNEL); if (length) goto out; - length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, + GFP_KERNEL); if (length) goto out; @@ -814,11 +819,13 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) objname = namebuf; } - length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, + GFP_KERNEL); if (length) goto out; - length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, + GFP_KERNEL); if (length) goto out; @@ -875,11 +882,13 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, + GFP_KERNEL); if (length) goto out; - length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, + GFP_KERNEL); if (length) goto out; @@ -931,7 +940,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s", con, user) != 2) goto out; - length = security_context_to_sid(con, strlen(con) + 1, &sid); + length = security_context_to_sid(con, strlen(con) + 1, &sid, GFP_KERNEL); if (length) goto out; @@ -991,11 +1000,13 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) goto out; - length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); + length = security_context_to_sid(scon, strlen(scon) + 1, &ssid, + GFP_KERNEL); if (length) goto out; - length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); + length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid, + GFP_KERNEL); if (length) goto out; @@ -1041,8 +1052,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, ssize_t length; ssize_t ret; int cur_enforcing; - struct inode *inode = filep->f_path.dentry->d_inode; - unsigned index = inode->i_ino & SEL_INO_MASK; + unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; const char *name = filep->f_path.dentry->d_name.name; mutex_lock(&sel_mutex); @@ -1076,8 +1086,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, char *page = NULL; ssize_t length; int new_value; - struct inode *inode = filep->f_path.dentry->d_inode; - unsigned index = inode->i_ino & SEL_INO_MASK; + unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; const char *name = filep->f_path.dentry->d_name.name; mutex_lock(&sel_mutex); @@ -1232,6 +1241,7 @@ static int sel_make_bools(void) kfree(bool_pending_names[i]); kfree(bool_pending_names); kfree(bool_pending_values); + bool_num = 0; bool_pending_names = NULL; bool_pending_values = NULL; @@ -1257,12 +1267,8 @@ static int sel_make_bools(void) if (!inode) goto out; - ret = -EINVAL; - len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); - if (len < 0) - goto out; - ret = -ENAMETOOLONG; + len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); if (len >= PAGE_SIZE) goto out; @@ -1299,7 +1305,7 @@ out: #define NULL_FILE_NAME "null" -struct dentry *selinux_null; +struct path selinux_null; static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, size_t count, loff_t *ppos) @@ -1488,13 +1494,11 @@ static int sel_make_avc_files(struct dentry *dir) static ssize_t sel_read_initcon(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode; char *con; u32 sid, len; ssize_t ret; - inode = file->f_path.dentry->d_inode; - sid = inode->i_ino&SEL_INO_MASK; + sid = file_inode(file)->i_ino&SEL_INO_MASK; ret = security_sid_to_context(sid, &con, &len); if (ret) return ret; @@ -1532,11 +1536,6 @@ static int sel_make_initcon_files(struct dentry *dir) return 0; } -static inline unsigned int sel_div(unsigned long a, unsigned long b) -{ - return a / b - (a % b < 0); -} - static inline unsigned long sel_class_to_ino(u16 class) { return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; @@ -1544,7 +1543,7 @@ static inline unsigned long sel_class_to_ino(u16 class) static inline u16 sel_ino_to_class(unsigned long ino) { - return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1); + return (ino & SEL_INO_MASK) / (SEL_VEC_MAX + 1); } static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) @@ -1560,19 +1559,10 @@ static inline u32 sel_ino_to_perm(unsigned long ino) static ssize_t sel_read_class(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - ssize_t rc, len; - char *page; - unsigned long ino = file->f_path.dentry->d_inode->i_ino; - - page = (char *)__get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); - rc = simple_read_from_buffer(buf, count, ppos, page, len); - free_page((unsigned long)page); - - return rc; + unsigned long ino = file_inode(file)->i_ino; + char res[TMPBUFLEN]; + ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_class(ino)); + return simple_read_from_buffer(buf, count, ppos, res, len); } static const struct file_operations sel_class_ops = { @@ -1583,19 +1573,10 @@ static const struct file_operations sel_class_ops = { static ssize_t sel_read_perm(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - ssize_t rc, len; - char *page; - unsigned long ino = file->f_path.dentry->d_inode->i_ino; - - page = (char *)__get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); - rc = simple_read_from_buffer(buf, count, ppos, page, len); - free_page((unsigned long)page); - - return rc; + unsigned long ino = file_inode(file)->i_ino; + char res[TMPBUFLEN]; + ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_perm(ino)); + return simple_read_from_buffer(buf, count, ppos, res, len); } static const struct file_operations sel_perm_ops = { @@ -1609,7 +1590,7 @@ static ssize_t sel_read_policycap(struct file *file, char __user *buf, int value; char tmpbuf[TMPBUFLEN]; ssize_t length; - unsigned long i_ino = file->f_path.dentry->d_inode->i_ino; + unsigned long i_ino = file_inode(file)->i_ino; value = security_policycap_supported(i_ino & SEL_INO_MASK); length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); @@ -1678,13 +1659,9 @@ static int sel_make_class_dir_entries(char *classname, int index, inode->i_ino = sel_class_to_ino(index); d_add(dentry, inode); - dentry = d_alloc_name(dir, "perms"); - if (!dentry) - return -ENOMEM; - - rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); - if (rc) - return rc; + dentry = sel_make_dir(dir, "perms", &last_class_ino); + if (IS_ERR(dentry)) + return PTR_ERR(dentry); rc = sel_make_perm_files(classname, index, dentry); @@ -1733,15 +1710,12 @@ static int sel_make_classes(void) for (i = 0; i < nclasses; i++) { struct dentry *class_name_dir; - rc = -ENOMEM; - class_name_dir = d_alloc_name(class_dir, classes[i]); - if (!class_name_dir) - goto out; - - rc = sel_make_dir(class_dir->d_inode, class_name_dir, + class_name_dir = sel_make_dir(class_dir, classes[i], &last_class_ino); - if (rc) + if (IS_ERR(class_name_dir)) { + rc = PTR_ERR(class_name_dir); goto out; + } /* i+1 since class values are 1-indexed */ rc = sel_make_class_dir_entries(classes[i], i + 1, @@ -1787,14 +1761,20 @@ static int sel_make_policycap(void) return 0; } -static int sel_make_dir(struct inode *dir, struct dentry *dentry, +static struct dentry *sel_make_dir(struct dentry *dir, const char *name, unsigned long *ino) { + struct dentry *dentry = d_alloc_name(dir, name); struct inode *inode; - inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); - if (!inode) - return -ENOMEM; + if (!dentry) + return ERR_PTR(-ENOMEM); + + inode = sel_make_inode(dir->d_sb, S_IFDIR | S_IRUGO | S_IXUGO); + if (!inode) { + dput(dentry); + return ERR_PTR(-ENOMEM); + } inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; @@ -1803,16 +1783,16 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry, inc_nlink(inode); d_add(dentry, inode); /* bump link count on parent directory, too */ - inc_nlink(dir); + inc_nlink(dir->d_inode); - return 0; + return dentry; } static int sel_fill_super(struct super_block *sb, void *data, int silent) { int ret; struct dentry *dentry; - struct inode *inode, *root_inode; + struct inode *inode; struct inode_security_struct *isec; static struct tree_descr selinux_files[] = { @@ -1832,25 +1812,19 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, - [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR}, + [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, /* last one */ {""} }; ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); if (ret) goto err; - root_inode = sb->s_root->d_inode; - - ret = -ENOMEM; - dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); - if (!dentry) - goto err; - - ret = sel_make_dir(root_inode, dentry, &sel_last_ino); - if (ret) + bool_dir = sel_make_dir(sb->s_root, BOOL_DIR_NAME, &sel_last_ino); + if (IS_ERR(bool_dir)) { + ret = PTR_ERR(bool_dir); + bool_dir = NULL; goto err; - - bool_dir = dentry; + } ret = -ENOMEM; dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); @@ -1870,56 +1844,41 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); d_add(dentry, inode); - selinux_null = dentry; - - ret = -ENOMEM; - dentry = d_alloc_name(sb->s_root, "avc"); - if (!dentry) - goto err; + selinux_null.dentry = dentry; - ret = sel_make_dir(root_inode, dentry, &sel_last_ino); - if (ret) + dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); goto err; + } ret = sel_make_avc_files(dentry); if (ret) goto err; - ret = -ENOMEM; - dentry = d_alloc_name(sb->s_root, "initial_contexts"); - if (!dentry) - goto err; - - ret = sel_make_dir(root_inode, dentry, &sel_last_ino); - if (ret) + dentry = sel_make_dir(sb->s_root, "initial_contexts", &sel_last_ino); + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); goto err; + } ret = sel_make_initcon_files(dentry); if (ret) goto err; - ret = -ENOMEM; - dentry = d_alloc_name(sb->s_root, "class"); - if (!dentry) - goto err; - - ret = sel_make_dir(root_inode, dentry, &sel_last_ino); - if (ret) + class_dir = sel_make_dir(sb->s_root, "class", &sel_last_ino); + if (IS_ERR(class_dir)) { + ret = PTR_ERR(class_dir); + class_dir = NULL; goto err; + } - class_dir = dentry; - - ret = -ENOMEM; - dentry = d_alloc_name(sb->s_root, "policy_capabilities"); - if (!dentry) + policycap_dir = sel_make_dir(sb->s_root, "policy_capabilities", &sel_last_ino); + if (IS_ERR(policycap_dir)) { + ret = PTR_ERR(policycap_dir); + policycap_dir = NULL; goto err; - - ret = sel_make_dir(root_inode, dentry, &sel_last_ino); - if (ret) - goto err; - - policycap_dir = dentry; - + } return 0; err: printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", @@ -1959,7 +1918,7 @@ static int __init init_sel_fs(void) return err; } - selinuxfs_mount = kern_mount(&sel_fs_type); + selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type); if (IS_ERR(selinuxfs_mount)) { printk(KERN_ERR "selinuxfs: could not mount!\n"); err = PTR_ERR(selinuxfs_mount); |
