include/linux/livepatch.h | 2 ++ kernel/livepatch/core.c | 50 +++++++++++++++++++++++++++++++ kernel/trace/Kconfig | 14 +++++++++ kernel/trace/bpf_trace.c | 14 ++++++--- kernel/trace/trace_kprobe.c | 49 ++++++++++++------------------ kernel/trace/trace_probe.h | 59 +++++++++++++++++++++++++++---------- 6 files changed, 139 insertions(+), 49 deletions(-)
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. Furthermore, this mechanism provides a lower-maintenance alternative to out-of-tree BPF hooks. Given the complexities of upstreaming custom BPF hooks (e.g., [0], [1]), this hybrid mode allows for the maintenance of stable, minimal hook points via livepatching with significantly reduced maintenance burden. Link: https://lwn.net/Articles/1054030/ [0] Link: https://lwn.net/Articles/1043548/ [1] Yafang Shao (4): trace: Simplify kprobe overridable function check trace: Allow kprobes to override livepatched functions livepatch: Add "replaceable" attribute to klp_patch livepatch: Implement livepatch hybrid mode include/linux/livepatch.h | 2 ++ kernel/livepatch/core.c | 50 +++++++++++++++++++++++++++++++ kernel/trace/Kconfig | 14 +++++++++ kernel/trace/bpf_trace.c | 14 ++++++--- kernel/trace/trace_kprobe.c | 49 ++++++++++++------------------ kernel/trace/trace_probe.h | 59 +++++++++++++++++++++++++++---------- 6 files changed, 139 insertions(+), 49 deletions(-) -- 2.47.3
Hi Yafang, On Thu, 2 Apr 2026 17:26:03 +0800 Yafang Shao <laoar.shao@gmail.com> wrote: > 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. First of all, I don't like this approach to test a new feature in the kernel, because it sounds like allowing multiple different generations of implementations to coexist simultaneously. The standard kernel code is not designed to withstand such implementations. For example, if you implement a well-designed framework in a specific subsystem, like Schedext, which allows multiple implementations extended with BPF to coexist, there's no problem (at least it's debatable). But if it is for any function, it is dangerous feature. Bugs that occur in kernels that use this functionality cannot be addressed here. They need to be treated the same way as out-of-tree drivers or forked kernels. I mean, add a tainted flag for this feature. And we don't care of it. > > 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. Can you share your actual problem to be solved? If the specific problem and the specific subsystem are clear, I think there is room to discuss it with the subsystem maintainer. > > Furthermore, this mechanism provides a lower-maintenance alternative to > out-of-tree BPF hooks. Given the complexities of upstreaming custom BPF > hooks (e.g., [0], [1]), this hybrid mode allows for the maintenance of > stable, minimal hook points via livepatching with significantly reduced > maintenance burden. Maintenance cost is the same. We need to add out-of-tree BPF hooks on source code. Maybe deploying cost will be reduced. Thank you, > > Link: https://lwn.net/Articles/1054030/ [0] > Link: https://lwn.net/Articles/1043548/ [1] > > Yafang Shao (4): > trace: Simplify kprobe overridable function check > trace: Allow kprobes to override livepatched functions > livepatch: Add "replaceable" attribute to klp_patch > livepatch: Implement livepatch hybrid mode > > include/linux/livepatch.h | 2 ++ > kernel/livepatch/core.c | 50 +++++++++++++++++++++++++++++++ > kernel/trace/Kconfig | 14 +++++++++ > kernel/trace/bpf_trace.c | 14 ++++++--- > kernel/trace/trace_kprobe.c | 49 ++++++++++++------------------ > kernel/trace/trace_probe.h | 59 +++++++++++++++++++++++++++---------- > 6 files changed, 139 insertions(+), 49 deletions(-) > > -- > 2.47.3 > -- Masami Hiramatsu (Google) <mhiramat@kernel.org>
On Fri, Apr 10, 2026 at 12:38 PM Masami Hiramatsu <mhiramat@kernel.org> wrote: > > Hi Yafang, > > On Thu, 2 Apr 2026 17:26:03 +0800 > Yafang Shao <laoar.shao@gmail.com> wrote: > > > 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. > > First of all, I don't like this approach to test a new feature in the > kernel, because it sounds like allowing multiple different generations > of implementations to coexist simultaneously. The standard kernel code > is not designed to withstand such implementations. However, this approach is invaluable for rapidly deploying new kernel features to production servers without downtime. Upgrading kernels across a large fleet remains a significant challenge. > > For example, if you implement a well-designed framework in a specific > subsystem, like Schedext, which allows multiple implementations extended > with BPF to coexist, there's no problem (at least it's debatable). > > But if it is for any function, it is dangerous feature. Bugs that occur > in kernels that use this functionality cannot be addressed here. They > need to be treated the same way as out-of-tree drivers or forked kernels. > I mean, add a tainted flag for this feature. And we don't care of it. Agreed. This should be handled as an OOT module rather than part of the core kernel. > > > > > 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. > > Can you share your actual problem to be solved? Here is an example we recently deployed on our production servers: https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ In one of our specific clusters, we needed to send BGP traffic out through specific NICs based on the destination IP. To achieve this without interrupting service, we live-patched bond_xmit_3ad_xor_slave_get(), added a new hook called bond_get_slave_hook(), and then ran a BPF program attached to that hook to select the outgoing NIC from the SKB. This allowed us to rapidly deploy the feature with zero downtime. [...] -- Regards Yafang
On Sun, 12 Apr 2026 21:50:31 +0800 Yafang Shao <laoar.shao@gmail.com> wrote: > On Fri, Apr 10, 2026 at 12:38 PM Masami Hiramatsu <mhiramat@kernel.org> wrote: > > > > Hi Yafang, > > > > On Thu, 2 Apr 2026 17:26:03 +0800 > > Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > 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. > > > > First of all, I don't like this approach to test a new feature in the > > kernel, because it sounds like allowing multiple different generations > > of implementations to coexist simultaneously. The standard kernel code > > is not designed to withstand such implementations. > > However, this approach is invaluable for rapidly deploying new kernel > features to production servers without downtime. Upgrading kernels > across a large fleet remains a significant challenge. I think that downtime should be accepted as a cost for stability in general. If your new kernel feature has a bug and causes a crash, anyway it gets your servers down. > > > > For example, if you implement a well-designed framework in a specific > > subsystem, like Schedext, which allows multiple implementations extended > > with BPF to coexist, there's no problem (at least it's debatable). > > > > But if it is for any function, it is dangerous feature. Bugs that occur > > in kernels that use this functionality cannot be addressed here. They > > need to be treated the same way as out-of-tree drivers or forked kernels. > > I mean, add a tainted flag for this feature. And we don't care of it. > > Agreed. This should be handled as an OOT module rather than part of > the core kernel. > > > > > > > > > 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. > > > > Can you share your actual problem to be solved? > > Here is an example we recently deployed on our production servers: > > https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ > > In one of our specific clusters, we needed to send BGP traffic out > through specific NICs based on the destination IP. To achieve this > without interrupting service, we live-patched > bond_xmit_3ad_xor_slave_get(), added a new hook called > bond_get_slave_hook(), and then ran a BPF program attached to that > hook to select the outgoing NIC from the SKB. This allowed us to > rapidly deploy the feature with zero downtime. In this case, you can make specific livepatch or kernel module to replace the kernel function without using BPF on your server. The BGP trafic in bonding device seems very specific, so it may not cause a trouble, but this is very generic change, which allows user to change more core kernel feature, e.g. memory management or scheduler etc. Excessive degrees of freedom introduce uncertainty and instability into a system. While the functionality is interesting, it would be a way to generalize schedext in an uncontrolled way. At a minimum, some form of build time and runtime constraint, along with a taint flag that clearly indicates in the crash logs that this feature is being used, would be necessary. (It means this is should not be used in production environment.) Thank you, > > [...] > > -- > Regards > Yafang -- Masami Hiramatsu (Google) <mhiramat@kernel.org>
On Thu, Apr 02, 2026 at 05:26:03PM +0800, Yafang Shao wrote: > Livepatching allows for rapid experimentation with new kernel features > without interrupting production workloads. Myabe it allows, or based on the rest of the mail not quite. But that is certainly not the intent at all, the intent is to fix critical bugs without downtime. > 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. Whol f**. now. Is this a delayed April 1st post?
On Mon, Apr 6, 2026 at 1:36 PM Christoph Hellwig <hch@infradead.org> wrote: > > On Thu, Apr 02, 2026 at 05:26:03PM +0800, Yafang Shao wrote: > > Livepatching allows for rapid experimentation with new kernel features > > without interrupting production workloads. > > Myabe it allows, or based on the rest of the mail not quite. But that > is certainly not the intent at all, the intent is to fix critical > bugs without downtime. > > > 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. > > Whol f**. now. Is this a delayed April 1st post? You're already in my spam list. Don't expect any further replies. Feel free to keep your verbose rubbish to yourself. -- Regards Yafang
Hi Yafang, On Thu, Apr 2, 2026 at 2:26 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > 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. Could you please provide a specific use case that can benefit from this? AFAICT, livepatch is more flexible but risky (may cause crash); while BPF is safe, but less flexible. The combination you are proposing seems to get the worse of the two sides. Maybe it can indeed get the benefit of both sides in some cases, but I cannot think of such examples. Thanks, Song
On Sat, Apr 4, 2026 at 12:07 AM Song Liu <song@kernel.org> wrote: > > Hi Yafang, > > On Thu, Apr 2, 2026 at 2:26 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > 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. > > Could you please provide a specific use case that can benefit from this? > AFAICT, livepatch is more flexible but risky (may cause crash); while > BPF is safe, but less flexible. The combination you are proposing seems > to get the worse of the two sides. Maybe it can indeed get the benefit of > both sides in some cases, but I cannot think of such examples. > Here is an example we recently deployed on our production servers: https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ In one of our specific clusters, we needed to send BGP traffic out through specific NICs based on the destination IP. To achieve this without interrupting service, we live-patched bond_xmit_3ad_xor_slave_get(), added a new hook called bond_get_slave_hook(), and then ran a BPF program attached to that hook to select the outgoing NIC from the SKB. This allowed us to rapidly deploy the feature with zero downtime. -- Regards Yafang
On Mon, Apr 6, 2026 at 3:55 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > On Sat, Apr 4, 2026 at 12:07 AM Song Liu <song@kernel.org> wrote: > > > > Hi Yafang, > > > > On Thu, Apr 2, 2026 at 2:26 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > > 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. > > > > Could you please provide a specific use case that can benefit from this? > > AFAICT, livepatch is more flexible but risky (may cause crash); while > > BPF is safe, but less flexible. The combination you are proposing seems > > to get the worse of the two sides. Maybe it can indeed get the benefit of > > both sides in some cases, but I cannot think of such examples. > > > > Here is an example we recently deployed on our production servers: > > https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ > > In one of our specific clusters, we needed to send BGP traffic out > through specific NICs based on the destination IP. To achieve this > without interrupting service, we live-patched > bond_xmit_3ad_xor_slave_get(), added a new hook called > bond_get_slave_hook(), and then ran a BPF program attached to that > hook to select the outgoing NIC from the SKB. This allowed us to > rapidly deploy the feature with zero downtime. I guess the idea here is: keep the risk part simple, and implement it in module/livepatch, then use BPF for the flexible and programmable part safe. Can we use struct_ops instead of bpf_override_return for this case? This should make the solution more flexible. Thanks, Song
On Tue, Apr 7, 2026 at 2:26 AM Song Liu <song@kernel.org> wrote: > > On Mon, Apr 6, 2026 at 3:55 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > On Sat, Apr 4, 2026 at 12:07 AM Song Liu <song@kernel.org> wrote: > > > > > > Hi Yafang, > > > > > > On Thu, Apr 2, 2026 at 2:26 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > > > > 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. > > > > > > Could you please provide a specific use case that can benefit from this? > > > AFAICT, livepatch is more flexible but risky (may cause crash); while > > > BPF is safe, but less flexible. The combination you are proposing seems > > > to get the worse of the two sides. Maybe it can indeed get the benefit of > > > both sides in some cases, but I cannot think of such examples. > > > > > > > Here is an example we recently deployed on our production servers: > > > > https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ > > > > In one of our specific clusters, we needed to send BGP traffic out > > through specific NICs based on the destination IP. To achieve this > > without interrupting service, we live-patched > > bond_xmit_3ad_xor_slave_get(), added a new hook called > > bond_get_slave_hook(), and then ran a BPF program attached to that > > hook to select the outgoing NIC from the SKB. This allowed us to > > rapidly deploy the feature with zero downtime. > > I guess the idea here is: keep the risk part simple, and implement > it in module/livepatch, then use BPF for the flexible and programmable > part safe. Right > > Can we use struct_ops instead of bpf_override_return for this case? > This should make the solution more flexible. Upstreaming struct_ops based BPF hooks is a challenging process, as seen in these examples: https://lwn.net/Articles/1054030/ https://lwn.net/Articles/1043548/ Even when successful, upstreaming can take a significant amount of time—often longer than our production requirements allow. To bridge this gap, we developed this livepatch+BPF solution. This allows us to rapidly deploy new features without maintaining custom hooks in our local kernel. Because these livepatch-based hooks are lightweight, they minimize maintenance overhead and simplify kernel upgrades (e.g., from 6.1 to 6.18). That said, we would still prefer to have our hooks accepted upstream to eliminate the need for self-maintenance entirely. -- Regards Yafang
On Mon, Apr 6, 2026 at 7:22 PM Yafang Shao <laoar.shao@gmail.com> wrote: > > On Tue, Apr 7, 2026 at 2:26 AM Song Liu <song@kernel.org> wrote: > > > > On Mon, Apr 6, 2026 at 3:55 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > > On Sat, Apr 4, 2026 at 12:07 AM Song Liu <song@kernel.org> wrote: > > > > > > > > Hi Yafang, > > > > > > > > On Thu, Apr 2, 2026 at 2:26 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > > > > > > 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. > > > > > > > > Could you please provide a specific use case that can benefit from this? > > > > AFAICT, livepatch is more flexible but risky (may cause crash); while > > > > BPF is safe, but less flexible. The combination you are proposing seems > > > > to get the worse of the two sides. Maybe it can indeed get the benefit of > > > > both sides in some cases, but I cannot think of such examples. > > > > > > > > > > Here is an example we recently deployed on our production servers: > > > > > > https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ > > > > > > In one of our specific clusters, we needed to send BGP traffic out > > > through specific NICs based on the destination IP. To achieve this > > > without interrupting service, we live-patched > > > bond_xmit_3ad_xor_slave_get(), added a new hook called > > > bond_get_slave_hook(), and then ran a BPF program attached to that > > > hook to select the outgoing NIC from the SKB. This allowed us to > > > rapidly deploy the feature with zero downtime. > > > > I guess the idea here is: keep the risk part simple, and implement > > it in module/livepatch, then use BPF for the flexible and programmable > > part safe. > > Right > > > > > Can we use struct_ops instead of bpf_override_return for this case? > > This should make the solution more flexible. > > Upstreaming struct_ops based BPF hooks is a challenging process, as > seen in these examples: > > https://lwn.net/Articles/1054030/ > https://lwn.net/Articles/1043548/ > > Even when successful, upstreaming can take a significant amount of > time—often longer than our production requirements allow. To bridge > this gap, we developed this livepatch+BPF solution. This allows us to > rapidly deploy new features without maintaining custom hooks in our > local kernel. Because these livepatch-based hooks are lightweight, > they minimize maintenance overhead and simplify kernel upgrades (e.g., > from 6.1 to 6.18). I didn't mean upstream struct_ops. We can define the struct_ops in an OOT kernel module. Then we can attach BPF programs to the struct_ops. We may need livepatch to connect the new struct_ops to original kernel logic. I think kernel side of this solution is mostly available, but we may need some work on the toolchain side. Does this make sense? Thanks, Song > That said, we would still prefer to have our hooks accepted upstream > to eliminate the need for self-maintenance entirely.
On Tue, Apr 7, 2026 at 10:47 AM Song Liu <song@kernel.org> wrote: > > On Mon, Apr 6, 2026 at 7:22 PM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > On Tue, Apr 7, 2026 at 2:26 AM Song Liu <song@kernel.org> wrote: > > > > > > On Mon, Apr 6, 2026 at 3:55 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > > > > On Sat, Apr 4, 2026 at 12:07 AM Song Liu <song@kernel.org> wrote: > > > > > > > > > > Hi Yafang, > > > > > > > > > > On Thu, Apr 2, 2026 at 2:26 AM Yafang Shao <laoar.shao@gmail.com> wrote: > > > > > > > > > > > > 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. > > > > > > > > > > Could you please provide a specific use case that can benefit from this? > > > > > AFAICT, livepatch is more flexible but risky (may cause crash); while > > > > > BPF is safe, but less flexible. The combination you are proposing seems > > > > > to get the worse of the two sides. Maybe it can indeed get the benefit of > > > > > both sides in some cases, but I cannot think of such examples. > > > > > > > > > > > > > Here is an example we recently deployed on our production servers: > > > > > > > > https://lore.kernel.org/bpf/CALOAHbDnNba_w_nWH3-S9GAXw0+VKuLTh1gy5hy9Yqgeo4C0iA@mail.gmail.com/ > > > > > > > > In one of our specific clusters, we needed to send BGP traffic out > > > > through specific NICs based on the destination IP. To achieve this > > > > without interrupting service, we live-patched > > > > bond_xmit_3ad_xor_slave_get(), added a new hook called > > > > bond_get_slave_hook(), and then ran a BPF program attached to that > > > > hook to select the outgoing NIC from the SKB. This allowed us to > > > > rapidly deploy the feature with zero downtime. > > > > > > I guess the idea here is: keep the risk part simple, and implement > > > it in module/livepatch, then use BPF for the flexible and programmable > > > part safe. > > > > Right > > > > > > > > Can we use struct_ops instead of bpf_override_return for this case? > > > This should make the solution more flexible. > > > > Upstreaming struct_ops based BPF hooks is a challenging process, as > > seen in these examples: > > > > https://lwn.net/Articles/1054030/ > > https://lwn.net/Articles/1043548/ > > > > Even when successful, upstreaming can take a significant amount of > > time—often longer than our production requirements allow. To bridge > > this gap, we developed this livepatch+BPF solution. This allows us to > > rapidly deploy new features without maintaining custom hooks in our > > local kernel. Because these livepatch-based hooks are lightweight, > > they minimize maintenance overhead and simplify kernel upgrades (e.g., > > from 6.1 to 6.18). > > I didn't mean upstream struct_ops. > > We can define the struct_ops in an OOT kernel module. Then we > can attach BPF programs to the struct_ops. We may need > livepatch to connect the new struct_ops to original kernel logic. > > I think kernel side of this solution is mostly available, but we may > need some work on the toolchain side. > > Does this make sense? Are there actual benefits to using struct_ops instead of bpf_override_return? So far, I’ve only found it adds complexity without much gain. Can we add something like ALLOW_LIVEPATCH_ERROR_INJECTION() to allow error injection on functions defined inside a livepatch? -- Regards Yafang
> Can we add something like ALLOW_LIVEPATCH_ERROR_INJECTION() to allow > error injection on functions defined inside a livepatch? No. I am sorry but you always seem to find band aids to your set up and how you deal with live patches internally. While I can see that something like a hybrid mode might be useful to people if done right (and we are not there yet), the combination of it with bpf overrides or anything like that is not something I would like to see in upstream. Miroslav
On Thu, Apr 9, 2026 at 6:08 PM Miroslav Benes <mbenes@suse.cz> wrote: > > > Can we add something like ALLOW_LIVEPATCH_ERROR_INJECTION() to allow > > error injection on functions defined inside a livepatch? > > No. > > I am sorry but you always seem to find band aids to your set up and how > you deal with live patches internally. While I can see that something like > a hybrid mode might be useful to people if done right (and we are not > there yet), the combination of it with bpf overrides or anything like that > is not something I would like to see in upstream. The upstream kernel already allows for combining BPF and livepatch to override functions. Song’s patch offers a great reference for implementing this without changing the kernel: https://lore.kernel.org/bpf/20260408175217.1011024-1-song@kernel.org/ -- Regards Yafang
On Mon, Apr 6, 2026 at 8:14 PM Yafang Shao <laoar.shao@gmail.com> wrote:
[...]
> > We can define the struct_ops in an OOT kernel module. Then we
> > can attach BPF programs to the struct_ops. We may need
> > livepatch to connect the new struct_ops to original kernel logic.
> >
> > I think kernel side of this solution is mostly available, but we may
> > need some work on the toolchain side.
> >
> > Does this make sense?
>
> Are there actual benefits to using struct_ops instead of
> bpf_override_return? So far, I’ve only found it adds complexity
> without much gain.
Yes, struct_ops can be more powerful. For example, we can use
something like the following to modify the content of /proc/cmdline
with a bpf program. AFAICT, this is not possible with
bpf_override_return.
Note that this example doesn't require kernel changes. This is
actually a fun example. I will send the full code as a new self test.
Thanks,
Song
======= key logic of the livepatch module =======
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,
}, { }
};
========== key logic of the bpf program =========
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;
}
SEC(".struct_ops.link")
struct klp_bpf_cmdline_ops cmdline_ops = {
.set_cmdline = (void *)set_cmdline,
};
© 2016 - 2026 Red Hat, Inc.