Commit 0b70160d authored by Stephen D. Smalley's avatar Stephen D. Smalley Committed by Linus Torvalds

[PATCH] SELinux: add null device node to selinuxfs, remove open_devnull

This patch adds a null device node to selinuxfs and replaces the SELinux
open_devnull() code by simply acquiring a reference to this node each time,
based on a comment by Al Viro on lkml (see
http://marc.theaimsgroup.com/?l=linux-kernel&m=108664922032035&w=2). 
Signed-off-by: default avatarStephen Smalley <sds@epoch.ncsc.mil>
Signed-off-by: default avatarJames Morris <jmorris@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 603a2af3
......@@ -62,7 +62,6 @@
#include <linux/nfs_mount.h>
#include <net/ipv6.h>
#include <linux/hugetlb.h>
#include <linux/major.h>
#include <linux/personality.h>
#include "avc.h"
......@@ -1726,64 +1725,8 @@ static void selinux_bprm_free_security(struct linux_binprm *bprm)
kfree(bsec);
}
/* Create an open file that refers to the null device.
Derived from the OpenWall LSM. */
struct file *open_devnull(void)
{
struct inode *inode;
struct dentry *dentry;
struct file *file = NULL;
struct inode_security_struct *isec;
dev_t dev;
inode = new_inode(current->fs->rootmnt->mnt_sb);
if (!inode)
goto out;
dentry = dget(d_alloc_root(inode));
if (!dentry)
goto out_iput;
file = get_empty_filp();
if (!file)
goto out_dput;
dev = MKDEV(MEM_MAJOR, 3); /* null device */
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_blksize = PAGE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_state = I_DIRTY; /* so that mark_inode_dirty won't touch us */
isec = inode->i_security;
isec->sid = SECINITSID_DEVNULL;
isec->sclass = SECCLASS_CHR_FILE;
isec->initialized = 1;
file->f_flags = O_RDWR;
file->f_mode = FMODE_READ | FMODE_WRITE;
file->f_dentry = dentry;
file->f_vfsmnt = mntget(current->fs->rootmnt);
file->f_pos = 0;
init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, dev);
if (inode->i_fop->open(inode, file))
goto out_fput;
out:
return file;
out_fput:
mntput(file->f_vfsmnt);
put_filp(file);
out_dput:
dput(dentry);
out_iput:
iput(inode);
file = NULL;
goto out;
}
extern struct vfsmount *selinuxfs_mount;
extern struct dentry *selinux_null;
/* Derived from fs/exec.c:flush_old_files. */
static inline void flush_unauthorized_files(struct files_struct * files)
......@@ -1826,7 +1769,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
if (devnull) {
atomic_inc(&devnull->f_count);
} else {
devnull = open_devnull();
devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
if (!devnull) {
put_unused_fd(fd);
fput(file);
......
......@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/security.h>
#include <linux/major.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
......@@ -886,12 +887,17 @@ static int sel_make_bools(void)
goto out;
}
#define NULL_FILE_NAME "null"
struct dentry *selinux_null = NULL;
static int sel_fill_super(struct super_block * sb, void * data, int silent)
{
int ret;
struct dentry *dentry;
struct inode *inode;
struct qstr qname;
struct inode_security_struct *isec;
static struct tree_descr selinux_files[] = {
[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
......@@ -929,10 +935,29 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
if (ret)
goto out;
qname.name = NULL_FILE_NAME;
qname.len = strlen(qname.name);
qname.hash = full_name_hash(qname.name, qname.len);
dentry = d_alloc(sb->s_root, &qname);
if (!dentry)
return -ENOMEM;
inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
if (!inode)
goto out;
isec = (struct inode_security_struct*)inode->i_security;
isec->sid = SECINITSID_DEVNULL;
isec->sclass = SECCLASS_CHR_FILE;
isec->initialized = 1;
init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
d_add(dentry, inode);
selinux_null = dentry;
return 0;
out:
dput(dentry);
printk(KERN_ERR "security: error creating conditional out_dput\n");
printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
return -ENOMEM;
}
......@@ -948,9 +973,24 @@ static struct file_system_type sel_fs_type = {
.kill_sb = kill_litter_super,
};
struct vfsmount *selinuxfs_mount;
static int __init init_sel_fs(void)
{
return selinux_enabled ? register_filesystem(&sel_fs_type) : 0;
int err;
if (!selinux_enabled)
return 0;
err = register_filesystem(&sel_fs_type);
if (!err) {
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);
selinuxfs_mount = NULL;
}
}
return err;
}
__initcall(init_sel_fs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment