Skip to content

Commit 27ecd6d

Browse files
committed
bpf: Reject narrower access to pointer ctx fields
JIRA: https://issues.redhat.com/browse/RHEL-110274 commit e092992 Author: Paul Chaignon <paul.chaignon@gmail.com> Date: Tue Jul 22 16:32:32 2025 +0200 bpf: Reject narrower access to pointer ctx fields The following BPF program, simplified from a syzkaller repro, causes a kernel warning: r0 = *(u8 *)(r1 + 169); exit; With pointer field sk being at offset 168 in __sk_buff. This access is detected as a narrower read in bpf_skb_is_valid_access because it doesn't match offsetof(struct __sk_buff, sk). It is therefore allowed and later proceeds to bpf_convert_ctx_access. Note that for the "is_narrower_load" case in the convert_ctx_accesses(), the insn->off is aligned, so the cnt may not be 0 because it matches the offsetof(struct __sk_buff, sk) in the bpf_convert_ctx_access. However, the target_size stays 0 and the verifier errors with a kernel warning: verifier bug: error during ctx access conversion(1) This patch fixes that to return a proper "invalid bpf_context access off=X size=Y" error on the load instruction. The same issue affects multiple other fields in context structures that allow narrow access. Some other non-affected fields (for sk_msg, sk_lookup, and sockopt) were also changed to use bpf_ctx_range_ptr for consistency. Note this syzkaller crash was reported in the "Closes" link below, which used to be about a different bug, fixed in commit fce7bd8 ("bpf/verifier: Handle BPF_LOAD_ACQ instructions in insn_def_regno()"). Because syzbot somehow confused the two bugs, the new crash and repro didn't get reported to the mailing list. Fixes: f96da09 ("bpf: simplify narrower ctx access") Fixes: 0df1a55 ("bpf: Warn on internal verifier errors") Reported-by: syzbot+0ef84a7bdf5301d4cbec@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0ef84a7bdf5301d4cbec Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://patch.msgid.link/3b8dcee67ff4296903351a974ddd9c4dca768b64.1753194596.git.paul.chaignon@gmail.com Signed-off-by: Viktor Malik <vmalik@redhat.com>
1 parent 40a90e6 commit 27ecd6d

File tree

2 files changed

+14
-14
lines changed

2 files changed

+14
-14
lines changed

kernel/bpf/cgroup.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,22 +2404,22 @@ static bool cg_sockopt_is_valid_access(int off, int size,
24042404
}
24052405

24062406
switch (off) {
2407-
case offsetof(struct bpf_sockopt, sk):
2407+
case bpf_ctx_range_ptr(struct bpf_sockopt, sk):
24082408
if (size != sizeof(__u64))
24092409
return false;
24102410
info->reg_type = PTR_TO_SOCKET;
24112411
break;
2412-
case offsetof(struct bpf_sockopt, optval):
2412+
case bpf_ctx_range_ptr(struct bpf_sockopt, optval):
24132413
if (size != sizeof(__u64))
24142414
return false;
24152415
info->reg_type = PTR_TO_PACKET;
24162416
break;
2417-
case offsetof(struct bpf_sockopt, optval_end):
2417+
case bpf_ctx_range_ptr(struct bpf_sockopt, optval_end):
24182418
if (size != sizeof(__u64))
24192419
return false;
24202420
info->reg_type = PTR_TO_PACKET_END;
24212421
break;
2422-
case offsetof(struct bpf_sockopt, retval):
2422+
case bpf_ctx_range(struct bpf_sockopt, retval):
24232423
if (size != size_default)
24242424
return false;
24252425
return prog->expected_attach_type == BPF_CGROUP_GETSOCKOPT;

net/core/filter.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8531,7 +8531,7 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
85318531
if (size != sizeof(__u64))
85328532
return false;
85338533
break;
8534-
case offsetof(struct __sk_buff, sk):
8534+
case bpf_ctx_range_ptr(struct __sk_buff, sk):
85358535
if (type == BPF_WRITE || size != sizeof(__u64))
85368536
return false;
85378537
info->reg_type = PTR_TO_SOCK_COMMON_OR_NULL;
@@ -9108,7 +9108,7 @@ static bool sock_addr_is_valid_access(int off, int size,
91089108
return false;
91099109
}
91109110
break;
9111-
case offsetof(struct bpf_sock_addr, sk):
9111+
case bpf_ctx_range_ptr(struct bpf_sock_addr, sk):
91129112
if (type != BPF_READ)
91139113
return false;
91149114
if (size != sizeof(__u64))
@@ -9158,17 +9158,17 @@ static bool sock_ops_is_valid_access(int off, int size,
91589158
if (size != sizeof(__u64))
91599159
return false;
91609160
break;
9161-
case offsetof(struct bpf_sock_ops, sk):
9161+
case bpf_ctx_range_ptr(struct bpf_sock_ops, sk):
91629162
if (size != sizeof(__u64))
91639163
return false;
91649164
info->reg_type = PTR_TO_SOCKET_OR_NULL;
91659165
break;
9166-
case offsetof(struct bpf_sock_ops, skb_data):
9166+
case bpf_ctx_range_ptr(struct bpf_sock_ops, skb_data):
91679167
if (size != sizeof(__u64))
91689168
return false;
91699169
info->reg_type = PTR_TO_PACKET;
91709170
break;
9171-
case offsetof(struct bpf_sock_ops, skb_data_end):
9171+
case bpf_ctx_range_ptr(struct bpf_sock_ops, skb_data_end):
91729172
if (size != sizeof(__u64))
91739173
return false;
91749174
info->reg_type = PTR_TO_PACKET_END;
@@ -9177,7 +9177,7 @@ static bool sock_ops_is_valid_access(int off, int size,
91779177
bpf_ctx_record_field_size(info, size_default);
91789178
return bpf_ctx_narrow_access_ok(off, size,
91799179
size_default);
9180-
case offsetof(struct bpf_sock_ops, skb_hwtstamp):
9180+
case bpf_ctx_range(struct bpf_sock_ops, skb_hwtstamp):
91819181
if (size != sizeof(__u64))
91829182
return false;
91839183
break;
@@ -9247,17 +9247,17 @@ static bool sk_msg_is_valid_access(int off, int size,
92479247
return false;
92489248

92499249
switch (off) {
9250-
case offsetof(struct sk_msg_md, data):
9250+
case bpf_ctx_range_ptr(struct sk_msg_md, data):
92519251
info->reg_type = PTR_TO_PACKET;
92529252
if (size != sizeof(__u64))
92539253
return false;
92549254
break;
9255-
case offsetof(struct sk_msg_md, data_end):
9255+
case bpf_ctx_range_ptr(struct sk_msg_md, data_end):
92569256
info->reg_type = PTR_TO_PACKET_END;
92579257
if (size != sizeof(__u64))
92589258
return false;
92599259
break;
9260-
case offsetof(struct sk_msg_md, sk):
9260+
case bpf_ctx_range_ptr(struct sk_msg_md, sk):
92619261
if (size != sizeof(__u64))
92629262
return false;
92639263
info->reg_type = PTR_TO_SOCKET;
@@ -11459,7 +11459,7 @@ static bool sk_lookup_is_valid_access(int off, int size,
1145911459
return false;
1146011460

1146111461
switch (off) {
11462-
case offsetof(struct bpf_sk_lookup, sk):
11462+
case bpf_ctx_range_ptr(struct bpf_sk_lookup, sk):
1146311463
info->reg_type = PTR_TO_SOCKET_OR_NULL;
1146411464
return size == sizeof(__u64);
1146511465

0 commit comments

Comments
 (0)