Re: [PATCH v3 1/2] livepatch: Fix UAF of unregistered patch kobjects
Song Liu <[email protected]>
| Newsgroups | org.kernel.vger.live-patching |
|---|---|
| Message-ID | <CAPhsuW42q8KKHaYPVwoWH139btRpf_wFbEenbCa_xji5REbsKw@mail.gmail.com> |
On Thu, Aug 20, 2026 at 8:17 PM Yafang Shao <[email protected]> wrote: > > The kobjects of a livepatch are released via kobject_put(). When > CONFIG_DEBUG_KOBJECT_RELEASE is enabled, kobject_put() does not release > the kobject synchronously but schedules a delayed release with a random > delay of up to 4 seconds (see kobject_release() in lib/kobject.c). I think I have seen this issue before. Thanks for fixing it! > > klp_free_patch_finish() only waits for the release of the patch kobject: > > klp_free_patch_finish(): > kobject_put(&patch->kobj); > wait_for_completion(&patch->finish); > > patch->finish is completed by the patch kobject's release callback. If > the patch kobject was never added to sysfs, or if some child kobjects > were initialized but never added to sysfs (e.g. when klp_enable_patch() > fails after klp_init_patch_early()), those un-added children do not hold > a reference on the patch kobject. kobject_add() is what takes the parent > reference, so the patch kobject can be released first, completing > patch->finish while the child releases are still pending. > > The caller then unloads the livepatch module, which destroys the static > klp_object and klp_func structures. The delayed child release callbacks > later access this freed memory, causing a use-after-free. > > Fix it by making every child kobject hold an explicit reference on its > parent from the moment the object is initialized: klp_init_object_early() > takes a reference on the patch kobject and klp_init_func_early() takes a > reference on the object kobject. Unlike the reference taken by > kobject_add(), these references also exist for objects that are never > added to sysfs, and the release callbacks drop them unconditionally. > This guarantees the patch kobject is released only after all child > kobjects have been released, so patch->finish cannot be completed before > the static structures are safe to free. > > Because kobj->parent is set only by kobject_add(), add explicit > back-pointers, obj->patch and func->obj, so the release callbacks can > find the parent. Dynamic objects and nop functions are freed by their > release callbacks; save the parent pointer before freeing and drop the > parent reference afterwards. > > Reported-by: sashiko-bot <[email protected]> > Closes: https://lore.kernel.org/all/[email protected]/ > Suggested-by: Petr Mladek <[email protected]> > Signed-off-by: Yafang Shao <[email protected]> Acked-by: Song Liu <[email protected]>