Skip to contentSkip to conversation

samples/livepatch: Add BPF struct_ops integration sample

PATCH In review Song Liu 4 participants 13 messages Apr 16 – Apr 26 Live patching

lore
Share & tools
lore

Song Liu

author maintainer
#0 lore raw

PATCH 1/1 samples/livepatch: Add BPF struct_ops integration sample

Add a sample module that demonstrates how BPF struct_ops can work together with kernel livepatch. The module livepatches cmdline_proc_show() and delegates the output to a BPF struct_ops callback. When no BPF program is attached, a fallback message is shown; when a BPF struct_ops program is attached, it controls the /proc/cmdline output via the bpf_klp_seq_write kfunc.

This builds on the existing livepatch-sample.c pattern but shows how livepatch and BPF struct_ops can be combined to make livepatched behavior programmable from userspace.

The module is built when both CONFIG_SAMPLE_LIVEPATCH and CONFIG_BPF_JIT are enabled.

---
 samples/livepatch/Makefile        |   3 +
 samples/livepatch/livepatch-bpf.c | 202 ++++++++++++++++++++++++++++++
 2 files changed, 205 insertions(+)
 create mode 100644 samples/livepatch/livepatch-bpf.c
samples/livepatch/Makefile +3 -0
index 9f853eeb6140..1ab4ecbf1f0f 100644
@@ -6,3 +6,6 @@ obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix2.o
 obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-demo.o
 obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-mod.o
 obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-busymod.o
+ifdef CONFIG_BPF_JIT
+obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-bpf.o
+endif
samples/livepatch/livepatch-bpf.c new file +202 -0

202 lines not on this page · raw message

Signature · 1 line
2.52.0
author maintainer
#1 lore raw
Quoted 8 lines · Song Liu

Add a sample module that demonstrates how BPF struct_ops can work together with kernel livepatch. The module livepatches cmdline_proc_show() and delegates the output to a BPF struct_ops callback. When no BPF program is attached, a fallback message is shown; when a BPF struct_ops program is attached, it controls the /proc/cmdline output via the bpf_klp_seq_write kfunc.

Quoted 8 lines

This builds on the existing livepatch-sample.c pattern but shows how livepatch and BPF struct_ops can be combined to make livepatched behavior programmable from userspace.

The module is built when both CONFIG_SAMPLE_LIVEPATCH and CONFIG_BPF_JIT are enabled.

Forgot to add

Assisted-by Claude:claude-opus-4-6
#2 lore raw
In reply to Song Liu
Quoted 133 lines · Song Liu

Add a sample module that demonstrates how BPF struct_ops can work together with kernel livepatch. The module livepatches cmdline_proc_show() and delegates the output to a BPF struct_ops callback. When no BPF program is attached, a fallback message is shown; when a BPF struct_ops program is attached, it controls the /proc/cmdline output via the bpf_klp_seq_write kfunc.

This builds on the existing livepatch-sample.c pattern but shows how livepatch and BPF struct_ops can be combined to make livepatched behavior programmable from userspace.

The module is built when both CONFIG_SAMPLE_LIVEPATCH and CONFIG_BPF_JIT are enabled.

---
 samples/livepatch/Makefile        |   3 +
 samples/livepatch/livepatch-bpf.c | 202 ++++++++++++++++++++++++++++++
 2 files changed, 205 insertions(+)
 create mode 100644 samples/livepatch/livepatch-bpf.c
samples/livepatch/Makefile +3 -0
index 9f853eeb6140..1ab4ecbf1f0f 100644
@@ -6,3 +6,6 @@ obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-shadow-fix2.o
 obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-demo.o
 obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-mod.o
 obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-callbacks-busymod.o
+ifdef CONFIG_BPF_JIT
+obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-bpf.o
+endif
samples/livepatch/livepatch-bpf.c new file +94 -0
new file mode 100644
index 000000000000..4a702a3b4726
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * livepatch-bpf.c - BPF struct_ops + Kernel Live Patching Sample Module
+ *
+ * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
+ *
+ * This sample demonstrates how BPF struct_ops can control kernel
+ * behavior through livepatch. The module livepatches cmdline_proc_show()
+ * and delegates output to a BPF struct_ops callback. A BPF program can
+ * then attach to override /proc/cmdline output via the bpf_klp_seq_write
+ * kfunc.
+ *
+ * Example:
+ *
+ * $ insmod livepatch-bpf.ko
+ * $ cat /proc/cmdline
+ * livepatch_bpf: no struct_ops attached
+ *
+ * (attach a BPF struct_ops program implementing set_cmdline, e.g.)
+ *
+ * SEC("struct_ops/set_cmdline")
+ * int BPF_PROG(set_cmdline, struct seq_file *m)
+ * {
+ *     char custom[] = "klp_bpf: custom cmdline\n";
+ *     bpf_klp_seq_write(m, custom, sizeof(custom) - 1);
+ *     return 0;
+ * }
+ *
+ * $ cat /proc/cmdline
+ * klp_bpf: custom cmdline
+ *
+ * $ echo 0 > /sys/kernel/livepatch/livepatch_bpf/enabled
+ * $ cat /proc/cmdline
+ * <your cmdline>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bpf.h>
+#include <linux/btf.h>
+#include <linux/btf_ids.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/livepatch.h>
+#include <linux/seq_file.h>
+#include <linux/bpf_verifier.h>
+
+struct klp_bpf_cmdline_ops {
+       int (*set_cmdline)(struct seq_file *m);
+};
+
+static struct klp_bpf_cmdline_ops *active_ops;
+
+/* --- kfunc: allow BPF struct_ops programs to write to seq_file --- */
+
+__bpf_kfunc_start_defs();
+
+__bpf_kfunc void bpf_klp_seq_write(struct seq_file *m,
+                                   const char *data, u32 data__sz)
+{
+       seq_write(m, data, data__sz);
+}
+
+__bpf_kfunc_end_defs();
+
+BTF_KFUNCS_START(klp_bpf_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_klp_seq_write)
+BTF_KFUNCS_END(klp_bpf_kfunc_ids)
+
+static const struct btf_kfunc_id_set klp_bpf_kfunc_set = {
+       .owner = THIS_MODULE,
+       .set   = &klp_bpf_kfunc_ids,
+};
+
+/* --- Livepatch replacement for cmdline_proc_show --- */
+
+static int livepatch_cmdline_proc_show(struct seq_file *m, void *v)
+{
+       struct klp_bpf_cmdline_ops *ops = READ_ONCE(active_ops);
+
+       if (ops && ops->set_cmdline)
+               return ops->set_cmdline(m);
+
+       seq_printf(m, "%s: no struct_ops attached\n", THIS_MODULE->name);
+       return 0;
+}
+
+static struct klp_func funcs[] = {
+       {
+               .old_name = "cmdline_proc_show",
+               .new_func = livepatch_cmdline_proc_show,
+       }, { }
+};
+

samples/livepatch/livepatch-bpf.c line 104

Quoted 10 lines
samples/livepatch/livepatch-bpf.c new file +10 -0
+static struct klp_object objs[] = {
+       {
+               /* name being NULL means vmlinux */
+               .funcs = funcs,
+       }, { }
+};
+
+static struct klp_patch patch = {
+       .mod = THIS_MODULE,
+       .objs = objs,

Nit: I suggest enabling the replace flag for this patch to align
with the recommended implementation.

.replace = true,

Other than that, it looks good to me:

[...]

Signature · 2 lines
Regards
Yafang
author maintainer
#3 lore raw

On Thu, Apr 16, 2026 at 12:46 AM Yafang Shao <[email protected]> wrote:
[...]

Quoted 9 lines

samples/livepatch/livepatch-bpf.c line 104

Quoted 4 lines
samples/livepatch/livepatch-bpf.c new file +4 -0
+
+static struct klp_patch patch = {
+       .mod = THIS_MODULE,
+       .objs = objs,

Nit: I suggest enabling the replace flag for this patch to align
with the recommended implementation.

.replace = true,

This is an interesting topic. To fully take advantage of the replace feature, we need more work on the BPF side.

For this sample, I guess we are OK either way.

Quoted 4 lines

Other than that, it looks good to me:

Thanks,
Song

#4 lore raw
Quoted 11 lines · Song Liu

On Thu, Apr 16, 2026 at 12:46 AM Yafang Shao <[email protected]> wrote:
[...]

Quoted 8 lines

samples/livepatch/livepatch-bpf.c line 104

Quoted 4 lines
samples/livepatch/livepatch-bpf.c new file +4 -0
+
+static struct klp_patch patch = {
+       .mod = THIS_MODULE,
+       .objs = objs,

Nit: I suggest enabling the replace flag for this patch to align
with the recommended implementation.

Quoted 4 lines
Quoted 1 line

.replace = true,

This is an interesting topic. To fully take advantage of the replace feature, we need more work on the BPF side.

Right.
Replacement seems to break struct_ops registration and BPF re-attachment. On the livepatch side, we should add support for the 'livepatch tag' to prevent these types of livepatches from being replaced ;)

Quoted 2 lines

For this sample, I guess we are OK either way.

OK

Signature · 2 lines
Regards
Yafang
author maintainer
#5 lore raw
Quoted 15 lines · Yafang Shao
Quoted 13 lines · Song Liu

On Thu, Apr 16, 2026 at 12:46 AM Yafang Shao <[email protected]> wrote:
[...]

Quoted 9 lines

samples/livepatch/livepatch-bpf.c line 104

Quoted 4 lines
samples/livepatch/livepatch-bpf.c new file +4 -0
+
+static struct klp_patch patch = {
+       .mod = THIS_MODULE,
+       .objs = objs,

Nit: I suggest enabling the replace flag for this patch to align
with the recommended implementation.

.replace = true,

Quoted 8 lines
Quoted 2 lines

This is an interesting topic. To fully take advantage of the replace feature, we need more work on the BPF side.

Right.
Replacement seems to break struct_ops registration and BPF re-attachment. On the livepatch side, we should add support for the 'livepatch tag' to prevent these types of livepatches from being replaced ;)

I somehow knew you were gonna say this. :) But I don't think this is a strong enough argument (and will probably scare folks more).

Thanks,
Song

maintainer
#6 lore raw
In reply to Song Liu
Quoted 10 lines · Song Liu

On Thu, Apr 16, 2026 at 12:46 AM Yafang Shao <[email protected]> wrote:
[...]

Quoted 8 lines

samples/livepatch/livepatch-bpf.c line 104

Quoted 4 lines
samples/livepatch/livepatch-bpf.c new file +4 -0
+
+static struct klp_patch patch = {
+       .mod = THIS_MODULE,
+       .objs = objs,

Nit: I suggest enabling the replace flag for this patch to align
with the recommended implementation.

Quoted 4 lines
Quoted 1 line

.replace = true,

This is an interesting topic. To fully take advantage of the replace feature, we need more work on the BPF side.

IMHO, this brings a synchronization problem. I do not have practical experience with BPF but I expect that:

+ The BPF program could be loaded only when the related bpf_struct_ops is registered.

+ The bpf_struct_ops is registered when the livepatch module is being loaded.

+ The new livepatch module would replace the older one when it is being loaded.

Now, we would need to load the BPF problem after the bpf_struct_ops is registered but before the livepatch gets enabled. Otherwise, the new livepatch would not continue working as the previous one.

Let' use the code from this patch:

static int __init livepatch_bpf_init(void)

{
	int ret;

	ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
					&klp_bpf_kfunc_set);
	ret = ret ?: register_bpf_struct_ops(&bpf_klp_bpf_cmdline_ops,
					     klp_bpf_cmdline_ops);
	if (ret)
		return ret;

---> /*
---> * We would need to wait here until the BPF program gets loaded.
---> * for the new bpf_struct_ops in this new livepatch.
---> */

	return klp_enable_patch(&patch);
}

Or maybe, the bpf_struct_ops can be _allocated dynamically_ and the pointer might be _passed via shadow variables_.

One problem is that shadow variables would add another overhead and need not be suitable for hot paths.

Anyway, I think that I have similar feelings as Miroslav. The combination of livepatches and BPF programs increases the complexity for all involved parties: core kernel maintainers, livepatch and BPF program authors, and system maintainers.

Do we really want to propagate it?
Is there any significant advantage in combining these two, please? Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to update BPF programs then livepatches?

IMHO, the livepatches should allow enough flexibility. And it might be easier to update the livepatch when needed.

Or do you install more independent livepatches as well?

Would the support of different replace tags help? They would allow to replace only livepatches with the same tag.

Best Regards,
Petr

author maintainer
#7 lore raw
Quoted 2 lines · Petr Mladek

On Thu 2026-04-16 09:32:46, Song Liu wrote:

[...]

Quoted 13 lines

Let' use the code from this patch:

static int __init livepatch_bpf_init(void)

{
        int ret;

        ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
                                        &klp_bpf_kfunc_set);
        ret = ret ?: register_bpf_struct_ops(&bpf_klp_bpf_cmdline_ops,
                                             klp_bpf_cmdline_ops);
        if (ret)
                return ret;
Quoted 6 lines

---> /*

--->     * We would need to wait here until the BPF program gets loaded.
--->     * for the new bpf_struct_ops in this new livepatch.
--->     */
        return klp_enable_patch(&patch);
}

Yes, something in this direction is needed to make atomic replace work. We have no plan to use this in production. I will let Yafang figure out his plan.

Quoted 12 lines

Or maybe, the bpf_struct_ops can be _allocated dynamically_ and the pointer might be _passed via shadow variables_.

One problem is that shadow variables would add another overhead and need not be suitable for hot paths.

Anyway, I think that I have similar feelings as Miroslav. The combination of livepatches and BPF programs increases the complexity for all involved parties: core kernel maintainers, livepatch and BPF program authors, and system maintainers.

Quoted 4 lines

Do we really want to propagate it?
Is there any significant advantage in combining these two, please? Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to update BPF programs then livepatches?

Some combination like this will probably make sense for Yafang's use cases. But I agree maybe we don't want this in the samples, because it is indeed complicated and could be more dangerous.

Thanks,
Song

Quoted 7 lines

IMHO, the livepatches should allow enough flexibility. And it might be easier to update the livepatch when needed.

Or do you install more independent livepatches as well?

Would the support of different replace tags help? They would allow to replace only livepatches with the same tag.

#8 lore raw
Quoted 18 lines · Song Liu
Quoted 2 lines · Petr Mladek

On Thu 2026-04-16 09:32:46, Song Liu wrote:

[...]

Quoted 13 lines

Let' use the code from this patch:

static int __init livepatch_bpf_init(void)

{
        int ret;

        ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
                                        &klp_bpf_kfunc_set);
        ret = ret ?: register_bpf_struct_ops(&bpf_klp_bpf_cmdline_ops,
                                             klp_bpf_cmdline_ops);
        if (ret)
                return ret;
Quoted 4 lines
Quoted 4 lines

---> /*

--->     * We would need to wait here until the BPF program gets loaded.
--->     * for the new bpf_struct_ops in this new livepatch.
--->     */

No waiting is necessary. If the BPF program is not attached, the default logic can be executed instead. Consider Song's test case: we can handle it as follows.

static int livepatch_cmdline_proc_show(struct seq_file *m, void *v)

{
    struct klp_bpf_cmdline_ops *ops = READ_ONCE(active_ops);

    if (ops && ops->set_cmdline)
        return ops->set_cmdline(m);

    // If no BPF program is attached, the default kernel function runs.
    return cmdline_proc_show(m, v);
}

However, as Song explained below, if we want atomic replace to work, we may need to wait for the new BPF program here. But that would make the combination of livepatch and BPF more complex.

Currently, on our production servers, we handle this through a user script, such as:

stop_traffic_relying_on_livepatch_bpf
kpatch load new-livepatch-bpf-module.ko
reattach_the_bpf_program
start_the_traffic_again

Although this approach requires restarting the affected traffic, other services running on the same server remain unaffected.

Quoted 23 lines
Quoted 2 lines
        return klp_enable_patch(&patch);
}

Yes, something in this direction is needed to make atomic replace work. We have no plan to use this in production. I will let Yafang figure out his plan.

Quoted 16 lines

Or maybe, the bpf_struct_ops can be _allocated dynamically_ and the pointer might be _passed via shadow variables_.

One problem is that shadow variables would add another overhead and need not be suitable for hot paths.

Anyway, I think that I have similar feelings as Miroslav. The combination of livepatches and BPF programs increases the complexity for all involved parties: core kernel maintainers, livepatch and BPF program authors, and system maintainers.

Do we really want to propagate it?
Is there any significant advantage in combining these two, please? Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to update BPF programs then livepatches?

This is an important feature for avoiding server restarts, particularly in a VM host environment. Since only one VM on the host may be affected by this feature, we can deploy it rapidly without impacting other VMs on the same host.

Quoted 12 lines

Some combination like this will probably make sense for Yafang's use cases. But I agree maybe we don't want this in the samples, because it is indeed complicated and could be more dangerous.

Thanks,
Song

Quoted 4 lines

IMHO, the livepatches should allow enough flexibility. And it might be easier to update the livepatch when needed.

Or do you install more independent livepatches as well?

If we want certain livepatches to be persistent on the server, we will need to support independent livepatches — and we do have such use cases.

Quoted 3 lines
Quoted 3 lines

Would the support of different replace tags help? They would allow to replace only livepatches with the same tag.

Right, it will help.

Signature · 2 lines
Regards
Yafang
maintainer
#9 lore raw
Quoted 19 lines · Yafang Shao
Quoted 18 lines · Song Liu
Quoted 2 lines · Petr Mladek

On Thu 2026-04-16 09:32:46, Song Liu wrote:

[...]

Quoted 13 lines

Let' use the code from this patch:

static int __init livepatch_bpf_init(void)

{
        int ret;

        ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
                                        &klp_bpf_kfunc_set);
        ret = ret ?: register_bpf_struct_ops(&bpf_klp_bpf_cmdline_ops,
                                             klp_bpf_cmdline_ops);
        if (ret)
                return ret;
Quoted 7 lines
Quoted 4 lines
Quoted 4 lines

---> /*

--->     * We would need to wait here until the BPF program gets loaded.
--->     * for the new bpf_struct_ops in this new livepatch.
--->     */

No waiting is necessary. If the BPF program is not attached, the default logic can be executed instead.

But it means a regression. I guess that you need the BPF program for a reason. The default logic is not good enough indeed.

Quoted 20 lines

Consider Song's test case: we can handle it as follows.

static int livepatch_cmdline_proc_show(struct seq_file *m, void *v)

{
    struct klp_bpf_cmdline_ops *ops = READ_ONCE(active_ops);

    if (ops && ops->set_cmdline)
        return ops->set_cmdline(m);

    // If no BPF program is attached, the default kernel function runs.
    return cmdline_proc_show(m, v);
}

However, as Song explained below, if we want atomic replace to work, we may need to wait for the new BPF program here. But that would make the combination of livepatch and BPF more complex.

Currently, on our production servers, we handle this through a user script, such as:

Quoted 7 lines

stop_traffic_relying_on_livepatch_bpf
kpatch load new-livepatch-bpf-module.ko
reattach_the_bpf_program
start_the_traffic_again

Although this approach requires restarting the affected traffic, other services running on the same server remain unaffected.

We put a lot of effort to make livepatching as less disruptive as possible. The atomic replace is supposed to work without any disruption.

Quoted 24 lines
Quoted 23 lines
Quoted 2 lines
        return klp_enable_patch(&patch);
}

Yes, something in this direction is needed to make atomic replace work. We have no plan to use this in production. I will let Yafang figure out his plan.

Quoted 16 lines

Or maybe, the bpf_struct_ops can be _allocated dynamically_ and the pointer might be _passed via shadow variables_.

One problem is that shadow variables would add another overhead and need not be suitable for hot paths.

Anyway, I think that I have similar feelings as Miroslav. The combination of livepatches and BPF programs increases the complexity for all involved parties: core kernel maintainers, livepatch and BPF program authors, and system maintainers.

Do we really want to propagate it?
Is there any significant advantage in combining these two, please? Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to update BPF programs then livepatches?

Quoted 4 lines

This is an important feature for avoiding server restarts, particularly in a VM host environment. Since only one VM on the host may be affected by this feature, we can deploy it rapidly without impacting other VMs on the same host.

This does not answer the question why you need the combination of livepatch + BPF. Why a livepatch is not enough?

Let me repeat the questions:

Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to install BPF programs then livepatches?

Quoted 4 lines
Quoted 2 lines
Quoted 2 lines

Would the support of different replace tags help? They would allow to replace only livepatches with the same tag.

Right, it will help.

Would this make a rapid update of livepatches easy enough so that you won't need the BPF part?

Best Regards,
Petr

#10 lore raw
Quoted 88 lines · Petr Mladek
Quoted 19 lines · Yafang Shao
Quoted 18 lines · Song Liu
Quoted 2 lines · Petr Mladek

On Thu 2026-04-16 09:32:46, Song Liu wrote:

[...]

Quoted 13 lines

Let' use the code from this patch:

static int __init livepatch_bpf_init(void)

{
        int ret;

        ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
                                        &klp_bpf_kfunc_set);
        ret = ret ?: register_bpf_struct_ops(&bpf_klp_bpf_cmdline_ops,
                                             klp_bpf_cmdline_ops);
        if (ret)
                return ret;
Quoted 7 lines
Quoted 4 lines
Quoted 4 lines

---> /*

--->     * We would need to wait here until the BPF program gets loaded.
--->     * for the new bpf_struct_ops in this new livepatch.
--->     */

No waiting is necessary. If the BPF program is not attached, the default logic can be executed instead.

But it means a regression. I guess that you need the BPF program for a reason. The default logic is not good enough indeed.

Quoted 20 lines

Consider Song's test case: we can handle it as follows.

static int livepatch_cmdline_proc_show(struct seq_file *m, void *v)

{
    struct klp_bpf_cmdline_ops *ops = READ_ONCE(active_ops);

    if (ops && ops->set_cmdline)
        return ops->set_cmdline(m);

    // If no BPF program is attached, the default kernel function runs.
    return cmdline_proc_show(m, v);
}

However, as Song explained below, if we want atomic replace to work, we may need to wait for the new BPF program here. But that would make the combination of livepatch and BPF more complex.

Currently, on our production servers, we handle this through a user script, such as:

Quoted 7 lines

stop_traffic_relying_on_livepatch_bpf
kpatch load new-livepatch-bpf-module.ko
reattach_the_bpf_program
start_the_traffic_again

Although this approach requires restarting the affected traffic, other services running on the same server remain unaffected.

We put a lot of effort to make livepatching as less disruptive as possible. The atomic replace is supposed to work without any disruption.

Quoted 24 lines
Quoted 23 lines
Quoted 2 lines
        return klp_enable_patch(&patch);
}

Yes, something in this direction is needed to make atomic replace work. We have no plan to use this in production. I will let Yafang figure out his plan.

Quoted 16 lines

Or maybe, the bpf_struct_ops can be _allocated dynamically_ and the pointer might be _passed via shadow variables_.

One problem is that shadow variables would add another overhead and need not be suitable for hot paths.

Anyway, I think that I have similar feelings as Miroslav. The combination of livepatches and BPF programs increases the complexity for all involved parties: core kernel maintainers, livepatch and BPF program authors, and system maintainers.

Do we really want to propagate it?
Is there any significant advantage in combining these two, please? Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to update BPF programs then livepatches?

Quoted 7 lines
Quoted 4 lines

This is an important feature for avoiding server restarts, particularly in a VM host environment. Since only one VM on the host may be affected by this feature, we can deploy it rapidly without impacting other VMs on the same host.

This does not answer the question why you need the combination of livepatch + BPF. Why a livepatch is not enough?

Consider this recent use case from our production servers:

https://lore.kernel.org/live-patching/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/

In one of our clusters, we needed to route BGP traffic through specific NICs based on destination IP addresses. To achieve this without service interruption, we applied a livepatch to bond_xmit_3ad_xor_slave_get() to introduce a new hook, bond_get_slave_hook(). We then attached a BPF program to this hook to select the outgoing NIC by parsing the SKB. Because the destination IPs must be adjusted on demand, a static livepatch alone was insufficient; the BPF integration provided the necessary dynamic flexibility.

Quoted 6 lines

Let me repeat the questions:

Is it significantly easier to write BPF program then a livepatch? Is it significantly easier to install BPF programs then livepatches?

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Quoted 2 lines

Would the support of different replace tags help? They would allow to replace only livepatches with the same tag.

Right, it will help.

Would this make a rapid update of livepatches easy enough so that you won't need the BPF part?

As explained above, we cannot rely solely on livepatching to handle destination IP changes, as these require real-time updates.

Signature · 2 lines
Regards
Yafang
maintainer
#11 lore raw
In reply to Song Liu

Hi,

Quoted 7 lines · Song Liu

Add a sample module that demonstrates how BPF struct_ops can work together with kernel livepatch. The module livepatches cmdline_proc_show() and delegates the output to a BPF struct_ops callback. When no BPF program is attached, a fallback message is shown; when a BPF struct_ops program is attached, it controls the /proc/cmdline output via the bpf_klp_seq_write kfunc.

Quoted 8 lines

This builds on the existing livepatch-sample.c pattern but shows how livepatch and BPF struct_ops can be combined to make livepatched behavior programmable from userspace.

The module is built when both CONFIG_SAMPLE_LIVEPATCH and CONFIG_BPF_JIT are enabled.

Interesting. It does not make me comfortable to be honest. Is this something we want to advertise through samples?

Sashiko has comments...
https://sashiko.dev/#/patchset/20260416001628.2062468-1-song%40kernel.org

Miroslav

author maintainer
#12 lore raw
Quoted 16 lines · Miroslav Benes

Hi,

Quoted 11 lines · Song Liu

Add a sample module that demonstrates how BPF struct_ops can work together with kernel livepatch. The module livepatches cmdline_proc_show() and delegates the output to a BPF struct_ops callback. When no BPF program is attached, a fallback message is shown; when a BPF struct_ops program is attached, it controls the /proc/cmdline output via the bpf_klp_seq_write kfunc.

This builds on the existing livepatch-sample.c pattern but shows how livepatch and BPF struct_ops can be combined to make livepatched behavior programmable from userspace.

Quoted 7 lines
Quoted 4 lines

The module is built when both CONFIG_SAMPLE_LIVEPATCH and CONFIG_BPF_JIT are enabled.

Interesting. It does not make me comfortable to be honest. Is this something we want to advertise through samples?

I can understand your concern. We don't have to add these to the samples.

Quoted 2 lines

Sashiko has comments...
https://sashiko.dev/#/patchset/20260416001628.2062468-1-song%40kernel.org

These are valid points.

Thanks,
Song