diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/proc/base.c | 77 | 
1 files changed, 77 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1c8b280146d..2ee514c7e64 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -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,  |