History

bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure

When bpf_trampoline_update() fails before modify_fentry_multi()/ unregister_fentry_multi() is called, cur_image is unchanged (cur_image == old_image) and ftrace still calls into it. Freeing old_image in that case causes a UAF. Only free old_image when it differs from cur_image.

Hui Zhu committed 3 months ago

Commit 02530731 parent df217531 file · +11 −1Browse files

Unified · Split

kernel/bpf/trampoline.c+11−1
@@ -1632,7 +1632,17 @@ static void bpf_trampoline_multi_attach_init(struct bpf_trampoline *tr) · 1631 unmodified lines
1632 1632
1633static void bpf_trampoline_multi_attach_free(struct bpf_trampoline *tr)1633static void bpf_trampoline_multi_attach_free(struct bpf_trampoline *tr)
1634{1634{
1635 if (tr->multi_attach.old_image)1635 /*
1636 * Only free old_image if it is no longer the active image.
1637 * When bpf_trampoline_update() fails before modify_fentry_multi()/
1638 * unregister_fentry_multi() is called, cur_image is unchanged
1639 * (cur_image == old_image) and ftrace still points to it. Freeing
1640 * it would cause a UAF when ftrace calls into the freed memory.
1641 * On success, cur_image is either a new image or NULL, so
1642 * old_image != cur_image means the image is stale.
1643 */
1644 if (tr->multi_attach.old_image &&
1645 tr->multi_attach.old_image != tr->cur_image)
1636 bpf_tramp_image_put(tr->multi_attach.old_image);1646 bpf_tramp_image_put(tr->multi_attach.old_image);
1637 1647
1638 tr->multi_attach.old_image = NULL;1648 tr->multi_attach.old_image = NULL;