From ddda424999817fbc17adf9013feb066903382ede Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 19 Dec 2010 21:59:56 -0300 Subject: [PATCH] [media] ivtv: Return EFAULT when copy_from_user() fails in ivtv_write_vbi_from_user() 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-fileops.c | 3 +-- drivers/media/video/ivtv/ivtv-vbi.c | 14 ++++++++++---- drivers/media/video/ivtv/ivtv-vbi.h | 7 ++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 4f46b00..c57a585 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -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; diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 7275f2d..2dfa957 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -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) diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index eda38d0..166dd0b 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -20,9 +20,10 @@ #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); -- 2.7.4