Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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

parent bc4809e9
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -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");
}

+21 −25
Original line number Diff line number Diff line
@@ -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 = {
+2 −2
Original line number Diff line number Diff line
@@ -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);