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

Daniel Borkmann says:

====================
pull-request: bpf 2020-04-10

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

We've added 13 non-merge commits during the last 7 day(s) which contain
a total of 13 files changed, 137 insertions(+), 43 deletions(-).

The main changes are:

1) JIT code emission fixes for riscv and arm32, from Luke Nelson and Xi Wang.

2) Disable vmlinux BTF info if GCC_PLUGIN_RANDSTRUCT is used, from Slava Bacherikov.

3) Fix oob write in AF_XDP when meta data is used, from Li RongQing.

4) Fix bpf_get_link_xdp_id() handling on single prog when flags are specified,
   from Andrey Ignatov.

5) Fix sk_assign() BPF helper for request sockets that can have sk_reuseport
   field uninitialized, from Joe Stringer.

6) Fix mprotect() test case for the BPF LSM, from KP Singh.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-04-09 17:39:22 -07:00
commit 40fc7ad2c8
13 changed files with 137 additions and 43 deletions

View File

@ -929,7 +929,11 @@ static inline void emit_a32_rsh_i64(const s8 dst[],
rd = arm_bpf_get_reg64(dst, tmp, ctx); rd = arm_bpf_get_reg64(dst, tmp, ctx);
/* Do LSR operation */ /* Do LSR operation */
if (val < 32) { if (val == 0) {
/* An immediate value of 0 encodes a shift amount of 32
* for LSR. To shift by 0, don't do anything.
*/
} else if (val < 32) {
emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx); emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx); emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx); emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx);
@ -955,7 +959,11 @@ static inline void emit_a32_arsh_i64(const s8 dst[],
rd = arm_bpf_get_reg64(dst, tmp, ctx); rd = arm_bpf_get_reg64(dst, tmp, ctx);
/* Do ARSH operation */ /* Do ARSH operation */
if (val < 32) { if (val == 0) {
/* An immediate value of 0 encodes a shift amount of 32
* for ASR. To shift by 0, don't do anything.
*/
} else if (val < 32) {
emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx); emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx); emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx); emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx);

View File

@ -55,7 +55,7 @@ config RISCV
select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_MMIOWB select ARCH_HAS_MMIOWB
select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VIRTUAL
select HAVE_EBPF_JIT select HAVE_EBPF_JIT if MMU
select EDAC_SUPPORT select EDAC_SUPPORT
select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_GIGANTIC_PAGE
select ARCH_WANT_HUGE_PMD_SHARE if 64BIT select ARCH_WANT_HUGE_PMD_SHARE if 64BIT

View File

@ -110,6 +110,16 @@ static bool is_32b_int(s64 val)
return -(1L << 31) <= val && val < (1L << 31); return -(1L << 31) <= val && val < (1L << 31);
} }
static bool in_auipc_jalr_range(s64 val)
{
/*
* auipc+jalr can reach any signed PC-relative offset in the range
* [-2^31 - 2^11, 2^31 - 2^11).
*/
return (-(1L << 31) - (1L << 11)) <= val &&
val < ((1L << 31) - (1L << 11));
}
static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx) static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx)
{ {
/* Note that the immediate from the add is sign-extended, /* Note that the immediate from the add is sign-extended,
@ -380,20 +390,24 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
*rd = RV_REG_T2; *rd = RV_REG_T2;
} }
static void emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr, static int emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
struct rv_jit_context *ctx) struct rv_jit_context *ctx)
{ {
s64 upper, lower; s64 upper, lower;
if (rvoff && is_21b_int(rvoff) && !force_jalr) { if (rvoff && is_21b_int(rvoff) && !force_jalr) {
emit(rv_jal(rd, rvoff >> 1), ctx); emit(rv_jal(rd, rvoff >> 1), ctx);
return; return 0;
} } else if (in_auipc_jalr_range(rvoff)) {
upper = (rvoff + (1 << 11)) >> 12; upper = (rvoff + (1 << 11)) >> 12;
lower = rvoff & 0xfff; lower = rvoff & 0xfff;
emit(rv_auipc(RV_REG_T1, upper), ctx); emit(rv_auipc(RV_REG_T1, upper), ctx);
emit(rv_jalr(rd, RV_REG_T1, lower), ctx); emit(rv_jalr(rd, RV_REG_T1, lower), ctx);
return 0;
}
pr_err("bpf-jit: target offset 0x%llx is out of range\n", rvoff);
return -ERANGE;
} }
static bool is_signed_bpf_cond(u8 cond) static bool is_signed_bpf_cond(u8 cond)
@ -407,18 +421,16 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
s64 off = 0; s64 off = 0;
u64 ip; u64 ip;
u8 rd; u8 rd;
int ret;
if (addr && ctx->insns) { if (addr && ctx->insns) {
ip = (u64)(long)(ctx->insns + ctx->ninsns); ip = (u64)(long)(ctx->insns + ctx->ninsns);
off = addr - ip; off = addr - ip;
if (!is_32b_int(off)) {
pr_err("bpf-jit: target call addr %pK is out of range\n",
(void *)addr);
return -ERANGE;
}
} }
emit_jump_and_link(RV_REG_RA, off, !fixed, ctx); ret = emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
if (ret)
return ret;
rd = bpf_to_rv_reg(BPF_REG_0, ctx); rd = bpf_to_rv_reg(BPF_REG_0, ctx);
emit(rv_addi(rd, RV_REG_A0, 0), ctx); emit(rv_addi(rd, RV_REG_A0, 0), ctx);
return 0; return 0;
@ -429,7 +441,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
{ {
bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 || bool is64 = BPF_CLASS(insn->code) == BPF_ALU64 ||
BPF_CLASS(insn->code) == BPF_JMP; BPF_CLASS(insn->code) == BPF_JMP;
int s, e, rvoff, i = insn - ctx->prog->insnsi; int s, e, rvoff, ret, i = insn - ctx->prog->insnsi;
struct bpf_prog_aux *aux = ctx->prog->aux; struct bpf_prog_aux *aux = ctx->prog->aux;
u8 rd = -1, rs = -1, code = insn->code; u8 rd = -1, rs = -1, code = insn->code;
s16 off = insn->off; s16 off = insn->off;
@ -699,7 +711,9 @@ out_be:
/* JUMP off */ /* JUMP off */
case BPF_JMP | BPF_JA: case BPF_JMP | BPF_JA:
rvoff = rv_offset(i, off, ctx); rvoff = rv_offset(i, off, ctx);
emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx); ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
if (ret)
return ret;
break; break;
/* IF (dst COND src) JUMP off */ /* IF (dst COND src) JUMP off */
@ -801,7 +815,6 @@ out_be:
case BPF_JMP | BPF_CALL: case BPF_JMP | BPF_CALL:
{ {
bool fixed; bool fixed;
int ret;
u64 addr; u64 addr;
mark_call(ctx); mark_call(ctx);
@ -826,7 +839,9 @@ out_be:
break; break;
rvoff = epilogue_offset(ctx); rvoff = epilogue_offset(ctx);
emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx); ret = emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
if (ret)
return ret;
break; break;
/* dst = imm64 */ /* dst = imm64 */

View File

@ -30,7 +30,7 @@ struct bpf_lru_node {
struct bpf_lru_list { struct bpf_lru_list {
struct list_head lists[NR_BPF_LRU_LIST_T]; struct list_head lists[NR_BPF_LRU_LIST_T];
unsigned int counts[NR_BPF_LRU_LIST_COUNT]; unsigned int counts[NR_BPF_LRU_LIST_COUNT];
/* The next inacitve list rotation starts from here */ /* The next inactive list rotation starts from here */
struct list_head *next_inactive_rotation; struct list_head *next_inactive_rotation;
raw_spinlock_t lock ____cacheline_aligned_in_smp; raw_spinlock_t lock ____cacheline_aligned_in_smp;

View File

@ -242,6 +242,8 @@ config DEBUG_INFO_DWARF4
config DEBUG_INFO_BTF config DEBUG_INFO_BTF
bool "Generate BTF typeinfo" bool "Generate BTF typeinfo"
depends on DEBUG_INFO depends on DEBUG_INFO
depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED
depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST
help help
Generate deduplicated BTF type information from DWARF debug info. Generate deduplicated BTF type information from DWARF debug info.
Turning this on expects presence of pahole tool, which will convert Turning this on expects presence of pahole tool, which will convert

View File

@ -5925,7 +5925,7 @@ BPF_CALL_3(bpf_sk_assign, struct sk_buff *, skb, struct sock *, sk, u64, flags)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (unlikely(dev_net(skb->dev) != sock_net(sk))) if (unlikely(dev_net(skb->dev) != sock_net(sk)))
return -ENETUNREACH; return -ENETUNREACH;
if (unlikely(sk->sk_reuseport)) if (unlikely(sk_fullsock(sk) && sk->sk_reuseport))
return -ESOCKTNOSUPPORT; return -ESOCKTNOSUPPORT;
if (sk_is_refcounted(sk) && if (sk_is_refcounted(sk) &&
unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))

View File

@ -1872,7 +1872,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
* as not suitable for copying when cloning. * as not suitable for copying when cloning.
*/ */
if (sk_user_data_is_nocopy(newsk)) if (sk_user_data_is_nocopy(newsk))
RCU_INIT_POINTER(newsk->sk_user_data, NULL); newsk->sk_user_data = NULL;
newsk->sk_err = 0; newsk->sk_err = 0;
newsk->sk_err_soft = 0; newsk->sk_err_soft = 0;

View File

@ -131,8 +131,9 @@ static void __xsk_rcv_memcpy(struct xdp_umem *umem, u64 addr, void *from_buf,
u64 page_start = addr & ~(PAGE_SIZE - 1); u64 page_start = addr & ~(PAGE_SIZE - 1);
u64 first_len = PAGE_SIZE - (addr - page_start); u64 first_len = PAGE_SIZE - (addr - page_start);
memcpy(to_buf, from_buf, first_len + metalen); memcpy(to_buf, from_buf, first_len);
memcpy(next_pg_addr, from_buf + first_len, len - first_len); memcpy(next_pg_addr, from_buf + first_len,
len + metalen - first_len);
return; return;
} }

View File

@ -142,7 +142,7 @@ static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
struct ifinfomsg ifinfo; struct ifinfomsg ifinfo;
char attrbuf[64]; char attrbuf[64];
} req; } req;
__u32 nl_pid; __u32 nl_pid = 0;
sock = libbpf_netlink_open(&nl_pid); sock = libbpf_netlink_open(&nl_pid);
if (sock < 0) if (sock < 0)
@ -288,7 +288,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
{ {
struct xdp_id_md xdp_id = {}; struct xdp_id_md xdp_id = {};
int sock, ret; int sock, ret;
__u32 nl_pid; __u32 nl_pid = 0;
__u32 mask; __u32 mask;
if (flags & ~XDP_FLAGS_MASK || !info_size) if (flags & ~XDP_FLAGS_MASK || !info_size)
@ -321,7 +321,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags) static __u32 get_xdp_id(struct xdp_link_info *info, __u32 flags)
{ {
if (info->attach_mode != XDP_ATTACHED_MULTI) if (info->attach_mode != XDP_ATTACHED_MULTI && !flags)
return info->prog_id; return info->prog_id;
if (flags & XDP_FLAGS_DRV_MODE) if (flags & XDP_FLAGS_DRV_MODE)
return info->drv_prog_id; return info->drv_prog_id;

View File

@ -15,7 +15,10 @@
char *CMD_ARGS[] = {"true", NULL}; char *CMD_ARGS[] = {"true", NULL};
int heap_mprotect(void) #define GET_PAGE_ADDR(ADDR, PAGE_SIZE) \
(char *)(((unsigned long) (ADDR + PAGE_SIZE)) & ~(PAGE_SIZE-1))
int stack_mprotect(void)
{ {
void *buf; void *buf;
long sz; long sz;
@ -25,12 +28,9 @@ int heap_mprotect(void)
if (sz < 0) if (sz < 0)
return sz; return sz;
buf = memalign(sz, 2 * sz); buf = alloca(sz * 3);
if (buf == NULL) ret = mprotect(GET_PAGE_ADDR(buf, sz), sz,
return -ENOMEM; PROT_READ | PROT_WRITE | PROT_EXEC);
ret = mprotect(buf, sz, PROT_READ | PROT_WRITE | PROT_EXEC);
free(buf);
return ret; return ret;
} }
@ -73,8 +73,8 @@ void test_test_lsm(void)
skel->bss->monitored_pid = getpid(); skel->bss->monitored_pid = getpid();
err = heap_mprotect(); err = stack_mprotect();
if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n", if (CHECK(errno != EPERM, "stack_mprotect", "want err=EPERM, got %d\n",
errno)) errno))
goto close_prog; goto close_prog;

View File

@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/if_link.h>
#include <test_progs.h>
#define IFINDEX_LO 1
void test_xdp_info(void)
{
__u32 len = sizeof(struct bpf_prog_info), duration = 0, prog_id;
const char *file = "./xdp_dummy.o";
struct bpf_prog_info info = {};
struct bpf_object *obj;
int err, prog_fd;
/* Get prog_id for XDP_ATTACHED_NONE mode */
err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, 0);
if (CHECK(err, "get_xdp_none", "errno=%d\n", errno))
return;
if (CHECK(prog_id, "prog_id_none", "unexpected prog_id=%u\n", prog_id))
return;
err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, XDP_FLAGS_SKB_MODE);
if (CHECK(err, "get_xdp_none_skb", "errno=%d\n", errno))
return;
if (CHECK(prog_id, "prog_id_none_skb", "unexpected prog_id=%u\n",
prog_id))
return;
/* Setup prog */
err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
if (CHECK_FAIL(err))
return;
err = bpf_obj_get_info_by_fd(prog_fd, &info, &len);
if (CHECK(err, "get_prog_info", "errno=%d\n", errno))
goto out_close;
err = bpf_set_link_xdp_fd(IFINDEX_LO, prog_fd, XDP_FLAGS_SKB_MODE);
if (CHECK(err, "set_xdp_skb", "errno=%d\n", errno))
goto out_close;
/* Get prog_id for single prog mode */
err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, 0);
if (CHECK(err, "get_xdp", "errno=%d\n", errno))
goto out;
if (CHECK(prog_id != info.id, "prog_id", "prog_id not available\n"))
goto out;
err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, XDP_FLAGS_SKB_MODE);
if (CHECK(err, "get_xdp_skb", "errno=%d\n", errno))
goto out;
if (CHECK(prog_id != info.id, "prog_id_skb", "prog_id not available\n"))
goto out;
err = bpf_get_link_xdp_id(IFINDEX_LO, &prog_id, XDP_FLAGS_DRV_MODE);
if (CHECK(err, "get_xdp_drv", "errno=%d\n", errno))
goto out;
if (CHECK(prog_id, "prog_id_drv", "unexpected prog_id=%u\n", prog_id))
goto out;
out:
bpf_set_link_xdp_fd(IFINDEX_LO, -1, 0);
out_close:
bpf_object__close(obj);
}

View File

@ -23,12 +23,12 @@ int BPF_PROG(test_int_hook, struct vm_area_struct *vma,
return ret; return ret;
__u32 pid = bpf_get_current_pid_tgid() >> 32; __u32 pid = bpf_get_current_pid_tgid() >> 32;
int is_heap = 0; int is_stack = 0;
is_heap = (vma->vm_start >= vma->vm_mm->start_brk && is_stack = (vma->vm_start <= vma->vm_mm->start_stack &&
vma->vm_end <= vma->vm_mm->brk); vma->vm_end >= vma->vm_mm->start_stack);
if (is_heap && monitored_pid == pid) { if (is_stack && monitored_pid == pid) {
mprotect_count++; mprotect_count++;
ret = -EPERM; ret = -EPERM;
} }

View File

@ -501,7 +501,7 @@
.result = REJECT .result = REJECT
}, },
{ {
"bounds check mixed 32bit and 64bit arithmatic. test1", "bounds check mixed 32bit and 64bit arithmetic. test1",
.insns = { .insns = {
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_MOV64_IMM(BPF_REG_1, -1), BPF_MOV64_IMM(BPF_REG_1, -1),
@ -520,7 +520,7 @@
.result = ACCEPT .result = ACCEPT
}, },
{ {
"bounds check mixed 32bit and 64bit arithmatic. test2", "bounds check mixed 32bit and 64bit arithmetic. test2",
.insns = { .insns = {
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_MOV64_IMM(BPF_REG_1, -1), BPF_MOV64_IMM(BPF_REG_1, -1),