From: Stephen Smalley 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: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton --- 25-akpm/security/selinux/hooks.c | 63 +---------------------------------- 25-akpm/security/selinux/selinuxfs.c | 44 +++++++++++++++++++++++- 2 files changed, 45 insertions(+), 62 deletions(-) diff -puN security/selinux/hooks.c~selinux-add-null-device-node-to-selinuxfs-remove-open_devnull security/selinux/hooks.c --- 25/security/selinux/hooks.c~selinux-add-null-device-node-to-selinuxfs-remove-open_devnull 2004-08-16 11:46:48.025984680 -0700 +++ 25-akpm/security/selinux/hooks.c 2004-08-16 11:46:48.032983616 -0700 @@ -62,7 +62,6 @@ #include #include #include -#include #include #include "avc.h" @@ -1726,64 +1725,8 @@ static void selinux_bprm_free_security(s 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_fi 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); diff -puN security/selinux/selinuxfs.c~selinux-add-null-device-node-to-selinuxfs-remove-open_devnull security/selinux/selinuxfs.c --- 25/security/selinux/selinuxfs.c~selinux-add-null-device-node-to-selinuxfs-remove-open_devnull 2004-08-16 11:46:48.026984528 -0700 +++ 25-akpm/security/selinux/selinuxfs.c 2004-08-16 11:46:48.034983312 -0700 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -886,12 +887,17 @@ err: 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_b 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_ty .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); _