All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Linux Media Mailing List <linux-media@vger.kernel.org>,
	Tomasz Figa <tfiga@chromium.org>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Sakari Ailus <sakari.ailus@linux.intel.com>
Subject: Re: [PATCH for v5.2] videobuf2-core.c: always reacquire USERPTR memory
Date: Fri, 7 Jun 2019 14:01:42 +0200	[thread overview]
Message-ID: <cb129a47-e114-6841-44cc-ec34ffa562c7@xs4all.nl> (raw)
In-Reply-To: <20190607111634.GA7593@pendragon.ideasonboard.com>

On 6/7/19 1:16 PM, Laurent Pinchart wrote:
> Hi Hans,
> 
> Thank you for the patch.
> 
> On Fri, Jun 07, 2019 at 10:45:31AM +0200, Hans Verkuil wrote:
>> The __prepare_userptr() function made the incorrect assumption that if the
>> same user pointer was used as the last one for which memory was acquired, then
>> there was no need to re-acquire the memory. This assumption was never properly
>> tested, and after doing that it became clear that this was in fact wrong.
> 
> Could you explain in the commit message why the assumption is not
> correct ?

You can free the memory, then allocate it again and you can get the same pointer,
even though it is not necessarily using the same physical pages for the memory
that the kernel is still using for it.

Worse, you can free the memory, then allocate only half the memory you need and
get back the same pointer. vb2 wouldn't notice this. And it seems to work (since
the original mapping still remains), but this can corrupt userspace memory
causing the application to crash. It's not quite clear to me how the memory can
get corrupted. I don't know enough of those low-level mm internals to understand
the sequence of events.

I have test code for v4l2-compliance available if someone wants to test this.

> 
>> Change the behavior to always reacquire memory.
> 
> One more reason to not use USERPTR :-)

I agree.

Regards,

	Hans

> 
>> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
>> Reported-by: Tomasz Figa <tfiga@chromium.org>
>> Cc: <stable@vger.kernel.org>      # for v5.1 and up
>> ---
>> This should be backported to all stable kernels, unfortunately this patch only
>> applies cleanly to 5.1, so this has to be backported manually.
>> ---
>> diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
>> index 4489744fbbd9..a6400391117f 100644
>> --- a/drivers/media/common/videobuf2/videobuf2-core.c
>> +++ b/drivers/media/common/videobuf2/videobuf2-core.c
>> @@ -1013,7 +1013,7 @@ static int __prepare_userptr(struct vb2_buffer *vb)
>>  	void *mem_priv;
>>  	unsigned int plane;
>>  	int ret = 0;
>> -	bool reacquired = vb->planes[0].mem_priv == NULL;
>> +	bool called_cleanup = false;
>>
>>  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>>  	/* Copy relevant information provided by the userspace */
>> @@ -1023,15 +1023,6 @@ static int __prepare_userptr(struct vb2_buffer *vb)
>>  		return ret;
>>
>>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>> -		/* Skip the plane if already verified */
>> -		if (vb->planes[plane].m.userptr &&
>> -			vb->planes[plane].m.userptr == planes[plane].m.userptr
>> -			&& vb->planes[plane].length == planes[plane].length)
>> -			continue;
>> -
>> -		dprintk(3, "userspace address for plane %d changed, reacquiring memory\n",
>> -			plane);
>> -
>>  		/* Check if the provided plane buffer is large enough */
>>  		if (planes[plane].length < vb->planes[plane].min_length) {
>>  			dprintk(1, "provided buffer size %u is less than setup size %u for plane %d\n",
>> @@ -1044,8 +1035,8 @@ static int __prepare_userptr(struct vb2_buffer *vb)
>>
>>  		/* Release previously acquired memory if present */
>>  		if (vb->planes[plane].mem_priv) {
>> -			if (!reacquired) {
>> -				reacquired = true;
>> +			if (!called_cleanup) {
>> +				called_cleanup = true;
>>  				vb->copied_timestamp = 0;
>>  				call_void_vb_qop(vb, buf_cleanup, vb);
>>  			}
> 
> Could we do this unconditionally before the loop ?
> 
>> @@ -1083,17 +1074,14 @@ static int __prepare_userptr(struct vb2_buffer *vb)
>>  		vb->planes[plane].data_offset = planes[plane].data_offset;
>>  	}
>>
>> -	if (reacquired) {
>> -		/*
>> -		 * One or more planes changed, so we must call buf_init to do
>> -		 * the driver-specific initialization on the newly acquired
>> -		 * buffer, if provided.
>> -		 */
>> -		ret = call_vb_qop(vb, buf_init, vb);
>> -		if (ret) {
>> -			dprintk(1, "buffer initialization failed\n");
>> -			goto err;
>> -		}
>> +	/*
>> +	 * Call buf_init to do the driver-specific initialization on
>> +	 * the newly acquired buffer.
>> +	 */
>> +	ret = call_vb_qop(vb, buf_init, vb);
>> +	if (ret) {
>> +		dprintk(1, "buffer initialization failed\n");
>> +		goto err;
>>  	}
>>
>>  	ret = call_vb_qop(vb, buf_prepare, vb);
> 


  reply	other threads:[~2019-06-07 12:01 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-07  8:45 [PATCH for v5.2] videobuf2-core.c: always reacquire USERPTR memory Hans Verkuil
2019-06-07 11:16 ` Laurent Pinchart
2019-06-07 12:01   ` Hans Verkuil [this message]
2019-06-07 12:14     ` Marek Szyprowski
2019-06-07 12:23       ` Hans Verkuil
2019-06-07 12:47         ` Hans Verkuil
2019-06-07 13:40           ` Hans Verkuil
2019-06-07 13:53             ` Tomasz Figa
2019-06-07 13:55             ` Marek Szyprowski
2019-06-07 13:58               ` Laurent Pinchart
2019-06-07 19:38                 ` Nicolas Dufresne
2019-06-11 10:24                   ` Laurent Pinchart
2019-06-12  0:09                     ` Nicolas Dufresne
2019-06-12  8:17                       ` Laurent Pinchart
2019-06-13  0:21                         ` Nicolas Dufresne
2019-07-03  9:08                           ` Tomasz Figa
2019-06-07 14:11               ` Hans Verkuil
2019-06-07 14:34                 ` Tomasz Figa
2019-06-07 15:09                   ` Laurent Pinchart
2019-06-11  7:48                   ` Hans Verkuil
2019-06-07 14:39                 ` Marek Szyprowski
2019-06-07 14:44                   ` Sakari Ailus
2019-06-07 19:43                   ` Nicolas Dufresne
2019-06-11  7:52                     ` Hans Verkuil
2019-06-11 11:56                       ` Marek Szyprowski
2019-06-12  0:12                         ` Nicolas Dufresne
2019-06-12  0:18                           ` Nicolas Dufresne
2019-06-07 14:41                 ` Sakari Ailus
2019-06-07 12:20     ` Tomasz Figa
2019-06-07 12:24       ` Hans Verkuil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cb129a47-e114-6841-44cc-ec34ffa562c7@xs4all.nl \
    --to=hverkuil@xs4all.nl \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=sakari.ailus@linux.intel.com \
    --cc=tfiga@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.