|
|
|
|
@@ -24,6 +24,7 @@
|
|
|
|
|
#include <linux/fs_struct.h>
|
|
|
|
|
|
|
|
|
|
static struct kmem_cache *user_ns_cachep __read_mostly;
|
|
|
|
|
static DEFINE_MUTEX(userns_state_mutex);
|
|
|
|
|
|
|
|
|
|
static bool new_idmap_permitted(const struct file *file,
|
|
|
|
|
struct user_namespace *ns, int cap_setid,
|
|
|
|
|
@@ -99,6 +100,11 @@ int create_user_ns(struct cred *new)
|
|
|
|
|
ns->owner = owner;
|
|
|
|
|
ns->group = group;
|
|
|
|
|
|
|
|
|
|
/* Inherit USERNS_SETGROUPS_ALLOWED from our parent */
|
|
|
|
|
mutex_lock(&userns_state_mutex);
|
|
|
|
|
ns->flags = parent_ns->flags;
|
|
|
|
|
mutex_unlock(&userns_state_mutex);
|
|
|
|
|
|
|
|
|
|
set_cred_user_ns(new, ns);
|
|
|
|
|
|
|
|
|
|
update_mnt_policy(ns);
|
|
|
|
|
@@ -577,9 +583,6 @@ static bool mappings_overlap(struct uid_gid_map *new_map, struct uid_gid_extent
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DEFINE_MUTEX(id_map_mutex);
|
|
|
|
|
|
|
|
|
|
static ssize_t map_write(struct file *file, const char __user *buf,
|
|
|
|
|
size_t count, loff_t *ppos,
|
|
|
|
|
int cap_setid,
|
|
|
|
|
@@ -596,7 +599,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
|
|
|
|
ssize_t ret = -EINVAL;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The id_map_mutex serializes all writes to any given map.
|
|
|
|
|
* The userns_state_mutex serializes all writes to any given map.
|
|
|
|
|
*
|
|
|
|
|
* Any map is only ever written once.
|
|
|
|
|
*
|
|
|
|
|
@@ -614,7 +617,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
|
|
|
|
* order and smp_rmb() is guaranteed that we don't have crazy
|
|
|
|
|
* architectures returning stale data.
|
|
|
|
|
*/
|
|
|
|
|
mutex_lock(&id_map_mutex);
|
|
|
|
|
mutex_lock(&userns_state_mutex);
|
|
|
|
|
|
|
|
|
|
ret = -EPERM;
|
|
|
|
|
/* Only allow one successful write to the map */
|
|
|
|
|
@@ -741,7 +744,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
|
|
|
|
*ppos = count;
|
|
|
|
|
ret = count;
|
|
|
|
|
out:
|
|
|
|
|
mutex_unlock(&id_map_mutex);
|
|
|
|
|
mutex_unlock(&userns_state_mutex);
|
|
|
|
|
if (page)
|
|
|
|
|
free_page(page);
|
|
|
|
|
return ret;
|
|
|
|
|
@@ -800,17 +803,21 @@ static bool new_idmap_permitted(const struct file *file,
|
|
|
|
|
struct user_namespace *ns, int cap_setid,
|
|
|
|
|
struct uid_gid_map *new_map)
|
|
|
|
|
{
|
|
|
|
|
/* Allow mapping to your own filesystem ids */
|
|
|
|
|
if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) {
|
|
|
|
|
const struct cred *cred = file->f_cred;
|
|
|
|
|
/* Don't allow mappings that would allow anything that wouldn't
|
|
|
|
|
* be allowed without the establishment of unprivileged mappings.
|
|
|
|
|
*/
|
|
|
|
|
if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1) &&
|
|
|
|
|
uid_eq(ns->owner, cred->euid)) {
|
|
|
|
|
u32 id = new_map->extent[0].lower_first;
|
|
|
|
|
if (cap_setid == CAP_SETUID) {
|
|
|
|
|
kuid_t uid = make_kuid(ns->parent, id);
|
|
|
|
|
if (uid_eq(uid, file->f_cred->fsuid))
|
|
|
|
|
if (uid_eq(uid, cred->euid))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (cap_setid == CAP_SETGID) {
|
|
|
|
|
} else if (cap_setid == CAP_SETGID) {
|
|
|
|
|
kgid_t gid = make_kgid(ns->parent, id);
|
|
|
|
|
if (gid_eq(gid, file->f_cred->fsgid))
|
|
|
|
|
if (!(ns->flags & USERNS_SETGROUPS_ALLOWED) &&
|
|
|
|
|
gid_eq(gid, cred->egid))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -830,6 +837,100 @@ static bool new_idmap_permitted(const struct file *file,
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int proc_setgroups_show(struct seq_file *seq, void *v)
|
|
|
|
|
{
|
|
|
|
|
struct user_namespace *ns = seq->private;
|
|
|
|
|
unsigned long userns_flags = ACCESS_ONCE(ns->flags);
|
|
|
|
|
|
|
|
|
|
seq_printf(seq, "%s\n",
|
|
|
|
|
(userns_flags & USERNS_SETGROUPS_ALLOWED) ?
|
|
|
|
|
"allow" : "deny");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssize_t proc_setgroups_write(struct file *file, const char __user *buf,
|
|
|
|
|
size_t count, loff_t *ppos)
|
|
|
|
|
{
|
|
|
|
|
struct seq_file *seq = file->private_data;
|
|
|
|
|
struct user_namespace *ns = seq->private;
|
|
|
|
|
char kbuf[8], *pos;
|
|
|
|
|
bool setgroups_allowed;
|
|
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
|
|
/* Only allow a very narrow range of strings to be written */
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
if ((*ppos != 0) || (count >= sizeof(kbuf)))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
/* What was written? */
|
|
|
|
|
ret = -EFAULT;
|
|
|
|
|
if (copy_from_user(kbuf, buf, count))
|
|
|
|
|
goto out;
|
|
|
|
|
kbuf[count] = '\0';
|
|
|
|
|
pos = kbuf;
|
|
|
|
|
|
|
|
|
|
/* What is being requested? */
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
if (strncmp(pos, "allow", 5) == 0) {
|
|
|
|
|
pos += 5;
|
|
|
|
|
setgroups_allowed = true;
|
|
|
|
|
}
|
|
|
|
|
else if (strncmp(pos, "deny", 4) == 0) {
|
|
|
|
|
pos += 4;
|
|
|
|
|
setgroups_allowed = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
/* Verify there is not trailing junk on the line */
|
|
|
|
|
pos = skip_spaces(pos);
|
|
|
|
|
if (*pos != '\0')
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
ret = -EPERM;
|
|
|
|
|
mutex_lock(&userns_state_mutex);
|
|
|
|
|
if (setgroups_allowed) {
|
|
|
|
|
/* Enabling setgroups after setgroups has been disabled
|
|
|
|
|
* is not allowed.
|
|
|
|
|
*/
|
|
|
|
|
if (!(ns->flags & USERNS_SETGROUPS_ALLOWED))
|
|
|
|
|
goto out_unlock;
|
|
|
|
|
} else {
|
|
|
|
|
/* Permanently disabling setgroups after setgroups has
|
|
|
|
|
* been enabled by writing the gid_map is not allowed.
|
|
|
|
|
*/
|
|
|
|
|
if (ns->gid_map.nr_extents != 0)
|
|
|
|
|
goto out_unlock;
|
|
|
|
|
ns->flags &= ~USERNS_SETGROUPS_ALLOWED;
|
|
|
|
|
}
|
|
|
|
|
mutex_unlock(&userns_state_mutex);
|
|
|
|
|
|
|
|
|
|
/* Report a successful write */
|
|
|
|
|
*ppos = count;
|
|
|
|
|
ret = count;
|
|
|
|
|
out:
|
|
|
|
|
return ret;
|
|
|
|
|
out_unlock:
|
|
|
|
|
mutex_unlock(&userns_state_mutex);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool userns_may_setgroups(const struct user_namespace *ns)
|
|
|
|
|
{
|
|
|
|
|
bool allowed;
|
|
|
|
|
|
|
|
|
|
mutex_lock(&userns_state_mutex);
|
|
|
|
|
/* It is not safe to use setgroups until a gid mapping in
|
|
|
|
|
* the user namespace has been established.
|
|
|
|
|
*/
|
|
|
|
|
allowed = ns->gid_map.nr_extents != 0;
|
|
|
|
|
/* Is setgroups allowed? */
|
|
|
|
|
allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED);
|
|
|
|
|
mutex_unlock(&userns_state_mutex);
|
|
|
|
|
|
|
|
|
|
return allowed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *userns_get(struct task_struct *task)
|
|
|
|
|
{
|
|
|
|
|
struct user_namespace *user_ns;
|
|
|
|
|
|