Skip to content

Commit 14c8d86

Browse files
bjotokernel-patches-bot
authored andcommitted
From: Björn Töpel <[email protected]>
For AF_XDP sockets, there was a discrepancy between the number of of pinned pages and the size of the umem region. The size of the umem region is used to validate the AF_XDP descriptor addresses. The logic that pinned the pages covered by the region only took whole pages into consideration, creating a mismatch between the size and pinned pages. A user could then pass AF_XDP addresses outside the range of pinned pages, but still within the size of the region, crashing the kernel. This change correctly calculates the number of pages to be pinned. Further, the size check for the aligned mode is simplified. Now the code simply checks if the size is divisible by the chunk size. Fixes: bbff2f3 ("xsk: new descriptor addressing scheme") Reported-by: Ciara Loftus <[email protected]> Signed-off-by: Björn Töpel <[email protected]> --- net/xdp/xdp_umem.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) base-commit: 746f534
1 parent 4153754 commit 14c8d86

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

net/xdp/xdp_umem.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,10 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
303303

304304
static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
305305
{
306+
u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom;
306307
bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
307-
u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
308308
u64 npgs, addr = mr->addr, size = mr->len;
309-
unsigned int chunks, chunks_per_page;
309+
unsigned int chunks, chunks_rem;
310310
int err;
311311

312312
if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
@@ -336,19 +336,18 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
336336
if ((addr + size) < addr)
337337
return -EINVAL;
338338

339-
npgs = size >> PAGE_SHIFT;
339+
npgs = div_u64_rem(size, PAGE_SIZE, &npgs_rem);
340+
if (npgs_rem)
341+
npgs++;
340342
if (npgs > U32_MAX)
341343
return -EINVAL;
342344

343-
chunks = (unsigned int)div_u64(size, chunk_size);
345+
chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem);
344346
if (chunks == 0)
345347
return -EINVAL;
346348

347-
if (!unaligned_chunks) {
348-
chunks_per_page = PAGE_SIZE / chunk_size;
349-
if (chunks < chunks_per_page || chunks % chunks_per_page)
350-
return -EINVAL;
351-
}
349+
if (!unaligned_chunks && chunks_rem)
350+
return -EINVAL;
352351

353352
if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
354353
return -EINVAL;

0 commit comments

Comments
 (0)