Livepatching allows for rapid experimentation with new kernel features without interrupting production workloads. However, static livepatches lack the flexibility required to tune features based on task-specific attributes, such as cgroup membership, which is critical in multi-tenant k8s environments. Furthermore, hardcoding logic into a livepatch prevents dynamic adjustments based on the runtime environment.
To address this, we propose a hybrid approach using BPF. Our production use case involves: 1. Deploying a Livepatch function to serve as a stable BPF hook. 2. Utilizing bpf_override_return() to dynamically modify the return value of that hook based on the current task's context. A significant challenge arises when atomic-replace is enabled. In this mode, deploying a new livepatch changes the target function's address, forcing a re-attachment of the BPF program. This re-attachment latency is unacceptable in critical paths, such as those handling networking policies. To solve this, we introduce a hybrid livepatch mode that allows specific patches to remain non-replaceable, ensuring the function address remains stable and the BPF program stays attached. Signed-off-by: Yafang Shao <[email protected]> --- kernel/livepatch/core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 04f9e84f114f..5a44154131c8 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -665,6 +665,8 @@ static int klp_add_nops(struct klp_patch *patch) klp_for_each_object(old_patch, old_obj) { int err; + if (!old_patch->replaceable) + continue; err = klp_add_object_nops(patch, old_obj); if (err) return err; @@ -837,6 +839,8 @@ void klp_free_replaced_patches_async(struct klp_patch *new_patch) klp_for_each_patch_safe(old_patch, tmp_patch) { if (old_patch == new_patch) return; + if (!old_patch->replaceable) + continue; klp_free_patch_async(old_patch); } } @@ -1239,6 +1243,8 @@ void klp_unpatch_replaced_patches(struct klp_patch *new_patch) if (old_patch == new_patch) return; + if (!old_patch->replaceable) + continue; old_patch->enabled = false; klp_unpatch_objects(old_patch); } -- 2.47.3
