mirror of https://gitee.com/openkylin/linux.git
fix execute checking in permission()
permission() checks that MAY_EXEC is only allowed on regular files if at least one execute bit is set in the file mode. generic_permission() already ensures this, so the extra check in permission() is superfluous. If the filesystem defines it's own ->permission() the check may still be needed. In this case move it after ->permission(). This is needed because filesystems such as FUSE may need to refresh the inode attributes before checking permissions. This check should be moved inside ->permission(), but that's another story. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
043f46f615
commit
22590e41cb
36
fs/namei.c
36
fs/namei.c
|
@ -227,10 +227,10 @@ int generic_permission(struct inode *inode, int mask,
|
|||
|
||||
int permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
{
|
||||
umode_t mode = inode->i_mode;
|
||||
int retval, submask;
|
||||
|
||||
if (mask & MAY_WRITE) {
|
||||
umode_t mode = inode->i_mode;
|
||||
|
||||
/*
|
||||
* Nobody gets write access to a read-only fs.
|
||||
|
@ -246,22 +246,34 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MAY_EXEC on regular files requires special handling: We override
|
||||
* filesystem execute permissions if the mode bits aren't set or
|
||||
* the fs is mounted with the "noexec" flag.
|
||||
*/
|
||||
if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
|
||||
(nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
|
||||
return -EACCES;
|
||||
if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
|
||||
/*
|
||||
* MAY_EXEC on regular files is denied if the fs is mounted
|
||||
* with the "noexec" flag.
|
||||
*/
|
||||
if (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* Ordinary permission routines do not understand MAY_APPEND. */
|
||||
submask = mask & ~MAY_APPEND;
|
||||
if (inode->i_op && inode->i_op->permission)
|
||||
if (inode->i_op && inode->i_op->permission) {
|
||||
retval = inode->i_op->permission(inode, submask, nd);
|
||||
else
|
||||
if (!retval) {
|
||||
/*
|
||||
* Exec permission on a regular file is denied if none
|
||||
* of the execute bits are set.
|
||||
*
|
||||
* This check should be done by the ->permission()
|
||||
* method.
|
||||
*/
|
||||
if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
|
||||
!(inode->i_mode & S_IXUGO))
|
||||
return -EACCES;
|
||||
}
|
||||
} else {
|
||||
retval = generic_permission(inode, submask, NULL);
|
||||
}
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
|
Loading…
Reference in New Issue