@@ -1961,12 +1961,13 @@ EXPORT_SYMBOL(inode_init_owner);
bool inode_owner_or_capable(const struct inode *inode)
{
struct user_namespace *ns;
+ kuid_t i_uid = vfs_shift_i_uid_to_virtual(inode);
- if (uid_eq(current_fsuid(), inode->i_uid))
+ if (uid_eq(current_fsuid(), i_uid))
return true;
ns = current_user_ns();
- if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid))
+ if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, i_uid))
return true;
return false;
}
@@ -289,8 +289,10 @@ static int check_acl(struct inode *inode, int mask)
static int acl_permission_check(struct inode *inode, int mask)
{
unsigned int mode = inode->i_mode;
+ kuid_t i_uid = vfs_shift_i_uid_to_virtual(inode);
+ kgid_t i_gid = vfs_shift_i_gid_to_virtual(inode);
- if (likely(uid_eq(current_fsuid(), inode->i_uid)))
+ if (likely(uid_eq(current_fsuid(), i_uid)))
mode >>= 6;
else {
if (IS_POSIXACL(inode) && (mode & S_IRWXG)) {
@@ -299,7 +301,7 @@ static int acl_permission_check(struct inode *inode, int mask)
return error;
}
- if (in_group_p(inode->i_gid))
+ if (in_group_p(i_gid))
mode >>= 3;
}
@@ -441,9 +441,19 @@ EXPORT_SYMBOL(file_ns_capable);
*/
bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
{
+ kuid_t i_uid;
+ kgid_t i_gid;
struct user_namespace *ns = current_user_ns();
- return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) &&
- kgid_has_mapping(ns, inode->i_gid);
+ /*
+ * Check if inode's UID/GID are mean to be shifted into the current
+ * mount namespace, if so we use the result to check if the shifted
+ * UID/GID have a mapping in current's user namespace.
+ */
+ i_uid = vfs_shift_i_uid_to_virtual(inode);
+ i_gid = vfs_shift_i_gid_to_virtual(inode);
+
+ return ns_capable(ns, cap) && kuid_has_mapping(ns, i_uid) &&
+ kgid_has_mapping(ns, i_gid);
}
EXPORT_SYMBOL(capable_wrt_inode_uidgid);