userns: Rework the user_namespace adding uid/gid mapping support
[deliverable/linux.git] / fs / proc / base.c
index 1c8b280146d7a0956dddd1f06e431f49671bd269..2ee514c7e64a7a601e756116d4dd541c7bc778bb 100644 (file)
@@ -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>
@@ -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)
 {
@@ -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,
@@ -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,
This page took 0.153887 seconds and 5 git commands to generate.