]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
fs: Limit file caps to the user namespace of the super block
authorSeth Forshee <seth.forshee@canonical.com>
Wed, 23 Sep 2015 20:16:04 +0000 (15:16 -0500)
committerEric W. Biederman <ebiederm@xmission.com>
Fri, 24 Jun 2016 15:40:31 +0000 (10:40 -0500)
Capability sets attached to files must be ignored except in the
user namespaces where the mounter is privileged, i.e. s_user_ns
and its descendants. Otherwise a vector exists for gaining
privileges in namespaces where a user is not already privileged.

Add a new helper function, current_in_user_ns(), to test whether a user
namespace is the same as or a descendant of another namespace.
Use this helper to determine whether a file's capability set
should be applied to the caps constructed during exec.

--EWB Replaced in_userns with the simpler current_in_userns.

Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
include/linux/user_namespace.h
kernel/user_namespace.c
security/commoncap.c

index 8297e5b341d863aa627a3b44a70d025bc8bc7c30..9217169c64cb80478420e55546aacda1e900d355 100644 (file)
@@ -72,6 +72,7 @@ extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t,
 extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
 extern int proc_setgroups_show(struct seq_file *m, void *v);
 extern bool userns_may_setgroups(const struct user_namespace *ns);
+extern bool current_in_userns(const struct user_namespace *target_ns);
 #else
 
 static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
@@ -100,6 +101,11 @@ static inline bool userns_may_setgroups(const struct user_namespace *ns)
 {
        return true;
 }
+
+static inline bool current_in_userns(const struct user_namespace *target_ns)
+{
+       return true;
+}
 #endif
 
 #endif /* _LINUX_USER_H */
index 9bafc211930c79fac444a77f6f075a04ccc7f980..68f5942127590e23b86c375369b12a2973f1c6e7 100644 (file)
@@ -938,6 +938,20 @@ bool userns_may_setgroups(const struct user_namespace *ns)
        return allowed;
 }
 
+/*
+ * Returns true if @ns is the same namespace as or a descendant of
+ * @target_ns.
+ */
+bool current_in_userns(const struct user_namespace *target_ns)
+{
+       struct user_namespace *ns;
+       for (ns = current_user_ns(); ns; ns = ns->parent) {
+               if (ns == target_ns)
+                       return true;
+       }
+       return false;
+}
+
 static inline struct user_namespace *to_user_ns(struct ns_common *ns)
 {
        return container_of(ns, struct user_namespace, ns);
index e7fadde737f41cb48aa1e25f6a486375e4d8f597..e109e6dac85870848c593790c6196f70dcaf877d 100644 (file)
@@ -455,6 +455,8 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
 
        if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
                return 0;
+       if (!current_in_userns(bprm->file->f_path.mnt->mnt_sb->s_user_ns))
+               return 0;
 
        rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
        if (rc < 0) {