Message ID | 20200903161446.29615-6-eperezma@redhat.com |
---|---|
State | Accepted |
Commit | 1804857f19f612f6907832e35599cdb51d4ec764 |
Headers | show |
Series | [RFC,1/1] memory: Delete assertion in memory_region_unregister_iommu_notifier | expand |
On Fri, Sep 4, 2020 at 6:34 AM Jason Wang <jasowang@redhat.com> wrote: > > > On 2020/9/4 上午12:14, Eugenio Pérez wrote: > > Device IOTLB invalidations can unmap arbitrary ranges, eiter outside of > > the memory region or even [0, ~0ULL] for all the space. The assertion > > could be hit by a guest, and rhel7 guest effectively hit it. > > > > Signed-off-by: Eugenio Pérez <eperezma@redhat.com> > > Reviewed-by: Peter Xu <peterx@redhat.com> > > Reviewed-by: Juan Quintela <quintela@redhat.com> > > --- > > softmmu/memory.c | 13 +++++++++++-- > > 1 file changed, 11 insertions(+), 2 deletions(-) > > > > diff --git a/softmmu/memory.c b/softmmu/memory.c > > index 8694fc7cf7..e723fcbaa1 100644 > > --- a/softmmu/memory.c > > +++ b/softmmu/memory.c > > @@ -1895,6 +1895,7 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > { > > IOMMUTLBEntry *entry = &event->entry; > > hwaddr entry_end = entry->iova + entry->addr_mask; > > + IOMMUTLBEntry tmp = *entry; > > > > if (event->type == IOMMU_NOTIFIER_UNMAP) { > > assert(entry->perm == IOMMU_NONE); > > @@ -1908,10 +1909,18 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > return; > > } > > > > - assert(entry->iova >= notifier->start && entry_end <= notifier->end); > > + if (notifier->notifier_flags & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { > > + /* Crop (iova, addr_mask) to range */ > > + tmp.iova = MAX(tmp.iova, notifier->start); > > + tmp.addr_mask = MIN(entry_end, notifier->end) - tmp.iova; > > + /* Confirm no underflow */ > > + assert(MIN(entry_end, notifier->end) >= tmp.iova); > > > It's still not clear to me why we need such assert. Consider > notifier->end is the possible IOVA range but not possible device IOTLB > invalidation range (e.g it allows [0, ULLONG_MAX]). > > Thanks > As far as I understood the device should admit that out of bounds notifications in that case, and the assert just makes sure that there was no underflow in tmp.addr_mask, i.e., that something very wrong that should never happen in production happened. Peter, would you mind to confirm/correct it? Is there anything else needed to pull this patch? Thanks! > > > + } else { > > + assert(entry->iova >= notifier->start && entry_end <= notifier->end); > > + } > > > > if (event->type & notifier->notifier_flags) { > > - notifier->notify(notifier, entry); > > + notifier->notify(notifier, &tmp); > > } > > } > > >
On Mon, Sep 28, 2020 at 11:05:01AM +0200, Eugenio Perez Martin wrote: > On Fri, Sep 4, 2020 at 6:34 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > On 2020/9/4 上午12:14, Eugenio Pérez wrote: > > > Device IOTLB invalidations can unmap arbitrary ranges, eiter outside of > > > the memory region or even [0, ~0ULL] for all the space. The assertion > > > could be hit by a guest, and rhel7 guest effectively hit it. > > > > > > Signed-off-by: Eugenio Pérez <eperezma@redhat.com> > > > Reviewed-by: Peter Xu <peterx@redhat.com> > > > Reviewed-by: Juan Quintela <quintela@redhat.com> > > > --- > > > softmmu/memory.c | 13 +++++++++++-- > > > 1 file changed, 11 insertions(+), 2 deletions(-) > > > > > > diff --git a/softmmu/memory.c b/softmmu/memory.c > > > index 8694fc7cf7..e723fcbaa1 100644 > > > --- a/softmmu/memory.c > > > +++ b/softmmu/memory.c > > > @@ -1895,6 +1895,7 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > > { > > > IOMMUTLBEntry *entry = &event->entry; > > > hwaddr entry_end = entry->iova + entry->addr_mask; > > > + IOMMUTLBEntry tmp = *entry; > > > > > > if (event->type == IOMMU_NOTIFIER_UNMAP) { > > > assert(entry->perm == IOMMU_NONE); > > > @@ -1908,10 +1909,18 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > > return; > > > } > > > > > > - assert(entry->iova >= notifier->start && entry_end <= notifier->end); > > > + if (notifier->notifier_flags & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { > > > + /* Crop (iova, addr_mask) to range */ > > > + tmp.iova = MAX(tmp.iova, notifier->start); > > > + tmp.addr_mask = MIN(entry_end, notifier->end) - tmp.iova; > > > + /* Confirm no underflow */ > > > + assert(MIN(entry_end, notifier->end) >= tmp.iova); > > > > > > It's still not clear to me why we need such assert. Consider > > notifier->end is the possible IOVA range but not possible device IOTLB > > invalidation range (e.g it allows [0, ULLONG_MAX]). > > > > Thanks > > > > As far as I understood the device should admit that out of bounds > notifications in that case, > and the assert just makes sure that there was no underflow in > tmp.addr_mask, i.e., that something > very wrong that should never happen in production happened. > > Peter, would you mind to confirm/correct it? I think Jason is right - since we have checked at the entry that the two regions cross over each other: /* * Skip the notification if the notification does not overlap * with registered range. */ if (notifier->start > entry_end || notifier->end < entry->iova) { return; } Then I don't see how this assertion can fail any more. But imho not a big problem either, and it shouldn't hurt to even keep the assertion of above isn't that straightforward. > > Is there anything else needed to pull this patch? I didn't post a pull for this only because I shouldn't :) - the plan was that all vt-d patches will still go via Michael's tree, iiuc. Though at least to me I think this series is acceptable for merging. Though it would always be good too if Jason would still like to review it. Jason, what's your opinion? Thanks, -- Peter Xu
On Mon, Sep 28, 2020 at 01:48:57PM -0400, Peter Xu wrote: > On Mon, Sep 28, 2020 at 11:05:01AM +0200, Eugenio Perez Martin wrote: > > On Fri, Sep 4, 2020 at 6:34 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > On 2020/9/4 上午12:14, Eugenio Pérez wrote: > > > > Device IOTLB invalidations can unmap arbitrary ranges, eiter outside of > > > > the memory region or even [0, ~0ULL] for all the space. The assertion > > > > could be hit by a guest, and rhel7 guest effectively hit it. > > > > > > > > Signed-off-by: Eugenio Pérez <eperezma@redhat.com> > > > > Reviewed-by: Peter Xu <peterx@redhat.com> > > > > Reviewed-by: Juan Quintela <quintela@redhat.com> > > > > --- > > > > softmmu/memory.c | 13 +++++++++++-- > > > > 1 file changed, 11 insertions(+), 2 deletions(-) > > > > > > > > diff --git a/softmmu/memory.c b/softmmu/memory.c > > > > index 8694fc7cf7..e723fcbaa1 100644 > > > > --- a/softmmu/memory.c > > > > +++ b/softmmu/memory.c > > > > @@ -1895,6 +1895,7 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > > > { > > > > IOMMUTLBEntry *entry = &event->entry; > > > > hwaddr entry_end = entry->iova + entry->addr_mask; > > > > + IOMMUTLBEntry tmp = *entry; > > > > > > > > if (event->type == IOMMU_NOTIFIER_UNMAP) { > > > > assert(entry->perm == IOMMU_NONE); > > > > @@ -1908,10 +1909,18 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > > > return; > > > > } > > > > > > > > - assert(entry->iova >= notifier->start && entry_end <= notifier->end); > > > > + if (notifier->notifier_flags & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { > > > > + /* Crop (iova, addr_mask) to range */ > > > > + tmp.iova = MAX(tmp.iova, notifier->start); > > > > + tmp.addr_mask = MIN(entry_end, notifier->end) - tmp.iova; > > > > + /* Confirm no underflow */ > > > > + assert(MIN(entry_end, notifier->end) >= tmp.iova); > > > > > > > > > It's still not clear to me why we need such assert. Consider > > > notifier->end is the possible IOVA range but not possible device IOTLB > > > invalidation range (e.g it allows [0, ULLONG_MAX]). > > > > > > Thanks > > > > > > > As far as I understood the device should admit that out of bounds > > notifications in that case, > > and the assert just makes sure that there was no underflow in > > tmp.addr_mask, i.e., that something > > very wrong that should never happen in production happened. > > > > Peter, would you mind to confirm/correct it? > > I think Jason is right - since we have checked at the entry that the two > regions cross over each other: > > /* > * Skip the notification if the notification does not overlap > * with registered range. > */ > if (notifier->start > entry_end || notifier->end < entry->iova) { > return; > } > > Then I don't see how this assertion can fail any more. > > But imho not a big problem either, and it shouldn't hurt to even keep the > assertion of above isn't that straightforward. > > > > > Is there anything else needed to pull this patch? > > I didn't post a pull for this only because I shouldn't :) - the plan was that > all vt-d patches will still go via Michael's tree, iiuc. Though at least to me > I think this series is acceptable for merging. Sure, that's ok. Eugenio, you sent patch 0 as a response to another series, which made me miss the series. Pls don't do that in the future. Looks like Jason reviewed the series - Jason, is that right? - so I'd like his ack if possible. > Though it would always be good too if Jason would still like to review it. > > Jason, what's your opinion? > > Thanks, > > -- > Peter Xu
On Sat, Oct 3, 2020 at 7:38 PM Michael S. Tsirkin <mst@redhat.com> wrote: > > On Mon, Sep 28, 2020 at 01:48:57PM -0400, Peter Xu wrote: > > On Mon, Sep 28, 2020 at 11:05:01AM +0200, Eugenio Perez Martin wrote: > > > On Fri, Sep 4, 2020 at 6:34 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > > > On 2020/9/4 上午12:14, Eugenio Pérez wrote: > > > > > Device IOTLB invalidations can unmap arbitrary ranges, eiter outside of > > > > > the memory region or even [0, ~0ULL] for all the space. The assertion > > > > > could be hit by a guest, and rhel7 guest effectively hit it. > > > > > > > > > > Signed-off-by: Eugenio Pérez <eperezma@redhat.com> > > > > > Reviewed-by: Peter Xu <peterx@redhat.com> > > > > > Reviewed-by: Juan Quintela <quintela@redhat.com> > > > > > --- > > > > > softmmu/memory.c | 13 +++++++++++-- > > > > > 1 file changed, 11 insertions(+), 2 deletions(-) > > > > > > > > > > diff --git a/softmmu/memory.c b/softmmu/memory.c > > > > > index 8694fc7cf7..e723fcbaa1 100644 > > > > > --- a/softmmu/memory.c > > > > > +++ b/softmmu/memory.c > > > > > @@ -1895,6 +1895,7 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > > > > { > > > > > IOMMUTLBEntry *entry = &event->entry; > > > > > hwaddr entry_end = entry->iova + entry->addr_mask; > > > > > + IOMMUTLBEntry tmp = *entry; > > > > > > > > > > if (event->type == IOMMU_NOTIFIER_UNMAP) { > > > > > assert(entry->perm == IOMMU_NONE); > > > > > @@ -1908,10 +1909,18 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, > > > > > return; > > > > > } > > > > > > > > > > - assert(entry->iova >= notifier->start && entry_end <= notifier->end); > > > > > + if (notifier->notifier_flags & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { > > > > > + /* Crop (iova, addr_mask) to range */ > > > > > + tmp.iova = MAX(tmp.iova, notifier->start); > > > > > + tmp.addr_mask = MIN(entry_end, notifier->end) - tmp.iova; > > > > > + /* Confirm no underflow */ > > > > > + assert(MIN(entry_end, notifier->end) >= tmp.iova); > > > > > > > > > > > > It's still not clear to me why we need such assert. Consider > > > > notifier->end is the possible IOVA range but not possible device IOTLB > > > > invalidation range (e.g it allows [0, ULLONG_MAX]). > > > > > > > > Thanks > > > > > > > > > > As far as I understood the device should admit that out of bounds > > > notifications in that case, > > > and the assert just makes sure that there was no underflow in > > > tmp.addr_mask, i.e., that something > > > very wrong that should never happen in production happened. > > > > > > Peter, would you mind to confirm/correct it? > > > > I think Jason is right - since we have checked at the entry that the two > > regions cross over each other: > > > > /* > > * Skip the notification if the notification does not overlap > > * with registered range. > > */ > > if (notifier->start > entry_end || notifier->end < entry->iova) { > > return; > > } > > > > Then I don't see how this assertion can fail any more. > > > > But imho not a big problem either, and it shouldn't hurt to even keep the > > assertion of above isn't that straightforward. > > > > > > > > Is there anything else needed to pull this patch? > > > > I didn't post a pull for this only because I shouldn't :) - the plan was that > > all vt-d patches will still go via Michael's tree, iiuc. Though at least to me > > I think this series is acceptable for merging. > > Sure, that's ok. > > Eugenio, you sent patch 0 as a response to another series, which > made me miss the series. Pls don't do that in the future. > Sorry, noted for the next time. Thanks! > Looks like Jason reviewed the series - Jason, is that right? - > so I'd like his ack if possible. > > > > Though it would always be good too if Jason would still like to review it. > > > > Jason, what's your opinion? > > > > Thanks, > > > > -- > > Peter Xu >
On 2020/10/4 上午1:38, Michael S. Tsirkin wrote: > On Mon, Sep 28, 2020 at 01:48:57PM -0400, Peter Xu wrote: >> On Mon, Sep 28, 2020 at 11:05:01AM +0200, Eugenio Perez Martin wrote: >>> On Fri, Sep 4, 2020 at 6:34 AM Jason Wang <jasowang@redhat.com> wrote: >>>> >>>> On 2020/9/4 上午12:14, Eugenio Pérez wrote: >>>>> Device IOTLB invalidations can unmap arbitrary ranges, eiter outside of >>>>> the memory region or even [0, ~0ULL] for all the space. The assertion >>>>> could be hit by a guest, and rhel7 guest effectively hit it. >>>>> >>>>> Signed-off-by: Eugenio Pérez <eperezma@redhat.com> >>>>> Reviewed-by: Peter Xu <peterx@redhat.com> >>>>> Reviewed-by: Juan Quintela <quintela@redhat.com> >>>>> --- >>>>> softmmu/memory.c | 13 +++++++++++-- >>>>> 1 file changed, 11 insertions(+), 2 deletions(-) >>>>> >>>>> diff --git a/softmmu/memory.c b/softmmu/memory.c >>>>> index 8694fc7cf7..e723fcbaa1 100644 >>>>> --- a/softmmu/memory.c >>>>> +++ b/softmmu/memory.c >>>>> @@ -1895,6 +1895,7 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, >>>>> { >>>>> IOMMUTLBEntry *entry = &event->entry; >>>>> hwaddr entry_end = entry->iova + entry->addr_mask; >>>>> + IOMMUTLBEntry tmp = *entry; >>>>> >>>>> if (event->type == IOMMU_NOTIFIER_UNMAP) { >>>>> assert(entry->perm == IOMMU_NONE); >>>>> @@ -1908,10 +1909,18 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, >>>>> return; >>>>> } >>>>> >>>>> - assert(entry->iova >= notifier->start && entry_end <= notifier->end); >>>>> + if (notifier->notifier_flags & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { >>>>> + /* Crop (iova, addr_mask) to range */ >>>>> + tmp.iova = MAX(tmp.iova, notifier->start); >>>>> + tmp.addr_mask = MIN(entry_end, notifier->end) - tmp.iova; >>>>> + /* Confirm no underflow */ >>>>> + assert(MIN(entry_end, notifier->end) >= tmp.iova); >>>> >>>> It's still not clear to me why we need such assert. Consider >>>> notifier->end is the possible IOVA range but not possible device IOTLB >>>> invalidation range (e.g it allows [0, ULLONG_MAX]). >>>> >>>> Thanks >>>> >>> As far as I understood the device should admit that out of bounds >>> notifications in that case, >>> and the assert just makes sure that there was no underflow in >>> tmp.addr_mask, i.e., that something >>> very wrong that should never happen in production happened. >>> >>> Peter, would you mind to confirm/correct it? >> I think Jason is right - since we have checked at the entry that the two >> regions cross over each other: >> >> /* >> * Skip the notification if the notification does not overlap >> * with registered range. >> */ >> if (notifier->start > entry_end || notifier->end < entry->iova) { >> return; >> } >> >> Then I don't see how this assertion can fail any more. >> >> But imho not a big problem either, and it shouldn't hurt to even keep the >> assertion of above isn't that straightforward. >> >>> Is there anything else needed to pull this patch? >> I didn't post a pull for this only because I shouldn't :) - the plan was that >> all vt-d patches will still go via Michael's tree, iiuc. Though at least to me >> I think this series is acceptable for merging. > Sure, that's ok. > > Eugenio, you sent patch 0 as a response to another series, which > made me miss the series. Pls don't do that in the future. > > Looks like Jason reviewed the series - Jason, is that right? - > so I'd like his ack if possible. Right. Euenio. If it's possible I would prefer to remove the assertion but it's ok it you leave it. And please repost the series. Thanks > > >> Though it would always be good too if Jason would still like to review it. >> >> Jason, what's your opinion? >> >> Thanks, >> >> -- >> Peter Xu >
diff --git a/softmmu/memory.c b/softmmu/memory.c index 8694fc7cf7..e723fcbaa1 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1895,6 +1895,7 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, { IOMMUTLBEntry *entry = &event->entry; hwaddr entry_end = entry->iova + entry->addr_mask; + IOMMUTLBEntry tmp = *entry; if (event->type == IOMMU_NOTIFIER_UNMAP) { assert(entry->perm == IOMMU_NONE); @@ -1908,10 +1909,18 @@ void memory_region_notify_iommu_one(IOMMUNotifier *notifier, return; } - assert(entry->iova >= notifier->start && entry_end <= notifier->end); + if (notifier->notifier_flags & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { + /* Crop (iova, addr_mask) to range */ + tmp.iova = MAX(tmp.iova, notifier->start); + tmp.addr_mask = MIN(entry_end, notifier->end) - tmp.iova; + /* Confirm no underflow */ + assert(MIN(entry_end, notifier->end) >= tmp.iova); + } else { + assert(entry->iova >= notifier->start && entry_end <= notifier->end); + } if (event->type & notifier->notifier_flags) { - notifier->notify(notifier, entry); + notifier->notify(notifier, &tmp); } }