|
@@ -315,31 +315,22 @@ static inline int do_inode_permission(struct inode *inode, int mask)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 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, ...)
|
|
|
+ * __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)
|
|
|
*
|
|
|
- * Used to check for read/write/execute permissions on an inode.
|
|
|
- * We use "fsuid" for this, letting us set arbitrary permissions
|
|
|
- * for filesystem access without changing the "normal" uids which
|
|
|
- * are used for other things.
|
|
|
+ * Check for read/write/execute permissions on an inode.
|
|
|
*
|
|
|
* When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
|
|
|
+ *
|
|
|
+ * This does not check for a read-only file system. You probably want
|
|
|
+ * inode_permission().
|
|
|
*/
|
|
|
-int 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;
|
|
|
-
|
|
|
- /*
|
|
|
- * Nobody gets write access to a read-only fs.
|
|
|
- */
|
|
|
- if (IS_RDONLY(inode) &&
|
|
|
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
|
|
|
- return -EROFS;
|
|
|
-
|
|
|
/*
|
|
|
* Nobody gets write access to an immutable file.
|
|
|
*/
|
|
@@ -358,6 +349,47 @@ int inode_permission(struct inode *inode, int mask)
|
|
|
return security_inode_permission(inode, mask);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * sb_permission - Check superblock-level permissions
|
|
|
+ * @sb: Superblock of inode to check permission on
|
|
|
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
|
|
|
+ *
|
|
|
+ * Separate out file-system wide checks from inode-specific permission checks.
|
|
|
+ */
|
|
|
+static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
|
|
|
+{
|
|
|
+ if (unlikely(mask & MAY_WRITE)) {
|
|
|
+ umode_t mode = inode->i_mode;
|
|
|
+
|
|
|
+ /* Nobody gets write access to a read-only fs. */
|
|
|
+ if ((sb->s_flags & MS_RDONLY) &&
|
|
|
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
|
|
|
+ return -EROFS;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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)
|
|
|
+ *
|
|
|
+ * Check for read/write/execute permissions on an inode. We use fs[ug]id for
|
|
|
+ * this, letting us set arbitrary permissions for filesystem access without
|
|
|
+ * changing the "normal" UIDs which are used for other things.
|
|
|
+ *
|
|
|
+ * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
|
|
|
+ */
|
|
|
+int inode_permission(struct inode *inode, int mask)
|
|
|
+{
|
|
|
+ int retval;
|
|
|
+
|
|
|
+ retval = sb_permission(inode->i_sb, inode, mask);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+ return __inode_permission(inode, mask);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* path_get - get a reference to a path
|
|
|
* @path: path to get the reference to
|