Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add cgroup_skb/egress test for load_bytes_relative

When cgroup_skb/egress triggers the MAC header is not set. Added a
test that asserts reading MAC header is a -EFAULT but NET header
succeeds. The test result from within the eBPF program is stored in
an 1-element array map that the userspace then reads and asserts on.

Another assertion is added that reading from a large offset, past
the end of packet, returns -EFAULT.

Signed-off-by: YiFei Zhu <zhuyifei@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/bpf/9028ccbea4385a620e69c0a104f469ffd655c01e.1591812755.git.zhuyifei@google.com

authored by

YiFei Zhu and committed by
Daniel Borkmann
bd6fecb9 0f5d82f1

+119
+71
tools/testing/selftests/bpf/prog_tests/load_bytes_relative.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * Copyright 2020 Google LLC. 5 + */ 6 + 7 + #include <test_progs.h> 8 + #include <network_helpers.h> 9 + 10 + void test_load_bytes_relative(void) 11 + { 12 + int server_fd, cgroup_fd, prog_fd, map_fd, client_fd; 13 + int err; 14 + struct bpf_object *obj; 15 + struct bpf_program *prog; 16 + struct bpf_map *test_result; 17 + __u32 duration = 0; 18 + 19 + __u32 map_key = 0; 20 + __u32 map_value = 0; 21 + 22 + cgroup_fd = test__join_cgroup("/load_bytes_relative"); 23 + if (CHECK_FAIL(cgroup_fd < 0)) 24 + return; 25 + 26 + server_fd = start_server(AF_INET, SOCK_STREAM); 27 + if (CHECK_FAIL(server_fd < 0)) 28 + goto close_cgroup_fd; 29 + 30 + err = bpf_prog_load("./load_bytes_relative.o", BPF_PROG_TYPE_CGROUP_SKB, 31 + &obj, &prog_fd); 32 + if (CHECK_FAIL(err)) 33 + goto close_server_fd; 34 + 35 + test_result = bpf_object__find_map_by_name(obj, "test_result"); 36 + if (CHECK_FAIL(!test_result)) 37 + goto close_bpf_object; 38 + 39 + map_fd = bpf_map__fd(test_result); 40 + if (map_fd < 0) 41 + goto close_bpf_object; 42 + 43 + prog = bpf_object__find_program_by_name(obj, "load_bytes_relative"); 44 + if (CHECK_FAIL(!prog)) 45 + goto close_bpf_object; 46 + 47 + err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 48 + BPF_F_ALLOW_MULTI); 49 + if (CHECK_FAIL(err)) 50 + goto close_bpf_object; 51 + 52 + client_fd = connect_to_fd(AF_INET, SOCK_STREAM, server_fd); 53 + if (CHECK_FAIL(client_fd < 0)) 54 + goto close_bpf_object; 55 + close(client_fd); 56 + 57 + err = bpf_map_lookup_elem(map_fd, &map_key, &map_value); 58 + if (CHECK_FAIL(err)) 59 + goto close_bpf_object; 60 + 61 + CHECK(map_value != 1, "bpf", "bpf program returned failure"); 62 + 63 + close_bpf_object: 64 + bpf_object__close(obj); 65 + 66 + close_server_fd: 67 + close(server_fd); 68 + 69 + close_cgroup_fd: 70 + close(cgroup_fd); 71 + }
+48
tools/testing/selftests/bpf/progs/load_bytes_relative.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * Copyright 2020 Google LLC. 5 + */ 6 + 7 + #include <errno.h> 8 + #include <linux/bpf.h> 9 + #include <linux/if_ether.h> 10 + #include <linux/ip.h> 11 + #include <bpf/bpf_helpers.h> 12 + 13 + struct { 14 + __uint(type, BPF_MAP_TYPE_ARRAY); 15 + __uint(max_entries, 1); 16 + __type(key, __u32); 17 + __type(value, __u32); 18 + } test_result SEC(".maps"); 19 + 20 + SEC("cgroup_skb/egress") 21 + int load_bytes_relative(struct __sk_buff *skb) 22 + { 23 + struct ethhdr eth; 24 + struct iphdr iph; 25 + 26 + __u32 map_key = 0; 27 + __u32 test_passed = 0; 28 + 29 + /* MAC header is not set by the time cgroup_skb/egress triggers */ 30 + if (bpf_skb_load_bytes_relative(skb, 0, &eth, sizeof(eth), 31 + BPF_HDR_START_MAC) != -EFAULT) 32 + goto fail; 33 + 34 + if (bpf_skb_load_bytes_relative(skb, 0, &iph, sizeof(iph), 35 + BPF_HDR_START_NET)) 36 + goto fail; 37 + 38 + if (bpf_skb_load_bytes_relative(skb, 0xffff, &iph, sizeof(iph), 39 + BPF_HDR_START_NET) != -EFAULT) 40 + goto fail; 41 + 42 + test_passed = 1; 43 + 44 + fail: 45 + bpf_map_update_elem(&test_result, &map_key, &test_passed, BPF_ANY); 46 + 47 + return 1; 48 + }