public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Petr Mladek <pmladek@suse.com>
To: Josh Poimboeuf <jpoimboe@kernel.org>, Miroslav Benes <mbenes@suse.cz>
Cc: Joe Lawrence <joe.lawrence@redhat.com>,
	Nicolai Stange <nstange@suse.de>,
	live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
	Petr Mladek <pmladek@suse.com>
Subject: [PATCH v1 02/19] livepatch: Allow to handle lifetime of shadow variables using the livepatch state
Date: Wed, 15 Jan 2025 09:24:14 +0100	[thread overview]
Message-ID: <20250115082431.5550-3-pmladek@suse.com> (raw)
In-Reply-To: <20250115082431.5550-1-pmladek@suse.com>

Managing the lifetime of shadow variables becomes challenging when atomic
replace is used. The new patch cannot determine whether a shadow variable
has already been used by a previous live patch or if there is a shadow
variable that is no longer in use.

Shadow variables are typically used alongside callbacks. At a minimum,
the @post_unpatch callback is called to free shadow variables that are
no longer needed. Additionally, @post_patch and @pre_unpatch callbacks
are sometimes used to enable or disable the use of shadow variables.
This is necessary when the shadow variable can only be used when
the entire system is capable of handling it.

The complexity increases when using the atomic replace feature,
as only the callbacks from the new live patch are executed.
Newly created live patches might manage obsolete shadow variables,
ensuring the upgrade functions correctly. However, older live
patches are unaware of shadow variables introduced later, which
could lead to leaks during a downgrade. Additionally, these
leaked variables might retain outdated information, potentially
causing issues if those variables are reused in a subsequent upgrade.

These issues are better addressed with the new callbacks associated
with a live patch state. These callbacks are triggered both when
the states are first introduced and when they become obsolete.
Additionally, the callbacks are invoked from the patch that
originally supported the state, ensuring that even downgrades are
handled safely.

Let’s formalize the process: Associate a shadow variable with a live
patch state by setting the "state.is_shadow" flag and using the same
"id" in both struct klp_shadow and struct klp_state.

The shadow variable will then share the same lifetime as the livepatch
state, allowing obsolete shadow variables to be automatically freed
without requiring an additional callback.

A generic callback will free the shadow variables using
the state->callbacks.shadow_dtor callback, if provided.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 include/linux/livepatch.h | 15 ++++++++++-----
 kernel/livepatch/state.c  |  3 +++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 79dddf3dbd52..c624f1105663 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -132,6 +132,11 @@ struct klp_object {
 struct klp_patch;
 struct klp_state;
 
+typedef int (*klp_shadow_ctor_t)(void *obj,
+				 void *shadow_data,
+				 void *ctor_data);
+typedef void (*klp_shadow_dtor_t)(void *obj, void *shadow_data);
+
 /**
  * struct klp_state_callbacks - callbacks manipulating the state
  * @pre_patch:		 executed only when the state is being enabled
@@ -142,6 +147,7 @@ struct klp_state;
  *			 before code unpatching
  * @post_unpatch:	 executed only when the state is being disabled
  *			 after code unpatching
+ * @shadow_dtor:	 destructor for the related shadow variable
  * @pre_patch_succeeded: internal state used by a rollback on error
  *
  * All callbacks are optional.
@@ -158,6 +164,7 @@ struct klp_state_callbacks {
 	void (*post_patch)(struct klp_patch *patch, struct klp_state *state);
 	void (*pre_unpatch)(struct klp_patch *patch, struct klp_state *state);
 	void (*post_unpatch)(struct klp_patch *patch, struct klp_state *state);
+	klp_shadow_dtor_t shadow_dtor;
 	bool pre_patch_succeeded;
 };
 
@@ -166,12 +173,15 @@ struct klp_state_callbacks {
  * @id:		system state identifier (non-zero)
  * @version:	version of the change
  * @callbacks:	optional callbacks used when enabling or disabling the state
+ * @is_shadow:	the state handles lifetime of a shadow variable with
+ *		the same @id
  * @data:	custom data
  */
 struct klp_state {
 	unsigned long id;
 	unsigned int version;
 	struct klp_state_callbacks callbacks;
+	bool is_shadow;
 	void *data;
 };
 
@@ -246,11 +256,6 @@ static inline bool klp_have_reliable_stack(void)
 	       IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE);
 }
 
-typedef int (*klp_shadow_ctor_t)(void *obj,
-				 void *shadow_data,
-				 void *ctor_data);
-typedef void (*klp_shadow_dtor_t)(void *obj, void *shadow_data);
-
 void *klp_shadow_get(void *obj, unsigned long id);
 void *klp_shadow_alloc(void *obj, unsigned long id,
 		       size_t size, gfp_t gfp_flags,
diff --git a/kernel/livepatch/state.c b/kernel/livepatch/state.c
index bf7ed988d2bb..16ad695b1e88 100644
--- a/kernel/livepatch/state.c
+++ b/kernel/livepatch/state.c
@@ -201,6 +201,9 @@ void klp_states_post_unpatch(struct klp_patch *patch)
 		if (state->callbacks.post_unpatch)
 			state->callbacks.post_unpatch(patch, state);
 
+		if (state->is_shadow)
+			klp_shadow_free_all(state->id, state->callbacks.shadow_dtor);
+
 		state->callbacks.pre_patch_succeeded = 0;
 	}
 }
-- 
2.47.1


  parent reply	other threads:[~2025-01-15  8:25 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-15  8:24 [PATCH v1 00/19] livepatch: Better integrate callbacks and shadow variables with the states API Petr Mladek
2025-01-15  8:24 ` [PATCH v1 01/19] livepatch: Add callbacks for introducing and removing states Petr Mladek
2025-01-15  8:24 ` Petr Mladek [this message]
2025-01-15  8:24 ` [PATCH v1 03/19] selftests/livepatch: Use per-state callbacks in state API tests Petr Mladek
2025-01-15  8:24 ` [PATCH v1 04/19] livepatch: Add "block_disable" flag to per-state API and remove versioning Petr Mladek
2025-01-15  8:24 ` [PATCH v1 05/19] livepatch: Remove "data" from struct klp_state Petr Mladek
2025-01-15  8:24 ` [PATCH v1 06/19] selftests/livepatch: Remove callbacks from sysfs interface testing Petr Mladek
2025-01-15  8:24 ` [PATCH v1 07/19] selftests/livepatch: Substitute hard-coded /sys/module path Petr Mladek
2025-01-15  8:24 ` [PATCH v1 08/19] selftests/livepatch: Move basic tests for livepatching modules Petr Mladek
2025-01-15  8:24 ` [PATCH v1 09/19] selftests/livepatch: Convert testing of multiple target modules Petr Mladek
2025-01-15  8:24 ` [PATCH v1 10/19] selftests/livepatch: Create a simple selftest for state callbacks Petr Mladek
2025-01-15  8:24 ` [PATCH v1 11/19] selftests/livepatch: Convert selftests for failing pre_patch callback Petr Mladek
2025-01-15  8:24 ` [PATCH v1 12/19] selftests/livepatch: Convert selftest with blocked transition Petr Mladek
2025-01-15  8:24 ` [PATCH v1 13/19] selftests/livepatch: Add more tests for state callbacks with blocked transitions Petr Mladek
2025-01-15  8:24 ` [PATCH v1 14/19] selftests/livepatch: Convert selftests for testing callbacks with more livepatches Petr Mladek
2025-01-15  8:24 ` [PATCH v1 15/19] selftests/livepatch: Do not use a livepatch with the obsolete per-object callbacks in the basic selftests Petr Mladek
2025-01-15  8:24 ` [PATCH v1 16/19] selftests/livepatch: Remove obsolete test modules for per-object callbacks Petr Mladek
2025-01-15  8:24 ` [PATCH v1 17/19] samples/livepatch: Replace sample module with obsolete " Petr Mladek
2025-01-15  8:24 ` [PATCH v1 18/19] Documentation/livepatch: Update documentation for state, callbacks, and shadow variables Petr Mladek
2025-03-06 22:54   ` Joe Lawrence
2025-03-07 12:26     ` Petr Mladek
2025-03-07 15:50       ` Joe Lawrence
2025-03-17 11:17         ` Petr Mladek
2025-01-15  8:24 ` [PATCH v1 19/19] livepatch: Remove obsolete per-object callbacks Petr Mladek

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=20250115082431.5550-3-pmladek@suse.com \
    --to=pmladek@suse.com \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=nstange@suse.de \
    /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