diff options
Diffstat (limited to 'kernel/uid16.c')
| -rw-r--r-- | kernel/uid16.c | 105 | 
1 files changed, 46 insertions, 59 deletions
diff --git a/kernel/uid16.c b/kernel/uid16.c index 419209893d8..602e5bbbcef 100644 --- a/kernel/uid16.c +++ b/kernel/uid16.c @@ -18,127 +18,107 @@  SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)  { -	long ret = sys_chown(filename, low2highuid(user), low2highgid(group)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(3, ret, filename, user, group); -	return ret; +	return sys_chown(filename, low2highuid(user), low2highgid(group));  }  SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)  { -	long ret = sys_lchown(filename, low2highuid(user), low2highgid(group)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(3, ret, filename, user, group); -	return ret; +	return sys_lchown(filename, low2highuid(user), low2highgid(group));  }  SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)  { -	long ret = sys_fchown(fd, low2highuid(user), low2highgid(group)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(3, ret, fd, user, group); -	return ret; +	return sys_fchown(fd, low2highuid(user), low2highgid(group));  }  SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)  { -	long ret = sys_setregid(low2highgid(rgid), low2highgid(egid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(2, ret, rgid, egid); -	return ret; +	return sys_setregid(low2highgid(rgid), low2highgid(egid));  }  SYSCALL_DEFINE1(setgid16, old_gid_t, gid)  { -	long ret = sys_setgid(low2highgid(gid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(1, ret, gid); -	return ret; +	return sys_setgid(low2highgid(gid));  }  SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)  { -	long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(2, ret, ruid, euid); -	return ret; +	return sys_setreuid(low2highuid(ruid), low2highuid(euid));  }  SYSCALL_DEFINE1(setuid16, old_uid_t, uid)  { -	long ret = sys_setuid(low2highuid(uid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(1, ret, uid); -	return ret; +	return sys_setuid(low2highuid(uid));  }  SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)  { -	long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid), +	return sys_setresuid(low2highuid(ruid), low2highuid(euid),  				 low2highuid(suid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(3, ret, ruid, euid, suid); -	return ret;  } -SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruid, old_uid_t __user *, euid, old_uid_t __user *, suid) +SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)  {  	const struct cred *cred = current_cred();  	int retval; +	old_uid_t ruid, euid, suid; -	if (!(retval   = put_user(high2lowuid(cred->uid),  ruid)) && -	    !(retval   = put_user(high2lowuid(cred->euid), euid))) -		retval = put_user(high2lowuid(cred->suid), suid); +	ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); +	euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); +	suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); + +	if (!(retval   = put_user(ruid, ruidp)) && +	    !(retval   = put_user(euid, euidp))) +		retval = put_user(suid, suidp);  	return retval;  }  SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)  { -	long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid), +	return sys_setresgid(low2highgid(rgid), low2highgid(egid),  				 low2highgid(sgid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(3, ret, rgid, egid, sgid); -	return ret;  } -SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgid, old_gid_t __user *, egid, old_gid_t __user *, sgid) +SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)  {  	const struct cred *cred = current_cred();  	int retval; +	old_gid_t rgid, egid, sgid; + +	rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); +	egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); +	sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); -	if (!(retval   = put_user(high2lowgid(cred->gid),  rgid)) && -	    !(retval   = put_user(high2lowgid(cred->egid), egid))) -		retval = put_user(high2lowgid(cred->sgid), sgid); +	if (!(retval   = put_user(rgid, rgidp)) && +	    !(retval   = put_user(egid, egidp))) +		retval = put_user(sgid, sgidp);  	return retval;  }  SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)  { -	long ret = sys_setfsuid(low2highuid(uid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(1, ret, uid); -	return ret; +	return sys_setfsuid(low2highuid(uid));  }  SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)  { -	long ret = sys_setfsgid(low2highgid(gid)); -	/* avoid REGPARM breakage on x86: */ -	asmlinkage_protect(1, ret, gid); -	return ret; +	return sys_setfsgid(low2highgid(gid));  }  static int groups16_to_user(old_gid_t __user *grouplist,      struct group_info *group_info)  { +	struct user_namespace *user_ns = current_user_ns();  	int i;  	old_gid_t group; +	kgid_t kgid;  	for (i = 0; i < group_info->ngroups; i++) { -		group = high2lowgid(GROUP_AT(group_info, i)); +		kgid = GROUP_AT(group_info, i); +		group = high2lowgid(from_kgid_munged(user_ns, kgid));  		if (put_user(group, grouplist+i))  			return -EFAULT;  	} @@ -149,13 +129,20 @@ static int groups16_to_user(old_gid_t __user *grouplist,  static int groups16_from_user(struct group_info *group_info,      old_gid_t __user *grouplist)  { +	struct user_namespace *user_ns = current_user_ns();  	int i;  	old_gid_t group; +	kgid_t kgid;  	for (i = 0; i < group_info->ngroups; i++) {  		if (get_user(group, grouplist+i))  			return  -EFAULT; -		GROUP_AT(group_info, i) = low2highgid(group); + +		kgid = make_kgid(user_ns, low2highgid(group)); +		if (!gid_valid(kgid)) +			return -EINVAL; + +		GROUP_AT(group_info, i) = kgid;  	}  	return 0; @@ -189,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)  	struct group_info *group_info;  	int retval; -	if (!capable(CAP_SETGID)) +	if (!ns_capable(current_user_ns(), CAP_SETGID))  		return -EPERM;  	if ((unsigned)gidsetsize > NGROUPS_MAX)  		return -EINVAL; @@ -211,20 +198,20 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)  SYSCALL_DEFINE0(getuid16)  { -	return high2lowuid(current_uid()); +	return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));  }  SYSCALL_DEFINE0(geteuid16)  { -	return high2lowuid(current_euid()); +	return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));  }  SYSCALL_DEFINE0(getgid16)  { -	return high2lowgid(current_gid()); +	return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));  }  SYSCALL_DEFINE0(getegid16)  { -	return high2lowgid(current_egid()); +	return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));  }  | 
