Live Patching
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: joe.lawrence@redhat.com, jpoimboe@kernel.org, mbenes@suse.cz,
	jikos@kernel.org, pmladek@suse.com, song@kernel.org,
	"Yafang Shao" <laoar.shao@gmail.com>
Cc: live-patching@vger.kernel.org
Subject: Re: [PATCH 2/2] livepatch: Fix UAF of unregistered patch kobjects
Date: Thu, 13 Aug 2026 03:16:11 +0000	[thread overview]
Message-ID: <20260813031611.A4EAD1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260813030408.9761-3-laoar.shao@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Critical] The newly added release signaling logic introduces a direct Use-After-Free when processing dynamically allocated objects and NOP functions in the kobject release paths.

Pre-existing issues:
- [High] The patch fails to fully resolve the original delayed kobject release Use-After-Free if partial initialization fails after the patch kobject has been added, leaving child kobjects un-added.
--

--- Patch [2]: [PATCH 2/2] livepatch: Fix UAF of unregistered patch kobjects ---
commit ac38837d810b471eed544191021bf254f8b9e585
Author: Yafang Shao <laoar.shao@gmail.com>

livepatch: Fix UAF of unregistered patch kobjects

When klp_enable_patch() fails after klp_init_patch_early() has run,
delayed kobject releases can cause use-after-free bugs when the module
is unloaded. This patch tracks pending kobject releases and waits for
them before completion.

Link: https://lore.kernel.org/all/20260809094046.50ED31F000E9@smtp.kernel.org/

> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 28d15ba58a26d..e07b026feeb99 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c

[ ... ]

> @@ -652,6 +653,14 @@ static void klp_kobj_release_object(struct kobject *kobj)
>  
>  	if (obj->dynamic)
>  		klp_free_object_dynamic(obj);
> +
> +	/*
> +	 * The object kobject was initialized but never added to sysfs.
> +	 * Signal the release to the owning patch.
> +	 */
> +	if (!obj->patch->kobj_added &&
> +	    atomic_dec_and_test(&obj->patch->kobj_pending))
> +		complete(&obj->patch->finish);
>  }

[Severity: Critical]
Does this dereference the freed obj pointer?

If obj->dynamic is true, klp_free_object_dynamic(obj) is called, which
frees the object structure. Immediately after this intentional free, the
newly added logic dereferences the freed pointer by evaluating
!obj->patch->kobj_added.

> @@ -668,6 +677,13 @@ static void klp_kobj_release_func(struct kobject *kobj)
>  
>  	if (func->nop)
>  		klp_free_func_nop(func);
> +	/*
> +	 * The function kobject was initialized but never added to sysfs.
> +	 * Signal the release to the owning patch.
> +	 */
> +	if (!func->obj->patch->kobj_added &&
> +	    atomic_dec_and_test(&func->obj->patch->kobj_pending))
> +		complete(&func->obj->patch->finish);
>  }

[Severity: Critical]
Similarly here, does this access func after it has been freed?

If func->nop is true, klp_free_func_nop(func) frees the function,
but the new check immediately dereferences func->obj->patch->kobj_added.

[ ... ]

> @@ -737,9 +753,29 @@ static void klp_free_objects_dynamic(struct klp_patch *patch)
>   */
>  static void klp_free_patch_start(struct klp_patch *patch)
>  {
> +	struct klp_object *obj;
> +	struct klp_func *func;
> +
>  	if (!list_empty(&patch->list))
>  		list_del(&patch->list);
>  
> +	if (!patch->kobj_added) {

[Severity: High]
This is a pre-existing issue, but does this check leave child kobjects
unprotected if partial initialization fails after the patch kobject has
been added?

If klp_init_patch() successfully adds the patch kobject, it sets
patch->kobj_added = true. If a subsequent operation like klp_add_nops()
or klp_init_object() fails, klp_free_patch_start() is called on the
error path.

Because patch->kobj_added is true, this check is bypassed and
patch->kobj_pending tracking is not initialized. However, child kobjects
that were initialized early but not yet added to sysfs do not hold a
reference to patch->kobj. Thus, patch->kobj will be released
independently, unblocking patch->finish, and allowing the livepatch
module to be unloaded while un-added child kobjects may still trigger
their delayed releases and access freed module memory.

> +		/*
> +		 * The kobjects were only initialized and never added to
> +		 * sysfs. Count them so that klp_free_patch_finish() can
> +		 * wait for all their releases before the patch module is
> +		 * unloaded. Without this, a delayed kobject release
> +		 * (CONFIG_DEBUG_KOBJECT_RELEASE) could access the freed
> +		 * module memory.
> +		 */
> +		atomic_set(&patch->kobj_pending, 1); /* the patch kobject */
> +		klp_for_each_object(patch, obj) {
> +			atomic_inc(&patch->kobj_pending);
> +			klp_for_each_func(obj, func)
> +				atomic_inc(&patch->kobj_pending);
> +		}
> +	}
> +
>  	klp_free_objects(patch);
>  }

[ ... ]

> @@ -987,6 +1027,7 @@ static int klp_init_patch(struct klp_patch *patch)
>  	ret = kobject_add(&patch->kobj, klp_root_kobj, "%s", patch->mod->name);
>  	if (ret)
>  		return ret;
> +	patch->kobj_added = true;
>  
>  	if (patch->replace) {
>  		ret = klp_add_nops(patch);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260813030408.9761-1-laoar.shao@gmail.com?part=2

  reply	other threads:[~2026-08-13  3:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-13  3:04 [PATCH 0/2] livepatch: Fix several bugs found during replace set implementation Yafang Shao
2026-08-13  3:04 ` [PATCH 1/2] livepatch: Fix wrong index in funcs cleanup error path Yafang Shao
2026-08-13  3:04 ` [PATCH 2/2] livepatch: Fix UAF of unregistered patch kobjects Yafang Shao
2026-08-13  3:16   ` sashiko-bot [this message]
2026-08-13  3:58     ` Yafang Shao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260813031611.A4EAD1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=laoar.shao@gmail.com \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@suse.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=song@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox