The XOL slot bitmap has the same lifetime as struct xol_area, but it is currently allocated separately. That adds another allocation failure path and a matching cleanup branch without buying any extra flexibility.
Store the bitmap as a flexible array member and allocate it together with the xol_area using kzalloc_flex(). The bitmap remains zero-initialized, while the allocation and error handling become simpler. Assisted-by: Codex:GPT-5.5 Signed-off-by: Rosen Penev <[email protected]> --- kernel/events/uprobes.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 4084e926e284..9ef74c2ad390 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -108,7 +108,6 @@ static LIST_HEAD(delayed_uprobe_list); */ struct xol_area { wait_queue_head_t wq; /* if all slots are busy */ - unsigned long *bitmap; /* 0 = free slot */ struct page *page; /* @@ -117,6 +116,7 @@ struct xol_area { * the vma go away, and we must handle that reasonably gracefully. */ unsigned long vaddr; /* Page(s) of instruction slots */ + unsigned long bitmap[]; /* 0 = free slot */ }; static void uprobe_warn(struct task_struct *t, const char *msg) @@ -1755,18 +1755,13 @@ static struct xol_area *__create_xol_area(unsigned long vaddr) struct xol_area *area; void *insns; - area = kzalloc_obj(*area); + area = kzalloc_flex(*area, bitmap, BITS_TO_LONGS(UINSNS_PER_PAGE)); if (unlikely(!area)) goto out; - area->bitmap = kcalloc(BITS_TO_LONGS(UINSNS_PER_PAGE), sizeof(long), - GFP_KERNEL); - if (!area->bitmap) - goto free_area; - area->page = alloc_page(GFP_HIGHUSER | __GFP_ZERO); if (!area->page) - goto free_bitmap; + goto free_area; area->vaddr = vaddr; init_waitqueue_head(&area->wq); @@ -1779,8 +1774,6 @@ static struct xol_area *__create_xol_area(unsigned long vaddr) return area; __free_page(area->page); - free_bitmap: - kfree(area->bitmap); free_area: kfree(area); out: -- 2.54.0
