On Wed, Mar 30, 2022 at 02:46:20PM +0000, Jag Raman wrote: > > > > On Mar 30, 2022, at 6:05 AM, Stefan Hajnoczi <stefa...@redhat.com> wrote: > > > > On Tue, Mar 29, 2022 at 03:51:17PM +0000, Jag Raman wrote: > >> > >> > >>> On Mar 29, 2022, at 8:50 AM, Stefan Hajnoczi <stefa...@redhat.com> wrote: > >>> > >>> On Fri, Mar 25, 2022 at 03:19:43PM -0400, Jagannathan Raman wrote: > >>>> @@ -324,6 +325,170 @@ static void dma_unregister(vfu_ctx_t *vfu_ctx, > >>>> vfu_dma_info_t *info) > >>>> trace_vfu_dma_unregister((uint64_t)info->iova.iov_base); > >>>> } > >>>> > >>>> +static size_t vfu_object_bar_rw(PCIDevice *pci_dev, int pci_bar, > >>>> + hwaddr offset, char * const buf, > >>>> + hwaddr len, const bool is_write) > >>>> +{ > >>>> + uint8_t *ptr = (uint8_t *)buf; > >>>> + uint8_t *ram_ptr = NULL; > >>>> + bool release_lock = false; > >>>> + MemoryRegionSection section = { 0 }; > >>>> + MemoryRegion *mr = NULL; > >>>> + int access_size; > >>>> + hwaddr size = 0; > >>>> + MemTxResult result; > >>>> + uint64_t val; > >>>> + > >>>> + section = memory_region_find(pci_dev->io_regions[pci_bar].memory, > >>>> + offset, len); > >>>> + > >>>> + if (!section.mr) { > >>>> + return 0; > >>>> + } > >>>> + > >>>> + mr = section.mr; > >>>> + offset = section.offset_within_region; > >>>> + > >>>> + if (is_write && mr->readonly) { > >>>> + warn_report("vfu: attempting to write to readonly region in " > >>>> + "bar %d - [0x%"PRIx64" - 0x%"PRIx64"]", > >>>> + pci_bar, offset, (offset + len)); > >>>> + return 0; > >>> > >>> A mr reference is leaked. The return statement can be replaced with goto > >>> exit. > >> > >> OK. > >> > >>> > >>>> + } > >>>> + > >>>> + if (memory_access_is_direct(mr, is_write)) { > >>>> + /** > >>>> + * Some devices expose a PCI expansion ROM, which could be > >>>> buffer > >>>> + * based as compared to other regions which are primarily based > >>>> on > >>>> + * MemoryRegionOps. memory_region_find() would already check > >>>> + * for buffer overflow, we don't need to repeat it here. > >>>> + */ > >>>> + ram_ptr = memory_region_get_ram_ptr(mr); > >>>> + > >>>> + size = len; > >>> > >>> This looks like it will access beyond the end of ram_ptr when > >>> section.size < len after memory_region_find() returns. > >> > >> OK - will will handle shorter sections returned by memory_region_find(). > >> > >>> > >>>> + > >>>> + if (is_write) { > >>>> + memcpy((ram_ptr + offset), buf, size); > >>>> + } else { > >>>> + memcpy(buf, (ram_ptr + offset), size); > >>>> + } > >>>> + > >>>> + goto exit; > >>> > >>> What happens when the access spans two adjacent MemoryRegions? I think > >>> the while (len > 0) loop is needed even in the memory_access_is_direct() > >>> case so we perform the full access instead of truncating it. > >> > >> OK - this should be covered by the shorter section handling above. > > > > No, shorter section handling truncates that access. I think the caller > > expects all len bytes to be accessed, not just the first few bytes? > > Yes, I also think that the caller expects to access all len bytes. > > I should’ve provided more details - but by shorter section handling I > meant iterating over all the sections that make up len bytes.
Okay, I think we're on the same page. I wanted to be make sure that if (memory_access_is_direct()) will be moved inside the loop. Stefan
signature.asc
Description: PGP signature