diff options
author | Andy Walls <awalls@md.metrocast.net> | 2010-12-19 19:59:56 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-12-29 05:17:10 -0500 |
commit | ddda424999817fbc17adf9013feb066903382ede (patch) | |
tree | 1f75abf4d6a4814519b74fce450296cd495ba56e | |
parent | b0c45686c8e8aecc7b0cd04d9b6af48d74418d53 (diff) |
[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 <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 3 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.c | 14 | ||||
-rw-r--r-- | 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 4f46b0070806..c57a58523ca8 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 | |||
570 | int elems = count / sizeof(struct v4l2_sliced_vbi_data); | 570 | int elems = count / sizeof(struct v4l2_sliced_vbi_data); |
571 | 571 | ||
572 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 572 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
573 | ivtv_write_vbi_from_user(itv, | 573 | return ivtv_write_vbi_from_user(itv, |
574 | (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); | 574 | (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); |
575 | return elems * sizeof(struct v4l2_sliced_vbi_data); | ||
576 | } | 575 | } |
577 | 576 | ||
578 | mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; | 577 | 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 7275f2d6597e..2dfa957b0fd5 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, | |||
157 | ivtv_write_vbi_cc_lines(itv, &cc); | 157 | ivtv_write_vbi_cc_lines(itv, &cc); |
158 | } | 158 | } |
159 | 159 | ||
160 | void ivtv_write_vbi_from_user(struct ivtv *itv, | 160 | ssize_t |
161 | const struct v4l2_sliced_vbi_data __user *sliced, | 161 | ivtv_write_vbi_from_user(struct ivtv *itv, |
162 | size_t cnt) | 162 | const struct v4l2_sliced_vbi_data __user *sliced, |
163 | size_t cnt) | ||
163 | { | 164 | { |
164 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; | 165 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; |
165 | int found_cc = 0; | 166 | int found_cc = 0; |
166 | size_t i; | 167 | size_t i; |
167 | struct v4l2_sliced_vbi_data d; | 168 | struct v4l2_sliced_vbi_data d; |
169 | ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data); | ||
168 | 170 | ||
169 | for (i = 0; i < cnt; i++) { | 171 | for (i = 0; i < cnt; i++) { |
170 | if (copy_from_user(&d, sliced + i, | 172 | if (copy_from_user(&d, sliced + i, |
171 | sizeof(struct v4l2_sliced_vbi_data))) | 173 | sizeof(struct v4l2_sliced_vbi_data))) { |
174 | ret = -EFAULT; | ||
172 | break; | 175 | break; |
176 | } | ||
173 | ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); | 177 | ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); |
174 | } | 178 | } |
175 | 179 | ||
176 | if (found_cc) | 180 | if (found_cc) |
177 | ivtv_write_vbi_cc_lines(itv, &cc); | 181 | ivtv_write_vbi_cc_lines(itv, &cc); |
182 | |||
183 | return ret; | ||
178 | } | 184 | } |
179 | 185 | ||
180 | static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) | 186 | 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 eda38d0ad7ce..166dd0b75d0f 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h | |||
@@ -20,9 +20,10 @@ | |||
20 | #ifndef IVTV_VBI_H | 20 | #ifndef IVTV_VBI_H |
21 | #define IVTV_VBI_H | 21 | #define IVTV_VBI_H |
22 | 22 | ||
23 | void ivtv_write_vbi_from_user(struct ivtv *itv, | 23 | ssize_t |
24 | const struct v4l2_sliced_vbi_data __user *sliced, | 24 | ivtv_write_vbi_from_user(struct ivtv *itv, |
25 | size_t count); | 25 | const struct v4l2_sliced_vbi_data __user *sliced, |
26 | size_t count); | ||
26 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | 27 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, |
27 | u64 pts_stamp, int streamtype); | 28 | u64 pts_stamp, int streamtype); |
28 | int ivtv_used_line(struct ivtv *itv, int line, int field); | 29 | int ivtv_used_line(struct ivtv *itv, int line, int field); |