[PATCH] Pass nameidata to security_inode_permission (Was: Re: path_post_lookup)

From: Stephen Smalley (sdsat_private)
Date: Mon Sep 08 2003 - 12:31:02 PDT

  • Next message: naradamoonat_private: "Your details"

    This patch against 2.6.0-test4 (or 2.6.0-test4-lsm1) adds the optional
    nameidata parameter to the security_inode_permission hook, and updates
    SELinux to use the nameidata when it is non-NULL.  The patch removes
    exec_permission_lite entirely rather than just updating it to pass the
    nameidata, since there no longer appears to be any reason to keep
    exec_permission_lite separate from permission (due to prior changes to
    the dcache locking).
    
    I considered updating some of the other inode security hooks in
    fs/namei.c as well, but found that this would require more extensive
    changes to update all callers and would change some interfaces that are
    exported to kernel modules, e.g. vfs_mkdir, vfs_mknod, etc.  Changing
    these interfaces would also raise the question of whether the underlying
    inode operations should also be extended to pass the nameidata for these
    operations.  Hence, I thought it best to defer updating the other inode
    security hooks to separate patches.  
    
    Comments?
    
     fs/namei.c               |   43 ++-----------------------------------------
     include/linux/security.h |   10 ++++++----
     security/dummy.c         |    2 +-
     security/selinux/hooks.c |    7 ++++++-
     4 files changed, 15 insertions(+), 47 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	8 Sep 2003 17:58:23 -0000
    @@ -218,7 +218,7 @@
     	if (retval)
     		return retval;
     
    -	return security_inode_permission(inode, mask);
    +	return security_inode_permission(inode, mask, nd);
     }
     
     /*
    @@ -293,42 +293,6 @@
     }
     
     /*
    - * Short-cut version of permission(), for calling by
    - * path_walk(), when dcache lock is held.  Combines parts
    - * of permission() and vfs_permission(), and tests ONLY for
    - * MAY_EXEC permission.
    - *
    - * If appropriate, check DAC only.  If not appropriate, or
    - * short-cut DAC fails, then call permission() to do more
    - * complete permission check.
    - */
    -static inline int exec_permission_lite(struct inode *inode)
    -{
    -	umode_t	mode = inode->i_mode;
    -
    -	if ((inode->i_op && inode->i_op->permission))
    -		return -EAGAIN;
    -
    -	if (current->fsuid == inode->i_uid)
    -		mode >>= 6;
    -	else if (in_group_p(inode->i_gid))
    -		mode >>= 3;
    -
    -	if (mode & MAY_EXEC)
    -		goto ok;
    -
    -	if ((inode->i_mode & S_IXUGO) && capable(CAP_DAC_OVERRIDE))
    -		goto ok;
    -
    -	if (S_ISDIR(inode->i_mode) && capable(CAP_DAC_READ_SEARCH))
    -		goto ok;
    -
    -	return -EACCES;
    -ok:
    -	return security_inode_permission(inode, MAY_EXEC);
    -}
    -
    -/*
      * This is called when everything else fails, and we actually have
      * to go to the low-level filesystem to find out what we should do..
      *
    @@ -584,10 +548,7 @@
     		struct qstr this;
     		unsigned int c;
     
    -		err = exec_permission_lite(inode);
    -		if (err == -EAGAIN) { 
    -			err = permission(inode, MAY_EXEC, nd);
    -		}
    +		err = permission(inode, MAY_EXEC, nd);
      		if (err)
     			break;
     
    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	8 Sep 2003 17:58:23 -0000
    @@ -1055,7 +1055,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 +1474,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 +2111,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	8 Sep 2003 17:58:23 -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	8 Sep 2003 17:58:23 -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 <sdsat_private>
    National Security Agency
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Mon Sep 08 2003 - 20:37:52 PDT