Commit d5f1f9dd authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Pass nameidata to security_inode_permission hook

From: Stephen Smalley <sds@epoch.ncsc.mil>

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.
parent 4dfbe983
...@@ -219,7 +219,7 @@ int permission(struct inode * inode,int mask, struct nameidata *nd) ...@@ -219,7 +219,7 @@ int permission(struct inode * inode,int mask, struct nameidata *nd)
if (retval) if (retval)
return retval; return retval;
return security_inode_permission(inode, mask); return security_inode_permission(inode, mask, nd);
} }
/* /*
...@@ -303,7 +303,8 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, ...@@ -303,7 +303,8 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
* short-cut DAC fails, then call permission() to do more * short-cut DAC fails, then call permission() to do more
* complete permission check. * 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; umode_t mode = inode->i_mode;
...@@ -326,7 +327,7 @@ static inline int exec_permission_lite(struct inode *inode) ...@@ -326,7 +327,7 @@ static inline int exec_permission_lite(struct inode *inode)
return -EACCES; return -EACCES;
ok: ok:
return security_inode_permission(inode, MAY_EXEC); return security_inode_permission(inode, MAY_EXEC, nd);
} }
/* /*
...@@ -585,7 +586,7 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -585,7 +586,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
struct qstr this; struct qstr this;
unsigned int c; unsigned int c;
err = exec_permission_lite(inode); err = exec_permission_lite(inode, nd);
if (err == -EAGAIN) { if (err == -EAGAIN) {
err = permission(inode, MAY_EXEC, nd); err = permission(inode, MAY_EXEC, nd);
} }
......
...@@ -334,6 +334,7 @@ struct swap_info_struct; ...@@ -334,6 +334,7 @@ struct swap_info_struct;
* called when the actual read/write operations are performed. * called when the actual read/write operations are performed.
* @inode contains the inode structure to check. * @inode contains the inode structure to check.
* @mask contains the permission mask. * @mask contains the permission mask.
* @nd contains the nameidata (may be NULL).
* Return 0 if permission is granted. * Return 0 if permission is granted.
* @inode_setattr: * @inode_setattr:
* Check permission before setting file attributes. Note that the kernel * Check permission before setting file attributes. Note that the kernel
...@@ -1055,7 +1056,7 @@ struct security_operations { ...@@ -1055,7 +1056,7 @@ struct security_operations {
struct dentry *new_dentry); struct dentry *new_dentry);
int (*inode_readlink) (struct dentry *dentry); int (*inode_readlink) (struct dentry *dentry);
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); 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_setattr) (struct dentry *dentry, struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_delete) (struct inode *inode); void (*inode_delete) (struct inode *inode);
...@@ -1474,9 +1475,10 @@ static inline int security_inode_follow_link (struct dentry *dentry, ...@@ -1474,9 +1475,10 @@ static inline int security_inode_follow_link (struct dentry *dentry,
return security_ops->inode_follow_link (dentry, nd); 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, static inline int security_inode_setattr (struct dentry *dentry,
...@@ -2110,7 +2112,8 @@ static inline int security_inode_follow_link (struct dentry *dentry, ...@@ -2110,7 +2112,8 @@ static inline int security_inode_follow_link (struct dentry *dentry,
return 0; 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; return 0;
} }
......
...@@ -364,7 +364,7 @@ static int dummy_inode_follow_link (struct dentry *dentry, ...@@ -364,7 +364,7 @@ static int dummy_inode_follow_link (struct dentry *dentry,
return 0; 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; return 0;
} }
......
...@@ -1730,13 +1730,18 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na ...@@ -1730,13 +1730,18 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
return dentry_has_perm(current, NULL, dentry, FILE__READ); 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) { if (!mask) {
/* No permission to check. Existence test. */ /* No permission to check. Existence test. */
return 0; 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, return inode_has_perm(current, inode,
file_mask_to_av(inode->i_mode, mask), NULL, NULL); file_mask_to_av(inode->i_mode, mask), NULL, NULL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment