Skip to content

Commit

Permalink
[MIPS] RTLX: Handle copy_*_user return values.
Browse files Browse the repository at this point in the history
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle committed Mar 17, 2007
1 parent bc4809e commit 46230aa
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 31 deletions.
18 changes: 14 additions & 4 deletions arch/mips/kernel/kspd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -201,15 +203,20 @@ 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;
}

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

Expand Down
46 changes: 21 additions & 25 deletions arch/mips/kernel/rtlx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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 = {
Expand Down
4 changes: 2 additions & 2 deletions include/asm-mips/rtlx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 46230aa

Please sign in to comment.