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

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

Daniel Borkmann says:

====================
pull-request: bpf 2018-07-20

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

The main changes are:

1) Fix in BPF Makefile to detect llvm-objcopy in a more robust way which is
   needed for pahole's BTF converter and minor UAPI tweaks in BTF_INT_BITS()
   to shrink the mask before eventual UAPI freeze, from Martin.

2) Fix a segfault in bpftool when prog pin id has no further arguments such
   as id value or file specified, from Taeung.

3) Fix powerpc JIT handling of XADD which has jumps to exit path that would
   potentially bypass verifier expectations e.g. with subprog calls. Also add
   a test case to make sure XADD is not mangling src/dst register, from Daniel.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fcf4793e 7c3e8b64
...@@ -286,6 +286,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, ...@@ -286,6 +286,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
u64 imm64; u64 imm64;
u8 *func; u8 *func;
u32 true_cond; u32 true_cond;
u32 tmp_idx;
/* /*
* addrs[] maps a BPF bytecode address into a real offset from * addrs[] maps a BPF bytecode address into a real offset from
...@@ -637,11 +638,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, ...@@ -637,11 +638,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
case BPF_STX | BPF_XADD | BPF_W: case BPF_STX | BPF_XADD | BPF_W:
/* Get EA into TMP_REG_1 */ /* Get EA into TMP_REG_1 */
PPC_ADDI(b2p[TMP_REG_1], dst_reg, off); PPC_ADDI(b2p[TMP_REG_1], dst_reg, off);
/* error if EA is not word-aligned */ tmp_idx = ctx->idx * 4;
PPC_ANDI(b2p[TMP_REG_2], b2p[TMP_REG_1], 0x03);
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + 12);
PPC_LI(b2p[BPF_REG_0], 0);
PPC_JMP(exit_addr);
/* load value from memory into TMP_REG_2 */ /* load value from memory into TMP_REG_2 */
PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0); PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
/* add value from src_reg into this */ /* add value from src_reg into this */
...@@ -649,32 +646,16 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, ...@@ -649,32 +646,16 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
/* store result back */ /* store result back */
PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]); PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
/* we're done if this succeeded */ /* we're done if this succeeded */
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (7*4)); PPC_BCC_SHORT(COND_NE, tmp_idx);
/* otherwise, let's try once more */
PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg);
PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
/* exit if the store was not successful */
PPC_LI(b2p[BPF_REG_0], 0);
PPC_BCC(COND_NE, exit_addr);
break; break;
/* *(u64 *)(dst + off) += src */ /* *(u64 *)(dst + off) += src */
case BPF_STX | BPF_XADD | BPF_DW: case BPF_STX | BPF_XADD | BPF_DW:
PPC_ADDI(b2p[TMP_REG_1], dst_reg, off); PPC_ADDI(b2p[TMP_REG_1], dst_reg, off);
/* error if EA is not doubleword-aligned */ tmp_idx = ctx->idx * 4;
PPC_ANDI(b2p[TMP_REG_2], b2p[TMP_REG_1], 0x07);
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (3*4));
PPC_LI(b2p[BPF_REG_0], 0);
PPC_JMP(exit_addr);
PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg);
PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (7*4));
PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0); PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg); PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg);
PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]); PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
PPC_LI(b2p[BPF_REG_0], 0); PPC_BCC_SHORT(COND_NE, tmp_idx);
PPC_BCC(COND_NE, exit_addr);
break; break;
/* /*
......
...@@ -76,7 +76,7 @@ struct btf_type { ...@@ -76,7 +76,7 @@ struct btf_type {
*/ */
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) #define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff) #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
/* Attributes stored in the BTF_INT_ENCODING */ /* Attributes stored in the BTF_INT_ENCODING */
#define BTF_INT_SIGNED (1 << 0) #define BTF_INT_SIGNED (1 << 0)
......
...@@ -450,7 +450,7 @@ static const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id) ...@@ -450,7 +450,7 @@ static const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
*/ */
static bool btf_type_int_is_regular(const struct btf_type *t) static bool btf_type_int_is_regular(const struct btf_type *t)
{ {
u16 nr_bits, nr_bytes; u8 nr_bits, nr_bytes;
u32 int_data; u32 int_data;
int_data = btf_type_int(t); int_data = btf_type_int(t);
...@@ -993,12 +993,16 @@ static void btf_int_bits_seq_show(const struct btf *btf, ...@@ -993,12 +993,16 @@ static void btf_int_bits_seq_show(const struct btf *btf,
{ {
u16 left_shift_bits, right_shift_bits; u16 left_shift_bits, right_shift_bits;
u32 int_data = btf_type_int(t); u32 int_data = btf_type_int(t);
u16 nr_bits = BTF_INT_BITS(int_data); u8 nr_bits = BTF_INT_BITS(int_data);
u16 total_bits_offset; u8 total_bits_offset;
u16 nr_copy_bytes; u8 nr_copy_bytes;
u16 nr_copy_bits; u8 nr_copy_bits;
u64 print_num; u64 print_num;
/*
* bits_offset is at most 7.
* BTF_INT_OFFSET() cannot exceed 64 bits.
*/
total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data); total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data);
data += BITS_ROUNDDOWN_BYTES(total_bits_offset); data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
bits_offset = BITS_PER_BYTE_MASKED(total_bits_offset); bits_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
...@@ -1028,7 +1032,7 @@ static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t, ...@@ -1028,7 +1032,7 @@ static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t,
u32 int_data = btf_type_int(t); u32 int_data = btf_type_int(t);
u8 encoding = BTF_INT_ENCODING(int_data); u8 encoding = BTF_INT_ENCODING(int_data);
bool sign = encoding & BTF_INT_SIGNED; bool sign = encoding & BTF_INT_SIGNED;
u32 nr_bits = BTF_INT_BITS(int_data); u8 nr_bits = BTF_INT_BITS(int_data);
if (bits_offset || BTF_INT_OFFSET(int_data) || if (bits_offset || BTF_INT_OFFSET(int_data) ||
BITS_PER_BYTE_MASKED(nr_bits)) { BITS_PER_BYTE_MASKED(nr_bits)) {
......
...@@ -217,6 +217,14 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)) ...@@ -217,6 +217,14 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
int err; int err;
int fd; int fd;
if (argc < 3) {
p_err("too few arguments, id ID and FILE path is required");
return -1;
} else if (argc > 3) {
p_err("too many arguments");
return -1;
}
if (!is_prefix(*argv, "id")) { if (!is_prefix(*argv, "id")) {
p_err("expected 'id' got %s", *argv); p_err("expected 'id' got %s", *argv);
return -1; return -1;
...@@ -230,9 +238,6 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)) ...@@ -230,9 +238,6 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
} }
NEXT_ARG(); NEXT_ARG();
if (argc != 1)
usage();
fd = get_fd_by_id(id); fd = get_fd_by_id(id);
if (fd < 0) { if (fd < 0) {
p_err("can't get prog by id (%u): %s", id, strerror(errno)); p_err("can't get prog by id (%u): %s", id, strerror(errno));
......
...@@ -105,7 +105,7 @@ $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline ...@@ -105,7 +105,7 @@ $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris)
BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF)
BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --version 2>&1 | grep LLVM) BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm')
ifneq ($(BTF_LLC_PROBE),) ifneq ($(BTF_LLC_PROBE),)
ifneq ($(BTF_PAHOLE_PROBE),) ifneq ($(BTF_PAHOLE_PROBE),)
......
...@@ -12004,6 +12004,46 @@ static struct bpf_test tests[] = { ...@@ -12004,6 +12004,46 @@ static struct bpf_test tests[] = {
.errstr = "BPF_XADD stores into R2 packet", .errstr = "BPF_XADD stores into R2 packet",
.prog_type = BPF_PROG_TYPE_XDP, .prog_type = BPF_PROG_TYPE_XDP,
}, },
{
"xadd/w check whether src/dst got mangled, 1",
.insns = {
BPF_MOV64_IMM(BPF_REG_0, 1),
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
BPF_JMP_REG(BPF_JNE, BPF_REG_6, BPF_REG_0, 3),
BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_10, 2),
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
BPF_EXIT_INSN(),
BPF_MOV64_IMM(BPF_REG_0, 42),
BPF_EXIT_INSN(),
},
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.retval = 3,
},
{
"xadd/w check whether src/dst got mangled, 2",
.insns = {
BPF_MOV64_IMM(BPF_REG_0, 1),
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8),
BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -8),
BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -8),
BPF_JMP_REG(BPF_JNE, BPF_REG_6, BPF_REG_0, 3),
BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_10, 2),
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8),
BPF_EXIT_INSN(),
BPF_MOV64_IMM(BPF_REG_0, 42),
BPF_EXIT_INSN(),
},
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
.retval = 3,
},
{ {
"bpf_get_stack return R0 within range", "bpf_get_stack return R0 within range",
.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