diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 586 | 
1 files changed, 332 insertions, 254 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 31deba8f7d16..ebe65c2c9873 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -112,12 +112,17 @@ EXPORT_SYMBOL(cad_pid);  void (*pm_power_off_prepare)(void); +/* + * set the priority of a task + * - the caller must hold the RCU read lock + */  static int set_one_prio(struct task_struct *p, int niceval, int error)  { +	const struct cred *cred = current_cred(), *pcred = __task_cred(p);  	int no_nice; -	if (p->uid != current->euid && -		p->euid != current->euid && !capable(CAP_SYS_NICE)) { +	if (pcred->uid  != cred->euid && +	    pcred->euid != cred->euid && !capable(CAP_SYS_NICE)) {  		error = -EPERM;  		goto out;  	} @@ -141,6 +146,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)  {  	struct task_struct *g, *p;  	struct user_struct *user; +	const struct cred *cred = current_cred();  	int error = -EINVAL;  	struct pid *pgrp; @@ -174,18 +180,18 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)  			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);  			break;  		case PRIO_USER: -			user = current->user; +			user = (struct user_struct *) cred->user;  			if (!who) -				who = current->uid; -			else -				if ((who != current->uid) && !(user = find_user(who))) -					goto out_unlock;	/* No processes for this user */ +				who = cred->uid; +			else if ((who != cred->uid) && +				 !(user = find_user(who))) +				goto out_unlock;	/* No processes for this user */  			do_each_thread(g, p) -				if (p->uid == who) +				if (__task_cred(p)->uid == who)  					error = set_one_prio(p, niceval, error);  			while_each_thread(g, p); -			if (who != current->uid) +			if (who != cred->uid)  				free_uid(user);		/* For find_user() */  			break;  	} @@ -205,6 +211,7 @@ asmlinkage long sys_getpriority(int which, int who)  {  	struct task_struct *g, *p;  	struct user_struct *user; +	const struct cred *cred = current_cred();  	long niceval, retval = -ESRCH;  	struct pid *pgrp; @@ -236,21 +243,21 @@ asmlinkage long sys_getpriority(int which, int who)  			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);  			break;  		case PRIO_USER: -			user = current->user; +			user = (struct user_struct *) cred->user;  			if (!who) -				who = current->uid; -			else -				if ((who != current->uid) && !(user = find_user(who))) -					goto out_unlock;	/* No processes for this user */ +				who = cred->uid; +			else if ((who != cred->uid) && +				 !(user = find_user(who))) +				goto out_unlock;	/* No processes for this user */  			do_each_thread(g, p) -				if (p->uid == who) { +				if (__task_cred(p)->uid == who) {  					niceval = 20 - task_nice(p);  					if (niceval > retval)  						retval = niceval;  				}  			while_each_thread(g, p); -			if (who != current->uid) +			if (who != cred->uid)  				free_uid(user);		/* for find_user() */  			break;  	} @@ -472,46 +479,48 @@ void ctrl_alt_del(void)   */  asmlinkage long sys_setregid(gid_t rgid, gid_t egid)  { -	int old_rgid = current->gid; -	int old_egid = current->egid; -	int new_rgid = old_rgid; -	int new_egid = old_egid; +	const struct cred *old; +	struct cred *new;  	int retval; +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; +	old = current_cred(); +  	retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);  	if (retval) -		return retval; +		goto error; +	retval = -EPERM;  	if (rgid != (gid_t) -1) { -		if ((old_rgid == rgid) || -		    (current->egid==rgid) || +		if (old->gid == rgid || +		    old->egid == rgid ||  		    capable(CAP_SETGID)) -			new_rgid = rgid; +			new->gid = rgid;  		else -			return -EPERM; +			goto error;  	}  	if (egid != (gid_t) -1) { -		if ((old_rgid == egid) || -		    (current->egid == egid) || -		    (current->sgid == egid) || +		if (old->gid == egid || +		    old->egid == egid || +		    old->sgid == egid ||  		    capable(CAP_SETGID)) -			new_egid = egid; +			new->egid = egid;  		else -			return -EPERM; -	} -	if (new_egid != old_egid) { -		set_dumpable(current->mm, suid_dumpable); -		smp_wmb(); +			goto error;  	} +  	if (rgid != (gid_t) -1 || -	    (egid != (gid_t) -1 && egid != old_rgid)) -		current->sgid = new_egid; -	current->fsgid = new_egid; -	current->egid = new_egid; -	current->gid = new_rgid; -	key_fsgid_changed(current); -	proc_id_connector(current, PROC_EVENT_GID); -	return 0; +	    (egid != (gid_t) -1 && egid != old->gid)) +		new->sgid = new->egid; +	new->fsgid = new->egid; + +	return commit_creds(new); + +error: +	abort_creds(new); +	return retval;  }  /* @@ -521,56 +530,54 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)   */  asmlinkage long sys_setgid(gid_t gid)  { -	int old_egid = current->egid; +	const struct cred *old; +	struct cred *new;  	int retval; +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; +	old = current_cred(); +  	retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);  	if (retval) -		return retval; +		goto error; -	if (capable(CAP_SETGID)) { -		if (old_egid != gid) { -			set_dumpable(current->mm, suid_dumpable); -			smp_wmb(); -		} -		current->gid = current->egid = current->sgid = current->fsgid = gid; -	} else if ((gid == current->gid) || (gid == current->sgid)) { -		if (old_egid != gid) { -			set_dumpable(current->mm, suid_dumpable); -			smp_wmb(); -		} -		current->egid = current->fsgid = gid; -	} +	retval = -EPERM; +	if (capable(CAP_SETGID)) +		new->gid = new->egid = new->sgid = new->fsgid = gid; +	else if (gid == old->gid || gid == old->sgid) +		new->egid = new->fsgid = gid;  	else -		return -EPERM; +		goto error; -	key_fsgid_changed(current); -	proc_id_connector(current, PROC_EVENT_GID); -	return 0; +	return commit_creds(new); + +error: +	abort_creds(new); +	return retval;  } -static int set_user(uid_t new_ruid, int dumpclear) +/* + * change the user struct in a credentials set to match the new UID + */ +static int set_user(struct cred *new)  {  	struct user_struct *new_user; -	new_user = alloc_uid(current->nsproxy->user_ns, new_ruid); +	new_user = alloc_uid(current_user_ns(), new->uid);  	if (!new_user)  		return -EAGAIN;  	if (atomic_read(&new_user->processes) >=  				current->signal->rlim[RLIMIT_NPROC].rlim_cur && -			new_user != current->nsproxy->user_ns->root_user) { +			new_user != INIT_USER) {  		free_uid(new_user);  		return -EAGAIN;  	} -	switch_uid(new_user); - -	if (dumpclear) { -		set_dumpable(current->mm, suid_dumpable); -		smp_wmb(); -	} -	current->uid = new_ruid; +	free_uid(new->user); +	new->user = new_user;  	return 0;  } @@ -591,54 +598,56 @@ static int set_user(uid_t new_ruid, int dumpclear)   */  asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)  { -	int old_ruid, old_euid, old_suid, new_ruid, new_euid; +	const struct cred *old; +	struct cred *new;  	int retval; +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; +	old = current_cred(); +  	retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);  	if (retval) -		return retval; - -	new_ruid = old_ruid = current->uid; -	new_euid = old_euid = current->euid; -	old_suid = current->suid; +		goto error; +	retval = -EPERM;  	if (ruid != (uid_t) -1) { -		new_ruid = ruid; -		if ((old_ruid != ruid) && -		    (current->euid != ruid) && +		new->uid = ruid; +		if (old->uid != ruid && +		    old->euid != ruid &&  		    !capable(CAP_SETUID)) -			return -EPERM; +			goto error;  	}  	if (euid != (uid_t) -1) { -		new_euid = euid; -		if ((old_ruid != euid) && -		    (current->euid != euid) && -		    (current->suid != euid) && +		new->euid = euid; +		if (old->uid != euid && +		    old->euid != euid && +		    old->suid != euid &&  		    !capable(CAP_SETUID)) -			return -EPERM; +			goto error;  	} -	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) -		return -EAGAIN; +	retval = -EAGAIN; +	if (new->uid != old->uid && set_user(new) < 0) +		goto error; -	if (new_euid != old_euid) { -		set_dumpable(current->mm, suid_dumpable); -		smp_wmb(); -	} -	current->fsuid = current->euid = new_euid;  	if (ruid != (uid_t) -1 || -	    (euid != (uid_t) -1 && euid != old_ruid)) -		current->suid = current->euid; -	current->fsuid = current->euid; +	    (euid != (uid_t) -1 && euid != old->uid)) +		new->suid = new->euid; +	new->fsuid = new->euid; -	key_fsuid_changed(current); -	proc_id_connector(current, PROC_EVENT_UID); - -	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); -} +	retval = security_task_fix_setuid(new, old, LSM_SETID_RE); +	if (retval < 0) +		goto error; +	return commit_creds(new); +error: +	abort_creds(new); +	return retval; +}  /*   * setuid() is implemented like SysV with SAVED_IDS  @@ -653,36 +662,41 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)   */  asmlinkage long sys_setuid(uid_t uid)  { -	int old_euid = current->euid; -	int old_ruid, old_suid, new_suid; +	const struct cred *old; +	struct cred *new;  	int retval; +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; +	old = current_cred(); +  	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);  	if (retval) -		return retval; +		goto error; -	old_ruid = current->uid; -	old_suid = current->suid; -	new_suid = old_suid; -	 +	retval = -EPERM;  	if (capable(CAP_SETUID)) { -		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) -			return -EAGAIN; -		new_suid = uid; -	} else if ((uid != current->uid) && (uid != new_suid)) -		return -EPERM; - -	if (old_euid != uid) { -		set_dumpable(current->mm, suid_dumpable); -		smp_wmb(); +		new->suid = new->uid = uid; +		if (uid != old->uid && set_user(new) < 0) { +			retval = -EAGAIN; +			goto error; +		} +	} else if (uid != old->uid && uid != new->suid) { +		goto error;  	} -	current->fsuid = current->euid = uid; -	current->suid = new_suid; -	key_fsuid_changed(current); -	proc_id_connector(current, PROC_EVENT_UID); +	new->fsuid = new->euid = uid; + +	retval = security_task_fix_setuid(new, old, LSM_SETID_ID); +	if (retval < 0) +		goto error; -	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); +	return commit_creds(new); + +error: +	abort_creds(new); +	return retval;  } @@ -692,54 +706,63 @@ asmlinkage long sys_setuid(uid_t uid)   */  asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)  { -	int old_ruid = current->uid; -	int old_euid = current->euid; -	int old_suid = current->suid; +	const struct cred *old; +	struct cred *new;  	int retval; +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; +  	retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);  	if (retval) -		return retval; +		goto error; +	old = current_cred(); +	retval = -EPERM;  	if (!capable(CAP_SETUID)) { -		if ((ruid != (uid_t) -1) && (ruid != current->uid) && -		    (ruid != current->euid) && (ruid != current->suid)) -			return -EPERM; -		if ((euid != (uid_t) -1) && (euid != current->uid) && -		    (euid != current->euid) && (euid != current->suid)) -			return -EPERM; -		if ((suid != (uid_t) -1) && (suid != current->uid) && -		    (suid != current->euid) && (suid != current->suid)) -			return -EPERM; +		if (ruid != (uid_t) -1 && ruid != old->uid && +		    ruid != old->euid  && ruid != old->suid) +			goto error; +		if (euid != (uid_t) -1 && euid != old->uid && +		    euid != old->euid  && euid != old->suid) +			goto error; +		if (suid != (uid_t) -1 && suid != old->uid && +		    suid != old->euid  && suid != old->suid) +			goto error;  	} + +	retval = -EAGAIN;  	if (ruid != (uid_t) -1) { -		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) -			return -EAGAIN; +		new->uid = ruid; +		if (ruid != old->uid && set_user(new) < 0) +			goto error;  	} -	if (euid != (uid_t) -1) { -		if (euid != current->euid) { -			set_dumpable(current->mm, suid_dumpable); -			smp_wmb(); -		} -		current->euid = euid; -	} -	current->fsuid = current->euid; +	if (euid != (uid_t) -1) +		new->euid = euid;  	if (suid != (uid_t) -1) -		current->suid = suid; +		new->suid = suid; +	new->fsuid = new->euid; + +	retval = security_task_fix_setuid(new, old, LSM_SETID_RES); +	if (retval < 0) +		goto error; -	key_fsuid_changed(current); -	proc_id_connector(current, PROC_EVENT_UID); +	return commit_creds(new); -	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); +error: +	abort_creds(new); +	return retval;  }  asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)  { +	const struct cred *cred = current_cred();  	int retval; -	if (!(retval = put_user(current->uid, ruid)) && -	    !(retval = put_user(current->euid, euid))) -		retval = put_user(current->suid, suid); +	if (!(retval   = put_user(cred->uid,  ruid)) && +	    !(retval   = put_user(cred->euid, euid))) +		retval = put_user(cred->suid, suid);  	return retval;  } @@ -749,48 +772,55 @@ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __us   */  asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)  { +	const struct cred *old; +	struct cred *new;  	int retval; +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; +	old = current_cred(); +  	retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);  	if (retval) -		return retval; +		goto error; +	retval = -EPERM;  	if (!capable(CAP_SETGID)) { -		if ((rgid != (gid_t) -1) && (rgid != current->gid) && -		    (rgid != current->egid) && (rgid != current->sgid)) -			return -EPERM; -		if ((egid != (gid_t) -1) && (egid != current->gid) && -		    (egid != current->egid) && (egid != current->sgid)) -			return -EPERM; -		if ((sgid != (gid_t) -1) && (sgid != current->gid) && -		    (sgid != current->egid) && (sgid != current->sgid)) -			return -EPERM; +		if (rgid != (gid_t) -1 && rgid != old->gid && +		    rgid != old->egid  && rgid != old->sgid) +			goto error; +		if (egid != (gid_t) -1 && egid != old->gid && +		    egid != old->egid  && egid != old->sgid) +			goto error; +		if (sgid != (gid_t) -1 && sgid != old->gid && +		    sgid != old->egid  && sgid != old->sgid) +			goto error;  	} -	if (egid != (gid_t) -1) { -		if (egid != current->egid) { -			set_dumpable(current->mm, suid_dumpable); -			smp_wmb(); -		} -		current->egid = egid; -	} -	current->fsgid = current->egid; +  	if (rgid != (gid_t) -1) -		current->gid = rgid; +		new->gid = rgid; +	if (egid != (gid_t) -1) +		new->egid = egid;  	if (sgid != (gid_t) -1) -		current->sgid = sgid; +		new->sgid = sgid; +	new->fsgid = new->egid; -	key_fsgid_changed(current); -	proc_id_connector(current, PROC_EVENT_GID); -	return 0; +	return commit_creds(new); + +error: +	abort_creds(new); +	return retval;  }  asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)  { +	const struct cred *cred = current_cred();  	int retval; -	if (!(retval = put_user(current->gid, rgid)) && -	    !(retval = put_user(current->egid, egid))) -		retval = put_user(current->sgid, sgid); +	if (!(retval   = put_user(cred->gid,  rgid)) && +	    !(retval   = put_user(cred->egid, egid))) +		retval = put_user(cred->sgid, sgid);  	return retval;  } @@ -804,27 +834,35 @@ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __us   */  asmlinkage long sys_setfsuid(uid_t uid)  { -	int old_fsuid; +	const struct cred *old; +	struct cred *new; +	uid_t old_fsuid; -	old_fsuid = current->fsuid; -	if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) -		return old_fsuid; +	new = prepare_creds(); +	if (!new) +		return current_fsuid(); +	old = current_cred(); +	old_fsuid = old->fsuid; -	if (uid == current->uid || uid == current->euid || -	    uid == current->suid || uid == current->fsuid ||  +	if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0) +		goto error; + +	if (uid == old->uid  || uid == old->euid  || +	    uid == old->suid || uid == old->fsuid ||  	    capable(CAP_SETUID)) {  		if (uid != old_fsuid) { -			set_dumpable(current->mm, suid_dumpable); -			smp_wmb(); +			new->fsuid = uid; +			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) +				goto change_okay;  		} -		current->fsuid = uid;  	} -	key_fsuid_changed(current); -	proc_id_connector(current, PROC_EVENT_UID); - -	security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS); +error: +	abort_creds(new); +	return old_fsuid; +change_okay: +	commit_creds(new);  	return old_fsuid;  } @@ -833,23 +871,34 @@ asmlinkage long sys_setfsuid(uid_t uid)   */  asmlinkage long sys_setfsgid(gid_t gid)  { -	int old_fsgid; +	const struct cred *old; +	struct cred *new; +	gid_t old_fsgid; + +	new = prepare_creds(); +	if (!new) +		return current_fsgid(); +	old = current_cred(); +	old_fsgid = old->fsgid; -	old_fsgid = current->fsgid;  	if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)) -		return old_fsgid; +		goto error; -	if (gid == current->gid || gid == current->egid || -	    gid == current->sgid || gid == current->fsgid ||  +	if (gid == old->gid  || gid == old->egid  || +	    gid == old->sgid || gid == old->fsgid ||  	    capable(CAP_SETGID)) {  		if (gid != old_fsgid) { -			set_dumpable(current->mm, suid_dumpable); -			smp_wmb(); +			new->fsgid = gid; +			goto change_okay;  		} -		current->fsgid = gid; -		key_fsgid_changed(current); -		proc_id_connector(current, PROC_EVENT_GID);  	} + +error: +	abort_creds(new); +	return old_fsgid; + +change_okay: +	commit_creds(new);  	return old_fsgid;  } @@ -1118,7 +1167,7 @@ EXPORT_SYMBOL(groups_free);  /* export the group_info to a user-space array */  static int groups_to_user(gid_t __user *grouplist, -    struct group_info *group_info) +			  const struct group_info *group_info)  {  	int i;  	unsigned int count = group_info->ngroups; @@ -1186,7 +1235,7 @@ static void groups_sort(struct group_info *group_info)  }  /* a simple bsearch */ -int groups_search(struct group_info *group_info, gid_t grp) +int groups_search(const struct group_info *group_info, gid_t grp)  {  	unsigned int left, right; @@ -1208,51 +1257,74 @@ int groups_search(struct group_info *group_info, gid_t grp)  	return 0;  } -/* validate and set current->group_info */ -int set_current_groups(struct group_info *group_info) +/** + * set_groups - Change a group subscription in a set of credentials + * @new: The newly prepared set of credentials to alter + * @group_info: The group list to install + * + * Validate a group subscription and, if valid, insert it into a set + * of credentials. + */ +int set_groups(struct cred *new, struct group_info *group_info)  {  	int retval; -	struct group_info *old_info;  	retval = security_task_setgroups(group_info);  	if (retval)  		return retval; +	put_group_info(new->group_info);  	groups_sort(group_info);  	get_group_info(group_info); +	new->group_info = group_info; +	return 0; +} + +EXPORT_SYMBOL(set_groups); -	task_lock(current); -	old_info = current->group_info; -	current->group_info = group_info; -	task_unlock(current); +/** + * set_current_groups - Change current's group subscription + * @group_info: The group list to impose + * + * Validate a group subscription and, if valid, impose it upon current's task + * security record. + */ +int set_current_groups(struct group_info *group_info) +{ +	struct cred *new; +	int ret; -	put_group_info(old_info); +	new = prepare_creds(); +	if (!new) +		return -ENOMEM; -	return 0; +	ret = set_groups(new, group_info); +	if (ret < 0) { +		abort_creds(new); +		return ret; +	} + +	return commit_creds(new);  }  EXPORT_SYMBOL(set_current_groups);  asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)  { -	int i = 0; - -	/* -	 *	SMP: Nobody else can change our grouplist. Thus we are -	 *	safe. -	 */ +	const struct cred *cred = current_cred(); +	int i;  	if (gidsetsize < 0)  		return -EINVAL;  	/* no need to grab task_lock here; it cannot change */ -	i = current->group_info->ngroups; +	i = cred->group_info->ngroups;  	if (gidsetsize) {  		if (i > gidsetsize) {  			i = -EINVAL;  			goto out;  		} -		if (groups_to_user(grouplist, current->group_info)) { +		if (groups_to_user(grouplist, cred->group_info)) {  			i = -EFAULT;  			goto out;  		} @@ -1296,9 +1368,11 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)   */  int in_group_p(gid_t grp)  { +	const struct cred *cred = current_cred();  	int retval = 1; -	if (grp != current->fsgid) -		retval = groups_search(current->group_info, grp); + +	if (grp != cred->fsgid) +		retval = groups_search(cred->group_info, grp);  	return retval;  } @@ -1306,9 +1380,11 @@ EXPORT_SYMBOL(in_group_p);  int in_egroup_p(gid_t grp)  { +	const struct cred *cred = current_cred();  	int retval = 1; -	if (grp != current->egid) -		retval = groups_search(current->group_info, grp); + +	if (grp != cred->egid) +		retval = groups_search(cred->group_info, grp);  	return retval;  } @@ -1624,50 +1700,56 @@ asmlinkage long sys_umask(int mask)  asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,  			  unsigned long arg4, unsigned long arg5)  { -	long error = 0; +	struct task_struct *me = current; +	unsigned char comm[sizeof(me->comm)]; +	long error; -	if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) +	error = security_task_prctl(option, arg2, arg3, arg4, arg5); +	if (error != -ENOSYS)  		return error; +	error = 0;  	switch (option) {  		case PR_SET_PDEATHSIG:  			if (!valid_signal(arg2)) {  				error = -EINVAL;  				break;  			} -			current->pdeath_signal = arg2; +			me->pdeath_signal = arg2; +			error = 0;  			break;  		case PR_GET_PDEATHSIG: -			error = put_user(current->pdeath_signal, (int __user *)arg2); +			error = put_user(me->pdeath_signal, (int __user *)arg2);  			break;  		case PR_GET_DUMPABLE: -			error = get_dumpable(current->mm); +			error = get_dumpable(me->mm);  			break;  		case PR_SET_DUMPABLE:  			if (arg2 < 0 || arg2 > 1) {  				error = -EINVAL;  				break;  			} -			set_dumpable(current->mm, arg2); +			set_dumpable(me->mm, arg2); +			error = 0;  			break;  		case PR_SET_UNALIGN: -			error = SET_UNALIGN_CTL(current, arg2); +			error = SET_UNALIGN_CTL(me, arg2);  			break;  		case PR_GET_UNALIGN: -			error = GET_UNALIGN_CTL(current, arg2); +			error = GET_UNALIGN_CTL(me, arg2);  			break;  		case PR_SET_FPEMU: -			error = SET_FPEMU_CTL(current, arg2); +			error = SET_FPEMU_CTL(me, arg2);  			break;  		case PR_GET_FPEMU: -			error = GET_FPEMU_CTL(current, arg2); +			error = GET_FPEMU_CTL(me, arg2);  			break;  		case PR_SET_FPEXC: -			error = SET_FPEXC_CTL(current, arg2); +			error = SET_FPEXC_CTL(me, arg2);  			break;  		case PR_GET_FPEXC: -			error = GET_FPEXC_CTL(current, arg2); +			error = GET_FPEXC_CTL(me, arg2);  			break;  		case PR_GET_TIMING:  			error = PR_TIMING_STATISTICAL; @@ -1675,33 +1757,28 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,  		case PR_SET_TIMING:  			if (arg2 != PR_TIMING_STATISTICAL)  				error = -EINVAL; +			else +				error = 0;  			break; -		case PR_SET_NAME: { -			struct task_struct *me = current; -			unsigned char ncomm[sizeof(me->comm)]; - -			ncomm[sizeof(me->comm)-1] = 0; -			if (strncpy_from_user(ncomm, (char __user *)arg2, -						sizeof(me->comm)-1) < 0) +		case PR_SET_NAME: +			comm[sizeof(me->comm)-1] = 0; +			if (strncpy_from_user(comm, (char __user *)arg2, +					      sizeof(me->comm) - 1) < 0)  				return -EFAULT; -			set_task_comm(me, ncomm); +			set_task_comm(me, comm);  			return 0; -		} -		case PR_GET_NAME: { -			struct task_struct *me = current; -			unsigned char tcomm[sizeof(me->comm)]; - -			get_task_comm(tcomm, me); -			if (copy_to_user((char __user *)arg2, tcomm, sizeof(tcomm))) +		case PR_GET_NAME: +			get_task_comm(comm, me); +			if (copy_to_user((char __user *)arg2, comm, +					 sizeof(comm)))  				return -EFAULT;  			return 0; -		}  		case PR_GET_ENDIAN: -			error = GET_ENDIAN(current, arg2); +			error = GET_ENDIAN(me, arg2);  			break;  		case PR_SET_ENDIAN: -			error = SET_ENDIAN(current, arg2); +			error = SET_ENDIAN(me, arg2);  			break;  		case PR_GET_SECCOMP: @@ -1725,6 +1802,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,  					current->default_timer_slack_ns;  			else  				current->timer_slack_ns = arg2; +			error = 0;  			break;  		default:  			error = -EINVAL;  | 
