1
0
Fork 0
mirror of https://passt.top/passt synced 2025-05-20 16:35:33 +02:00

packet: More cautious checks to avoid pointer arithmetic UB

packet_check_range and vu_packet_check_range() verify that the packet or
section of packet we're interested in lies in the packet buffer pool we
expect it to.  However, in doing so it doesn't avoid the possibility of
an integer overflow while performing pointer arithmetic, with is UB.  In
fact, AFAICT it's UB even to use arbitrary pointer arithmetic to construct
a pointer outside of a known valid buffer.

To do this safely, we can't calculate the end of a memory region with
pointer addition when then the length as untrusted.  Instead we must work
out the offset of one memory region within another using pointer
subtraction, then do integer checks against the length of the outer region.
We then need to be careful about the order of checks so that those integer
checks can't themselves overflow.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2025-03-17 20:24:15 +11:00 committed by Stefano Brivio
parent 4592719a74
commit e43e00719d
2 changed files with 16 additions and 6 deletions

View file

@ -52,9 +52,15 @@ static int packet_check_range(const struct pool *p, const char *ptr, size_t len,
return -1;
}
if (ptr + len > p->buf + p->buf_size) {
trace("packet range end %p after buffer end %p, %s:%i",
(void *)(ptr + len), (void *)(p->buf + p->buf_size),
if (len > p->buf_size) {
trace("packet range length %zu larger than buffer %zu, %s:%i",
len, p->buf_size, func, line);
return -1;
}
if ((size_t)(ptr - p->buf) > p->buf_size - len) {
trace("packet range %p, len %zu after buffer end %p, %s:%i",
(void *)ptr, len, (void *)(p->buf + p->buf_size),
func, line);
return -1;
}

View file

@ -36,11 +36,15 @@ int vu_packet_check_range(void *buf, const char *ptr, size_t len)
struct vu_dev_region *dev_region;
for (dev_region = buf; dev_region->mmap_addr; dev_region++) {
/* NOLINTNEXTLINE(performance-no-int-to-ptr) */
char *m = (char *)(uintptr_t)dev_region->mmap_addr +
uintptr_t base_addr = dev_region->mmap_addr +
dev_region->mmap_offset;
/* NOLINTNEXTLINE(performance-no-int-to-ptr) */
const char *base = (const char *)base_addr;
if (m <= ptr && ptr + len <= m + dev_region->size)
ASSERT(base_addr >= dev_region->mmap_addr);
if (len <= dev_region->size && base <= ptr &&
(size_t)(ptr - base) <= dev_region->size - len)
return 0;
}