Hi folks, This RFC is intended to continue the "Livepatch callback state management" [1] discussion from last year's Plumbers Conference. A quick recap (please correct anything if I have it wrong): * Nicolai's talk started by highlighting what could be done by hacking about with the klp callbacks. * Atomic replace introduces a few wrinkles including the skipping of replaced-patch-callbacks. (See the Limitations section of Documentation/cumulative-patches.txt) * Petr floated the idea of allocating a struct with the callbacks embedded, so that proper callbacks could be invoked even when reverting patches. * Feature-ids were suggested to flag special compatibility concerns. * Miroslav suggested starting simple. * Josh pointed out that shadow variables could be used today (presumably from pre-patch callbacks) to manage patch compatibility. In the interest of starting simple, I shied away from directly touching the callback mechanisms. Instead, I added two small policy features to the livepatching core: livepatch versioning and a mechanism to disable disablement (which I call 'sticky' for lack of a better term). Together I think they would simplify the livepatch upgrade model, while addressing the safety concerns discussed at the LPC. Both could have been implemented by livepatch callbacks, but codifying them into the livepatch core was pretty easy -- the diffstat at the bottom is deceiving; most of the churn was documentation and adding self-tests to verify policy. Finally IMHO, settling on a common set of code, policy and vocabulary would be saner than everyone writing bespoke callbacks. For full policy details, see the Documentation files from the patch. A quick tl;dr summary as follows: Versioning ---------- Only livepatches with increasing version numbers may be loaded. The RFC policy relies on a few assumptions: 0 - Livepatch v10 may be loaded even if v9 has NOT been loaded. 1 - Livepatches must be compatible with any special requirements of previous livepatch versions. For example, livepatch v10 must be safe to load if livepatch v9 has been loaded. 2 - Downgrades are allowed: - (via disablement) A patch may be disabled, decrementing the livepatch core's latest-version counter. Older livepatches that meet the version policy may be reloaded. - (via replacement) A follow up cumulative patch may revert behavior of a previously loaded patch. This must be safe by keeping assumption #1. 'Sticky' patches ---------------- Livepatches with their klp_patch.sticky bool set to true may not be (directly) disabled. The RFC policy allows for: - Sticky patch disablement during its transition to KLP_PATCHED. - Cumulative follow-ups may update the sticky state. These two caveats allow the user to reverse the patch transition and for newer livepatch versions to undo a previous version's stickiness. RFC notes --------- A simplified upgrade model with versioning and sticky atomic-replace patches would distill down to: Only newer livepatches may be loaded and their higher version is an acknowledgement that it assumes responsibility to operate safely when earlier versioned patches are loaded. and: 'Sticky' livepatches are an indication from a livepatch that is has done something unsafe. They may not be disabled or replaced without a succeeding patch accepting the previous statement. Comments, idea, flames welcome :) This was largely an experiment in trying to avoid further callback complexity. If anyone is already coding up interesting callbacks to handle unsafe scenarios, I'd be interested in seeing what was implemented. For this RFC, my main concern were the L1TF modifications that Nicolai had mentioned. Perhaps I've missed other scenarios that need to be considered, too. Thanks, -- Joe On top of: livepatching/for-5.1/atomic-replace [PATCH] livepatch/selftests: use "$@" to preserve argument list Joe Lawrence (2): livepatch: implement patch versioning livepatch: implement 'sticky' patches .../ABI/testing/sysfs-kernel-livepatch | 21 +++ Documentation/livepatch/sticky-patches.txt | 27 +++ Documentation/livepatch/versioning.txt | 31 ++++ include/linux/livepatch.h | 4 + kernel/livepatch/core.c | 68 ++++++- kernel/livepatch/core.h | 1 + kernel/livepatch/transition.c | 6 + lib/livepatch/Makefile | 8 +- lib/livepatch/test_klp_sticky_0.c | 43 +++++ lib/livepatch/test_klp_sticky_1.c | 43 +++++ lib/livepatch/test_klp_version_0.c | 34 ++++ lib/livepatch/test_klp_version_1.c | 34 ++++ lib/livepatch/test_klp_version_2.c | 34 ++++ lib/livepatch/test_klp_version_3.c | 34 ++++ tools/testing/selftests/livepatch/Makefile | 4 +- .../selftests/livepatch/test-sticky.sh | 61 +++++++ .../selftests/livepatch/test-versions.sh | 172 ++++++++++++++++++ 17 files changed, 622 insertions(+), 3 deletions(-) create mode 100644 Documentation/livepatch/sticky-patches.txt create mode 100644 Documentation/livepatch/versioning.txt create mode 100644 lib/livepatch/test_klp_sticky_0.c create mode 100644 lib/livepatch/test_klp_sticky_1.c create mode 100644 lib/livepatch/test_klp_version_0.c create mode 100644 lib/livepatch/test_klp_version_1.c create mode 100644 lib/livepatch/test_klp_version_2.c create mode 100644 lib/livepatch/test_klp_version_3.c create mode 100755 tools/testing/selftests/livepatch/test-sticky.sh create mode 100755 tools/testing/selftests/livepatch/test-versions.sh -- 2.20.1