diff options
| author | Alexander Viro <viro@parcelfarce.linux.theplanet.co.uk> | 2004-07-12 21:00:50 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-07-12 21:00:50 -0700 |
| commit | ebabc32db2c2156da56b14bb7a1862a682e02204 (patch) | |
| tree | 59fac6d788194850a26f2493ff82785b4cfb6241 | |
| parent | cb915a90d793d4dbc405492ac054909a3b284de3 (diff) | |
[PATCH] sparse: saa fix
direct write to userland pointer.
| -rw-r--r-- | drivers/media/video/saa5246a.c | 97 |
1 files changed, 50 insertions, 47 deletions
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 7226ef56f1e3..c2fb64d57ca7 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -485,73 +485,76 @@ static inline int saa5246a_get_status(struct saa5246a_device *t, static inline int saa5246a_get_page(struct saa5246a_device *t, vtx_pagereq_t *req) { - int start, end; + int start, end, size; + char *buf; + int err; if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || req->start > req->end || req->end >= VTX_PAGESIZE) return -EINVAL; - /* Read "normal" part of page */ - end = min(req->end, VTX_PAGESIZE - 1); - if (i2c_senddata(t, SAA5246A_REGISTER_R8, - req->pgbuf | - R8_DO_NOT_CLEAR_MEMORY, + buf = kmalloc(VTX_PAGESIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - ROW(req->start), + /* Read "normal" part of page */ + err = -EIO; - COLUMN(req->start), + end = min(req->end, VTX_PAGESIZE - 1); + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + req->pgbuf | R8_DO_NOT_CLEAR_MEMORY, + ROW(req->start), COLUMN(req->start), COMMAND_END)) + goto out; + if (i2c_getdata(t, end - req->start + 1, buf)) + goto out; + err = -EFAULT; + if (copy_to_user(req->buffer, buf, end - req->start + 1)) + goto out; - COMMAND_END) || - i2c_getdata(t, end - req->start + 1, req->buffer)) - { - return -EIO; - } /* Always get the time from buffer 4, since this stupid SAA5246A only * updates the currently displayed buffer... */ - if (REQ_CONTAINS_TIME(req)) - { + if (REQ_CONTAINS_TIME(req)) { start = max(req->start, POS_TIME_START); end = min(req->end, POS_TIME_END); + size = end - start + 1; + err = -EINVAL; + if (size < 0) + goto out; + err = -EIO; if (i2c_senddata(t, SAA5246A_REGISTER_R8, - - R8_ACTIVE_CHAPTER_4 | - R8_DO_NOT_CLEAR_MEMORY, - - R9_CURSER_ROW_0, - - start, - - COMMAND_END) || - i2c_getdata(t, end - start + 1, - req->buffer + start - req->start)) - { - return -EIO; - } + R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY, + R9_CURSER_ROW_0, start, COMMAND_END)) + goto out; + if (i2c_getdata(t, size, buf)) + goto out; + err = -EFAULT; + if (copy_to_user(req->buffer + start - req->start, buf, size)) + goto out; } /* Insert the header from buffer 4 only, if acquisition circuit is still searching for a page */ - if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf]) - { + if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf]) { start = max(req->start, POS_HEADER_START); end = min(req->end, POS_HEADER_END); + size = end - start + 1; + err = -EINVAL; + if (size < 0) + goto out; + err = -EIO; if (i2c_senddata(t, SAA5246A_REGISTER_R8, - - R8_ACTIVE_CHAPTER_4 | - R8_DO_NOT_CLEAR_MEMORY, - - R9_CURSER_ROW_0, - - start, - - COMMAND_END) || - i2c_getdata(t, end - start + 1, - req->buffer + start - req->start)) - { - return -EIO; - } + R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY, + R9_CURSER_ROW_0, start, COMMAND_END)) + goto out; + if (i2c_getdata(t, end - start + 1, buf)) + goto out; + err = -EFAULT; + if (copy_to_user(req->buffer + start - req->start, buf, size)) + goto out; } - - return 0; + err = 0; +out: + kfree(buf); + return err; } /* Stops the acquisition circuit given in dau_no. The page buffer associated |
