From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755590AbcKNDtt (ORCPT ); Sun, 13 Nov 2016 22:49:49 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:44995 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752718AbcKNCEQ (ORCPT ); Sun, 13 Nov 2016 21:04:16 -0500 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "kbuild test robot" , "Mauro Carvalho Chehab" Date: Mon, 14 Nov 2016 00:14:20 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 053/346] [media] ngene: properly handle __user ptr In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.39-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Mauro Carvalho Chehab commit 04da2daee383391954b34e7d0fe0281d75447d61 upstream. 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] *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 Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Ben Hutchings --- drivers/media/dvb-core/dvb_ringbuffer.c | 26 ++++++++++++++++++++++++++ drivers/media/dvb-core/dvb_ringbuffer.h | 2 ++ drivers/media/pci/ngene/ngene-dvb.c | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) --- a/drivers/media/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb-core/dvb_ringbuffer.c @@ -166,6 +166,31 @@ ssize_t dvb_ringbuffer_write(struct dvb_ 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_spinl EXPORT_SYMBOL(dvb_ringbuffer_read_user); EXPORT_SYMBOL(dvb_ringbuffer_read); EXPORT_SYMBOL(dvb_ringbuffer_write); +EXPORT_SYMBOL(dvb_ringbuffer_write_user); --- a/drivers/media/dvb-core/dvb_ringbuffer.h +++ b/drivers/media/dvb-core/dvb_ringbuffer.h @@ -133,6 +133,8 @@ extern void dvb_ringbuffer_read(struct d */ 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); /** --- a/drivers/media/pci/ngene/ngene-dvb.c +++ b/drivers/media/pci/ngene/ngene-dvb.c @@ -59,7 +59,7 @@ static ssize_t ts_write(struct file *fil (&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; }