WSL2-Linux-Kernel/kernel
Daniel Borkmann 2d2be8cab2 bpf: fix range propagation on direct packet access
LLVM can generate code that tests for direct packet access via
skb->data/data_end in a way that currently gets rejected by the
verifier, example:

  [...]
   7: (61) r3 = *(u32 *)(r6 +80)
   8: (61) r9 = *(u32 *)(r6 +76)
   9: (bf) r2 = r9
  10: (07) r2 += 54
  11: (3d) if r3 >= r2 goto pc+12
   R1=inv R2=pkt(id=0,off=54,r=0) R3=pkt_end R4=inv R6=ctx
   R9=pkt(id=0,off=0,r=0) R10=fp
  12: (18) r4 = 0xffffff7a
  14: (05) goto pc+430
  [...]

  from 11 to 24: R1=inv R2=pkt(id=0,off=54,r=0) R3=pkt_end R4=inv
                 R6=ctx R9=pkt(id=0,off=0,r=0) R10=fp
  24: (7b) *(u64 *)(r10 -40) = r1
  25: (b7) r1 = 0
  26: (63) *(u32 *)(r6 +56) = r1
  27: (b7) r2 = 40
  28: (71) r8 = *(u8 *)(r9 +20)
  invalid access to packet, off=20 size=1, R9(id=0,off=0,r=0)

The reason why this gets rejected despite a proper test is that we
currently call find_good_pkt_pointers() only in case where we detect
tests like rX > pkt_end, where rX is of type pkt(id=Y,off=Z,r=0) and
derived, for example, from a register of type pkt(id=Y,off=0,r=0)
pointing to skb->data. find_good_pkt_pointers() then fills the range
in the current branch to pkt(id=Y,off=0,r=Z) on success.

For above case, we need to extend that to recognize pkt_end >= rX
pattern and mark the other branch that is taken on success with the
appropriate pkt(id=Y,off=0,r=Z) type via find_good_pkt_pointers().
Since eBPF operates on BPF_JGT (>) and BPF_JGE (>=), these are the
only two practical options to test for from what LLVM could have
generated, since there's no such thing as BPF_JLT (<) or BPF_JLE (<=)
that we would need to take into account as well.

After the fix:

  [...]
   7: (61) r3 = *(u32 *)(r6 +80)
   8: (61) r9 = *(u32 *)(r6 +76)
   9: (bf) r2 = r9
  10: (07) r2 += 54
  11: (3d) if r3 >= r2 goto pc+12
   R1=inv R2=pkt(id=0,off=54,r=0) R3=pkt_end R4=inv R6=ctx
   R9=pkt(id=0,off=0,r=0) R10=fp
  12: (18) r4 = 0xffffff7a
  14: (05) goto pc+430
  [...]

  from 11 to 24: R1=inv R2=pkt(id=0,off=54,r=54) R3=pkt_end R4=inv
                 R6=ctx R9=pkt(id=0,off=0,r=54) R10=fp
  24: (7b) *(u64 *)(r10 -40) = r1
  25: (b7) r1 = 0
  26: (63) *(u32 *)(r6 +56) = r1
  27: (b7) r2 = 40
  28: (71) r8 = *(u8 *)(r9 +20)
  29: (bf) r1 = r8
  30: (25) if r8 > 0x3c goto pc+47
   R1=inv56 R2=imm40 R3=pkt_end R4=inv R6=ctx R8=inv56
   R9=pkt(id=0,off=0,r=54) R10=fp
  31: (b7) r1 = 1
  [...]

Verifier test cases are also added in this work, one that demonstrates
the mentioned example here and one that tries a bad packet access for
the current/fall-through branch (the one with types pkt(id=X,off=Y,r=0),
pkt(id=X,off=0,r=0)), then a case with good and bad accesses, and two
with both test variants (>, >=).

Fixes: 969bf05eb3 ("bpf: direct packet access")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-08 17:28:37 -07:00
..
bpf bpf: fix range propagation on direct packet access 2016-09-08 17:28:37 -07:00
configs config: add android config fragments 2016-08-02 19:35:42 -04:00
debug
events perf, bpf: fix conditional call to bpf_overflow_handler 2016-09-06 16:34:14 -07:00
gcov gcov: add support for gcc version >= 6 2016-07-15 14:54:27 +09:00
irq genirq/affinity: Use get/put_online_cpus around cpumask operations 2016-08-22 11:22:44 +02:00
livepatch modules: add ro_after_init support 2016-08-04 10:16:55 +09:30
locking locking/pvqspinlock: Fix a bug in qstat_read() 2016-08-10 14:13:29 +02:00
power Merge branch 'pm-sleep' 2016-08-18 03:27:08 +02:00
printk printk: fix parsing of "brl=" option 2016-08-26 17:39:35 -07:00
rcu Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-07-29 13:55:30 -07:00
sched sched/cputime: Resync steal time when guest & host lose sync 2016-08-18 11:19:48 +02:00
time timekeeping: Cap array access in timekeeping_debug 2016-08-24 09:34:32 +02:00
trace bpf: introduce BPF_PROG_TYPE_PERF_EVENT program type 2016-09-02 10:46:44 -07:00
.gitignore
Kconfig.freezer
Kconfig.hz
Kconfig.locks
Kconfig.preempt
Makefile ELF/MIPS build fix 2016-05-23 17:04:14 -07:00
acct.c
async.c
audit.c Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit 2016-07-29 17:54:17 -07:00
audit.h Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit 2016-07-29 17:54:17 -07:00
audit_fsnotify.c
audit_tree.c
audit_watch.c
auditfilter.c audit: add fields to exclude filter by reusing user filter 2016-06-27 11:01:00 -04:00
auditsc.c Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit 2016-07-29 17:54:17 -07:00
backtracetest.c
bounds.c
capability.c kernel: Add noaudit variant of ns_capable() 2016-06-06 20:16:18 +10:00
cgroup.c Merge branch 'for-4.7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup 2016-07-29 14:29:04 -07:00
cgroup_freezer.c
cgroup_pids.c cgroup: Use lld instead of ld when printing pids controller events_limit 2016-06-21 15:03:36 -04:00
compat.c
configs.c
context_tracking.c
cpu.c timers/core: Correct callback order during CPU hot plug 2016-07-28 18:56:22 +02:00
cpu_pm.c
cpuset.c cpuset, mm: fix TIF_MEMDIE check in cpuset_change_task_nodemask 2016-07-28 16:07:41 -07:00
crash_dump.c
cred.c cred: Reject inodes with invalid ids in set_create_file_as() 2016-06-30 18:05:09 -05:00
delayacct.c
dma.c
elfcore.c
exec_domain.c
exit.c kernel/exit.c: quieten greatest stack depth printk 2016-08-02 19:35:23 -04:00
extable.c
fork.c mm: fix memcg stack accounting for sub-page stacks 2016-07-28 16:07:41 -07:00
freezer.c freezer, oom: check TIF_MEMDIE on the correct task 2016-07-28 16:07:41 -07:00
futex.c futex: Assume all mappings are private on !MMU systems 2016-07-29 18:44:14 +02:00
futex_compat.c
groups.c
hung_task.c
irq_work.c
jump_label.c powerpc updates for 4.8 #2 2016-08-05 09:00:54 -04:00
kallsyms.c
kcmp.c
kcov.c kernel/kcov: unproxify debugfs file's fops 2016-06-15 04:56:35 -07:00
kexec.c kexec: allow architectures to override boot mapping 2016-08-02 19:35:27 -04:00
kexec_core.c kexec: add restriction on kexec_load() segment sizes 2016-08-02 19:35:31 -04:00
kexec_file.c kexec: introduce a protection mechanism for the crashkernel reserved memory 2016-05-23 17:04:14 -07:00
kexec_internal.h
kmod.c
kprobes.c
ksysfs.c kexec: add a kexec_crash_loaded() function 2016-08-02 19:35:30 -04:00
kthread.c
latencytop.c
membarrier.c
memremap.c libnvdimm for 4.8 2016-07-28 17:38:16 -07:00
module-internal.h
module.c Removed the MODULE_SIG_FORCE-means-no-MODULE_FORCE_LOAD patch. 2016-08-04 09:14:38 -04:00
module_signing.c
notifier.c
nsproxy.c
padata.c kernel/padata.c: hide unused functions 2016-05-19 19:12:14 -07:00
panic.c kexec: use core_param for crash_kexec_post_notifiers boot option 2016-08-02 19:35:29 -04:00
params.c
pid.c remove lots of IS_ERR_VALUE abuses 2016-05-27 15:26:11 -07:00
pid_namespace.c
profile.c profile: Convert to hotplug state machine 2016-07-15 10:41:42 +02:00
ptrace.c tree-wide: replace config_enabled() with IS_ENABLED() 2016-08-04 08:50:07 -04:00
range.c
reboot.c
relay.c relay: add global mode support for buffer-only channels 2016-08-02 19:35:41 -04:00
resource.c
seccomp.c tree-wide: replace config_enabled() with IS_ENABLED() 2016-08-04 08:50:07 -04:00
signal.c signals: Use hrtimer for sigtimedwait() 2016-07-07 10:35:07 +02:00
smp.c Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-07-29 13:55:30 -07:00
smpboot.c
smpboot.h
softirq.c
stacktrace.c
stop_machine.c stop_machine: Touch_nmi_watchdog() after MULTI_STOP_PREPARE 2016-07-27 11:12:11 +02:00
sys.c prctl: make PR_SET_THP_DISABLE wait for mmap_sem killable 2016-05-23 17:04:14 -07:00
sys_ni.c
sysctl.c sysctl: handle error writing UINT_MAX to u32 fields 2016-08-26 17:39:35 -07:00
sysctl_binary.c kernel/sysctl_binary.c: use generic UUID library 2016-05-20 17:58:30 -07:00
task_work.c task_work: use READ_ONCE/lockless_dereference, avoid pi_lock if !task_works 2016-08-02 19:35:02 -04:00
taskstats.c
test_kprobes.c
torture.c torture: Stop onoff task if there is only one cpu 2016-06-14 16:03:28 -07:00
tracepoint.c
tsacct.c
uid16.c
up.c
user-return-notifier.c
user.c
user_namespace.c fs: Limit file caps to the user namespace of the super block 2016-06-24 10:40:31 -05:00
utsname.c
utsname_sysctl.c
watchdog.c Revert "perf/x86/intel, watchdog: Switch NMI watchdog to ref cycles on x86" 2016-07-10 20:58:36 +02:00
workqueue.c Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-07-29 13:55:30 -07:00
workqueue_internal.h