Context |
Check |
Description |
bpf/vmtest-bpf-next-PR |
success
|
PR summary
|
bpf/vmtest-bpf-next-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-next-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-next-VM_Test-2 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-next-VM_Test-3 |
success
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-4 |
success
|
Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-6 |
success
|
Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-7 |
success
|
Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-8 |
success
|
Logs for aarch64-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-9 |
pending
|
Logs for s390x-gcc / build / build for s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-10 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-next-VM_Test-11 |
success
|
Logs for x86_64-gcc / build / build for x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-12 |
success
|
Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-13 |
success
|
Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-16 |
success
|
Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-14 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-15 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-18 |
success
|
Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-20 |
success
|
Logs for x86_64-llvm-16 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-19 |
success
|
Logs for x86_64-llvm-16 / build / build for x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-17 |
success
|
Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-21 |
success
|
Logs for x86_64-llvm-16 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-22 |
success
|
Logs for x86_64-llvm-16 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-24 |
success
|
Logs for x86_64-llvm-16 / veristat
|
bpf/vmtest-bpf-next-VM_Test-23 |
success
|
Logs for x86_64-llvm-16 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-16
|
bpf/vmtest-bpf-next-VM_Test-5 |
fail
|
Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
|
netdev/series_format |
success
|
Posting correctly formatted
|
netdev/tree_selection |
success
|
Clearly marked for bpf-next
|
netdev/fixes_present |
success
|
Fixes tag not required for -next series
|
netdev/header_inline |
success
|
No static functions without inline keyword in header files
|
netdev/build_32bit |
success
|
Errors and warnings before: 1352 this patch: 1352
|
netdev/cc_maintainers |
warning
|
9 maintainers not CCed: haoluo@google.com song@kernel.org linux-kselftest@vger.kernel.org shuah@kernel.org martin.lau@linux.dev kpsingh@kernel.org jolsa@kernel.org sdf@google.com mykolal@fb.com
|
netdev/build_clang |
success
|
Errors and warnings before: 1379 this patch: 1379
|
netdev/verify_signedoff |
success
|
Signed-off-by tag matches author and committer
|
netdev/deprecated_api |
success
|
None detected
|
netdev/check_selftest |
success
|
No net selftest shell script
|
netdev/verify_fixes |
success
|
No Fixes tag
|
netdev/build_allmodconfig_warn |
success
|
Errors and warnings before: 1380 this patch: 1380
|
netdev/checkpatch |
warning
|
WARNING: Improper SPDX comment style for 'kernel/bpf/wrange.c', please use '//' instead
WARNING: Missing or malformed SPDX-License-Identifier tag in line 1
WARNING: Missing or malformed SPDX-License-Identifier tag in line 2
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
|
netdev/build_clang_rust |
success
|
No Rust files in patch. Skipping build
|
netdev/kdoc |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/source_inline |
success
|
Was 0 now: 0
|
@@ -11,6 +11,8 @@ struct wrange32 {
u32 end;
};
+struct wrange32 wrange32_add(struct wrange32 a, struct wrange32 b);
+
static inline bool wrange32_uwrapping(struct wrange32 a) {
return a.end < a.start;
}
@@ -6,7 +6,8 @@ cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse
endif
CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy)
-obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o log.o
+# At least make sure wrange.c compiles
+obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o log.o wrange.o
obj-$(CONFIG_BPF_SYSCALL) += bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o
obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o bloom_filter.o
obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o
new file mode 100644
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/wrange.h>
+
+#define WRANGE32(_s, _e) ((struct wrange32) {.start = _s, .end = _e})
+
+struct wrange32 wrange32_add(struct wrange32 a, struct wrange32 b)
+{
+ u32 a_len = a.end - a.start;
+ u32 b_len = b.end - b.start;
+ u32 new_len = a_len + b_len;
+
+ /* the new start/end pair goes full circle, so any value is possible */
+ if (new_len < a_len || new_len < b_len)
+ return WRANGE32(U32_MIN, U32_MAX);
+ else
+ return WRANGE32(a.start + b.start, a.end + b.end);
+}
@@ -24,6 +24,10 @@ class Wrange(abc.ABC):
# allow end < start, so any start/end combination is valid
return BoolVal(True)
+ @property
+ def length(self):
+ return self.end - self.start
+
@property
def uwrapping(self):
# unsigned comparison, (u32)end < (u32)start
new file mode 100755
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+from z3 import *
+from wrange import *
+
+
+def wrange_add(a: Wrange, b: Wrange):
+ wrange_class = type(a)
+ assert(a.SIZE == b.SIZE)
+
+ new_length = a.length + b.length
+ too_wide = Or(ULT(new_length, a.length), ULT(new_length, b.length))
+ new_start = If(too_wide, BitVecVal(0, a.SIZE), a.start + b.start)
+ new_end = If(too_wide, BitVecVal(2**a.SIZE-1, a.SIZE), a.end + b.end)
+ return wrange_class(f'{a.name} + {b.name}', new_start, new_end)
+
+
+def main():
+ x = BitVec32('x')
+ w = wrange_add(
+ # {1, 2, 3}
+ Wrange32('w1', start=BitVecVal32(1), end=BitVecVal32(3)),
+ # + {0}
+ Wrange32('w2', start=BitVecVal32(0), end=BitVecVal32(0)),
+ ) # = {1, 2, 3}
+ print('Checking {1, 2, 3} + {0} = {1, 2, 3}')
+ prove( # 1 <= x <= 3
+ w.contains(x) == And(BitVecVal32(1) <= x, x <= BitVecVal32(3)),
+ )
+
+ w = wrange_add(
+ # {-1}
+ Wrange32('w1', start=BitVecVal32(-1), end=BitVecVal32(-1)),
+ # + {0, 1, 2}
+ Wrange32('w2', start=BitVecVal32(0), end=BitVecVal32(2)),
+ ) # = {-1, 0, 1}
+ print('\nChecking {-1} + {0, 1, 2} = {-1, 0, 1}')
+ prove( # -1 <= x <= 1
+ w.contains(x) == And(BitVecVal32(-1) <= x, x <= BitVecVal32(1)),
+ )
+
+ # A general check to make sure wrange_add() is sound
+ x = BitVec32('x')
+ y = BitVec32('y')
+ w1 = Wrange32('w1')
+ w2 = Wrange32('w2')
+ w = wrange_add(w1, w2)
+ premise = And(
+ w1.wellformed(),
+ w2.wellformed(),
+ w1.contains(x),
+ w2.contains(y),
+ )
+ # Suppose we have a wrange32 called w1 that contains the 32-bit integer x
+ # (where x can be any possible value contained inside w1), and another
+ # wrange32 called w2 that similarly contains 32-bit integer y.
+ #
+ # The sum of w1 and w2 calculated from wrange_add(w1, w2), called w, should
+ # _always_ contains the sum of x and y, no matter what.
+ print('\nChecking that if w1.contains(x) and w2.contains(y), then wrange32_add(w1, w2).contains(x+y)')
+ print('(note: this may take awhile)')
+ prove(
+ Implies(
+ premise,
+ And(
+ w.contains(x + y),
+ w.wellformed(),
+ ),
+ )
+ )
+
+
+if __name__ == '__main__':
+ main()
Implement wrange32_add() that takes two wrange32 and compute a new wrange32 that contains all possible combinations of sums produced by adding values in the two wrange32. This is done by adding start and end of both wrange32 for the majority of cases, and works even when the addition overflows. However, there still exist cases where the addition of two wrange32 result in a range that is too large to track, this happens when the combined length is too large. When this happens we fallback to start=U32_MIN and end=U32_MAX. (Calling end-minus-start as "length" because one can visual wrange32 as a number line, and thus end point minus starting point would naturally be the length of such line) Additionally, make sure wrange.c gets compilation checked, and add wrange_add.py that models and check wrange32_add(). Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com> --- include/linux/wrange.h | 2 + kernel/bpf/Makefile | 3 +- kernel/bpf/wrange.c | 17 +++++ tools/testing/selftests/bpf/formal/wrange.py | 4 + .../selftests/bpf/formal/wrange_add.py | 73 +++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 kernel/bpf/wrange.c create mode 100755 tools/testing/selftests/bpf/formal/wrange_add.py