linux/tools/testing/selftests
Daniel Borkmann a08dd0da53 bpf: fix regression on verifier pruning wrt map lookups
Commit 57a09bf0a4 ("bpf: Detect identical PTR_TO_MAP_VALUE_OR_NULL
registers") introduced a regression where existing programs stopped
loading due to reaching the verifier's maximum complexity limit,
whereas prior to this commit they were loading just fine; the affected
program has roughly 2k instructions.

What was found is that state pruning couldn't be performed effectively
anymore due to mismatches of the verifier's register state, in particular
in the id tracking. It doesn't mean that 57a09bf0a4 is incorrect per
se, but rather that verifier needs to perform a lot more work for the
same program with regards to involved map lookups.

Since commit 57a09bf0a4 is only about tracking registers with type
PTR_TO_MAP_VALUE_OR_NULL, the id is only needed to follow registers
until they are promoted through pattern matching with a NULL check to
either PTR_TO_MAP_VALUE or UNKNOWN_VALUE type. After that point, the
id becomes irrelevant for the transitioned types.

For UNKNOWN_VALUE, id is already reset to 0 via mark_reg_unknown_value(),
but not so for PTR_TO_MAP_VALUE where id is becoming stale. It's even
transferred further into other types that don't make use of it. Among
others, one example is where UNKNOWN_VALUE is set on function call
return with RET_INTEGER return type.

states_equal() will then fall through the memcmp() on register state;
note that the second memcmp() uses offsetofend(), so the id is part of
that since d2a4dd37f6 ("bpf: fix state equivalence"). But the bisect
pointed already to 57a09bf0a4, where we really reach beyond complexity
limit. What I found was that states_equal() often failed in this
case due to id mismatches in spilled regs with registers in type
PTR_TO_MAP_VALUE. Unlike non-spilled regs, spilled regs just perform
a memcmp() on their reg state and don't have any other optimizations
in place, therefore also id was relevant in this case for making a
pruning decision.

We can safely reset id to 0 as well when converting to PTR_TO_MAP_VALUE.
For the affected program, it resulted in a ~17 fold reduction of
complexity and let the program load fine again. Selftest suite also
runs fine. The only other place where env->id_gen is used currently is
through direct packet access, but for these cases id is long living, thus
a different scenario.

Also, the current logic in mark_map_regs() is not fully correct when
marking NULL branch with UNKNOWN_VALUE. We need to cache the destination
reg's id in any case. Otherwise, once we marked that reg as UNKNOWN_VALUE,
it's id is reset and any subsequent registers that hold the original id
and are of type PTR_TO_MAP_VALUE_OR_NULL won't be marked UNKNOWN_VALUE
anymore, since mark_map_reg() reuses the uncached regs[regno].id that
was just overridden. Note, we don't need to cache it outside of
mark_map_regs(), since it's called once on this_branch and the other
time on other_branch, which are both two independent verifier states.
A test case for this is added here, too.

Fixes: 57a09bf0a4 ("bpf: Detect identical PTR_TO_MAP_VALUE_OR_NULL registers")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Thomas Graf <tgraf@suug.ch>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-12-17 10:51:31 -05:00
..
bpf bpf: fix regression on verifier pruning wrt map lookups 2016-12-17 10:51:31 -05:00
breakpoints selftests: add missing .gitignore file or entry 2016-02-25 13:16:36 -07:00
capabilities selftests/capabilities: clean up for Makefile 2015-11-23 13:20:10 -07:00
cpu-hotplug selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
efivarfs efi: Make efivarfs entries immutable by default 2016-02-10 16:25:52 +00:00
exec selftests/exec: Makefile is a run-time dependency, add it to the install list 2016-06-15 13:35:55 -06:00
filesystems selftests: move dnotify_test from Documentation/filesystems 2016-09-20 09:09:00 -06:00
firmware selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
ftrace ftracetest: Fix hist unsupported result in hist selftests 2016-06-20 09:46:21 -04:00
futex selftests/futex: Check ANSI terminal color support 2016-10-11 07:38:36 -06:00
ia64 selftests: move ia64 tests from Documentation/ia64 2016-09-20 09:58:12 -06:00
intel_pstate tools: testing: define the _GNU_SOURCE macro 2016-05-16 09:06:17 -06:00
ipc selftests: add missing .gitignore file or entry 2016-02-25 13:16:36 -07:00
kcmp selftests: Set CC using CROSS_COMPILE once in lib.mk 2015-03-19 15:16:51 -06:00
lib selftests/lib: set printf.sh executable 2016-06-27 13:17:14 -06:00
media_tests selftests: media_tests add a new video device test 2016-07-26 09:59:30 -06:00
membarrier membarrier: clean up selftest 2015-09-22 15:09:53 -07:00
memfd selftests: Make scripts executable 2015-11-03 16:54:57 -07:00
memory-hotplug selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
mount selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
mqueue selftests: Add missing #include directives 2015-11-03 16:53:53 -07:00
net reuseport, bpf: add test case for bpf_get_numa_node_id 2016-10-22 17:05:52 -04:00
networking/timestamping selftests: Move networking/timestamping from Documentation 2016-09-20 09:59:50 -06:00
nsfs tools/testing: add a test to check nsfs ioctl-s 2016-09-22 19:59:41 -05:00
ntb ntb_test: Add a selftest script for the NTB subsystem 2016-08-05 10:21:08 -04:00
powerpc selftests/powerpc: Fix build break caused by EXPORT_SYMBOL changes 2016-10-06 22:26:42 +11:00
prctl selftests: move prctl tests from Documentation/prctl 2016-09-20 09:09:09 -06:00
pstore selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
ptp selftests: move ptp tests from Documentation/ptp 2016-09-20 09:54:38 -06:00
ptrace add ptrace/.gitignore 2016-01-07 13:38:11 -07:00
rcutorture torture: Inflict default jitter 2016-06-14 16:03:32 -07:00
seccomp seccomp: add tests for ptrace hole 2016-06-14 10:54:38 -07:00
sigaltstack signals/sigaltstack: Change SS_AUTODISARM to (1U << 31) 2016-05-04 08:34:14 +02:00
size selftests: Set CC using CROSS_COMPILE once in lib.mk 2015-03-19 15:16:51 -06:00
static_keys selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
sysctl selftests: Add install target 2015-03-13 15:21:56 -06:00
timers selftests/timers: Add missing error code assignment before test 2016-09-20 09:00:28 -06:00
user selftests: create test-specific kconfig fragments 2016-02-25 09:47:52 -07:00
vDSO selftests: move vDSO tests from Documentation/vDSO 2016-09-20 09:58:04 -06:00
vm selftests: expanding more mlock selftest 2016-10-07 18:46:28 -07:00
watchdog selftests: move watchdog tests from Documentation/watchdog 2016-09-20 09:58:34 -06:00
x86 Merge branch 'mm-pkeys-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-10-10 11:01:51 -07:00
zram selftests/zram: replace ZRAM_LZ4_COMPRESS 2016-09-20 09:00:01 -06:00
gen_kselftest_tar.sh selftests: Add tool to generate kselftest tar archive 2015-03-24 08:43:19 -06:00
kselftest_install.sh selftests: Add kselftest install tool 2015-03-24 08:43:05 -06:00
kselftest.h kselftest: Add exit code defines 2015-05-26 15:58:08 -06:00
lib.mk selftests: change install command to rsync 2015-09-14 16:43:51 -06:00
Makefile bpf: add initial suite for selftests 2016-10-18 11:35:55 -04:00