Commit 46230aa6 authored by Ralf Baechle's avatar Ralf Baechle

[MIPS] RTLX: Handle copy_*_user return values.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent bc4809e9
...@@ -191,6 +191,8 @@ void sp_work_handle_request(void) ...@@ -191,6 +191,8 @@ void sp_work_handle_request(void)
struct mtsp_syscall_generic generic; struct mtsp_syscall_generic generic;
struct mtsp_syscall_ret ret; struct mtsp_syscall_ret ret;
struct kspd_notifications *n; struct kspd_notifications *n;
unsigned long written;
mm_segment_t old_fs;
struct timeval tv; struct timeval tv;
struct timezone tz; struct timezone tz;
int cmd; int cmd;
...@@ -201,7 +203,11 @@ void sp_work_handle_request(void) ...@@ -201,7 +203,11 @@ void sp_work_handle_request(void)
ret.retval = -1; 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"); printk(KERN_ERR "Expected request but nothing to read\n");
return; return;
} }
...@@ -209,7 +215,8 @@ void sp_work_handle_request(void) ...@@ -209,7 +215,8 @@ void sp_work_handle_request(void)
size = sc.size; size = sc.size;
if (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"); printk(KERN_ERR "Expected request but nothing to read\n");
return; return;
} }
...@@ -282,8 +289,11 @@ void sp_work_handle_request(void) ...@@ -282,8 +289,11 @@ void sp_work_handle_request(void)
if (vpe_getuid(SP_VPE)) if (vpe_getuid(SP_VPE))
sp_setfsuidgid( 0, 0); sp_setfsuidgid( 0, 0);
if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0)) old_fs = get_fs();
< sizeof(struct mtsp_syscall_ret)) 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"); printk("KSPD: sp_work_handle_request failed to send to SP\n");
} }
......
...@@ -289,26 +289,11 @@ unsigned int rtlx_write_poll(int index) ...@@ -289,26 +289,11 @@ unsigned int rtlx_write_poll(int index)
return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); 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) ssize_t rtlx_read(int index, void __user *buff, 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)
{ {
size_t lx_write, fl = 0L; size_t lx_write, fl = 0L;
struct rtlx_channel *lx; struct rtlx_channel *lx;
unsigned long failed;
if (rtlx == NULL) if (rtlx == NULL)
return -ENOSYS; return -ENOSYS;
...@@ -327,11 +312,16 @@ ssize_t rtlx_read(int index, void *buff, size_t count, int user) ...@@ -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 */ /* then how much from the read pointer onwards */
fl = min(count, (size_t)lx->buffer_size - lx->lx_read); 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 */ /* and if there is anything left at the beginning of the buffer */
if (count - fl) 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(); smp_wmb();
lx->lx_read = (lx->lx_read + count) % lx->buffer_size; 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) ...@@ -341,7 +331,7 @@ ssize_t rtlx_read(int index, void *buff, size_t count, int user)
return count; 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; struct rtlx_channel *rt;
size_t rt_read; size_t rt_read;
...@@ -363,11 +353,17 @@ ssize_t rtlx_write(int index, void *buffer, size_t count, int user) ...@@ -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 */ /* first bit from write pointer to the end of the buffer, or count */
fl = min(count, (size_t) rt->buffer_size - rt->rt_write); 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 there's any left copy to the beginning of the buffer */
if (count - fl) if (count - fl) {
copy_from(rt->rt_buffer, buffer + fl, count - fl, user); failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
}
out:
count -= cailed;
smp_wmb(); smp_wmb();
rt->rt_write = (rt->rt_write + count) % rt->buffer_size; 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, ...@@ -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 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, 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, ...@@ -452,7 +448,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
return ret; return ret;
} }
return rtlx_write(minor, (void *)buffer, count, 1); return rtlx_write(minor, buffer, count);
} }
static const struct file_operations rtlx_fops = { static const struct file_operations rtlx_fops = {
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
extern int rtlx_open(int index, int can_sleep); extern int rtlx_open(int index, int can_sleep);
extern int rtlx_release(int index); extern int rtlx_release(int index);
extern ssize_t rtlx_read(int index, void *buff, size_t count, int user); extern ssize_t rtlx_read(int index, void __user *buff, size_t count);
extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user); extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count);
extern unsigned int rtlx_read_poll(int index, int can_sleep); extern unsigned int rtlx_read_poll(int index, int can_sleep);
extern unsigned int rtlx_write_poll(int index); extern unsigned int rtlx_write_poll(int index);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment