Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305994
b: refs/heads/master
c: 22d917d
h: refs/heads/master
v: v3
  • Loading branch information
Eric W. Biederman committed Apr 26, 2012
1 parent a311fc4 commit a376d32
Show file tree
Hide file tree
Showing 6 changed files with 645 additions and 49 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 783291e6900292521a3895583785e0c04a56c5b3
refs/heads/master: 22d917d80e842829d0ca0a561967d728eb1d6303
77 changes: 77 additions & 0 deletions trunk/fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#include <linux/oom.h>
#include <linux/elf.h>
#include <linux/pid_namespace.h>
#include <linux/user_namespace.h>
#include <linux/fs_struct.h>
#include <linux/slab.h>
#include <linux/flex_array.h>
Expand Down Expand Up @@ -2943,6 +2944,74 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
}
#endif /* CONFIG_TASK_IO_ACCOUNTING */

#ifdef CONFIG_USER_NS
static int proc_id_map_open(struct inode *inode, struct file *file,
struct seq_operations *seq_ops)
{
struct user_namespace *ns = NULL;
struct task_struct *task;
struct seq_file *seq;
int ret = -EINVAL;

task = get_proc_task(inode);
if (task) {
rcu_read_lock();
ns = get_user_ns(task_cred_xxx(task, user_ns));
rcu_read_unlock();
put_task_struct(task);
}
if (!ns)
goto err;

ret = seq_open(file, seq_ops);
if (ret)
goto err_put_ns;

seq = file->private_data;
seq->private = ns;

return 0;
err_put_ns:
put_user_ns(ns);
err:
return ret;
}

static int proc_id_map_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;
struct user_namespace *ns = seq->private;
put_user_ns(ns);
return seq_release(inode, file);
}

static int proc_uid_map_open(struct inode *inode, struct file *file)
{
return proc_id_map_open(inode, file, &proc_uid_seq_operations);
}

static int proc_gid_map_open(struct inode *inode, struct file *file)
{
return proc_id_map_open(inode, file, &proc_gid_seq_operations);
}

static const struct file_operations proc_uid_map_operations = {
.open = proc_uid_map_open,
.write = proc_uid_map_write,
.read = seq_read,
.llseek = seq_lseek,
.release = proc_id_map_release,
};

static const struct file_operations proc_gid_map_operations = {
.open = proc_gid_map_open,
.write = proc_gid_map_write,
.read = seq_read,
.llseek = seq_lseek,
.release = proc_id_map_release,
};
#endif /* CONFIG_USER_NS */

static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
Expand Down Expand Up @@ -3045,6 +3114,10 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_HARDWALL
INF("hardwall", S_IRUGO, proc_pid_hardwall),
#endif
#ifdef CONFIG_USER_NS
REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
#endif
};

static int proc_tgid_base_readdir(struct file * filp,
Expand Down Expand Up @@ -3400,6 +3473,10 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_HARDWALL
INF("hardwall", S_IRUGO, proc_pid_hardwall),
#endif
#ifdef CONFIG_USER_NS
REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
#endif
};

static int proc_tid_base_readdir(struct file * filp,
Expand Down
24 changes: 24 additions & 0 deletions trunk/include/linux/uidgid.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,28 @@ static inline bool gid_valid(kgid_t gid)
return !gid_eq(gid, INVALID_GID);
}

#ifdef CONFIG_USER_NS

extern kuid_t make_kuid(struct user_namespace *from, uid_t uid);
extern kgid_t make_kgid(struct user_namespace *from, gid_t gid);

extern uid_t from_kuid(struct user_namespace *to, kuid_t uid);
extern gid_t from_kgid(struct user_namespace *to, kgid_t gid);
extern uid_t from_kuid_munged(struct user_namespace *to, kuid_t uid);
extern gid_t from_kgid_munged(struct user_namespace *to, kgid_t gid);

static inline bool kuid_has_mapping(struct user_namespace *ns, kuid_t uid)
{
return from_kuid(ns, uid) != (uid_t) -1;
}

static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid)
{
return from_kgid(ns, gid) != (gid_t) -1;
}

#else

static inline kuid_t make_kuid(struct user_namespace *from, uid_t uid)
{
return KUIDT_INIT(uid);
Expand Down Expand Up @@ -173,4 +195,6 @@ static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid)
return true;
}

#endif /* CONFIG_USER_NS */

#endif /* _LINUX_UIDGID_H */
30 changes: 23 additions & 7 deletions trunk/include/linux/user_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@
#include <linux/sched.h>
#include <linux/err.h>

#define UID_GID_MAP_MAX_EXTENTS 5

struct uid_gid_map { /* 64 bytes -- 1 cache line */
u32 nr_extents;
struct uid_gid_extent {
u32 first;
u32 lower_first;
u32 count;
} extent[UID_GID_MAP_MAX_EXTENTS];
};

struct user_namespace {
struct uid_gid_map uid_map;
struct uid_gid_map gid_map;
struct kref kref;
struct user_namespace *parent;
kuid_t owner;
Expand All @@ -33,9 +46,11 @@ static inline void put_user_ns(struct user_namespace *ns)
kref_put(&ns->kref, free_user_ns);
}

uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid);
gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid);

struct seq_operations;
extern struct seq_operations proc_uid_seq_operations;
extern struct seq_operations proc_gid_seq_operations;
extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *);
extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *);
#else

static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
Expand All @@ -52,17 +67,18 @@ static inline void put_user_ns(struct user_namespace *ns)
{
}

#endif

static inline uid_t user_ns_map_uid(struct user_namespace *to,
const struct cred *cred, uid_t uid)
{
return uid;
return from_kuid_munged(to, make_kuid(cred->user_ns, uid));
}

static inline gid_t user_ns_map_gid(struct user_namespace *to,
const struct cred *cred, gid_t gid)
{
return gid;
return from_kgid_munged(to, make_kgid(cred->user_ns, gid));
}

#endif

#endif /* _LINUX_USER_H */
16 changes: 16 additions & 0 deletions trunk/kernel/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@
* and 1 for... ?
*/
struct user_namespace init_user_ns = {
.uid_map = {
.nr_extents = 1,
.extent[0] = {
.first = 0,
.lower_first = 0,
.count = 4294967295,
},
},
.gid_map = {
.nr_extents = 1,
.extent[0] = {
.first = 0,
.lower_first = 0,
.count = 4294967295,
},
},
.kref = {
.refcount = ATOMIC_INIT(3),
},
Expand Down
Loading

0 comments on commit a376d32

Please sign in to comment.