On Tue, Mar 29, 2022 at 03:51:17PM +0000, Jag Raman wrote: > > > > On Mar 29, 2022, at 8:50 AM, Stefan Hajnoczi 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? Stefan