Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22590e41 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds
Browse files

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: default avatarMiklos Szeredi <mszeredi@suse.cz>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 043f46f6
Loading
Loading
Loading
Loading
+24 −12
Original line number Diff line number Diff line
@@ -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;
	}


	if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
		/*
	 * 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.
		 * MAY_EXEC on regular files is denied if 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))))
		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;