]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
capabilities: Don't allow writing ambiguous v3 file capabilities
authorEric W. Biederman <ebiederm@xmission.com>
Thu, 17 Dec 2020 15:42:00 +0000 (09:42 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Mar 2021 09:26:26 +0000 (10:26 +0100)
[ Upstream commit 95ebabde382c371572297915b104e55403674e73 ]

The v3 file capabilities have a uid field that records the filesystem
uid of the root user of the user namespace the file capabilities are
valid in.

When someone is silly enough to have the same underlying uid as the
root uid of multiple nested containers a v3 filesystem capability can
be ambiguous.

In the spirit of don't do that then, forbid writing a v3 filesystem
capability if it is ambiguous.

Fixes: 8db6c34f1dbc ("Introduce v3 namespaced file capabilities")
Reviewed-by: Andrew G. Morgan <morgan@kernel.org>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
security/commoncap.c

index 28a6939bcc4e55ee0f970978b54b51d63f4a13d2..ed89a6dd4f83dad7784b06722bfa205d8b9af72e 100644 (file)
@@ -500,7 +500,8 @@ int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size)
        __u32 magic, nsmagic;
        struct inode *inode = d_backing_inode(dentry);
        struct user_namespace *task_ns = current_user_ns(),
-               *fs_ns = inode->i_sb->s_user_ns;
+               *fs_ns = inode->i_sb->s_user_ns,
+               *ancestor;
        kuid_t rootid;
        size_t newsize;
 
@@ -523,6 +524,15 @@ int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size)
        if (nsrootid == -1)
                return -EINVAL;
 
+       /*
+        * Do not allow allow adding a v3 filesystem capability xattr
+        * if the rootid field is ambiguous.
+        */
+       for (ancestor = task_ns->parent; ancestor; ancestor = ancestor->parent) {
+               if (from_kuid(ancestor, rootid) == 0)
+                       return -EINVAL;
+       }
+
        newsize = sizeof(struct vfs_ns_cap_data);
        nscap = kmalloc(newsize, GFP_ATOMIC);
        if (!nscap)