summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2020-12-17 09:42:00 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-04 11:37:52 +0100
commit54b4e5df958c6ec1cb4afe502e045369ab5557f6 (patch)
treecd7d23a49109e2e0533dd47a824a696b44ee3589 /security
parentbf24c51d62d1a59ae8b05e70fe0409cef41729c1 (diff)
capabilities: Don't allow writing ambiguous v3 file capabilities
[ 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>
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index a6c9bb4441d5..b2a656947504 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -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)