aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/fs/namei.c b/fs/namei.c
index c6dcb4c8f86c..1b6474687698 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -315,31 +315,22 @@ static inline int do_inode_permission(struct inode *inode, int mask)
315} 315}
316 316
317/** 317/**
318 * inode_permission - check for access rights to a given inode 318 * __inode_permission - Check for access rights to a given inode
319 * @inode: inode to check permission on 319 * @inode: Inode to check permission on
320 * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...) 320 * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
321 * 321 *
322 * Used to check for read/write/execute permissions on an inode. 322 * Check for read/write/execute permissions on an inode.
323 * We use "fsuid" for this, letting us set arbitrary permissions
324 * for filesystem access without changing the "normal" uids which
325 * are used for other things.
326 * 323 *
327 * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. 324 * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
325 *
326 * This does not check for a read-only file system. You probably want
327 * inode_permission().
328 */ 328 */
329int inode_permission(struct inode *inode, int mask) 329int __inode_permission(struct inode *inode, int mask)
330{ 330{
331 int retval; 331 int retval;
332 332
333 if (unlikely(mask & MAY_WRITE)) { 333 if (unlikely(mask & MAY_WRITE)) {
334 umode_t mode = inode->i_mode;
335
336 /*
337 * Nobody gets write access to a read-only fs.
338 */
339 if (IS_RDONLY(inode) &&
340 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
341 return -EROFS;
342
343 /* 334 /*
344 * Nobody gets write access to an immutable file. 335 * Nobody gets write access to an immutable file.
345 */ 336 */
@@ -359,6 +350,47 @@ int inode_permission(struct inode *inode, int mask)
359} 350}
360 351
361/** 352/**
353 * sb_permission - Check superblock-level permissions
354 * @sb: Superblock of inode to check permission on
355 * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
356 *
357 * Separate out file-system wide checks from inode-specific permission checks.
358 */
359static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
360{
361 if (unlikely(mask & MAY_WRITE)) {
362 umode_t mode = inode->i_mode;
363
364 /* Nobody gets write access to a read-only fs. */
365 if ((sb->s_flags & MS_RDONLY) &&
366 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
367 return -EROFS;
368 }
369 return 0;
370}
371
372/**
373 * inode_permission - Check for access rights to a given inode
374 * @inode: Inode to check permission on
375 * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
376 *
377 * Check for read/write/execute permissions on an inode. We use fs[ug]id for
378 * this, letting us set arbitrary permissions for filesystem access without
379 * changing the "normal" UIDs which are used for other things.
380 *
381 * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
382 */
383int inode_permission(struct inode *inode, int mask)
384{
385 int retval;
386
387 retval = sb_permission(inode->i_sb, inode, mask);
388 if (retval)
389 return retval;
390 return __inode_permission(inode, mask);
391}
392
393/**
362 * path_get - get a reference to a path 394 * path_get - get a reference to a path
363 * @path: path to get the reference to 395 * @path: path to get the reference to
364 * 396 *