Skip to content

Bug: chunk.used should not be up-aligned before the size check #1529

@jsjolen

Description

@jsjolen

Hi,

Consider these lines from dma_alloc:

   -- Skip allocation forward pointer to suit alignment
   chunk.used = lib.align(chunk.used, align)
   -- Need a new chunk to service this allocation?
   if chunk.used + bytes > chunk.size then

I assume that lib.align does up-alignment (down would be very strange). Then there are two issues:

  1. If lib.align(chunk.used, align) > chunk.sizethen the chunk will have used more than is available, then that's probably an invariant violation as chunk.used > chunk.size. Let's say there's 2 bytes left and it's on a 2-byte alignment, but needs 16-byte alignment, then oops, it'll overshoot by 14 bytes.
  2. If the branch is reached and issue 1. doesn't occur, then it will still 'leak' a few bytes, leading to a small amount of internal fragmentation.

To be fair, I haven't looked at the surrounding context, so this may not be an issue anyway. I'm assuming that the latest chunk will at some time be deallocated and the previous invariant-breaking chunk will at some point be accessed.

I bet the issue doesn't manifest because the last valid address in a huge page is 2M aligned, and nothing uses such a high alignment anyway. Since the fix is so easy, maybe it's worth fixing anyway?

Full function for reference:

function dma_alloc (bytes,  align)
   align = align or 128
   assert(bytes <= huge_page_size)
   -- Get current chunk of memory to allocate from
   if #chunks == 0 then allocate_next_chunk() end
   local chunk = chunks[#chunks]
   -- Skip allocation forward pointer to suit alignment
   chunk.used = lib.align(chunk.used, align)
   -- Need a new chunk to service this allocation?
   if chunk.used + bytes > chunk.size then
      allocate_next_chunk()
      chunk = chunks[#chunks]
   end
   -- Slice out the memory we need
   local where = chunk.used
   chunk.used = chunk.used + bytes
   return chunk.pointer + where, chunk.physical + where, bytes
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions