Re: [PATCH] samples/livepatch: Add BPF struct_ops integration sample
From: Yafang Shao
Date: Thu Apr 16 2026 - 03:48:24 EST
On Thu, Apr 16, 2026 at 8:16 AM Song Liu <song@xxxxxxxxxx> wrote:
>
> 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.
>
> Signed-off-by: Song Liu <song@xxxxxxxxxx>
> ---
> samples/livepatch/Makefile | 3 +
> samples/livepatch/livepatch-bpf.c | 202 ++++++++++++++++++++++++++++++
> 2 files changed, 205 insertions(+)
> create mode 100644 samples/livepatch/livepatch-bpf.c
>
> diff --git a/samples/livepatch/Makefile b/samples/livepatch/Makefile
> index 9f853eeb6140..1ab4ecbf1f0f 100644
> --- a/samples/livepatch/Makefile
> +++ b/samples/livepatch/Makefile
> @@ -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
> diff --git a/samples/livepatch/livepatch-bpf.c b/samples/livepatch/livepatch-bpf.c
> new file mode 100644
> index 000000000000..4a702a3b4726
> --- /dev/null
> +++ b/samples/livepatch/livepatch-bpf.c
> @@ -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,
> + }, { }
> +};
> +
> +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:
Tested-and-acked-by: Yafang Shao <laoar.shao@xxxxxxxxx>
[...]
--
Regards
Yafang