Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>

+29 -1
+26
drivers/media/dvb-core/dvb_ringbuffer.c
··· 166 166 return len; 167 167 } 168 168 169 + ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, 170 + const u8 __user *buf, size_t len) 171 + { 172 + int status; 173 + size_t todo = len; 174 + size_t split; 175 + 176 + split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; 177 + 178 + if (split > 0) { 179 + status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split); 180 + if (status) 181 + return len - todo; 182 + buf += split; 183 + todo -= split; 184 + rbuf->pwrite = 0; 185 + } 186 + status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo); 187 + if (status) 188 + return len - todo; 189 + rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size; 190 + 191 + return len; 192 + } 193 + 169 194 ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) 170 195 { 171 196 int status; ··· 322 297 EXPORT_SYMBOL(dvb_ringbuffer_read_user); 323 298 EXPORT_SYMBOL(dvb_ringbuffer_read); 324 299 EXPORT_SYMBOL(dvb_ringbuffer_write); 300 + EXPORT_SYMBOL(dvb_ringbuffer_write_user);
+2
drivers/media/dvb-core/dvb_ringbuffer.h
··· 133 133 */ 134 134 extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, 135 135 size_t len); 136 + extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, 137 + const u8 __user *buf, size_t len); 136 138 137 139 138 140 /**
+1 -1
drivers/media/pci/ngene/ngene-dvb.c
··· 59 59 (&dev->tsout_rbuf) >= count) < 0) 60 60 return 0; 61 61 62 - dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); 62 + dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count); 63 63 64 64 return count; 65 65 }