LWN: Comments on "Exceptions in BPF" https://lwn.net/Articles/938435/ This is a special feed containing comments posted to the individual LWN article titled "Exceptions in BPF". en-us Sun, 31 Aug 2025 07:08:49 +0000 Sun, 31 Aug 2025 07:08:49 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net Exceptions in BPF https://lwn.net/Articles/950280/ https://lwn.net/Articles/950280/ ibukanov <div class="FormattedComment"> Go panics are exactly the exceptions. They can be caught at arbitrary points and can pass arbitrary values across the stack.<br> </div> Sun, 05 Nov 2023 13:03:13 +0000 Exceptions in BPF https://lwn.net/Articles/939138/ https://lwn.net/Articles/939138/ taladar <div class="FormattedComment"> Setting a custom panic handler is also frequently used in situations where the panic should be logged before exiting.<br> </div> Tue, 25 Jul 2023 06:59:07 +0000 Exceptions in BPF https://lwn.net/Articles/939019/ https://lwn.net/Articles/939019/ Cyberax <div class="FormattedComment"> One of the bragging points of BPF was "but it always returns a value!", and that's why it's apparently better than WASM.<br> <p> With the addition of exceptions, this guarantee is lost.<br> <p> Not that it mattered either way in practice, but still. BPF is now just adding features without even considering their impact on the overall BPF model.<br> </div> Mon, 24 Jul 2023 04:13:25 +0000 Exceptions in BPF https://lwn.net/Articles/939003/ https://lwn.net/Articles/939003/ rqosa <p>Maybe naming it "error" (or something like that) would be a reasonable choice that isn't too similar to those 2 other terms?</p> <p>(Java uses the word "error" in a similar sense in <tt>java.lang.Error</tt>'s name — i.e. for "<font class="QuotedText">serious problems that a reasonable application should not try to catch</font>".)</p> Sun, 23 Jul 2023 18:48:17 +0000 Exceptions in BPF https://lwn.net/Articles/938993/ https://lwn.net/Articles/938993/ xi0n <div class="FormattedComment"> Panics in idiomatic Rust are only caught to prevent them from crossing an FFI boundary, i.e. escaping a Rust callback that’s been called from C. Otherwise, programs can set a global panic handler if the standard one is inadequate, but that is only really used for embedded and other no_std environments.<br> <p> This saying, the mechanism proposed here is so close to Rust panics (and Go panics) that NOT calling it such will only lead to confusion, esp. when “exception” is such an overloaded term already.<br> </div> Sun, 23 Jul 2023 07:35:20 +0000 Exceptions in BPF https://lwn.net/Articles/938989/ https://lwn.net/Articles/938989/ iteratedlateralus <div class="FormattedComment"> I think this is the natural progression of things technological. It becomes easier and easier to build abstractions on top of something that used to be a lot of hard work to accomplish even the most basic of tasks. I think the BPF feature set should be purposefully limited in scope due to the valuable attack surface that features create.<br> </div> Sun, 23 Jul 2023 02:44:57 +0000 Exceptions in BPF https://lwn.net/Articles/938983/ https://lwn.net/Articles/938983/ walters <div class="FormattedComment"> <span class="QuotedText">&gt; True, kernel Rust has its own standard library, but most of it seems to be littered with '#[cfg(not(no_global_oom_handling))]' just like the userspace std library.</span><br> <p> (We're now a bit past my relatively superficial knowledge of Linux kernel Rust but...)<br> <p> I'm pretty sure that's because they don't want a long term fork of alloc.rs and vec.rs etc. The upstream Rust project has this config option I'm pretty sure *precisely* to help enable usage of the upstream battle-tested collections while disabling the APIs that will implicitly panic on OOM.<br> <p> And the Linux build system does pass "--cfg no_global_oom_handling". And the example Rust code does use try_push() not push(), etc.<br> <p> Or to say this simply: kernel Rust does not have implicit panics on OOM.<br> <p> What would certainly be interesting to try to evaluate is how many possible panics there are in any nontrivial kernel Rust code. The classic example is somevec[offset]. I'd expect the number is greater than zero. But are there "a lot"? Are there enough where it *actually* feels like "panic if any of a large number of things goes wrong" is true? I'm doubtful.<br> <p> </div> Sat, 22 Jul 2023 18:28:09 +0000 Rust and static safety https://lwn.net/Articles/938977/ https://lwn.net/Articles/938977/ randomguy3 <div class="FormattedComment"> this is kind of what I was trying to get at with my comment, but you did a much better job!<br> </div> Sat, 22 Jul 2023 16:19:53 +0000 Exceptions in BPF https://lwn.net/Articles/938976/ https://lwn.net/Articles/938976/ NYKevin <div class="FormattedComment"> Maybe. Sort of. With a lot of effort.<br> <p> The problem is that you need to return all the way up the stack, and therefore you need to return some kind of "we're bailing out" status code to indicate the problem to the caller. But you probably already have return values at many of those call sites, so now you need to transform those return values in some way, probably into an option type or tagged union (or some equivalent). In principle that should be possible, but I don't know if BPF makes it straightforward or performant.<br> </div> Sat, 22 Jul 2023 16:00:30 +0000 Exceptions in BPF https://lwn.net/Articles/938970/ https://lwn.net/Articles/938970/ dezgeg <div class="FormattedComment"> Sounds it would be too confusing when 'Kernel panic' is already a thing<br> </div> Sat, 22 Jul 2023 12:07:31 +0000 Exceptions in BPF https://lwn.net/Articles/938966/ https://lwn.net/Articles/938966/ softball <div class="FormattedComment"> A core difference is: BPF looks to treat throws as success-by-default (rc 0), Rust panics are failure-by-default. Rust panics have to be caught explicitly. My experience with Rust is limited so far, but catching panics seems rare and unidiomatic: there's already featureful error handling available (Result type), so any panics are usually serious enough to not be handlable.<br> </div> Sat, 22 Jul 2023 09:15:04 +0000 Exceptions in BPF https://lwn.net/Articles/938965/ https://lwn.net/Articles/938965/ softball <div class="FormattedComment"> A core aspect they have in common is to err on the side of false-positives. False-negatives would be disastrous, and perfect, 1:1 deduction isn't possible (halting problem), so the only reasonable thing to do is disallow certain known-good (to the developer) scenarios.<br> </div> Sat, 22 Jul 2023 09:07:39 +0000 Exceptions in BPF https://lwn.net/Articles/938963/ https://lwn.net/Articles/938963/ jezuch <div class="FormattedComment"> Maybe this thould be renamed as "panic", because it's doing the same thing as panic in Rust. These are no generic exceptions.<br> </div> Sat, 22 Jul 2023 08:42:01 +0000 Exceptions in BPF https://lwn.net/Articles/938955/ https://lwn.net/Articles/938955/ wahern <div class="FormattedComment"> <span class="QuotedText">&gt; If you’re talking about Rust code using std certainty there can be a lot of implicit OOM panics. But kernel Rust doesn’t use std.</span><br> <p> True, kernel Rust has its own standard library, but most of it seems to be littered with '#[cfg(not(no_global_oom_handling))]' just like the userspace std library.<br> <p> </div> Sat, 22 Jul 2023 04:24:34 +0000 Rust and static safety https://lwn.net/Articles/938938/ https://lwn.net/Articles/938938/ geofft <div class="FormattedComment"> <span class="QuotedText">&gt; A Rust program will, by default, panic if any of a large number of things goes wrong. BPF programs, instead, are intended to be verified as simply lacking that sort of wrong behavior before they are ever allowed to execute.</span><br> <p> Well... kind of. There are indeed a large number of things that cause a Rust panic (which, for kernelspace Rust code, turns into an oops, not a kernel panic), such as indexing an array out of bounds. But there are also a large number of things that are verified by the Rust compiler, preventing wrong behavior before it can ever execute, and I think that's sort of the selling point of Rust!<br> <p> A good example is the venerable null pointer. It's not actually a pointer - it's someone using a pointer type to convey there is nothing to point to. In C, you can attempt to "dereference" a null pointer, which is a fundamentally meaningless operation that will lead to incorrect behavior. In Rust, pointer types are defined as non-null, and the standard Optional data type when wrapping a pointer ends up in memory just like a nullable C pointer, but the language prevents you from using it if the value is equal to zero. An Optional type cannot be used directly; you have to use an if or match statement that breaks down the two possibilities, Some actual value or None. (Or you can call a function that does so - such as the standard .unwrap() function which will generate a Rust panic if it's None.)<br> <p> In other words, at compile time, a Rust program can be verified as never dereferencing a null reference.<br> <p> This can be generalized in a few ways. Rust also ensures that all references are to valid data, which is what the feared "borrow checker" does: if the compiler can't be convinced that the pointed-to data is still around when you're using the pointer, it will fail to compile. You can also imagine data types that have more than just null as special cases, such as the kernel's ERR_PTR scheme, where small negative values are actually errnos. A function that returns a char * might actually return (char *)-ENOMEM, aka ERR_PTR(-ENOMEM), and expect callers to check IS_ERR on the pointer before using it, with bad consequences if they forget. In Rust this is better defined as a data type that can be either a pointer or an error code (and indeed rust/kernel/error.rs defines it this way): you can't misinterpret an error code as a pointer or vice versa. Currently this isn't stored all in one pointer-sized data type the way it is in C, but it will be soon.<br> <p> The big difference between Rust and BPF in this context is that Rust treats all of these tools as aids to the programmer, which can be bypassed if needed if you're doing something complex, and BPF treats these as hard requirements and simply refuses to let you do complex things. Rust is trying to eliminate common types of mistakes, but it's not intended to be used in a way where the output is more highly privileged than the input. So it is possible (and quite common for interop with C) to "unsafely" produce a reference from somewhere, effectively telling Rust, hey trust me on this one, this is a valid pointer even though I can't prove it to you. BPF, on the other hand, is all about allowing userspace to load programs into the kernel without the security risk of loading a real kernel module. So it can't have any bypass mechanisms. (And so it needs something like the mechanism in this article to say, I can't prove this assumption to you, so you can just evaluate whether it's true at runtime and bail out of executing the program if it isn't.)<br> </div> Sat, 22 Jul 2023 01:32:41 +0000 Exceptions in BPF https://lwn.net/Articles/938948/ https://lwn.net/Articles/938948/ walters <div class="FormattedComment"> <span class="QuotedText">&gt; A Rust program will, by default, panic if any of a large number of things goes wrong</span><br> <p> I don’t think so. If you’re talking about Rust code using std certainty there can be a lot of implicit OOM panics. But kernel Rust doesn’t use std. <br> <p> Idiomatic Rust avoids gratuitous unwrap invocations and array accesses, etc. Iterators can often remove implicit bounds checks too. Now, writing probably panic-free code is an active topic. <br> <p> But I don’t think “if any of a large number of things” is really accurate, on balance.<br> </div> Sat, 22 Jul 2023 01:30:58 +0000 Exceptions in BPF https://lwn.net/Articles/938943/ https://lwn.net/Articles/938943/ randomguy3 <div class="FormattedComment"> I'd argue that rust borrow checks and panics are conceptually very similar to bpf verification and exceptions. In both cases, you are attempting to eliminate certain classes of failures before running the program, and providing a mechanism to assert invariants and cleanly handle bugs.<br> <p> The difference is primarily scope: as a general purpose language, rust's borrow checker is weaker than bpf's verification (with a few escape hatches provided as well), and its use of asserts/panics more extensive.<br> </div> Fri, 21 Jul 2023 23:07:05 +0000 Exceptions in BPF https://lwn.net/Articles/938919/ https://lwn.net/Articles/938919/ Smon <div class="FormattedComment"> Couldn't a compiler simulate this already with existing functionality?<br> </div> Fri, 21 Jul 2023 20:00:25 +0000 Exceptions in BPF https://lwn.net/Articles/938909/ https://lwn.net/Articles/938909/ adobriyan <div class="FormattedComment"> Superficially kuint devs did exceptions first:<br> <p> struct kunit_try_catch {<br> /* private: internal use only. */<br> struct kunit *test;<br> struct completion *try_completion;<br> int try_result;<br> kunit_try_catch_func_t try;<br> kunit_try_catch_func_t catch;<br> void *context;<br> };<br> </div> Fri, 21 Jul 2023 16:55:55 +0000 Exceptions in BPF https://lwn.net/Articles/938907/ https://lwn.net/Articles/938907/ Cyberax <div class="FormattedComment"> Guys, really? You are now adding freaking exceptions.<br> <p> This is not just "feature creep", it's a "feature runaway train at 100mph".<br> </div> Fri, 21 Jul 2023 16:25:21 +0000