[media] ivtv: Return EFAULT when copy_from_user() fails in ivtv_write_vbi_from_user()
authorAndy Walls <awalls@md.metrocast.net>
Mon, 20 Dec 2010 00:59:56 +0000 (21:59 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 29 Dec 2010 10:17:10 +0000 (08:17 -0200)
If write() on a VBI device node fails due to a bad buffer pointer from
userspace, we should notify the application properly with EFAULT, per the
V4L2 API spec.

Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-vbi.c
drivers/media/video/ivtv/ivtv-vbi.h

index 4f46b00..c57a585 100644 (file)
@@ -570,9 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
                int elems = count / sizeof(struct v4l2_sliced_vbi_data);
 
                set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               ivtv_write_vbi_from_user(itv,
+               return ivtv_write_vbi_from_user(itv,
                   (const struct v4l2_sliced_vbi_data __user *)user_buf, elems);
-               return elems * sizeof(struct v4l2_sliced_vbi_data);
        }
 
        mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
index 7275f2d..2dfa957 100644 (file)
@@ -157,24 +157,30 @@ static void ivtv_write_vbi(struct ivtv *itv,
                ivtv_write_vbi_cc_lines(itv, &cc);
 }
 
-void ivtv_write_vbi_from_user(struct ivtv *itv,
-                             const struct v4l2_sliced_vbi_data __user *sliced,
-                             size_t cnt)
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+                        const struct v4l2_sliced_vbi_data __user *sliced,
+                        size_t cnt)
 {
        struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
        int found_cc = 0;
        size_t i;
        struct v4l2_sliced_vbi_data d;
+       ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
 
        for (i = 0; i < cnt; i++) {
                if (copy_from_user(&d, sliced + i,
-                                  sizeof(struct v4l2_sliced_vbi_data)))
+                                  sizeof(struct v4l2_sliced_vbi_data))) {
+                       ret = -EFAULT;
                        break;
+               }
                ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
        }
 
        if (found_cc)
                ivtv_write_vbi_cc_lines(itv, &cc);
+
+       return ret;
 }
 
 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
index eda38d0..166dd0b 100644 (file)
 #ifndef IVTV_VBI_H
 #define IVTV_VBI_H
 
-void ivtv_write_vbi_from_user(struct ivtv *itv,
-                             const struct v4l2_sliced_vbi_data __user *sliced,
-                             size_t count);
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+                        const struct v4l2_sliced_vbi_data __user *sliced,
+                        size_t count);
 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
                           u64 pts_stamp, int streamtype);
 int ivtv_used_line(struct ivtv *itv, int line, int field);