aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-10-17 02:27:08 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:52 -0400
commit22590e41cb569add194829c08dc0ceea74b38a65 (patch)
tree0db73fe0e78bcde816dcf289e0aa5323abf73833 /fs/namei.c
parent043f46f6151df2c518988b5e41376e42491257b5 (diff)
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>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 7cba63295a82..2792e0ca01d4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -227,10 +227,10 @@ int generic_permission(struct inode *inode, int mask,
227 227
228int permission(struct inode *inode, int mask, struct nameidata *nd) 228int permission(struct inode *inode, int mask, struct nameidata *nd)
229{ 229{
230 umode_t mode = inode->i_mode;
231 int retval, submask; 230 int retval, submask;
232 231
233 if (mask & MAY_WRITE) { 232 if (mask & MAY_WRITE) {
233 umode_t mode = inode->i_mode;
234 234
235 /* 235 /*
236 * Nobody gets write access to a read-only fs. 236 * Nobody gets write access to a read-only fs.
@@ -246,22 +246,34 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
246 return -EACCES; 246 return -EACCES;
247 } 247 }
248 248
249 249 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
250 /* 250 /*
251 * MAY_EXEC on regular files requires special handling: We override 251 * MAY_EXEC on regular files is denied if the fs is mounted
252 * filesystem execute permissions if the mode bits aren't set or 252 * with the "noexec" flag.
253 * the fs is mounted with the "noexec" flag. 253 */
254 */ 254 if (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))
255 if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) || 255 return -EACCES;
256 (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC)))) 256 }
257 return -EACCES;
258 257
259 /* Ordinary permission routines do not understand MAY_APPEND. */ 258 /* Ordinary permission routines do not understand MAY_APPEND. */
260 submask = mask & ~MAY_APPEND; 259 submask = mask & ~MAY_APPEND;
261 if (inode->i_op && inode->i_op->permission) 260 if (inode->i_op && inode->i_op->permission) {
262 retval = inode->i_op->permission(inode, submask, nd); 261 retval = inode->i_op->permission(inode, submask, nd);
263 else 262 if (!retval) {
263 /*
264 * Exec permission on a regular file is denied if none
265 * of the execute bits are set.
266 *
267 * This check should be done by the ->permission()
268 * method.
269 */
270 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
271 !(inode->i_mode & S_IXUGO))
272 return -EACCES;
273 }
274 } else {
264 retval = generic_permission(inode, submask, NULL); 275 retval = generic_permission(inode, submask, NULL);
276 }
265 if (retval) 277 if (retval)
266 return retval; 278 return retval;
267 279