summary refs log tree commit diff
path: root/arch/alpha
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-06 22:04:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-06 22:04:27 -0700
commit1c91d2c6915b288bc8595b21d37e1bb662a40e55 (patch)
treeb84ebde2f278ecfa1591b741dee86be22db6dd14 /arch/alpha
parentc856863988ebf612d159e55eeddbcd27de63b40d (diff)
parent8d2fd30ecfc81f2b5f2bd60815bd3951cb23601c (diff)
downloadlinux-1c91d2c6915b288bc8595b21d37e1bb662a40e55.tar.gz
Merge branch 'misc.alpha' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull alpha user access updates from Al Viro:
 "Several alpha osf_sys.c uaccess cleanups - getdomainname() had insane
  byte-by-byte copying of string to userland (instead of strnlen +
  copy_to_user) plus yet another compat variant of timeval/itimerval
  with associated copyin/copyout primitives"

* 'misc.alpha' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  osf_sigstack(): switch to put_user()
  osf_sys.c: switch handling of timeval32/itimerval32 to copy_{to,from}_user()
  osf_getdomainname(): use copy_to_user()
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/kernel/osf_sys.c81
1 files changed, 40 insertions, 41 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index b23d6fbbb225..df0d0a5e9353 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -564,25 +564,20 @@ SYSCALL_DEFINE0(getdtablesize)
  */
 SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
 {
-	unsigned len;
-	int i;
+	int len, err = 0;
+	char *kname;
 
-	if (!access_ok(VERIFY_WRITE, name, namelen))
-		return -EFAULT;
-
-	len = namelen;
-	if (len > 32)
-		len = 32;
+	if (namelen > 32)
+		namelen = 32;
 
 	down_read(&uts_sem);
-	for (i = 0; i < len; ++i) {
-		__put_user(utsname()->domainname[i], name + i);
-		if (utsname()->domainname[i] == '\0')
-			break;
-	}
+	kname = utsname()->domainname;
+	len = strnlen(kname, namelen);
+	if (copy_to_user(name, kname, min(len + 1, namelen)))
+		err = -EFAULT;
 	up_read(&uts_sem);
 
-	return 0;
+	return err;
 }
 
 /*
@@ -718,9 +713,8 @@ SYSCALL_DEFINE2(osf_sigstack, struct sigstack __user *, uss,
 
 	if (uoss) {
 		error = -EFAULT;
-		if (! access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))
-		    || __put_user(oss_sp, &uoss->ss_sp)
-		    || __put_user(oss_os, &uoss->ss_onstack))
+		if (put_user(oss_sp, &uoss->ss_sp) ||
+		    put_user(oss_os, &uoss->ss_onstack))
 			goto out;
 	}
 
@@ -957,37 +951,45 @@ struct itimerval32
 static inline long
 get_tv32(struct timeval *o, struct timeval32 __user *i)
 {
-	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-		(__get_user(o->tv_sec, &i->tv_sec) |
-		 __get_user(o->tv_usec, &i->tv_usec)));
+	struct timeval32 tv;
+	if (copy_from_user(&tv, i, sizeof(struct timeval32)))
+		return -EFAULT;
+	o->tv_sec = tv.tv_sec;
+	o->tv_usec = tv.tv_usec;
+	return 0;
 }
 
 static inline long
 put_tv32(struct timeval32 __user *o, struct timeval *i)
 {
-	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-		(__put_user(i->tv_sec, &o->tv_sec) |
-		 __put_user(i->tv_usec, &o->tv_usec)));
+	return copy_to_user(o, &(struct timeval32){
+				.tv_sec = o->tv_sec,
+				.tv_usec = o->tv_usec},
+			    sizeof(struct timeval32));
 }
 
 static inline long
 get_it32(struct itimerval *o, struct itimerval32 __user *i)
 {
-	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
-		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
-		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
-		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
+	struct itimerval32 itv;
+	if (copy_from_user(&itv, i, sizeof(struct itimerval32)))
+		return -EFAULT;
+	o->it_interval.tv_sec = itv.it_interval.tv_sec;
+	o->it_interval.tv_usec = itv.it_interval.tv_usec;
+	o->it_value.tv_sec = itv.it_value.tv_sec;
+	o->it_value.tv_usec = itv.it_value.tv_usec;
+	return 0;
 }
 
 static inline long
 put_it32(struct itimerval32 __user *o, struct itimerval *i)
 {
-	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
-		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
-		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
-		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
+	return copy_to_user(o, &(struct itimerval32){
+				.it_interval.tv_sec = o->it_interval.tv_sec,
+				.it_interval.tv_usec = o->it_interval.tv_usec,
+				.it_value.tv_sec = o->it_value.tv_sec,
+				.it_value.tv_usec = o->it_value.tv_usec},
+			    sizeof(struct itimerval32));
 }
 
 static inline void
@@ -1106,20 +1108,17 @@ SYSCALL_DEFINE5(osf_select, int, n, fd_set __user *, inp, fd_set __user *, outp,
 {
 	struct timespec end_time, *to = NULL;
 	if (tvp) {
-		time_t sec, usec;
-
+		struct timeval tv;
 		to = &end_time;
 
-		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
-		    || __get_user(sec, &tvp->tv_sec)
-		    || __get_user(usec, &tvp->tv_usec)) {
+		if (get_tv32(&tv, tvp))
 		    	return -EFAULT;
-		}
 
-		if (sec < 0 || usec < 0)
+		if (tv.tv_sec < 0 || tv.tv_usec < 0)
 			return -EINVAL;
 
-		if (poll_select_set_timeout(to, sec, usec * NSEC_PER_USEC))
+		if (poll_select_set_timeout(to, tv.tv_sec,
+					    tv.tv_usec * NSEC_PER_USEC))
 			return -EINVAL;		
 
 	}