Commit 78b87711 authored by David S. Miller's avatar David S. Miller
Browse files


Daniel Borkmann says:

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

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

We've added 10 non-merge commits during the last 3 day(s) which contain
a total of 11 files changed, 238 insertions(+), 95 deletions(-).

The main changes are:

1) Fix offset overflow for BPF_MEM BPF_DW insn mapping on arm32 JIT,
   from Luke Nelson and Xi Wang.

2) Prevent mprotect() to make frozen & mmap()'ed BPF map writeable
   again, from Andrii Nakryiko and Jann Horn.

3) Fix type of old_fd in bpf_xdp_set_link_opts to int in libbpf and add
   selftests, from Toke Høiland-Jørgensen.

4) Fix AF_XDP to check that headroom cannot be larger than the available
   space in the chunk, from Magnus Karlsson.

5) Fix reset of XDP prog when expected_fd is set, from David Ahern.

6) Fix a segfault in bpftool's struct_ops command when BTF is not
   available, from Daniel T. Lee.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6058ee09 c6c11152
Loading
Loading
Loading
Loading
+24 −16
Original line number Diff line number Diff line
@@ -1000,21 +1000,35 @@ static inline void emit_a32_mul_r64(const s8 dst[], const s8 src[],
	arm_bpf_put_reg32(dst_hi, rd[0], ctx);
}

static bool is_ldst_imm(s16 off, const u8 size)
{
	s16 off_max = 0;

	switch (size) {
	case BPF_B:
	case BPF_W:
		off_max = 0xfff;
		break;
	case BPF_H:
		off_max = 0xff;
		break;
	case BPF_DW:
		/* Need to make sure off+4 does not overflow. */
		off_max = 0xfff - 4;
		break;
	}
	return -off_max <= off && off <= off_max;
}

/* *(size *)(dst + off) = src */
static inline void emit_str_r(const s8 dst, const s8 src[],
			      s32 off, struct jit_ctx *ctx, const u8 sz){
			      s16 off, struct jit_ctx *ctx, const u8 sz){
	const s8 *tmp = bpf2a32[TMP_REG_1];
	s32 off_max;
	s8 rd;

	rd = arm_bpf_get_reg32(dst, tmp[1], ctx);

	if (sz == BPF_H)
		off_max = 0xff;
	else
		off_max = 0xfff;

	if (off < 0 || off > off_max) {
	if (!is_ldst_imm(off, sz)) {
		emit_a32_mov_i(tmp[0], off, ctx);
		emit(ARM_ADD_R(tmp[0], tmp[0], rd), ctx);
		rd = tmp[0];
@@ -1043,18 +1057,12 @@ static inline void emit_str_r(const s8 dst, const s8 src[],

/* dst = *(size*)(src + off) */
static inline void emit_ldx_r(const s8 dst[], const s8 src,
			      s32 off, struct jit_ctx *ctx, const u8 sz){
			      s16 off, struct jit_ctx *ctx, const u8 sz){
	const s8 *tmp = bpf2a32[TMP_REG_1];
	const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
	s8 rm = src;
	s32 off_max;

	if (sz == BPF_H)
		off_max = 0xff;
	else
		off_max = 0xfff;

	if (off < 0 || off > off_max) {
	if (!is_ldst_imm(off, sz)) {
		emit_a32_mov_i(tmp[0], off, ctx);
		emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
		rm = tmp[0];
+7 −9
Original line number Diff line number Diff line
@@ -586,9 +586,7 @@ static void bpf_map_mmap_open(struct vm_area_struct *vma)
{
	struct bpf_map *map = vma->vm_file->private_data;

	bpf_map_inc_with_uref(map);

	if (vma->vm_flags & VM_WRITE) {
	if (vma->vm_flags & VM_MAYWRITE) {
		mutex_lock(&map->freeze_mutex);
		map->writecnt++;
		mutex_unlock(&map->freeze_mutex);
@@ -600,13 +598,11 @@ static void bpf_map_mmap_close(struct vm_area_struct *vma)
{
	struct bpf_map *map = vma->vm_file->private_data;

	if (vma->vm_flags & VM_WRITE) {
	if (vma->vm_flags & VM_MAYWRITE) {
		mutex_lock(&map->freeze_mutex);
		map->writecnt--;
		mutex_unlock(&map->freeze_mutex);
	}

	bpf_map_put_with_uref(map);
}

static const struct vm_operations_struct bpf_map_default_vmops = {
@@ -635,14 +631,16 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
	/* set default open/close callbacks */
	vma->vm_ops = &bpf_map_default_vmops;
	vma->vm_private_data = map;
	vma->vm_flags &= ~VM_MAYEXEC;
	if (!(vma->vm_flags & VM_WRITE))
		/* disallow re-mapping with PROT_WRITE */
		vma->vm_flags &= ~VM_MAYWRITE;

	err = map->ops->map_mmap(map, vma);
	if (err)
		goto out;

	bpf_map_inc_with_uref(map);

	if (vma->vm_flags & VM_WRITE)
	if (vma->vm_flags & VM_MAYWRITE)
		map->writecnt++;
out:
	mutex_unlock(&map->freeze_mutex);
+1 −2
Original line number Diff line number Diff line
@@ -1255,8 +1255,7 @@ static void __mark_reg_unknown(const struct bpf_verifier_env *env,
	reg->type = SCALAR_VALUE;
	reg->var_off = tnum_unknown;
	reg->frameno = 0;
	reg->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks ?
		       true : false;
	reg->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks;
	__mark_reg_unbounded(reg);
}

+2 −1
Original line number Diff line number Diff line
@@ -8667,8 +8667,8 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
	const struct net_device_ops *ops = dev->netdev_ops;
	enum bpf_netdev_command query;
	u32 prog_id, expected_id = 0;
	struct bpf_prog *prog = NULL;
	bpf_op_t bpf_op, bpf_chk;
	struct bpf_prog *prog;
	bool offload;
	int err;

@@ -8734,6 +8734,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
	} else {
		if (!prog_id)
			return 0;
		prog = NULL;
	}

	err = dev_xdp_install(dev, bpf_op, extack, flags, prog);
+2 −3
Original line number Diff line number Diff line
@@ -343,7 +343,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
	u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
	unsigned int chunks, chunks_per_page;
	u64 addr = mr->addr, size = mr->len;
	int size_chk, err;
	int err;

	if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
		/* Strictly speaking we could support this, if:
@@ -382,8 +382,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
			return -EINVAL;
	}

	size_chk = chunk_size - headroom - XDP_PACKET_HEADROOM;
	if (size_chk < 0)
	if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
		return -EINVAL;

	umem->address = (unsigned long)addr;
Loading