V4L/DVB (8131): dmx_write: memcpy from user-supplied pointer
authorAl Viro <viro@ftp.linux.org.uk>
Sun, 22 Jun 2008 17:20:19 +0000 (14:20 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sun, 20 Jul 2008 10:13:27 +0000 (07:13 -0300)
... copy to kernel memory first

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/dvb/dvb-core/demux.h
drivers/media/dvb/dvb-core/dvb_demux.c

index b0d347daae47a889ba54f89b938ecd8dd3ee46a5..eb91fd808c16307a9d7259f960ff89be70efbd96 100644 (file)
@@ -247,7 +247,7 @@ struct dmx_demux {
        void* priv;                  /* Pointer to private data of the API client */
        int (*open) (struct dmx_demux* demux);
        int (*close) (struct dmx_demux* demux);
-       int (*write) (struct dmx_demux* demux, const charbuf, size_t count);
+       int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
        int (*allocate_ts_feed) (struct dmx_demux* demux,
                                 struct dmx_ts_feed** feed,
                                 dmx_ts_cb callback);
index 934e15fffc565f4660dfc5954a49d1346748d315..e2eca0b1fe7cfad6dc1215aa6d2bd1247497b93e 100644 (file)
@@ -1056,16 +1056,27 @@ static int dvbdmx_close(struct dmx_demux *demux)
        return 0;
 }
 
-static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
+static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
 {
        struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+       void *p;
 
        if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
                return -EINVAL;
 
-       if (mutex_lock_interruptible(&dvbdemux->mutex))
+       p = kmalloc(count, GFP_USER);
+       if (!p)
+               return -ENOMEM;
+       if (copy_from_user(p, buf, count)) {
+               kfree(p);
+               return -EFAULT;
+       }
+       if (mutex_lock_interruptible(&dvbdemux->mutex)) {
+               kfree(p);
                return -ERESTARTSYS;
-       dvb_dmx_swfilter(dvbdemux, (u8 *)buf, count);
+       }
+       dvb_dmx_swfilter(dvbdemux, p, count);
+       kfree(p);
        mutex_unlock(&dvbdemux->mutex);
 
        if (signal_pending(current))