Commit 04da2dae authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] ngene: properly handle __user ptr



Sparse is complaining about ngene's bad usage of a __user ptr:

>> drivers/media/pci/ngene/ngene-dvb.c:62:48: sparse: incorrect type in argument 2 (different address spaces)
   drivers/media/pci/ngene/ngene-dvb.c:62:48:    expected unsigned char const [usertype] *buf
   drivers/media/pci/ngene/ngene-dvb.c:62:48:    got char const [noderef] <asn:1>*buf

As this is intercepting a .write() file ops, we can't just memcpy. We need to use
copy_from_user.

Reported-by: default avatarkbuild test robot <fengguang.wu@intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent ce9e1ac1
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -166,6 +166,31 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t
	return len;
}

ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
				  const u8 __user *buf, size_t len)
{
	int status;
	size_t todo = len;
	size_t split;

	split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;

	if (split > 0) {
		status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split);
		if (status)
			return len - todo;
		buf += split;
		todo -= split;
		rbuf->pwrite = 0;
	}
	status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
	if (status)
		return len - todo;
	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;

	return len;
}

ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
{
	int status;
@@ -297,3 +322,4 @@ EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
EXPORT_SYMBOL(dvb_ringbuffer_read_user);
EXPORT_SYMBOL(dvb_ringbuffer_read);
EXPORT_SYMBOL(dvb_ringbuffer_write);
EXPORT_SYMBOL(dvb_ringbuffer_write_user);
+2 −0
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
*/
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
				    size_t len);
extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
				         const u8 __user *buf, size_t len);


/**
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ static ssize_t ts_write(struct file *file, const char __user *buf,
				     (&dev->tsout_rbuf) >= count) < 0)
		return 0;

	dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count);
	dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count);

	return count;
}