diff options
Diffstat (limited to 'fs/proc/base.c')
| -rw-r--r-- | fs/proc/base.c | 30 | 
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index e42bbd843ed..623e2ffb5d2 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1095,8 +1095,12 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,  	if (!capable(CAP_AUDIT_CONTROL))  		return -EPERM; -	if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) +	rcu_read_lock(); +	if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) { +		rcu_read_unlock();  		return -EPERM; +	} +	rcu_read_unlock();  	if (count >= PAGE_SIZE)  		count = PAGE_SIZE - 1; @@ -2369,16 +2373,30 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)  {  	struct pid_namespace *ns = dentry->d_sb->s_fs_info;  	pid_t tgid = task_tgid_nr_ns(current, ns); -	char tmp[PROC_NUMBUF]; -	if (!tgid) -		return ERR_PTR(-ENOENT); -	sprintf(tmp, "%d", task_tgid_nr_ns(current, ns)); -	return ERR_PTR(vfs_follow_link(nd,tmp)); +	char *name = ERR_PTR(-ENOENT); +	if (tgid) { +		name = __getname(); +		if (!name) +			name = ERR_PTR(-ENOMEM); +		else +			sprintf(name, "%d", tgid); +	} +	nd_set_link(nd, name); +	return NULL; +} + +static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd, +				void *cookie) +{ +	char *s = nd_get_link(nd); +	if (!IS_ERR(s)) +		__putname(s);  }  static const struct inode_operations proc_self_inode_operations = {  	.readlink	= proc_self_readlink,  	.follow_link	= proc_self_follow_link, +	.put_link	= proc_self_put_link,  };  /*  |