summary refs log tree commit diff
path: root/arch/mips
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-03-16 12:16:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2007-03-17 01:03:29 +0000
commit46230aa6ea1671690e3e5efa2a961fc0745fe9b5 (patch)
tree9224af1ccdb48fac6d0b400b6a76e2d62f104972 /arch/mips
parentbc4809e939b91c9642f1ddaea732e2d432ee6af6 (diff)
downloadlinux-46230aa6ea1671690e3e5efa2a961fc0745fe9b5.tar.gz
[MIPS] RTLX: Handle copy_*_user return values.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/kspd.c18
-rw-r--r--arch/mips/kernel/rtlx.c46
2 files changed, 35 insertions, 29 deletions
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index 241ee7a2906e..29eadd404fa5 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -191,6 +191,8 @@ void sp_work_handle_request(void)
 	struct mtsp_syscall_generic generic;
 	struct mtsp_syscall_ret ret;
 	struct kspd_notifications *n;
+	unsigned long written;
+	mm_segment_t old_fs;
 	struct timeval tv;
 	struct timezone tz;
 	int cmd;
@@ -201,7 +203,11 @@ void sp_work_handle_request(void)
 
 	ret.retval = -1;
 
-	if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall))) {
+		set_fs(old_fs);
 		printk(KERN_ERR "Expected request but nothing to read\n");
 		return;
 	}
@@ -209,7 +215,8 @@ void sp_work_handle_request(void)
 	size = sc.size;
 
 	if (size) {
-		if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
+		if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size)) {
+			set_fs(old_fs);
 			printk(KERN_ERR "Expected request but nothing to read\n");
 			return;
 		}
@@ -282,8 +289,11 @@ void sp_work_handle_request(void)
 	if (vpe_getuid(SP_VPE))
 		sp_setfsuidgid( 0, 0);
 
-	if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
-	    < sizeof(struct mtsp_syscall_ret))
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	written = rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(ret));
+	set_fs(old_fs);
+	if (written < sizeof(ret))
 		printk("KSPD: sp_work_handle_request failed to send to SP\n");
 }
 
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 745649e15adc..e6e3047151a6 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -289,26 +289,11 @@ unsigned int rtlx_write_poll(int index)
 	return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
 }
 
-static inline void copy_to(void *dst, void *src, size_t count, int user)
-{
-	if (user)
-		copy_to_user(dst, src, count);
-	else
-		memcpy(dst, src, count);
-}
-
-static inline void copy_from(void *dst, void *src, size_t count, int user)
-{
-	if (user)
-		copy_from_user(dst, src, count);
-	else
-		memcpy(dst, src, count);
-}
-
-ssize_t rtlx_read(int index, void *buff, size_t count, int user)
+ssize_t rtlx_read(int index, void __user *buff, size_t count, int user)
 {
 	size_t lx_write, fl = 0L;
 	struct rtlx_channel *lx;
+	unsigned long failed;
 
 	if (rtlx == NULL)
 		return -ENOSYS;
@@ -327,11 +312,16 @@ ssize_t rtlx_read(int index, void *buff, size_t count, int user)
 	/* then how much from the read pointer onwards */
 	fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
 
-	copy_to(buff, lx->lx_buffer + lx->lx_read, fl, user);
+	failed = copy_to_user(buff, lx->lx_buffer + lx->lx_read, fl);
+	if (failed)
+		goto out;
 
 	/* and if there is anything left at the beginning of the buffer */
 	if (count - fl)
-		copy_to(buff + fl, lx->lx_buffer, count - fl, user);
+		failed = copy_to_user(buff + fl, lx->lx_buffer, count - fl);
+
+out:
+	count -= failed;
 
 	smp_wmb();
 	lx->lx_read = (lx->lx_read + count) % lx->buffer_size;
@@ -341,7 +331,7 @@ ssize_t rtlx_read(int index, void *buff, size_t count, int user)
 	return count;
 }
 
-ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
+ssize_t rtlx_write(int index, const void __user *buffer, size_t count, int user)
 {
 	struct rtlx_channel *rt;
 	size_t rt_read;
@@ -363,11 +353,17 @@ ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
 	/* first bit from write pointer to the end of the buffer, or count */
 	fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
 
-	copy_from(rt->rt_buffer + rt->rt_write, buffer, fl, user);
+	failed = copy_from_user(rt->rt_buffer + rt->rt_write, buffer, fl);
+	if (failed)
+		goto out;
 
 	/* if there's any left copy to the beginning of the buffer */
-	if (count - fl)
-		copy_from(rt->rt_buffer, buffer + fl, count - fl, user);
+	if (count - fl) {
+		failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
+	}
+
+out:
+	count -= cailed;
 
 	smp_wmb();
 	rt->rt_write = (rt->rt_write + count) % rt->buffer_size;
@@ -426,7 +422,7 @@ static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
 		return 0;	// -EAGAIN makes cat whinge
 	}
 
-	return rtlx_read(minor, buffer, count, 1);
+	return rtlx_read(minor, buffer, count);
 }
 
 static ssize_t file_write(struct file *file, const char __user * buffer,
@@ -452,7 +448,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
 			return ret;
 	}
 
-	return rtlx_write(minor, (void *)buffer, count, 1);
+	return rtlx_write(minor, buffer, count);
 }
 
 static const struct file_operations rtlx_fops = {