summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-06-19 02:22:53 +0200
committerDaniel Borkmann <daniel@iogearbox.net>2019-06-19 02:22:53 +0200
commit94079b64255fe40b9b53fd2e4081f68b9b14f54a (patch)
tree2901e802c5161bb29dc5882fa14043f46de96cd0 /tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
parenta324aae32fa9bfdd03e89078e20ebcbd7737fda5 (diff)
parentb5dc0163d8fd78e64a7e21f309cf932fda34353e (diff)
downloadblackbird-op-linux-94079b64255fe40b9b53fd2e4081f68b9b14f54a.tar.gz
blackbird-op-linux-94079b64255fe40b9b53fd2e4081f68b9b14f54a.zip
Merge branch 'bpf-bounded-loops'
Alexei Starovoitov says: ==================== v2->v3: fixed issues in backtracking pointed out by Andrii. The next step is to add a lot more tests for backtracking. v1->v2: addressed Andrii's feedback. this patch set introduces verifier support for bounded loops and adds several other improvements. Ideally they would be introduced one at a time, but to support bounded loop the verifier needs to 'step back' in the patch 1. That patch introduces tracking of spill/fill of constants through the stack. Though it's a useful feature it hurts cilium tests. Patch 3 introduces another feature by extending is_branch_taken logic to 'if rX op rY' conditions. This feature is also necessary to support bounded loops. Then patch 4 adds support for the loops while adding key heuristics with jmp_processed. Introduction of parentage chain of verifier states in patch 4 allows patch 9 to add backtracking of precise scalar registers which finally resolves degradation from patch 1. The end result is much faster verifier for existing programs and new support for loops. See patch 8 for many kinds of loops that are now validated. Patch 9 is the most tricky one and could be rewritten with a different algorithm in the future. ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/testing/selftests/bpf/progs/test_sysctl_loop2.c')
-rw-r--r--tools/testing/selftests/bpf/progs/test_sysctl_loop2.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c b/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
new file mode 100644
index 000000000000..cb201cbe11e7
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019 Facebook
+
+#include <stdint.h>
+#include <string.h>
+
+#include <linux/stddef.h>
+#include <linux/bpf.h>
+
+#include "bpf_helpers.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+/* tcp_mem sysctl has only 3 ints, but this test is doing TCP_MEM_LOOPS */
+#define TCP_MEM_LOOPS 20 /* because 30 doesn't fit into 512 bytes of stack */
+#define MAX_ULONG_STR_LEN 7
+#define MAX_VALUE_STR_LEN (TCP_MEM_LOOPS * MAX_ULONG_STR_LEN)
+
+static __attribute__((noinline)) int is_tcp_mem(struct bpf_sysctl *ctx)
+{
+ volatile char tcp_mem_name[] = "net/ipv4/tcp_mem/very_very_very_very_long_pointless_string_to_stress_byte_loop";
+ unsigned char i;
+ char name[64];
+ int ret;
+
+ memset(name, 0, sizeof(name));
+ ret = bpf_sysctl_get_name(ctx, name, sizeof(name), 0);
+ if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
+ return 0;
+
+#pragma clang loop unroll(disable)
+ for (i = 0; i < sizeof(tcp_mem_name); ++i)
+ if (name[i] != tcp_mem_name[i])
+ return 0;
+
+ return 1;
+}
+
+
+SEC("cgroup/sysctl")
+int sysctl_tcp_mem(struct bpf_sysctl *ctx)
+{
+ unsigned long tcp_mem[TCP_MEM_LOOPS] = {};
+ char value[MAX_VALUE_STR_LEN];
+ unsigned char i, off = 0;
+ int ret;
+
+ if (ctx->write)
+ return 0;
+
+ if (!is_tcp_mem(ctx))
+ return 0;
+
+ ret = bpf_sysctl_get_current_value(ctx, value, MAX_VALUE_STR_LEN);
+ if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
+ return 0;
+
+#pragma clang loop unroll(disable)
+ for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
+ ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
+ tcp_mem + i);
+ if (ret <= 0 || ret > MAX_ULONG_STR_LEN)
+ return 0;
+ off += ret & MAX_ULONG_STR_LEN;
+ }
+
+ return tcp_mem[0] < tcp_mem[1] && tcp_mem[1] < tcp_mem[2];
+}
+
+char _license[] SEC("license") = "GPL";
OpenPOWER on IntegriCloud