From: Stephen Smalley This patch changes the security_inode_permission hook to also take a nameidata parameter in addition to the existing inode and mask parameters. A nameidata is already passed (although sometimes NULL) to fs/namei.c:permission(), and the patch changes exec_permission_lite() to also take a nameidata parameter so that it can pass it along to the security hook. The patch includes corresponding changes to the SELinux module to use the nameidata information when it is available; this allows SELinux to include pathname information in audit messages when a nameidata structure was supplied. fs/namei.c | 9 +++++---- include/linux/security.h | 11 +++++++---- security/dummy.c | 2 +- security/selinux/hooks.c | 7 ++++++- 4 files changed, 19 insertions(+), 10 deletions(-) diff -puN fs/namei.c~security_inode_permission-wants-nameidata fs/namei.c --- 25/fs/namei.c~security_inode_permission-wants-nameidata 2003-09-24 12:10:29.000000000 -0700 +++ 25-akpm/fs/namei.c 2003-09-24 12:10:29.000000000 -0700 @@ -222,7 +222,7 @@ int permission(struct inode * inode,int if (retval) return retval; - return security_inode_permission(inode, mask); + return security_inode_permission(inode, mask, nd); } /* @@ -306,7 +306,8 @@ static struct dentry * cached_lookup(str * short-cut DAC fails, then call permission() to do more * complete permission check. */ -static inline int exec_permission_lite(struct inode *inode) +static inline int exec_permission_lite(struct inode *inode, + struct nameidata *nd) { umode_t mode = inode->i_mode; @@ -329,7 +330,7 @@ static inline int exec_permission_lite(s return -EACCES; ok: - return security_inode_permission(inode, MAY_EXEC); + return security_inode_permission(inode, MAY_EXEC, nd); } /* @@ -588,7 +589,7 @@ int link_path_walk(const char * name, st struct qstr this; unsigned int c; - err = exec_permission_lite(inode); + err = exec_permission_lite(inode, nd); if (err == -EAGAIN) { err = permission(inode, MAY_EXEC, nd); } diff -puN include/linux/security.h~security_inode_permission-wants-nameidata include/linux/security.h --- 25/include/linux/security.h~security_inode_permission-wants-nameidata 2003-09-24 12:10:29.000000000 -0700 +++ 25-akpm/include/linux/security.h 2003-09-24 12:10:29.000000000 -0700 @@ -334,6 +334,7 @@ struct swap_info_struct; * called when the actual read/write operations are performed. * @inode contains the inode structure to check. * @mask contains the permission mask. + * @nd contains the nameidata (may be NULL). * Return 0 if permission is granted. * @inode_setattr: * Check permission before setting file attributes. Note that the kernel @@ -1055,7 +1056,7 @@ struct security_operations { struct dentry *new_dentry); int (*inode_readlink) (struct dentry *dentry); int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); - int (*inode_permission) (struct inode *inode, int mask); + int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd); int (*inode_setattr) (struct dentry *dentry, struct iattr *attr); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); void (*inode_delete) (struct inode *inode); @@ -1474,9 +1475,10 @@ static inline int security_inode_follow_ return security_ops->inode_follow_link (dentry, nd); } -static inline int security_inode_permission (struct inode *inode, int mask) +static inline int security_inode_permission (struct inode *inode, int mask, + struct nameidata *nd) { - return security_ops->inode_permission (inode, mask); + return security_ops->inode_permission (inode, mask, nd); } static inline int security_inode_setattr (struct dentry *dentry, @@ -2110,7 +2112,8 @@ static inline int security_inode_follow_ return 0; } -static inline int security_inode_permission (struct inode *inode, int mask) +static inline int security_inode_permission (struct inode *inode, int mask, + struct nameidata *nd) { return 0; } diff -puN security/dummy.c~security_inode_permission-wants-nameidata security/dummy.c --- 25/security/dummy.c~security_inode_permission-wants-nameidata 2003-09-24 12:10:29.000000000 -0700 +++ 25-akpm/security/dummy.c 2003-09-24 12:10:29.000000000 -0700 @@ -364,7 +364,7 @@ static int dummy_inode_follow_link (stru return 0; } -static int dummy_inode_permission (struct inode *inode, int mask) +static int dummy_inode_permission (struct inode *inode, int mask, struct nameidata *nd) { return 0; } diff -puN security/selinux/hooks.c~security_inode_permission-wants-nameidata security/selinux/hooks.c --- 25/security/selinux/hooks.c~security_inode_permission-wants-nameidata 2003-09-24 12:10:29.000000000 -0700 +++ 25-akpm/security/selinux/hooks.c 2003-09-24 12:10:29.000000000 -0700 @@ -1730,13 +1730,18 @@ static int selinux_inode_follow_link(str return dentry_has_perm(current, NULL, dentry, FILE__READ); } -static int selinux_inode_permission(struct inode *inode, int mask) +static int selinux_inode_permission(struct inode *inode, int mask, + struct nameidata *nd) { if (!mask) { /* No permission to check. Existence test. */ return 0; } + if (nd && nd->dentry) + return dentry_has_perm(current, nd->mnt, nd->dentry, + file_mask_to_av(inode->i_mode, mask)); + return inode_has_perm(current, inode, file_mask_to_av(inode->i_mode, mask), NULL, NULL); } _