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

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Ralf Baechle 2007-03-16 12:16:27 +00:00
parent bc4809e939
commit 46230aa6ea
3 changed files with 37 additions and 31 deletions

View file

@ -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");
}

View file

@ -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 = {

View file

@ -23,8 +23,8 @@
extern int rtlx_open(int index, int can_sleep);
extern int rtlx_release(int index);
extern ssize_t rtlx_read(int index, void *buff, size_t count, int user);
extern ssize_t rtlx_write(int index, void *buffer, 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, const void __user *buffer, size_t count);
extern unsigned int rtlx_read_poll(int index, int can_sleep);
extern unsigned int rtlx_write_poll(int index);