Home Home > GIT Browse > SLE15-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2018-05-18 16:54:10 +0200
committerJiri Kosina <jkosina@suse.cz>2018-05-18 17:17:39 +0200
commitf1ac4a9a231c257dce6d22c8814b73dc8f171040 (patch)
treefb61f332c77ee84c534adc171091f9d8930ea0c7
parent81bdbb02cc5f4894a7b92feb389fec927f5dd1cd (diff)
bpf: prevent memory disambiguation attack (bsc#1087082
CVE-2018-3639).
-rw-r--r--patches.kabi/bpf-prevent-memory-disambiguation-attack.patch24
-rw-r--r--patches.suse/bpf-prevent-memory-disambiguation-attack.patch134
-rw-r--r--series.conf2
3 files changed, 160 insertions, 0 deletions
diff --git a/patches.kabi/bpf-prevent-memory-disambiguation-attack.patch b/patches.kabi/bpf-prevent-memory-disambiguation-attack.patch
new file mode 100644
index 0000000000..5a692eec02
--- /dev/null
+++ b/patches.kabi/bpf-prevent-memory-disambiguation-attack.patch
@@ -0,0 +1,24 @@
+From: Jiri Kosina <jkosina@suse.cz>
+Subject: [PATCH] kabi: ignore struct bpf_insn_aux_data change
+Patch-mainline: No, SUSE-specific
+References: References: bsc#1087082
+
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+---
+ include/linux/bpf_verifier.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -115,8 +115,10 @@ struct bpf_insn_aux_data {
+ struct bpf_map *map_ptr; /* pointer for call insn into lookup_elem */
+ };
+ int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
+- int sanitize_stack_off; /* stack slot to be cleared */
+ bool seen; /* this insn was processed by the verifier */
++#ifndef __GENKSYMS__
++ int sanitize_stack_off; /* stack slot to be cleared */
++#endif
+ };
+
+ #define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
diff --git a/patches.suse/bpf-prevent-memory-disambiguation-attack.patch b/patches.suse/bpf-prevent-memory-disambiguation-attack.patch
new file mode 100644
index 0000000000..a1b940b52b
--- /dev/null
+++ b/patches.suse/bpf-prevent-memory-disambiguation-attack.patch
@@ -0,0 +1,134 @@
+From: Alexei Starovoitov <ast@kernel.org>
+Date: Tue, 15 May 2018 09:27:05 -0700
+Subject: [PATCH] bpf: prevent memory disambiguation attack
+References: bsc#1087082 CVE-2018-3639
+Patch-mainline: Not yet, under development
+
+Detect code patterns where malicious 'speculative store bypass' can be used
+and sanitize such patterns.
+
+ 39: (bf) r3 = r10
+ 40: (07) r3 += -216
+ 41: (79) r8 = *(u64 *)(r7 +0) // slow read
+ 42: (7a) *(u64 *)(r10 -72) = 0 // verifier inserts this instruction
+ 43: (7b) *(u64 *)(r8 +0) = r3 // this store becomes slow due to r8
+ 44: (79) r1 = *(u64 *)(r6 +0) // cpu speculatively executes this load
+ 45: (71) r2 = *(u8 *)(r1 +0) // speculatively arbitrary 'load byte'
+ // is now sanitized
+
+Above code after x86 JIT becomes:
+ e5: mov %rbp,%rdx
+ e8: add $0xffffffffffffff28,%rdx
+ ef: mov 0x0(%r13),%r14
+ f3: movq $0x0,-0x48(%rbp)
+ fb: mov %rdx,0x0(%r14)
+ ff: mov 0x0(%rbx),%rdi
+103: movzbq 0x0(%rdi),%rsi
+
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+---
+ include/linux/bpf_verifier.h | 1
+ kernel/bpf/verifier.c | 59 ++++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 57 insertions(+), 3 deletions(-)
+
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -115,6 +115,7 @@ struct bpf_insn_aux_data {
+ struct bpf_map *map_ptr; /* pointer for call insn into lookup_elem */
+ };
+ int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
++ int sanitize_stack_off; /* stack slot to be cleared */
+ bool seen; /* this insn was processed by the verifier */
+ };
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -658,7 +658,7 @@ static bool is_spillable_regtype(enum bp
+ */
+ static int check_stack_write(struct bpf_verifier_env *env,
+ struct bpf_verifier_state *state, int off,
+- int size, int value_regno)
++ int size, int value_regno, int insn_idx)
+ {
+ int i, slot = -off - 1, spi = slot / BPF_REG_SIZE, err;
+
+@@ -689,8 +689,33 @@ static int check_stack_write(struct bpf_
+ state->stack[spi].spilled_ptr = state->regs[value_regno];
+ state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
+
+- for (i = 0; i < BPF_REG_SIZE; i++)
++ for (i = 0; i < BPF_REG_SIZE; i++) {
++ if (state->stack[spi].slot_type[i] == STACK_MISC &&
++ !env->allow_ptr_leaks) {
++ int *poff = &env->insn_aux_data[insn_idx].sanitize_stack_off;
++ int soff = (-spi - 1) * BPF_REG_SIZE;
++
++ /* detected reuse of integer stack slot with a pointer
++ * which means either llvm is reusing stack slot or
++ * an attacker is trying to exploit CVE-2018-3639
++ * (speculative store bypass)
++ * Have to sanitize that slot with preemptive
++ * store of zero.
++ */
++ if (*poff && *poff != soff) {
++ /* disallow programs where single insn stores
++ * into two different stack slots, since verifier
++ * cannot sanitize them
++ */
++ verbose(env,
++ "insn %d cannot access two stack slots fp%d and fp%d",
++ insn_idx, *poff, soff);
++ return -EINVAL;
++ }
++ *poff = soff;
++ }
+ state->stack[spi].slot_type[i] = STACK_SPILL;
++ }
+ } else {
+ /* regular write of data into stack */
+ state->stack[spi].spilled_ptr = (struct bpf_reg_state) {};
+@@ -1181,7 +1206,7 @@ static int check_mem_access(struct bpf_v
+
+ if (t == BPF_WRITE)
+ err = check_stack_write(env, state, off, size,
+- value_regno);
++ value_regno, insn_idx);
+ else
+ err = check_stack_read(env, state, off, size,
+ value_regno);
+@@ -4232,6 +4257,34 @@ static int convert_ctx_accesses(struct b
+ else
+ continue;
+
++ if (type == BPF_WRITE &&
++ env->insn_aux_data[i + delta].sanitize_stack_off) {
++ struct bpf_insn patch[] = {
++ /* Sanitize suspicious stack slot with zero.
++ * There are no memory dependencies for this store,
++ * since it's only using frame pointer and immediate
++ * constant of zero
++ */
++ BPF_ST_MEM(BPF_DW, BPF_REG_FP,
++ env->insn_aux_data[i + delta].sanitize_stack_off,
++ 0),
++ /* the original STX instruction will immediately
++ * overwrite the same stack slot with appropriate value
++ */
++ *insn,
++ };
++
++ cnt = ARRAY_SIZE(patch);
++ new_prog = bpf_patch_insn_data(env, i + delta, patch, cnt);
++ if (!new_prog)
++ return -ENOMEM;
++
++ delta += cnt - 1;
++ env->prog = new_prog;
++ insn = new_prog->insnsi + i + delta;
++ continue;
++ }
++
+ if (env->insn_aux_data[i + delta].ptr_type != PTR_TO_CTX)
+ continue;
+
diff --git a/series.conf b/series.conf
index 953ea2c27a..05e1df3d61 100644
--- a/series.conf
+++ b/series.conf
@@ -12468,6 +12468,8 @@
patches.suse/26-x86-bugs-rename-rds-to-ssbd.patch
patches.suse/27-proc-use-underscores-for-ssbd-in-status.patch
patches.arch/KVM--SVM--Move-spec-control-call-after-restore-of-GS.patch
+ patches.suse/bpf-prevent-memory-disambiguation-attack.patch
+ patches.kabi/bpf-prevent-memory-disambiguation-attack.patch
########################################################
# You'd better have a good reason for adding a patch