Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/bpf.h>
4#include <bpf/bpf_helpers.h>
5
6struct {
7 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
8 __type(key, struct bpf_cgroup_storage_key);
9 __type(value, __u64);
10} cgroup_storage SEC(".maps");
11
12SEC("cgroup_skb/egress")
13int bpf_prog(struct __sk_buff *skb)
14{
15 __u64 *counter;
16
17 counter = bpf_get_local_storage(&cgroup_storage, 0);
18 __sync_fetch_and_add(counter, 1);
19
20 /* Drop one out of every two packets */
21 return (*counter & 1);
22}
23
24/* Maps for OOB test */
25struct {
26 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
27 __type(key, struct bpf_cgroup_storage_key);
28 __type(value, __u32); /* 4-byte value - not 8-byte aligned */
29} cgroup_storage_oob SEC(".maps");
30
31struct {
32 __uint(type, BPF_MAP_TYPE_LRU_PERCPU_HASH);
33 __uint(max_entries, 1);
34 __type(key, __u32);
35 __type(value, __u32); /* 4-byte value - same as cgroup storage */
36} lru_map SEC(".maps");
37
38SEC("cgroup/sock_create")
39int trigger_oob(struct bpf_sock *sk)
40{
41 __u32 key = 0;
42 __u32 *cgroup_val;
43 __u32 value = 0x12345678;
44
45 /* Get cgroup storage value */
46 cgroup_val = bpf_get_local_storage(&cgroup_storage_oob, 0);
47 if (!cgroup_val)
48 return 0;
49
50 /* Initialize cgroup storage */
51 *cgroup_val = value;
52
53 /* This triggers the OOB read:
54 * bpf_map_update_elem() -> htab_map_update_elem() ->
55 * pcpu_init_value() -> copy_map_value_long() ->
56 * bpf_obj_memcpy(..., long_memcpy=true) ->
57 * bpf_long_memcpy(dst, src, round_up(4, 8))
58 *
59 * The copy size is rounded up to 8 bytes, but cgroup_val
60 * points to a 4-byte buffer, causing a 4-byte OOB read.
61 */
62 bpf_map_update_elem(&lru_map, &key, cgroup_val, BPF_ANY);
63
64 return 1;
65}
66
67char _license[] SEC("license") = "GPL";