This patch allows LSM to check permission using "struct vfsmount" without passing "struct vfsmount" to VFS helper functions. Signed-off-by: Kentaro Takeda <takedakn@xxxxxxxxxxxxx> Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Toshiharu Harada <haradats@xxxxxxxxxxxxx> --- fs/exec.c | 10 ++ fs/namei.c | 129 +++++++++++++++++++++++++++++++--- fs/open.c | 7 + include/linux/fs.h | 8 ++ include/linux/security.h | 178 +++++++++++++++++++++++++++++++++++++++++++++++ net/unix/af_unix.c | 4 + security/dummy.c | 73 +++++++++++++++++++ security/security.c | 63 ++++++++++++++++ 8 files changed, 462 insertions(+), 10 deletions(-) --- mm.orig/fs/exec.c +++ mm/fs/exec.c @@ -119,6 +119,16 @@ asmlinkage long sys_uselib(const char __ if (error) goto exit; + /* + * sys_access() with both R_OK and X_OK flags makes LSM's + * security_inode_permission() unable to tell whether the request is + * "just checking for permissions" or "actually loading a shared + * library". + */ + error = security_path_uselib(&nd); + if (error) + goto exit; + file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); error = PTR_ERR(file); if (IS_ERR(file)) --- mm.orig/fs/namei.c +++ mm/fs/namei.c @@ -1595,6 +1595,9 @@ int vfs_create(struct inode *dir, struct error = security_inode_create(dir, dentry, mode); if (error) return error; + error = security_path_create(dir, dentry, mode, nd); + if (error) + return error; DQUOT_INIT(dir); error = dir->i_op->create(dir, dentry, mode, nd); if (!error) @@ -1650,6 +1653,17 @@ int may_open(struct nameidata *nd, int a return -EPERM; /* + * security_inode_permission() called from vfs_permission() + * can't know that the file is going to be truncated when + * open(filename, O_WRONLY | O_TRUNC | O_APPEND) is used. + * So, this hook checks O_APPEND and O_TRUNC flags as well + * as MAY_READ and MAY_WRITE flags. + */ + error = security_path_open(nd->path.dentry, nd->path.mnt, flag); + if (error) + return error; + + /* * Ensure there are no outstanding leases on the file. */ error = break_lease(inode, flag); @@ -2021,7 +2035,12 @@ fail: } EXPORT_SYMBOL_GPL(lookup_create); -int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +/* + * These pre_vfs_*() functions are separated from vfs_*() functions so that + * LSM's security_path_*() functions can do DAC checks before MAC checks + * without duplicating may_create()/may_delete() functions. + */ +int pre_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode) { int error = may_create(dir, dentry, NULL); @@ -2033,6 +2052,14 @@ int vfs_mknod(struct inode *dir, struct if (!dir->i_op || !dir->i_op->mknod) return -EPERM; + return 0; +} + +int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ + int error = pre_vfs_mknod(dir, dentry, mode); + if (error) + return error; error = devcgroup_inode_mknod(mode, dev); if (error) @@ -2096,6 +2123,9 @@ asmlinkage long sys_mknodat(int dfd, con error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; + error = security_path_mknod(&nd.path, dentry, mode, dev); + if (error) + goto out_drop_write; switch (mode & S_IFMT) { case 0: case S_IFREG: error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); @@ -2108,6 +2138,7 @@ asmlinkage long sys_mknodat(int dfd, con error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); break; } +out_drop_write: mnt_drop_write(nd.path.mnt); out_dput: dput(dentry); @@ -2125,7 +2156,7 @@ asmlinkage long sys_mknod(const char __u return sys_mknodat(AT_FDCWD, filename, mode, dev); } -int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +int pre_vfs_mkdir(struct inode *dir, struct dentry *dentry) { int error = may_create(dir, dentry, NULL); @@ -2134,6 +2165,14 @@ int vfs_mkdir(struct inode *dir, struct if (!dir->i_op || !dir->i_op->mkdir) return -EPERM; + return 0; +} + +int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int error = pre_vfs_mkdir(dir, dentry); + if (error) + return error; mode &= (S_IRWXUGO|S_ISVTX); error = security_inode_mkdir(dir, dentry, mode); @@ -2172,7 +2211,11 @@ asmlinkage long sys_mkdirat(int dfd, con error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; + error = security_path_mkdir(&nd.path, dentry, mode); + if (error) + goto out_drop_write; error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); +out_drop_write: mnt_drop_write(nd.path.mnt); out_dput: dput(dentry); @@ -2217,7 +2260,7 @@ void dentry_unhash(struct dentry *dentry spin_unlock(&dcache_lock); } -int vfs_rmdir(struct inode *dir, struct dentry *dentry) +int pre_vfs_rmdir(struct inode *dir, struct dentry *dentry) { int error = may_delete(dir, dentry, 1); @@ -2226,6 +2269,14 @@ int vfs_rmdir(struct inode *dir, struct if (!dir->i_op || !dir->i_op->rmdir) return -EPERM; + return 0; +} + +int vfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int error = pre_vfs_rmdir(dir, dentry); + if (error) + return error; DQUOT_INIT(dir); @@ -2284,7 +2335,11 @@ static long do_rmdir(int dfd, const char error = mnt_want_write(nd.path.mnt); if (error) goto exit3; + error = security_path_rmdir(&nd.path, dentry); + if (error) + goto exit4; error = vfs_rmdir(nd.path.dentry->d_inode, dentry); +exit4: mnt_drop_write(nd.path.mnt); exit3: dput(dentry); @@ -2302,7 +2357,7 @@ asmlinkage long sys_rmdir(const char __u return do_rmdir(AT_FDCWD, pathname); } -int vfs_unlink(struct inode *dir, struct dentry *dentry) +int pre_vfs_unlink(struct inode *dir, struct dentry *dentry) { int error = may_delete(dir, dentry, 0); @@ -2311,6 +2366,14 @@ int vfs_unlink(struct inode *dir, struct if (!dir->i_op || !dir->i_op->unlink) return -EPERM; + return 0; +} + +int vfs_unlink(struct inode *dir, struct dentry *dentry) +{ + int error = pre_vfs_unlink(dir, dentry); + if (error) + return error; DQUOT_INIT(dir); @@ -2370,7 +2433,11 @@ static long do_unlinkat(int dfd, const c error = mnt_want_write(nd.path.mnt); if (error) goto exit2; + error = security_path_unlink(&nd.path, dentry); + if (error) + goto exit3; error = vfs_unlink(nd.path.dentry->d_inode, dentry); +exit3: mnt_drop_write(nd.path.mnt); exit2: dput(dentry); @@ -2406,7 +2473,7 @@ asmlinkage long sys_unlink(const char __ return do_unlinkat(AT_FDCWD, pathname); } -int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) +int pre_vfs_symlink(struct inode *dir, struct dentry *dentry) { int error = may_create(dir, dentry, NULL); @@ -2415,6 +2482,15 @@ int vfs_symlink(struct inode *dir, struc if (!dir->i_op || !dir->i_op->symlink) return -EPERM; + return 0; +} + +int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, + int mode) +{ + int error = pre_vfs_symlink(dir, dentry); + if (error) + return error; error = security_inode_symlink(dir, dentry, oldname); if (error) @@ -2455,7 +2531,11 @@ asmlinkage long sys_symlinkat(const char error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; + error = security_path_symlink(&nd.path, dentry, from); + if (error) + goto out_drop_write; error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); +out_drop_write: mnt_drop_write(nd.path.mnt); out_dput: dput(dentry); @@ -2474,7 +2554,8 @@ asmlinkage long sys_symlink(const char _ return sys_symlinkat(oldname, AT_FDCWD, newname); } -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +int pre_vfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *new_dentry) { struct inode *inode = old_dentry->d_inode; int error; @@ -2498,6 +2579,15 @@ int vfs_link(struct dentry *old_dentry, return -EPERM; if (S_ISDIR(old_dentry->d_inode->i_mode)) return -EPERM; + return 0; +} + +int vfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *new_dentry) +{ + int error = pre_vfs_link(old_dentry, dir, new_dentry); + if (error) + return error; error = security_inode_link(old_dentry, dir, new_dentry); if (error) @@ -2555,7 +2645,11 @@ asmlinkage long sys_linkat(int olddfd, c error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; + error = security_path_link(&old_nd.path, &nd.path, new_dentry); + if (error) + goto out_drop_write; error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); +out_drop_write: mnt_drop_write(nd.path.mnt); out_dput: dput(new_dentry); @@ -2679,16 +2773,15 @@ static int vfs_rename_other(struct inode return error; } -int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) +int pre_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { int error; int is_dir = S_ISDIR(old_dentry->d_inode->i_mode); - const char *old_name; if (old_dentry->d_inode == new_dentry->d_inode) return 0; - + error = may_delete(old_dir, old_dentry, is_dir); if (error) return error; @@ -2702,6 +2795,17 @@ int vfs_rename(struct inode *old_dir, st if (!old_dir->i_op || !old_dir->i_op->rename) return -EPERM; + return 0; +} + +int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + int error = pre_vfs_rename(old_dir, old_dentry, new_dir, new_dentry); + int is_dir = S_ISDIR(old_dentry->d_inode->i_mode); + const char *old_name; + if (error) + return error; DQUOT_INIT(old_dir); DQUOT_INIT(new_dir); @@ -2786,8 +2890,13 @@ static int do_rename(int olddfd, const c error = mnt_want_write(oldnd.path.mnt); if (error) goto exit5; + error = security_path_rename(&oldnd.path, old_dentry, + &newnd.path, new_dentry); + if (error) + goto exit6; error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); +exit6: mnt_drop_write(oldnd.path.mnt); exit5: dput(new_dentry); --- mm.orig/fs/open.c +++ mm/fs/open.c @@ -268,6 +268,9 @@ static long do_sys_truncate(const char _ if (error) goto put_write_and_out; + error = security_path_truncate(&nd.path, length, 0, NULL); + if (error) + goto put_write_and_out; error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); @@ -324,6 +327,10 @@ static long do_sys_ftruncate(unsigned in if (IS_APPEND(inode)) goto out_putf; + error = security_path_truncate(&file->f_path, length, + ATTR_MTIME|ATTR_CTIME, file); + if (error) + goto out_putf; error = locks_verify_truncate(inode, file, length); if (!error) error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); --- mm.orig/include/linux/fs.h +++ mm/include/linux/fs.h @@ -1124,12 +1124,20 @@ extern void unlock_super(struct super_bl */ extern int vfs_permission(struct nameidata *, int); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); +extern int pre_vfs_mkdir(struct inode *, struct dentry *); extern int vfs_mkdir(struct inode *, struct dentry *, int); +extern int pre_vfs_mknod(struct inode *, struct dentry *, int); extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); +extern int pre_vfs_symlink(struct inode *, struct dentry *); extern int vfs_symlink(struct inode *, struct dentry *, const char *, int); +extern int pre_vfs_link(struct dentry *, struct inode *, struct dentry *); extern int vfs_link(struct dentry *, struct inode *, struct dentry *); +extern int pre_vfs_rmdir(struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *); +extern int pre_vfs_unlink(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); +extern int pre_vfs_rename(struct inode *, struct dentry *, struct inode *, + struct dentry *); extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); /* --- mm.orig/include/linux/security.h +++ mm/include/linux/security.h @@ -343,23 +343,50 @@ static inline void security_free_mnt_opt * @dentry contains the dentry structure for the file to be created. * @mode contains the file mode of the file to be created. * Return 0 if permission is granted. + * @path_create: + * Check permission to create a regular file. + * @dir contains inode structure of the parent of the new file. + * @dentry contains the dentry structure for the file to be created. + * @mode contains the file mode of the file to be created. + * @nd contains the nameidata structure (may be NULL). + * Return 0 if permission is granted. * @inode_link: * Check permission before creating a new hard link to a file. * @old_dentry contains the dentry structure for an existing link to the file. * @dir contains the inode structure of the parent directory of the new link. * @new_dentry contains the dentry structure for the new link. * Return 0 if permission is granted. + * @path_link: + * Check permission before creating a new hard link to a file. + * @old_path contains the path structure for an existing link + * to the file. + * @new_dir contains the path structure of the parent directory of + * the new link. + * @new_dentry contains the dentry structure for the new link. + * Return 0 if permission is granted. * @inode_unlink: * Check the permission to remove a hard link to a file. * @dir contains the inode structure of parent directory of the file. * @dentry contains the dentry structure for file to be unlinked. * Return 0 if permission is granted. + * @path_unlink: + * Check the permission to remove a hard link to a file. + * @dir contains the path structure of parent directory of the file. + * @dentry contains the dentry structure for file to be unlinked. + * Return 0 if permission is granted. * @inode_symlink: * Check the permission to create a symbolic link to a file. * @dir contains the inode structure of parent directory of the symbolic link. * @dentry contains the dentry structure of the symbolic link. * @old_name contains the pathname of file. * Return 0 if permission is granted. + * @path_symlink: + * Check the permission to create a symbolic link to a file. + * @dir contains the path structure of parent directory of + * the symbolic link. + * @dentry contains the dentry structure of the symbolic link. + * @old_name contains the pathname of file. + * Return 0 if permission is granted. * @inode_mkdir: * Check permissions to create a new directory in the existing directory * associated with inode strcture @dir. @@ -367,11 +394,25 @@ static inline void security_free_mnt_opt * @dentry contains the dentry structure of new directory. * @mode contains the mode of new directory. * Return 0 if permission is granted. + * @path_mkdir: + * Check permissions to create a new directory in the existing directory + * associated with path strcture @path. + * @dir containst the path structure of parent of the directory + * to be created. + * @dentry contains the dentry structure of new directory. + * @mode contains the mode of new directory. + * Return 0 if permission is granted. * @inode_rmdir: * Check the permission to remove a directory. * @dir contains the inode structure of parent of the directory to be removed. * @dentry contains the dentry structure of directory to be removed. * Return 0 if permission is granted. + * @path_rmdir: + * Check the permission to remove a directory. + * @dir contains the path structure of parent of the directory to be + * removed. + * @dentry contains the dentry structure of directory to be removed. + * Return 0 if permission is granted. * @inode_mknod: * Check permissions when creating a special file (or a socket or a fifo * file created via the mknod system call). Note that if mknod operation @@ -382,6 +423,15 @@ static inline void security_free_mnt_opt * @mode contains the mode of the new file. * @dev contains the device number. * Return 0 if permission is granted. + * @path_mknod: + * Check permissions when creating a file. Note that this hook is called + * even if mknod operation is being done for a regular file. + * @dir contains the path structure of parent of the new file. + * @dentry contains the dentry structure of the new file. + * @mode contains the mode of the new file. + * @dev contains the undecoded device number. Use new_decode_dev() to get + * the decoded device number. + * Return 0 if permission is granted. * @inode_rename: * Check for permission to rename a file or directory. * @old_dir contains the inode structure for parent of the old link. @@ -389,6 +439,13 @@ static inline void security_free_mnt_opt * @new_dir contains the inode structure for parent of the new link. * @new_dentry contains the dentry structure of the new link. * Return 0 if permission is granted. + * @path_rename: + * Check for permission to rename a file or directory. + * @old_dir contains the path structure for parent of the old link. + * @old_dentry contains the dentry structure of the old link. + * @new_dir contains the path structure for parent of the new link. + * @new_dentry contains the dentry structure of the new link. + * Return 0 if permission is granted. * @inode_readlink: * Check the permission to read the symbolic link. * @dentry contains the dentry structure for the file link. @@ -409,6 +466,12 @@ static inline void security_free_mnt_opt * @mask contains the permission mask. * @nd contains the nameidata (may be NULL). * Return 0 if permission is granted. + * @path_open: + * Check permission to open a file. + * @dentry contains the dentry structure for the file to be opened. + * @mnt contains the vfsmount structure for the file to be opened. + * @flags contains the open flags. + * Return 0 if permission is granted. * @inode_setattr: * Check permission before setting file attributes. Note that the kernel * call to notify_change is performed from several locations, whenever @@ -417,6 +480,17 @@ static inline void security_free_mnt_opt * @dentry contains the dentry structure for the file. * @attr is the iattr structure containing the new file attributes. * Return 0 if permission is granted. + * @path_truncate: + * Check permission before truncating a file. + * @path contains the path structure for the file. + * @length is the new length of the file. + * @time_attrs is the flags passed to do_truncate(). + * @filp is the file structure (may be NULL). + * Return 0 if permission is granted. + * @path_uselib: + * Check permission before using a library. + * @nd contains the nameidata. + * Return 0 if permission is granted. * @inode_getattr: * Check permission before obtaining file attributes. * @mnt is the vfsmount where the dentry was looked up @@ -1351,6 +1425,25 @@ struct security_operations { struct super_block *newsb); int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); + int (*path_create) (struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd); + int (*path_unlink) (struct path *dir, struct dentry *dentry); + int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode); + int (*path_rmdir) (struct path *dir, struct dentry *dentry); + int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, + unsigned int dev); + int (*path_truncate) (struct path *path, loff_t length, + unsigned int time_attrs, struct file *filp); + int (*path_uselib) (struct nameidata *nd); + int (*path_symlink) (struct path *dir, struct dentry *dentry, + const char *old_name); + int (*path_link) (struct path *old_path, struct path *new_dir, + struct dentry *new_dentry); + int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, + struct path *new_dir, struct dentry *new_dentry); + int (*path_open) (struct dentry *dentry, struct vfsmount *mnt, + int flags); + int (*inode_alloc_security) (struct inode *inode); void (*inode_free_security) (struct inode *inode); int (*inode_init_security) (struct inode *inode, struct inode *dir, @@ -1625,6 +1718,24 @@ void security_sb_clone_mnt_opts(const st struct super_block *newsb); int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); +int security_path_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd); +int security_path_unlink(struct path *dir, struct dentry *dentry); +int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode); +int security_path_rmdir(struct path *dir, struct dentry *dentry); +int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, + unsigned int dev); +int security_path_truncate(struct path *path, loff_t length, + unsigned int time_attrs, struct file *filp); +int security_path_uselib(struct nameidata *nd); +int security_path_symlink(struct path *dir, struct dentry *dentry, + const char *old_name); +int security_path_link(struct path *old_path, struct path *new_dir, + struct dentry *new_dentry); +int security_path_rename(struct path *old_dir, struct dentry *old_dentry, + struct path *new_dir, struct dentry *new_dentry); +int security_path_open(struct dentry *dentry, struct vfsmount *mnt, int flags); + int security_inode_alloc(struct inode *inode); void security_inode_free(struct inode *inode); int security_inode_init_security(struct inode *inode, struct inode *dir, @@ -1950,6 +2061,73 @@ static inline int security_sb_parse_opts return 0; } +static inline int security_path_create(struct inode *dir, struct dentry *dentry, + int mode, struct nameidata *nd) +{ + return 0; +} +static inline int security_path_unlink(struct path *dir, struct dentry *dentry) +{ + return 0; +} + +static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, + int mode) +{ + return 0; +} + +static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) +{ + return 0; +} + +static inline int security_path_mknod(struct path *dir, struct dentry *dentry, + int mode, unsigned int dev) +{ + return 0; +} + +static inline int security_path_truncate(struct path *path, loff_t length, + unsigned int time_attrs, + struct file *filp) +{ + return 0; +} + +static inline int security_path_uselib(struct nameidata *nd) +{ + return 0; +} + +static inline int security_path_symlink(struct path *dir, struct dentry *dentry, + const char *old_name) +{ + return 0; +} + +static inline int security_path_link(struct path *old_path, + struct path *new_dir, + struct dentry *new_dentry) +{ + return 0; +} + +static inline int security_path_rename(struct path *old_dir, + struct dentry *old_dentry, + struct path *new_dir, + struct dentry *new_dentry) +{ + return 0; +} + +static inline int security_path_open(struct dentry *dentry, + struct vfsmount *mnt, + int flags) +{ + return 0; +} + static inline int security_inode_alloc (struct inode *inode) { return 0; --- mm.orig/net/unix/af_unix.c +++ mm/net/unix/af_unix.c @@ -822,7 +822,11 @@ static int unix_bind(struct socket *sock err = mnt_want_write(nd.path.mnt); if (err) goto out_mknod_dput; + err = security_path_mknod(&nd.path, dentry, mode, 0); + if (err) + goto out_drop_write; err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); +out_drop_write: mnt_drop_write(nd.path.mnt); if (err) goto out_mknod_dput; --- mm.orig/security/dummy.c +++ mm/security/dummy.c @@ -270,6 +270,68 @@ static int dummy_sb_parse_opts_str(char return 0; } +static int dummy_path_create(struct inode *inode, struct dentry *dentry, + int mask, struct nameidata *nd) +{ + return 0; +} + +static int dummy_path_mknod(struct path *dir, struct dentry *dentry, int mode, + unsigned int dev) +{ + return 0; +} + +static int dummy_path_mkdir(struct path *dir, struct dentry *dentry, int mode) +{ + return 0; +} + +static int dummy_path_rmdir(struct path *dir, struct dentry *dentry) +{ + return 0; +} + +static int dummy_path_unlink(struct path *dir, struct dentry *dentry) +{ + return 0; +} + +static int dummy_path_symlink(struct path *dir, struct dentry *dentry, + const char *old_name) +{ + return 0; +} + +static int dummy_path_link(struct path *old_path, struct path *new_dir, + struct dentry *new_dentry) +{ + return 0; +} + +static int dummy_path_rename(struct path *old_path, struct dentry *old_dentry, + struct path *new_path, struct dentry *new_dentry) +{ + return 0; +} + +static int dummy_path_open(struct dentry *dentry, struct vfsmount *mnt, + int flags) +{ + return 0; +} + +static int dummy_path_truncate(struct path *path, loff_t length, + unsigned int time_attrs, struct file *filp) +{ + return 0; +} + +static int dummy_path_uselib(struct nameidata *nd) +{ + return 0; +} + static int dummy_inode_alloc_security (struct inode *inode) { return 0; @@ -1079,6 +1141,17 @@ void security_fixup_ops (struct security set_to_dummy_if_null(ops, sb_set_mnt_opts); set_to_dummy_if_null(ops, sb_clone_mnt_opts); set_to_dummy_if_null(ops, sb_parse_opts_str); + set_to_dummy_if_null(ops, path_create); + set_to_dummy_if_null(ops, path_mknod); + set_to_dummy_if_null(ops, path_mkdir); + set_to_dummy_if_null(ops, path_rmdir); + set_to_dummy_if_null(ops, path_unlink); + set_to_dummy_if_null(ops, path_symlink); + set_to_dummy_if_null(ops, path_link); + set_to_dummy_if_null(ops, path_rename); + set_to_dummy_if_null(ops, path_open); + set_to_dummy_if_null(ops, path_truncate); + set_to_dummy_if_null(ops, path_uselib); set_to_dummy_if_null(ops, inode_alloc_security); set_to_dummy_if_null(ops, inode_free_security); set_to_dummy_if_null(ops, inode_init_security); --- mm.orig/security/security.c +++ mm/security/security.c @@ -388,6 +388,69 @@ int security_inode_init_security(struct } EXPORT_SYMBOL(security_inode_init_security); +int security_path_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + if (unlikely(IS_PRIVATE(dir))) + return 0; + return security_ops->path_create(dir, dentry, mode, nd); +} +int security_path_mknod(struct path *path, struct dentry *dentry, int mode, + unsigned int dev) +{ + return security_ops->path_mknod(path, dentry, mode, dev); +} + +int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) +{ + return security_ops->path_mkdir(path, dentry, mode); +} + +int security_path_rmdir(struct path *path, struct dentry *dentry) +{ + return security_ops->path_rmdir(path, dentry); +} + +int security_path_unlink(struct path *path, struct dentry *dentry) +{ + return security_ops->path_unlink(path, dentry); +} + +int security_path_symlink(struct path *path, struct dentry *dentry, + const char *old_name) +{ + return security_ops->path_symlink(path, dentry, old_name); +} + +int security_path_link(struct path *old_path, struct path *new_dir, + struct dentry *new_dentry) +{ + return security_ops->path_link(old_path, new_dir, new_dentry); +} + +int security_path_rename(struct path *old_dir, struct dentry *old_dentry, + struct path *new_dir, struct dentry *new_dentry) +{ + return security_ops->path_rename(old_dir, old_dentry, new_dir, + new_dentry); +} + +int security_path_open(struct dentry *dentry, struct vfsmount *mnt, int flags) +{ + return security_ops->path_open(dentry, mnt, flags); +} + +int security_path_truncate(struct path *path, loff_t length, + unsigned int time_attrs, struct file *filp) +{ + return security_ops->path_truncate(path, length, time_attrs, filp); +} + +int security_path_uselib(struct nameidata *nd) +{ + return security_ops->path_uselib(nd); +} + int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) { if (unlikely(IS_PRIVATE(dir))) -- -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html