Re: bpf_errno. Was: [PATCH RFC bpf-next 1/3] bpf: report probe fault to BPF stderr
From: Leon Hwang <hidden>
Date: 2025-10-09 14:15:47
Also in:
bpf, lkml
On 2025/10/9 00:27, Alexei Starovoitov wrote:
On Wed, Oct 8, 2025 at 7:41 AM Leon Hwang [off-list ref] wrote:quoted
On 2025/10/7 14:14, Menglong Dong wrote:quoted
On 2025/10/2 10:03, Alexei Starovoitov wrote:quoted
On Fri, Sep 26, 2025 at 11:12 PM Menglong Dong [off-list ref] wrote:quoted
[...]
quoted
quoted
Leon suggested to add a global errno for each BPF programs, and I haven't dig deeply on this idea yet.Yeah, as we discussed, a global errno would be a much more lightweight approach for handling such faults. The idea would look like this: DEFINE_PER_CPU(int, bpf_errno); __bpf_kfunc void bpf_errno_clear(void); __bpf_kfunc void bpf_errno_set(int errno); __bpf_kfunc int bpf_errno_get(void); When a fault occurs, the kernel can simply call 'bpf_errno_set(-EFAULT);'. If users want to detect whether a fault happened, they can do: bpf_errno_clear(); header = READ_ONCE(skb->network_header); if (header == 0 && bpf_errno_get() == -EFAULT) /* handle fault */; This way, users can identify faults immediately and handle them gracefully. Furthermore, these kfuncs can be inlined by the verifier, so there would be no runtime function call overhead.Interesting idea, but errno as-is doesn't quite fit, since we only have 2 (or 3 ?) cases without explicit error return: probe_read_kernel above, arena read, arena write. I guess we can add may_goto to this set as well. But in all these cases we'll struggle to find an appropriate errno code, so it probably should be a custom enum and not called "errno".
To avoid introducing a global errno, here's a more lightweight approach:
1. Introduce an internal BPF_REG_AUX and a helper
'bpf_jit_supports_reg_aux()'.
2. Introduce a kfunc 'int bpf_reg_aux(void)'.
When a fault occurs, we can set 'BPF_REG_AUX = -EFAULT;' in
'ex_handler_bpf()'.
Otherwise, 'BPF_REG_AUX = 0;'.
(Alternatively, BPF_REG_AUX can use a custom enum instead of '-EFAULT'.)
If users want to check whether a fault happened, they can do:
header = READ_ONCE(skb->network_header);
if (header == 0 && bpf_reg_aux() == -EFAULT)
/* handle fault */;
This allows users to detect faults immediately without any extra global
state.
The verifier can rewrite 'bpf_reg_aux()' into the following instructions:
dst_reg = BPF_REG_AUX;
BPF_REG_AUX = 0; /* clear BPF_REG_AUX */
As for the architecture-specific implementation, BPF_REG_AUX can be
mapped to an appropriate register per arch — for example, r11 on x86_64.
The verifier would ensure that BPF_REG_AUX is not clobbered after a
probe read.
As a result, this avoids the need for a global errno and introduces no
runtime function call overhead.
Thanks,
Leon