Skip to content

Commit fac710e

Browse files
hverkuilmchehab
authored andcommitted
[media] vb2: fix nasty vb2_thread regression
The vb2_thread implementation was made generic and was moved from videobuf2-v4l2.c to videobuf2-core.c in commit af3bac1. Unfortunately that clearly was never tested since it broke read() causing NULL address references. The root cause was confused handling of vb2_buffer vs v4l2_buffer (the pb pointer in various core functions). The v4l2_buffer no longer exists after moving the code into the core and it is no longer needed. However, the vb2_thread code passed a pointer to a vb2_buffer to the core functions were a v4l2_buffer pointer was expected and vb2_thread expected that the vb2_buffer fields would be filled in correctly. This is obviously wrong since v4l2_buffer != vb2_buffer. Note that the pb pointer is a void pointer, so no type-checking took place. This patch fixes this problem: 1) allow pb to be NULL for vb2_core_(d)qbuf. The vb2_thread code will use a NULL pointer here since they don't care about v4l2_buffer anyway. 2) let vb2_core_dqbuf pass back the index of the received buffer. This is all vb2_thread needs: this index is the index into the q->bufs array and vb2_thread just gets the vb2_buffer from there. 3) the fileio->b pointer (that originally contained a v4l2_buffer) is removed altogether since it is no longer needed. Tested with vivid and the cobalt driver. Cc: [email protected] # Kernel >= 4.3 Signed-off-by: Hans Verkuil <[email protected]> Reported-by: Matthias Schwarzott <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent e8beb02 commit fac710e

File tree

3 files changed

+46
-54
lines changed

3 files changed

+46
-54
lines changed

drivers/media/v4l2-core/videobuf2-core.c

Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,8 +1063,11 @@ EXPORT_SYMBOL_GPL(vb2_discard_done);
10631063
*/
10641064
static int __qbuf_mmap(struct vb2_buffer *vb, const void *pb)
10651065
{
1066-
int ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1067-
vb, pb, vb->planes);
1066+
int ret = 0;
1067+
1068+
if (pb)
1069+
ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1070+
vb, pb, vb->planes);
10681071
return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
10691072
}
10701073

@@ -1077,14 +1080,16 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb)
10771080
struct vb2_queue *q = vb->vb2_queue;
10781081
void *mem_priv;
10791082
unsigned int plane;
1080-
int ret;
1083+
int ret = 0;
10811084
enum dma_data_direction dma_dir =
10821085
q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
10831086
bool reacquired = vb->planes[0].mem_priv == NULL;
10841087

10851088
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
10861089
/* Copy relevant information provided by the userspace */
1087-
ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
1090+
if (pb)
1091+
ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1092+
vb, pb, planes);
10881093
if (ret)
10891094
return ret;
10901095

@@ -1192,14 +1197,16 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb)
11921197
struct vb2_queue *q = vb->vb2_queue;
11931198
void *mem_priv;
11941199
unsigned int plane;
1195-
int ret;
1200+
int ret = 0;
11961201
enum dma_data_direction dma_dir =
11971202
q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
11981203
bool reacquired = vb->planes[0].mem_priv == NULL;
11991204

12001205
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
12011206
/* Copy relevant information provided by the userspace */
1202-
ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
1207+
if (pb)
1208+
ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
1209+
vb, pb, planes);
12031210
if (ret)
12041211
return ret;
12051212

@@ -1520,7 +1527,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
15201527
q->waiting_for_buffers = false;
15211528
vb->state = VB2_BUF_STATE_QUEUED;
15221529

1523-
call_void_bufop(q, copy_timestamp, vb, pb);
1530+
if (pb)
1531+
call_void_bufop(q, copy_timestamp, vb, pb);
15241532

15251533
trace_vb2_qbuf(q, vb);
15261534

@@ -1532,7 +1540,8 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
15321540
__enqueue_in_driver(vb);
15331541

15341542
/* Fill buffer information for the userspace */
1535-
call_void_bufop(q, fill_user_buffer, vb, pb);
1543+
if (pb)
1544+
call_void_bufop(q, fill_user_buffer, vb, pb);
15361545

15371546
/*
15381547
* If streamon has been called, and we haven't yet called
@@ -1731,7 +1740,8 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
17311740
* The return values from this function are intended to be directly returned
17321741
* from vidioc_dqbuf handler in driver.
17331742
*/
1734-
int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
1743+
int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
1744+
bool nonblocking)
17351745
{
17361746
struct vb2_buffer *vb = NULL;
17371747
int ret;
@@ -1754,8 +1764,12 @@ int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
17541764

17551765
call_void_vb_qop(vb, buf_finish, vb);
17561766

1767+
if (pindex)
1768+
*pindex = vb->index;
1769+
17571770
/* Fill buffer information for the userspace */
1758-
call_void_bufop(q, fill_user_buffer, vb, pb);
1771+
if (pb)
1772+
call_void_bufop(q, fill_user_buffer, vb, pb);
17591773

17601774
/* Remove from videobuf queue */
17611775
list_del(&vb->queued_entry);
@@ -1828,7 +1842,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
18281842
* that's done in dqbuf, but that's not going to happen when we
18291843
* cancel the whole queue. Note: this code belongs here, not in
18301844
* __vb2_dqbuf() since in vb2_internal_dqbuf() there is a critical
1831-
* call to __fill_v4l2_buffer() after buf_finish(). That order can't
1845+
* call to __fill_user_buffer() after buf_finish(). That order can't
18321846
* be changed, so we can't move the buf_finish() to __vb2_dqbuf().
18331847
*/
18341848
for (i = 0; i < q->num_buffers; ++i) {
@@ -2357,7 +2371,6 @@ struct vb2_fileio_data {
23572371
unsigned int count;
23582372
unsigned int type;
23592373
unsigned int memory;
2360-
struct vb2_buffer *b;
23612374
struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
23622375
unsigned int cur_index;
23632376
unsigned int initial_index;
@@ -2410,12 +2423,6 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
24102423
if (fileio == NULL)
24112424
return -ENOMEM;
24122425

2413-
fileio->b = kzalloc(q->buf_struct_size, GFP_KERNEL);
2414-
if (fileio->b == NULL) {
2415-
kfree(fileio);
2416-
return -ENOMEM;
2417-
}
2418-
24192426
fileio->read_once = q->fileio_read_once;
24202427
fileio->write_immediately = q->fileio_write_immediately;
24212428

@@ -2460,13 +2467,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
24602467
* Queue all buffers.
24612468
*/
24622469
for (i = 0; i < q->num_buffers; i++) {
2463-
struct vb2_buffer *b = fileio->b;
2464-
2465-
memset(b, 0, q->buf_struct_size);
2466-
b->type = q->type;
2467-
b->memory = q->memory;
2468-
b->index = i;
2469-
ret = vb2_core_qbuf(q, i, b);
2470+
ret = vb2_core_qbuf(q, i, NULL);
24702471
if (ret)
24712472
goto err_reqbufs;
24722473
fileio->bufs[i].queued = 1;
@@ -2511,7 +2512,6 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q)
25112512
q->fileio = NULL;
25122513
fileio->count = 0;
25132514
vb2_core_reqbufs(q, fileio->memory, &fileio->count);
2514-
kfree(fileio->b);
25152515
kfree(fileio);
25162516
dprintk(3, "file io emulator closed\n");
25172517
}
@@ -2539,7 +2539,8 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
25392539
* else is able to provide this information with the write() operation.
25402540
*/
25412541
bool copy_timestamp = !read && q->copy_timestamp;
2542-
int ret, index;
2542+
unsigned index;
2543+
int ret;
25432544

25442545
dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
25452546
read ? "read" : "write", (long)*ppos, count,
@@ -2564,22 +2565,20 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
25642565
*/
25652566
index = fileio->cur_index;
25662567
if (index >= q->num_buffers) {
2567-
struct vb2_buffer *b = fileio->b;
2568+
struct vb2_buffer *b;
25682569

25692570
/*
25702571
* Call vb2_dqbuf to get buffer back.
25712572
*/
2572-
memset(b, 0, q->buf_struct_size);
2573-
b->type = q->type;
2574-
b->memory = q->memory;
2575-
ret = vb2_core_dqbuf(q, b, nonblock);
2573+
ret = vb2_core_dqbuf(q, &index, NULL, nonblock);
25762574
dprintk(5, "vb2_dqbuf result: %d\n", ret);
25772575
if (ret)
25782576
return ret;
25792577
fileio->dq_count += 1;
25802578

2581-
fileio->cur_index = index = b->index;
2579+
fileio->cur_index = index;
25822580
buf = &fileio->bufs[index];
2581+
b = q->bufs[index];
25832582

25842583
/*
25852584
* Get number of bytes filled by the driver
@@ -2630,7 +2629,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
26302629
* Queue next buffer if required.
26312630
*/
26322631
if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
2633-
struct vb2_buffer *b = fileio->b;
2632+
struct vb2_buffer *b = q->bufs[index];
26342633

26352634
/*
26362635
* Check if this is the last buffer to read.
@@ -2643,15 +2642,11 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
26432642
/*
26442643
* Call vb2_qbuf and give buffer to the driver.
26452644
*/
2646-
memset(b, 0, q->buf_struct_size);
2647-
b->type = q->type;
2648-
b->memory = q->memory;
2649-
b->index = index;
26502645
b->planes[0].bytesused = buf->pos;
26512646

26522647
if (copy_timestamp)
26532648
b->timestamp = ktime_get_ns();
2654-
ret = vb2_core_qbuf(q, index, b);
2649+
ret = vb2_core_qbuf(q, index, NULL);
26552650
dprintk(5, "vb2_dbuf result: %d\n", ret);
26562651
if (ret)
26572652
return ret;
@@ -2713,10 +2708,9 @@ static int vb2_thread(void *data)
27132708
{
27142709
struct vb2_queue *q = data;
27152710
struct vb2_threadio_data *threadio = q->threadio;
2716-
struct vb2_fileio_data *fileio = q->fileio;
27172711
bool copy_timestamp = false;
2718-
int prequeue = 0;
2719-
int index = 0;
2712+
unsigned prequeue = 0;
2713+
unsigned index = 0;
27202714
int ret = 0;
27212715

27222716
if (q->is_output) {
@@ -2728,37 +2722,34 @@ static int vb2_thread(void *data)
27282722

27292723
for (;;) {
27302724
struct vb2_buffer *vb;
2731-
struct vb2_buffer *b = fileio->b;
27322725

27332726
/*
27342727
* Call vb2_dqbuf to get buffer back.
27352728
*/
2736-
memset(b, 0, q->buf_struct_size);
2737-
b->type = q->type;
2738-
b->memory = q->memory;
27392729
if (prequeue) {
2740-
b->index = index++;
2730+
vb = q->bufs[index++];
27412731
prequeue--;
27422732
} else {
27432733
call_void_qop(q, wait_finish, q);
27442734
if (!threadio->stop)
2745-
ret = vb2_core_dqbuf(q, b, 0);
2735+
ret = vb2_core_dqbuf(q, &index, NULL, 0);
27462736
call_void_qop(q, wait_prepare, q);
27472737
dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
2738+
if (!ret)
2739+
vb = q->bufs[index];
27482740
}
27492741
if (ret || threadio->stop)
27502742
break;
27512743
try_to_freeze();
27522744

2753-
vb = q->bufs[b->index];
2754-
if (b->state == VB2_BUF_STATE_DONE)
2745+
if (vb->state == VB2_BUF_STATE_DONE)
27552746
if (threadio->fnc(vb, threadio->priv))
27562747
break;
27572748
call_void_qop(q, wait_finish, q);
27582749
if (copy_timestamp)
2759-
b->timestamp = ktime_get_ns();;
2750+
vb->timestamp = ktime_get_ns();;
27602751
if (!threadio->stop)
2761-
ret = vb2_core_qbuf(q, b->index, b);
2752+
ret = vb2_core_qbuf(q, vb->index, NULL);
27622753
call_void_qop(q, wait_prepare, q);
27632754
if (ret || threadio->stop)
27642755
break;

drivers/media/v4l2-core/videobuf2-v4l2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
625625
return -EINVAL;
626626
}
627627

628-
ret = vb2_core_dqbuf(q, b, nonblocking);
628+
ret = vb2_core_dqbuf(q, NULL, b, nonblocking);
629629

630630
return ret;
631631
}

include/media/videobuf2-core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
533533
const unsigned int requested_sizes[]);
534534
int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
535535
int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
536-
int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking);
536+
int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb,
537+
bool nonblocking);
537538

538539
int vb2_core_streamon(struct vb2_queue *q, unsigned int type);
539540
int vb2_core_streamoff(struct vb2_queue *q, unsigned int type);

0 commit comments

Comments
 (0)