diff options
Diffstat (limited to 'fs/proc/base.c')
| -rw-r--r-- | fs/proc/base.c | 93 | 
1 files changed, 85 insertions, 8 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 57b8159f26f..d2d3108a611 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> @@ -1561,8 +1562,8 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)  	generic_fillattr(inode, stat);  	rcu_read_lock(); -	stat->uid = 0; -	stat->gid = 0; +	stat->uid = GLOBAL_ROOT_UID; +	stat->gid = GLOBAL_ROOT_GID;  	task = pid_task(proc_pid(inode), PIDTYPE_PID);  	if (task) {  		if (!has_pid_permissions(pid, task, 2)) { @@ -1622,8 +1623,8 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd)  			inode->i_gid = cred->egid;  			rcu_read_unlock();  		} else { -			inode->i_uid = 0; -			inode->i_gid = 0; +			inode->i_uid = GLOBAL_ROOT_UID; +			inode->i_gid = GLOBAL_ROOT_GID;  		}  		inode->i_mode &= ~(S_ISUID | S_ISGID);  		security_task_to_inode(task, inode); @@ -1815,8 +1816,8 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)  					inode->i_gid = cred->egid;  					rcu_read_unlock();  				} else { -					inode->i_uid = 0; -					inode->i_gid = 0; +					inode->i_uid = GLOBAL_ROOT_UID; +					inode->i_gid = GLOBAL_ROOT_GID;  				}  				i_mode = S_IFLNK; @@ -2045,8 +2046,8 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)  			inode->i_gid = cred->egid;  			rcu_read_unlock();  		} else { -			inode->i_uid = 0; -			inode->i_gid = 0; +			inode->i_uid = GLOBAL_ROOT_UID; +			inode->i_gid = GLOBAL_ROOT_GID;  		}  		security_task_to_inode(task, inode);  		status = 1; @@ -2924,6 +2925,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)  { @@ -3026,6 +3095,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, @@ -3381,6 +3454,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,  |