Commit 22170094 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Alexei Starovoitov says:

====================
pull-request: bpf 2018-02-22

The following pull-request contains BPF updates for your *net* tree.

The main changes are:

1) two urgent fixes for bpf_tail_call logic for x64 and arm64 JITs, from Daniel.

2) cond_resched points in percpu array alloc/free paths, from Eric.

3) lockdep and other minor fixes, from Yonghong, Arnd, Anders, Li.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d903ec77 16338a9b
...@@ -250,8 +250,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) ...@@ -250,8 +250,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
off = offsetof(struct bpf_array, map.max_entries); off = offsetof(struct bpf_array, map.max_entries);
emit_a64_mov_i64(tmp, off, ctx); emit_a64_mov_i64(tmp, off, ctx);
emit(A64_LDR32(tmp, r2, tmp), ctx); emit(A64_LDR32(tmp, r2, tmp), ctx);
emit(A64_MOV(0, r3, r3), ctx);
emit(A64_CMP(0, r3, tmp), ctx); emit(A64_CMP(0, r3, tmp), ctx);
emit(A64_B_(A64_COND_GE, jmp_offset), ctx); emit(A64_B_(A64_COND_CS, jmp_offset), ctx);
/* if (tail_call_cnt > MAX_TAIL_CALL_CNT) /* if (tail_call_cnt > MAX_TAIL_CALL_CNT)
* goto out; * goto out;
...@@ -259,7 +260,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) ...@@ -259,7 +260,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
*/ */
emit_a64_mov_i64(tmp, MAX_TAIL_CALL_CNT, ctx); emit_a64_mov_i64(tmp, MAX_TAIL_CALL_CNT, ctx);
emit(A64_CMP(1, tcc, tmp), ctx); emit(A64_CMP(1, tcc, tmp), ctx);
emit(A64_B_(A64_COND_GT, jmp_offset), ctx); emit(A64_B_(A64_COND_HI, jmp_offset), ctx);
emit(A64_ADD_I(1, tcc, tcc, 1), ctx); emit(A64_ADD_I(1, tcc, tcc, 1), ctx);
/* prog = array->ptrs[index]; /* prog = array->ptrs[index];
......
...@@ -177,4 +177,41 @@ static inline void indirect_branch_prediction_barrier(void) ...@@ -177,4 +177,41 @@ static inline void indirect_branch_prediction_barrier(void)
} }
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/*
* Below is used in the eBPF JIT compiler and emits the byte sequence
* for the following assembly:
*
* With retpolines configured:
*
* callq do_rop
* spec_trap:
* pause
* lfence
* jmp spec_trap
* do_rop:
* mov %rax,(%rsp)
* retq
*
* Without retpolines configured:
*
* jmp *%rax
*/
#ifdef CONFIG_RETPOLINE
# define RETPOLINE_RAX_BPF_JIT_SIZE 17
# define RETPOLINE_RAX_BPF_JIT() \
EMIT1_off32(0xE8, 7); /* callq do_rop */ \
/* spec_trap: */ \
EMIT2(0xF3, 0x90); /* pause */ \
EMIT3(0x0F, 0xAE, 0xE8); /* lfence */ \
EMIT2(0xEB, 0xF9); /* jmp spec_trap */ \
/* do_rop: */ \
EMIT4(0x48, 0x89, 0x04, 0x24); /* mov %rax,(%rsp) */ \
EMIT1(0xC3); /* retq */
#else
# define RETPOLINE_RAX_BPF_JIT_SIZE 2
# define RETPOLINE_RAX_BPF_JIT() \
EMIT2(0xFF, 0xE0); /* jmp *%rax */
#endif
#endif /* _ASM_X86_NOSPEC_BRANCH_H_ */ #endif /* _ASM_X86_NOSPEC_BRANCH_H_ */
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/set_memory.h> #include <asm/set_memory.h>
#include <asm/nospec-branch.h>
#include <linux/bpf.h> #include <linux/bpf.h>
/* /*
...@@ -290,7 +291,7 @@ static void emit_bpf_tail_call(u8 **pprog) ...@@ -290,7 +291,7 @@ static void emit_bpf_tail_call(u8 **pprog)
EMIT2(0x89, 0xD2); /* mov edx, edx */ EMIT2(0x89, 0xD2); /* mov edx, edx */
EMIT3(0x39, 0x56, /* cmp dword ptr [rsi + 16], edx */ EMIT3(0x39, 0x56, /* cmp dword ptr [rsi + 16], edx */
offsetof(struct bpf_array, map.max_entries)); offsetof(struct bpf_array, map.max_entries));
#define OFFSET1 43 /* number of bytes to jump */ #define OFFSET1 (41 + RETPOLINE_RAX_BPF_JIT_SIZE) /* number of bytes to jump */
EMIT2(X86_JBE, OFFSET1); /* jbe out */ EMIT2(X86_JBE, OFFSET1); /* jbe out */
label1 = cnt; label1 = cnt;
...@@ -299,7 +300,7 @@ static void emit_bpf_tail_call(u8 **pprog) ...@@ -299,7 +300,7 @@ static void emit_bpf_tail_call(u8 **pprog)
*/ */
EMIT2_off32(0x8B, 0x85, 36); /* mov eax, dword ptr [rbp + 36] */ EMIT2_off32(0x8B, 0x85, 36); /* mov eax, dword ptr [rbp + 36] */
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
#define OFFSET2 32 #define OFFSET2 (30 + RETPOLINE_RAX_BPF_JIT_SIZE)
EMIT2(X86_JA, OFFSET2); /* ja out */ EMIT2(X86_JA, OFFSET2); /* ja out */
label2 = cnt; label2 = cnt;
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
...@@ -313,7 +314,7 @@ static void emit_bpf_tail_call(u8 **pprog) ...@@ -313,7 +314,7 @@ static void emit_bpf_tail_call(u8 **pprog)
* goto out; * goto out;
*/ */
EMIT3(0x48, 0x85, 0xC0); /* test rax,rax */ EMIT3(0x48, 0x85, 0xC0); /* test rax,rax */
#define OFFSET3 10 #define OFFSET3 (8 + RETPOLINE_RAX_BPF_JIT_SIZE)
EMIT2(X86_JE, OFFSET3); /* je out */ EMIT2(X86_JE, OFFSET3); /* je out */
label3 = cnt; label3 = cnt;
...@@ -326,7 +327,7 @@ static void emit_bpf_tail_call(u8 **pprog) ...@@ -326,7 +327,7 @@ static void emit_bpf_tail_call(u8 **pprog)
* rdi == ctx (1st arg) * rdi == ctx (1st arg)
* rax == prog->bpf_func + prologue_size * rax == prog->bpf_func + prologue_size
*/ */
EMIT2(0xFF, 0xE0); /* jmp rax */ RETPOLINE_RAX_BPF_JIT();
/* out: */ /* out: */
BUILD_BUG_ON(cnt - label1 != OFFSET1); BUILD_BUG_ON(cnt - label1 != OFFSET1);
......
...@@ -26,8 +26,10 @@ static void bpf_array_free_percpu(struct bpf_array *array) ...@@ -26,8 +26,10 @@ static void bpf_array_free_percpu(struct bpf_array *array)
{ {
int i; int i;
for (i = 0; i < array->map.max_entries; i++) for (i = 0; i < array->map.max_entries; i++) {
free_percpu(array->pptrs[i]); free_percpu(array->pptrs[i]);
cond_resched();
}
} }
static int bpf_array_alloc_percpu(struct bpf_array *array) static int bpf_array_alloc_percpu(struct bpf_array *array)
...@@ -43,6 +45,7 @@ static int bpf_array_alloc_percpu(struct bpf_array *array) ...@@ -43,6 +45,7 @@ static int bpf_array_alloc_percpu(struct bpf_array *array)
return -ENOMEM; return -ENOMEM;
} }
array->pptrs[i] = ptr; array->pptrs[i] = ptr;
cond_resched();
} }
return 0; return 0;
......
...@@ -569,8 +569,7 @@ static void trie_free(struct bpf_map *map) ...@@ -569,8 +569,7 @@ static void trie_free(struct bpf_map *map)
slot = &trie->root; slot = &trie->root;
for (;;) { for (;;) {
node = rcu_dereference_protected(*slot, node = rcu_dereference_protected(*slot, 1);
lockdep_is_held(&trie->lock));
if (!node) if (!node)
goto out; goto out;
......
...@@ -3381,17 +3381,13 @@ BPF_CALL_2(bpf_sock_ops_cb_flags_set, struct bpf_sock_ops_kern *, bpf_sock, ...@@ -3381,17 +3381,13 @@ BPF_CALL_2(bpf_sock_ops_cb_flags_set, struct bpf_sock_ops_kern *, bpf_sock,
struct sock *sk = bpf_sock->sk; struct sock *sk = bpf_sock->sk;
int val = argval & BPF_SOCK_OPS_ALL_CB_FLAGS; int val = argval & BPF_SOCK_OPS_ALL_CB_FLAGS;
if (!sk_fullsock(sk)) if (!IS_ENABLED(CONFIG_INET) || !sk_fullsock(sk))
return -EINVAL; return -EINVAL;
#ifdef CONFIG_INET
if (val) if (val)
tcp_sk(sk)->bpf_sock_ops_cb_flags = val; tcp_sk(sk)->bpf_sock_ops_cb_flags = val;
return argval & (~BPF_SOCK_OPS_ALL_CB_FLAGS); return argval & (~BPF_SOCK_OPS_ALL_CB_FLAGS);
#else
return -EINVAL;
#endif
} }
static const struct bpf_func_proto bpf_sock_ops_cb_flags_set_proto = { static const struct bpf_func_proto bpf_sock_ops_cb_flags_set_proto = {
......
...@@ -11,3 +11,4 @@ test_progs ...@@ -11,3 +11,4 @@ test_progs
test_tcpbpf_user test_tcpbpf_user
test_verifier_log test_verifier_log
feature feature
test_libbpf_open
...@@ -126,6 +126,8 @@ static void test_hashmap_sizes(int task, void *data) ...@@ -126,6 +126,8 @@ static void test_hashmap_sizes(int task, void *data)
fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j, fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
2, map_flags); 2, map_flags);
if (fd < 0) { if (fd < 0) {
if (errno == ENOMEM)
return;
printf("Failed to create hashmap key=%d value=%d '%s'\n", printf("Failed to create hashmap key=%d value=%d '%s'\n",
i, j, strerror(errno)); i, j, strerror(errno));
exit(1); exit(1);
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/in6.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/tcp.h> #include <linux/tcp.h>
......
...@@ -2586,6 +2586,32 @@ static struct bpf_test tests[] = { ...@@ -2586,6 +2586,32 @@ static struct bpf_test tests[] = {
.result_unpriv = REJECT, .result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
}, },
{
"runtime/jit: pass negative index to tail_call",
.insns = {
BPF_MOV64_IMM(BPF_REG_3, -1),
BPF_LD_MAP_FD(BPF_REG_2, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_tail_call),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
.fixup_prog = { 1 },
.result = ACCEPT,
},
{
"runtime/jit: pass > 32bit index to tail_call",
.insns = {
BPF_LD_IMM64(BPF_REG_3, 0x100000000ULL),
BPF_LD_MAP_FD(BPF_REG_2, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_tail_call),
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
.fixup_prog = { 2 },
.result = ACCEPT,
},
{ {
"stack pointer arithmetic", "stack pointer arithmetic",
.insns = { .insns = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment