[RFC][PATCH] Pass nameidata to security_inode_permission hook

From: Stephen Smalley (sds@private)
Date: Wed Sep 24 2003 - 09:13:38 PDT

  • Next message: Kristofer Spinka: "Multiple calls to inode_permission"

    This patch against 2.6.0-test5 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.  If anyone has
    any objections to this change, please let me know.
    
     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(-)
    
    Index: linux-2.6/fs/namei.c
    ===================================================================
    RCS file: /nfshome/pal/CVS/linux-2.6/fs/namei.c,v
    retrieving revision 1.13
    diff -u -r1.13 namei.c
    --- linux-2.6/fs/namei.c	25 Aug 2003 15:29:19 -0000	1.13
    +++ linux-2.6/fs/namei.c	24 Sep 2003 14:54:40 -0000
    @@ -218,7 +218,7 @@
     	if (retval)
     		return retval;
     
    -	return security_inode_permission(inode, mask);
    +	return security_inode_permission(inode, mask, nd);
     }
     
     /*
    @@ -302,7 +302,8 @@
      * 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;
     
    @@ -325,7 +326,7 @@
     
     	return -EACCES;
     ok:
    -	return security_inode_permission(inode, MAY_EXEC);
    +	return security_inode_permission(inode, MAY_EXEC, nd);
     }
     
     /*
    @@ -584,7 +585,7 @@
     		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);
     		}
    Index: linux-2.6/include/linux/security.h
    ===================================================================
    RCS file: /nfshome/pal/CVS/linux-2.6/include/linux/security.h,v
    retrieving revision 1.25
    diff -u -r1.25 security.h
    --- linux-2.6/include/linux/security.h	24 Jun 2003 14:55:43 -0000	1.25
    +++ linux-2.6/include/linux/security.h	24 Sep 2003 14:55:17 -0000
    @@ -334,6 +334,7 @@
      *	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 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 @@
     	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 @@
     	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;
     }
    Index: linux-2.6/security/dummy.c
    ===================================================================
    RCS file: /nfshome/pal/CVS/linux-2.6/security/dummy.c,v
    retrieving revision 1.22
    diff -u -r1.22 dummy.c
    --- linux-2.6/security/dummy.c	3 Jul 2003 14:31:12 -0000	1.22
    +++ linux-2.6/security/dummy.c	24 Sep 2003 14:54:40 -0000
    @@ -364,7 +364,7 @@
     	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;
     }
    Index: linux-2.6/security/selinux/hooks.c
    ===================================================================
    RCS file: /nfshome/pal/CVS/linux-2.6/security/selinux/hooks.c,v
    retrieving revision 1.73
    diff -u -r1.73 hooks.c
    --- linux-2.6/security/selinux/hooks.c	4 Sep 2003 18:23:49 -0000	1.73
    +++ linux-2.6/security/selinux/hooks.c	24 Sep 2003 14:54:40 -0000
    @@ -1730,12 +1730,17 @@
     	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);
    
    
    
    -- 
    Stephen Smalley <sds@private>
    National Security Agency
    



    This archive was generated by hypermail 2b30 : Wed Sep 24 2003 - 09:14:52 PDT