Skip to content

Commit

Permalink
fs: Limit file caps to the user namespace of the super block
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Seth Forshee <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
  • Loading branch information
Seth Forshee authored and ebiederm committed Jun 24, 2016
1 parent cc50a07 commit d07b846
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/linux/user_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 */
14 changes: 14 additions & 0 deletions kernel/user_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions security/commoncap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit d07b846

Please sign in to comment.