diff mbox

CHROMIUM: dma-buf: restore args on failure of dma_buf_mmap

Message ID 1360633824-2563-1-git-send-email-sheu@google.com
State Accepted
Commit 495c10cc1c0c359871d5bef32dd173252fc17995
Headers show

Commit Message

sheu@google.com Feb. 12, 2013, 1:50 a.m. UTC
From: John Sheu <sheu@google.com>

Callers to dma_buf_mmap expect to fput() the vma struct's vm_file
themselves on failure.  Not restoring the struct's data on failure
causes a double-decrement of the vm_file's refcount.

Signed-off-by: John Sheu <sheu@google.com>

---
 drivers/base/dma-buf.c |   21 +++++++++++++++------
 1 files changed, 15 insertions(+), 6 deletions(-)

Comments

Sumit Semwal Feb. 12, 2013, 8:47 a.m. UTC | #1
+dri-devel ML


On 12 February 2013 07:20, <sheu@google.com> wrote:

> From: John Sheu <sheu@google.com>
>
> Callers to dma_buf_mmap expect to fput() the vma struct's vm_file
> themselves on failure.  Not restoring the struct's data on failure
> causes a double-decrement of the vm_file's refcount.
>
> Signed-off-by: John Sheu <sheu@google.com>
>
> ---
>  drivers/base/dma-buf.c |   21 +++++++++++++++------
>  1 files changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
> index 09e6878..06c6225 100644
> --- a/drivers/base/dma-buf.c
> +++ b/drivers/base/dma-buf.c
> @@ -536,6 +536,9 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap);
>  int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
>                  unsigned long pgoff)
>  {
> +       struct file *oldfile;
> +       int ret;
> +
>         if (WARN_ON(!dmabuf || !vma))
>                 return -EINVAL;
>
> @@ -549,15 +552,21 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct
> vm_area_struct *vma,
>                 return -EINVAL;
>
>         /* readjust the vma */
> -       if (vma->vm_file)
> -               fput(vma->vm_file);
> -
> +       get_file(dmabuf->file);
> +       oldfile = vma->vm_file;
>         vma->vm_file = dmabuf->file;
> -       get_file(vma->vm_file);
> -
>         vma->vm_pgoff = pgoff;
>
> -       return dmabuf->ops->mmap(dmabuf, vma);
> +       ret = dmabuf->ops->mmap(dmabuf, vma);
> +       if (ret) {
> +               /* restore old parameters on failure */
> +               vma->vm_file = oldfile;
> +               fput(dmabuf->file);
> +       } else {
> +               if (oldfile)
> +                       fput(oldfile);
> +       }
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_mmap);
>
> --
> 1.7.8.6
>
>
Sumit Semwal Feb. 12, 2013, 8:49 a.m. UTC | #2
+dri-devel ML
>
>
> On 12 February 2013 07:20, <sheu@google.com> wrote:
>>
>> From: John Sheu <sheu@google.com>
>>
>> Callers to dma_buf_mmap expect to fput() the vma struct's vm_file
>> themselves on failure.  Not restoring the struct's data on failure
>> causes a double-decrement of the vm_file's refcount.
>>
>> Signed-off-by: John Sheu <sheu@google.com>
>>
>> ---
>>  drivers/base/dma-buf.c |   21 +++++++++++++++------
>>  1 files changed, 15 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
>> index 09e6878..06c6225 100644
>> --- a/drivers/base/dma-buf.c
>> +++ b/drivers/base/dma-buf.c
>> @@ -536,6 +536,9 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap);
>>  int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
>>                  unsigned long pgoff)
>>  {
>> +       struct file *oldfile;
>> +       int ret;
>> +
>>         if (WARN_ON(!dmabuf || !vma))
>>                 return -EINVAL;
>>
>> @@ -549,15 +552,21 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct
>> vm_area_struct *vma,
>>                 return -EINVAL;
>>
>>         /* readjust the vma */
>> -       if (vma->vm_file)
>> -               fput(vma->vm_file);
>> -
>> +       get_file(dmabuf->file);
>> +       oldfile = vma->vm_file;
>>         vma->vm_file = dmabuf->file;
>> -       get_file(vma->vm_file);
>> -
>>         vma->vm_pgoff = pgoff;
>>
>> -       return dmabuf->ops->mmap(dmabuf, vma);
>> +       ret = dmabuf->ops->mmap(dmabuf, vma);
>> +       if (ret) {
>> +               /* restore old parameters on failure */
>> +               vma->vm_file = oldfile;
>> +               fput(dmabuf->file);
>> +       } else {
>> +               if (oldfile)
>> +                       fput(oldfile);
>> +       }
>> +       return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(dma_buf_mmap);
>>
>> --
>> 1.7.8.6
>>
>
>
>
> --
>
> Thanks and regards,
>
> Sumit Semwal
>
> Linaro Kernel Engineer - Graphics working group
>
> Linaro.org │ Open source software for ARM SoCs
>
> Follow Linaro: Facebook | Twitter | Blog
Daniel Vetter Feb. 14, 2013, 10:46 a.m. UTC | #3
On Tue, Feb 12, 2013 at 2:50 AM,  <sheu@google.com> wrote:
> From: John Sheu <sheu@google.com>
>
> Callers to dma_buf_mmap expect to fput() the vma struct's vm_file
> themselves on failure.  Not restoring the struct's data on failure
> causes a double-decrement of the vm_file's refcount.
>
> Signed-off-by: John Sheu <sheu@google.com>

Yeah, makes sense that this little helper here cleans up any damage it
caused when the callback fails.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> ---
>  drivers/base/dma-buf.c |   21 +++++++++++++++------
>  1 files changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
> index 09e6878..06c6225 100644
> --- a/drivers/base/dma-buf.c
> +++ b/drivers/base/dma-buf.c
> @@ -536,6 +536,9 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap);
>  int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
>                  unsigned long pgoff)
>  {
> +       struct file *oldfile;
> +       int ret;
> +
>         if (WARN_ON(!dmabuf || !vma))
>                 return -EINVAL;
>
> @@ -549,15 +552,21 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
>                 return -EINVAL;
>
>         /* readjust the vma */
> -       if (vma->vm_file)
> -               fput(vma->vm_file);
> -
> +       get_file(dmabuf->file);
> +       oldfile = vma->vm_file;
>         vma->vm_file = dmabuf->file;
> -       get_file(vma->vm_file);
> -
>         vma->vm_pgoff = pgoff;
>
> -       return dmabuf->ops->mmap(dmabuf, vma);
> +       ret = dmabuf->ops->mmap(dmabuf, vma);
> +       if (ret) {
> +               /* restore old parameters on failure */
> +               vma->vm_file = oldfile;
> +               fput(dmabuf->file);
> +       } else {
> +               if (oldfile)
> +                       fput(oldfile);
> +       }
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_mmap);
>
> --
> 1.7.8.6
>
>
> _______________________________________________
> Linaro-mm-sig mailing list
> Linaro-mm-sig@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-mm-sig
Sumit Semwal Feb. 14, 2013, 10:48 a.m. UTC | #4
On 14 February 2013 16:16, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> On Tue, Feb 12, 2013 at 2:50 AM,  <sheu@google.com> wrote:
>> From: John Sheu <sheu@google.com>
>>
>> Callers to dma_buf_mmap expect to fput() the vma struct's vm_file
>> themselves on failure.  Not restoring the struct's data on failure
>> causes a double-decrement of the vm_file's refcount.
>>
>> Signed-off-by: John Sheu <sheu@google.com>
>
> Yeah, makes sense that this little helper here cleans up any damage it
> caused when the callback fails.
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Thanks John, Daniel!

I'll pull it in the for-next soon.

Best regards,
~Sumit.
>>
>> ---
>>  drivers/base/dma-buf.c |   21 +++++++++++++++------
>>  1 files changed, 15 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
>> index 09e6878..06c6225 100644
>> --- a/drivers/base/dma-buf.c
>> +++ b/drivers/base/dma-buf.c
>> @@ -536,6 +536,9 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap);
>>  int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
>>                  unsigned long pgoff)
>>  {
>> +       struct file *oldfile;
>> +       int ret;
>> +
>>         if (WARN_ON(!dmabuf || !vma))
>>                 return -EINVAL;
>>
>> @@ -549,15 +552,21 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
>>                 return -EINVAL;
>>
>>         /* readjust the vma */
>> -       if (vma->vm_file)
>> -               fput(vma->vm_file);
>> -
>> +       get_file(dmabuf->file);
>> +       oldfile = vma->vm_file;
>>         vma->vm_file = dmabuf->file;
>> -       get_file(vma->vm_file);
>> -
>>         vma->vm_pgoff = pgoff;
>>
>> -       return dmabuf->ops->mmap(dmabuf, vma);
>> +       ret = dmabuf->ops->mmap(dmabuf, vma);
>> +       if (ret) {
>> +               /* restore old parameters on failure */
>> +               vma->vm_file = oldfile;
>> +               fput(dmabuf->file);
>> +       } else {
>> +               if (oldfile)
>> +                       fput(oldfile);
>> +       }
>> +       return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(dma_buf_mmap);
>>
>> --
>> 1.7.8.6
>>
>>
>> _______________________________________________
>> Linaro-mm-sig mailing list
>> Linaro-mm-sig@lists.linaro.org
>> http://lists.linaro.org/mailman/listinfo/linaro-mm-sig
>
>
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
diff mbox

Patch

diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 09e6878..06c6225 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -536,6 +536,9 @@  EXPORT_SYMBOL_GPL(dma_buf_kunmap);
 int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
 		 unsigned long pgoff)
 {
+	struct file *oldfile;
+	int ret;
+
 	if (WARN_ON(!dmabuf || !vma))
 		return -EINVAL;
 
@@ -549,15 +552,21 @@  int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
 		return -EINVAL;
 
 	/* readjust the vma */
-	if (vma->vm_file)
-		fput(vma->vm_file);
-
+	get_file(dmabuf->file);
+	oldfile = vma->vm_file;
 	vma->vm_file = dmabuf->file;
-	get_file(vma->vm_file);
-
 	vma->vm_pgoff = pgoff;
 
-	return dmabuf->ops->mmap(dmabuf, vma);
+	ret = dmabuf->ops->mmap(dmabuf, vma);
+	if (ret) {
+		/* restore old parameters on failure */
+		vma->vm_file = oldfile;
+		fput(dmabuf->file);
+	} else {
+		if (oldfile)
+			fput(oldfile);
+	}
+	return ret;
 }
 EXPORT_SYMBOL_GPL(dma_buf_mmap);