* [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault()
@ 2019-08-23 22:17 Ralph Campbell
2019-08-23 22:17 ` [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug Ralph Campbell
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Ralph Campbell @ 2019-08-23 22:17 UTC (permalink / raw)
To: linux-mm
Cc: linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Jason Gunthorpe, Andrew Morton,
Christoph Hellwig, Ralph Campbell
I have been working on converting Jerome's hmm_dummy driver and self
tests into a stand-alone set of tests to be included in
tools/testing/selftests/vm and came across these two bug fixes in the
process. The tests aren't quite ready to be posted as a patch.
I'm posting the fixes now since I thought they shouldn't wait.
They should probably have a fixes line but with all the HMM changes,
I wasn't sure exactly which commit to use.
These are based on top of Jason's latest hmm branch.
Ralph Campbell (2):
mm/hmm: hmm_range_fault() NULL pointer bug
mm/hmm: hmm_range_fault() infinite loop
mm/hmm.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug
2019-08-23 22:17 [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Ralph Campbell
@ 2019-08-23 22:17 ` Ralph Campbell
2019-08-24 22:37 ` Christoph Hellwig
2019-08-23 22:17 ` [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop Ralph Campbell
2019-08-27 22:48 ` [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Jason Gunthorpe
2 siblings, 1 reply; 12+ messages in thread
From: Ralph Campbell @ 2019-08-23 22:17 UTC (permalink / raw)
To: linux-mm
Cc: linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Jason Gunthorpe, Andrew Morton,
Christoph Hellwig, Ralph Campbell
Although hmm_range_fault() calls find_vma() to make sure that a vma exists
before calling walk_page_range(), hmm_vma_walk_hole() can still be called
with walk->vma == NULL if the start and end address are not contained
within the vma range.
hmm_range_fault() /* calls find_vma() but no range check */
walk_page_range() /* calls find_vma(), sets walk->vma = NULL */
__walk_page_range()
walk_pgd_range()
walk_p4d_range()
walk_pud_range()
hmm_vma_walk_hole()
hmm_vma_walk_hole_()
hmm_vma_do_fault()
handle_mm_fault(vma=0)
Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
---
mm/hmm.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/mm/hmm.c b/mm/hmm.c
index fc05c8fe78b4..29371485fe94 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -229,6 +229,9 @@ static int hmm_vma_do_fault(struct mm_walk *walk, unsigned long addr,
struct vm_area_struct *vma = walk->vma;
vm_fault_t ret;
+ if (!vma)
+ goto err;
+
if (hmm_vma_walk->flags & HMM_FAULT_ALLOW_RETRY)
flags |= FAULT_FLAG_ALLOW_RETRY;
if (write_fault)
@@ -239,12 +242,14 @@ static int hmm_vma_do_fault(struct mm_walk *walk, unsigned long addr,
/* Note, handle_mm_fault did up_read(&mm->mmap_sem)) */
return -EAGAIN;
}
- if (ret & VM_FAULT_ERROR) {
- *pfn = range->values[HMM_PFN_ERROR];
- return -EFAULT;
- }
+ if (ret & VM_FAULT_ERROR)
+ goto err;
return -EBUSY;
+
+err:
+ *pfn = range->values[HMM_PFN_ERROR];
+ return -EFAULT;
}
static int hmm_pfns_bad(unsigned long addr,
--
2.20.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop
2019-08-23 22:17 [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Ralph Campbell
2019-08-23 22:17 ` [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug Ralph Campbell
@ 2019-08-23 22:17 ` Ralph Campbell
2019-08-24 22:39 ` Christoph Hellwig
2019-08-27 18:41 ` Jason Gunthorpe
2019-08-27 22:48 ` [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Jason Gunthorpe
2 siblings, 2 replies; 12+ messages in thread
From: Ralph Campbell @ 2019-08-23 22:17 UTC (permalink / raw)
To: linux-mm
Cc: linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Jason Gunthorpe, Andrew Morton,
Christoph Hellwig, Ralph Campbell
Normally, callers to handle_mm_fault() are supposed to check the
vma->vm_flags first. hmm_range_fault() checks for VM_READ but doesn't
check for VM_WRITE if the caller requests a page to be faulted in
with write permission (via the hmm_range.pfns[] value).
If the vma is write protected, this can result in an infinite loop:
hmm_range_fault()
walk_page_range()
...
hmm_vma_walk_hole()
hmm_vma_walk_hole_()
hmm_vma_do_fault()
handle_mm_fault(FAULT_FLAG_WRITE)
/* returns VM_FAULT_WRITE */
/* returns -EBUSY */
/* returns -EBUSY */
/* returns -EBUSY */
/* loops on -EBUSY and range->valid */
Prevent this by checking for vma->vm_flags & VM_WRITE before calling
handle_mm_fault().
Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
---
mm/hmm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mm/hmm.c b/mm/hmm.c
index 29371485fe94..4882b83aeccb 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -292,6 +292,9 @@ static int hmm_vma_walk_hole_(unsigned long addr, unsigned long end,
hmm_vma_walk->last = addr;
i = (addr - range->start) >> PAGE_SHIFT;
+ if (write_fault && walk->vma && !(walk->vma->vm_flags & VM_WRITE))
+ return -EPERM;
+
for (; addr < end; addr += PAGE_SIZE, i++) {
pfns[i] = range->values[HMM_PFN_NONE];
if (fault || write_fault) {
--
2.20.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug
2019-08-23 22:17 ` [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug Ralph Campbell
@ 2019-08-24 22:37 ` Christoph Hellwig
2019-08-26 18:02 ` Ralph Campbell
0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2019-08-24 22:37 UTC (permalink / raw)
To: Ralph Campbell
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Jason Gunthorpe, Andrew Morton,
Christoph Hellwig
On Fri, Aug 23, 2019 at 03:17:52PM -0700, Ralph Campbell wrote:
> Although hmm_range_fault() calls find_vma() to make sure that a vma exists
> before calling walk_page_range(), hmm_vma_walk_hole() can still be called
> with walk->vma == NULL if the start and end address are not contained
> within the vma range.
Should we convert to walk_vma_range instead? Or keep walk_page_range
but drop searching the vma ourselves?
Except for that the patch looks good to me:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop
2019-08-23 22:17 ` [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop Ralph Campbell
@ 2019-08-24 22:39 ` Christoph Hellwig
2019-08-27 18:41 ` Jason Gunthorpe
1 sibling, 0 replies; 12+ messages in thread
From: Christoph Hellwig @ 2019-08-24 22:39 UTC (permalink / raw)
To: Ralph Campbell
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Jason Gunthorpe, Andrew Morton,
Christoph Hellwig
On Fri, Aug 23, 2019 at 03:17:53PM -0700, Ralph Campbell wrote:
> Normally, callers to handle_mm_fault() are supposed to check the
> vma->vm_flags first. hmm_range_fault() checks for VM_READ but doesn't
> check for VM_WRITE if the caller requests a page to be faulted in
> with write permission (via the hmm_range.pfns[] value).
> If the vma is write protected, this can result in an infinite loop:
> hmm_range_fault()
> walk_page_range()
> ...
> hmm_vma_walk_hole()
> hmm_vma_walk_hole_()
> hmm_vma_do_fault()
> handle_mm_fault(FAULT_FLAG_WRITE)
> /* returns VM_FAULT_WRITE */
> /* returns -EBUSY */
> /* returns -EBUSY */
> /* returns -EBUSY */
> /* loops on -EBUSY and range->valid */
> Prevent this by checking for vma->vm_flags & VM_WRITE before calling
> handle_mm_fault().
>
> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug
2019-08-24 22:37 ` Christoph Hellwig
@ 2019-08-26 18:02 ` Ralph Campbell
2019-08-26 18:09 ` Jason Gunthorpe
0 siblings, 1 reply; 12+ messages in thread
From: Ralph Campbell @ 2019-08-26 18:02 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Jason Gunthorpe, Andrew Morton
On 8/24/19 3:37 PM, Christoph Hellwig wrote:
> On Fri, Aug 23, 2019 at 03:17:52PM -0700, Ralph Campbell wrote:
>> Although hmm_range_fault() calls find_vma() to make sure that a vma exists
>> before calling walk_page_range(), hmm_vma_walk_hole() can still be called
>> with walk->vma == NULL if the start and end address are not contained
>> within the vma range.
>
> Should we convert to walk_vma_range instead? Or keep walk_page_range
> but drop searching the vma ourselves?
>
> Except for that the patch looks good to me:
>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
>
I think keeping the call to walk_page_range() makes sense.
Jason is hoping to be able to snapshot a range with & without vmas
and have the pfns[] filled with empty/valid entries as appropriate.
I plan to repost my patch changing hmm_range_fault() to use
walk.test_walk which will remove the call to find_vma().
Jason had some concerns about testing it so that's why I have
been working on some HMM self tests before resending it.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug
2019-08-26 18:02 ` Ralph Campbell
@ 2019-08-26 18:09 ` Jason Gunthorpe
2019-08-26 18:21 ` Ralph Campbell
0 siblings, 1 reply; 12+ messages in thread
From: Jason Gunthorpe @ 2019-08-26 18:09 UTC (permalink / raw)
To: Ralph Campbell
Cc: Christoph Hellwig, linux-mm, linux-kernel, amd-gfx, dri-devel,
nouveau, Jérôme Glisse, Andrew Morton
On Mon, Aug 26, 2019 at 11:02:12AM -0700, Ralph Campbell wrote:
>
> On 8/24/19 3:37 PM, Christoph Hellwig wrote:
> > On Fri, Aug 23, 2019 at 03:17:52PM -0700, Ralph Campbell wrote:
> > > Although hmm_range_fault() calls find_vma() to make sure that a vma exists
> > > before calling walk_page_range(), hmm_vma_walk_hole() can still be called
> > > with walk->vma == NULL if the start and end address are not contained
> > > within the vma range.
> >
> > Should we convert to walk_vma_range instead? Or keep walk_page_range
> > but drop searching the vma ourselves?
> >
> > Except for that the patch looks good to me:
> >
> > Reviewed-by: Christoph Hellwig <hch@lst.de>
> >
>
> I think keeping the call to walk_page_range() makes sense.
> Jason is hoping to be able to snapshot a range with & without vmas
> and have the pfns[] filled with empty/valid entries as appropriate.
>
> I plan to repost my patch changing hmm_range_fault() to use
> walk.test_walk which will remove the call to find_vma().
> Jason had some concerns about testing it so that's why I have
> been working on some HMM self tests before resending it.
I'm really excited to see tests for hmm_range_fault()!
Did you find this bug with the tests??
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug
2019-08-26 18:09 ` Jason Gunthorpe
@ 2019-08-26 18:21 ` Ralph Campbell
0 siblings, 0 replies; 12+ messages in thread
From: Ralph Campbell @ 2019-08-26 18:21 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Christoph Hellwig, linux-mm, linux-kernel, amd-gfx, dri-devel,
nouveau, Jérôme Glisse, Andrew Morton
On 8/26/19 11:09 AM, Jason Gunthorpe wrote:
> On Mon, Aug 26, 2019 at 11:02:12AM -0700, Ralph Campbell wrote:
>>
>> On 8/24/19 3:37 PM, Christoph Hellwig wrote:
>>> On Fri, Aug 23, 2019 at 03:17:52PM -0700, Ralph Campbell wrote:
>>>> Although hmm_range_fault() calls find_vma() to make sure that a vma exists
>>>> before calling walk_page_range(), hmm_vma_walk_hole() can still be called
>>>> with walk->vma == NULL if the start and end address are not contained
>>>> within the vma range.
>>>
>>> Should we convert to walk_vma_range instead? Or keep walk_page_range
>>> but drop searching the vma ourselves?
>>>
>>> Except for that the patch looks good to me:
>>>
>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
>>>
>>
>> I think keeping the call to walk_page_range() makes sense.
>> Jason is hoping to be able to snapshot a range with & without vmas
>> and have the pfns[] filled with empty/valid entries as appropriate.
>>
>> I plan to repost my patch changing hmm_range_fault() to use
>> walk.test_walk which will remove the call to find_vma().
>> Jason had some concerns about testing it so that's why I have
>> been working on some HMM self tests before resending it.
>
> I'm really excited to see tests for hmm_range_fault()!
>
> Did you find this bug with the tests??
>
> Jason
>
Yes, I found both bugs with the tests.
I started with Jerome's hmm_dummy driver and user level test code.
Hopefully I can send it out this week.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop
2019-08-23 22:17 ` [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop Ralph Campbell
2019-08-24 22:39 ` Christoph Hellwig
@ 2019-08-27 18:41 ` Jason Gunthorpe
2019-08-27 20:16 ` Ralph Campbell
1 sibling, 1 reply; 12+ messages in thread
From: Jason Gunthorpe @ 2019-08-27 18:41 UTC (permalink / raw)
To: Ralph Campbell
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Andrew Morton, Christoph Hellwig
On Fri, Aug 23, 2019 at 03:17:53PM -0700, Ralph Campbell wrote:
> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
> mm/hmm.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/mm/hmm.c b/mm/hmm.c
> index 29371485fe94..4882b83aeccb 100644
> +++ b/mm/hmm.c
> @@ -292,6 +292,9 @@ static int hmm_vma_walk_hole_(unsigned long addr, unsigned long end,
> hmm_vma_walk->last = addr;
> i = (addr - range->start) >> PAGE_SHIFT;
>
> + if (write_fault && walk->vma && !(walk->vma->vm_flags & VM_WRITE))
> + return -EPERM;
Can walk->vma be NULL here? hmm_vma_do_fault() touches it
unconditionally.
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop
2019-08-27 18:41 ` Jason Gunthorpe
@ 2019-08-27 20:16 ` Ralph Campbell
2019-08-27 22:22 ` Jason Gunthorpe
0 siblings, 1 reply; 12+ messages in thread
From: Ralph Campbell @ 2019-08-27 20:16 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Andrew Morton, Christoph Hellwig
On 8/27/19 11:41 AM, Jason Gunthorpe wrote:
> On Fri, Aug 23, 2019 at 03:17:53PM -0700, Ralph Campbell wrote:
>
>> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
>> mm/hmm.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/mm/hmm.c b/mm/hmm.c
>> index 29371485fe94..4882b83aeccb 100644
>> +++ b/mm/hmm.c
>> @@ -292,6 +292,9 @@ static int hmm_vma_walk_hole_(unsigned long addr, unsigned long end,
>> hmm_vma_walk->last = addr;
>> i = (addr - range->start) >> PAGE_SHIFT;
>>
>> + if (write_fault && walk->vma && !(walk->vma->vm_flags & VM_WRITE))
>> + return -EPERM;
>
> Can walk->vma be NULL here? hmm_vma_do_fault() touches it
> unconditionally.
>
> Jason
>
walk->vma can be NULL. hmm_vma_do_fault() no longer touches it
unconditionally, that is what the preceding patch fixes.
I suppose I could change hmm_vma_walk_hole_() to check for NULL
and fill in the pfns[] array, I just chose to handle it in
hmm_vma_do_fault().
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop
2019-08-27 20:16 ` Ralph Campbell
@ 2019-08-27 22:22 ` Jason Gunthorpe
0 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2019-08-27 22:22 UTC (permalink / raw)
To: Ralph Campbell
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Andrew Morton, Christoph Hellwig
On Tue, Aug 27, 2019 at 01:16:13PM -0700, Ralph Campbell wrote:
>
> On 8/27/19 11:41 AM, Jason Gunthorpe wrote:
> > On Fri, Aug 23, 2019 at 03:17:53PM -0700, Ralph Campbell wrote:
> >
> > > Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
> > > mm/hmm.c | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > diff --git a/mm/hmm.c b/mm/hmm.c
> > > index 29371485fe94..4882b83aeccb 100644
> > > +++ b/mm/hmm.c
> > > @@ -292,6 +292,9 @@ static int hmm_vma_walk_hole_(unsigned long addr, unsigned long end,
> > > hmm_vma_walk->last = addr;
> > > i = (addr - range->start) >> PAGE_SHIFT;
> > > + if (write_fault && walk->vma && !(walk->vma->vm_flags & VM_WRITE))
> > > + return -EPERM;
> >
> > Can walk->vma be NULL here? hmm_vma_do_fault() touches it
> > unconditionally.
> >
> > Jason
> >
> walk->vma can be NULL. hmm_vma_do_fault() no longer touches it
> unconditionally, that is what the preceding patch fixes.
> I suppose I could change hmm_vma_walk_hole_() to check for NULL
> and fill in the pfns[] array, I just chose to handle it in
> hmm_vma_do_fault().
Okay, yes maybe long term it would be clearer to do the vma null check
closer to the start of the callback, but this is a good enough bug fix
Reviewed-by: Jason Gunthorpe <jgg@mellanox.com>
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault()
2019-08-23 22:17 [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Ralph Campbell
2019-08-23 22:17 ` [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug Ralph Campbell
2019-08-23 22:17 ` [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop Ralph Campbell
@ 2019-08-27 22:48 ` Jason Gunthorpe
2 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2019-08-27 22:48 UTC (permalink / raw)
To: Ralph Campbell
Cc: linux-mm, linux-kernel, amd-gfx, dri-devel, nouveau,
Jérôme Glisse, Andrew Morton, Christoph Hellwig
On Fri, Aug 23, 2019 at 03:17:51PM -0700, Ralph Campbell wrote:
> I have been working on converting Jerome's hmm_dummy driver and self
> tests into a stand-alone set of tests to be included in
> tools/testing/selftests/vm and came across these two bug fixes in the
> process. The tests aren't quite ready to be posted as a patch.
> I'm posting the fixes now since I thought they shouldn't wait.
> They should probably have a fixes line but with all the HMM changes,
> I wasn't sure exactly which commit to use.
>
> These are based on top of Jason's latest hmm branch.
>
> Ralph Campbell (2):
> mm/hmm: hmm_range_fault() NULL pointer bug
> mm/hmm: hmm_range_fault() infinite loop
Applied to hmm.git
Thanks,
Jason
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2019-08-27 22:48 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-23 22:17 [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Ralph Campbell
2019-08-23 22:17 ` [PATCH 1/2] mm/hmm: hmm_range_fault() NULL pointer bug Ralph Campbell
2019-08-24 22:37 ` Christoph Hellwig
2019-08-26 18:02 ` Ralph Campbell
2019-08-26 18:09 ` Jason Gunthorpe
2019-08-26 18:21 ` Ralph Campbell
2019-08-23 22:17 ` [PATCH 2/2] mm/hmm: hmm_range_fault() infinite loop Ralph Campbell
2019-08-24 22:39 ` Christoph Hellwig
2019-08-27 18:41 ` Jason Gunthorpe
2019-08-27 20:16 ` Ralph Campbell
2019-08-27 22:22 ` Jason Gunthorpe
2019-08-27 22:48 ` [PATCH 0/2] mm/hmm: two bug fixes for hmm_range_fault() Jason Gunthorpe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).