aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c48
-rw-r--r--include/linux/fs.h1
2 files changed, 32 insertions, 17 deletions
diff --git a/fs/namei.c b/fs/namei.c
index f09edf3eeef..caf090c4862 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -315,6 +315,36 @@ static inline int do_inode_permission(struct inode *inode, int mask)
}
/**
+ * inode_only_permission - check access rights to a given inode only
+ * @inode: inode to check permissions on
+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
+ *
+ * Uses to check read/write/execute permissions on an inode directly, we do
+ * not check filesystem permissions.
+ */
+int inode_only_permission(struct inode *inode, int mask)
+{
+ int retval;
+
+ /*
+ * Nobody gets write access to an immutable file.
+ */
+ if (unlikely(mask & MAY_WRITE) && IS_IMMUTABLE(inode))
+ return -EACCES;
+
+ retval = do_inode_permission(inode, mask);
+ if (retval)
+ return retval;
+
+ retval = devcgroup_inode_permission(inode, mask);
+ if (retval)
+ return retval;
+
+ return security_inode_permission(inode, mask);
+}
+EXPORT_SYMBOL(inode_only_permission);
+
+/**
* inode_permission - check for access rights to a given inode
* @inode: inode to check permission on
* @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
@@ -328,8 +358,6 @@ static inline int do_inode_permission(struct inode *inode, int mask)
*/
int inode_permission(struct inode *inode, int mask)
{
- int retval;
-
if (unlikely(mask & MAY_WRITE)) {
umode_t mode = inode->i_mode;
@@ -339,23 +367,9 @@ int inode_permission(struct inode *inode, int mask)
if (IS_RDONLY(inode) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
-
- /*
- * Nobody gets write access to an immutable file.
- */
- if (IS_IMMUTABLE(inode))
- return -EACCES;
}
- retval = do_inode_permission(inode, mask);
- if (retval)
- return retval;
-
- retval = devcgroup_inode_permission(inode, mask);
- if (retval)
- return retval;
-
- return security_inode_permission(inode, mask);
+ return inode_only_permission(inode, mask);
}
/**
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 49b86cf0564..e99bb48293d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2263,6 +2263,7 @@ extern sector_t bmap(struct inode *, sector_t);
#endif
extern int notify_change(struct dentry *, struct iattr *);
extern int inode_permission(struct inode *, int);
+extern int inode_only_permission(struct inode *, int);
extern int generic_permission(struct inode *, int);
static inline bool execute_ok(struct inode *inode)