Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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


Daniel Borkmann says:

====================
pull-request: bpf 2018-06-08

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

The main changes are:

1) Fix in the BPF verifier to reject modified ctx pointers on helper
   functions, from Daniel.

2) Fix in BPF kselftests for get_cgroup_id_user() helper to only
   record the cgroup id for a provided pid in order to reduce test
   failures from processes interferring with the test, from Yonghong.

3) Fix a crash in AF_XDP's mem accounting when the process owning
   the sock has CAP_IPC_LOCK capabilities set, from Daniel.

4) Fix an issue for AF_XDP on 32 bit machines where XDP_UMEM_PGOFF_*_RING
   defines need ULL suffixes and use loff_t type as they are otherwise
   truncated, from Geert.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8d97ca6b c09290c5
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -63,8 +63,8 @@ struct xdp_statistics {
/* Pgoff for mmaping the rings */
#define XDP_PGOFF_RX_RING			  0
#define XDP_PGOFF_TX_RING		 0x80000000
#define XDP_UMEM_PGOFF_FILL_RING	0x100000000
#define XDP_UMEM_PGOFF_COMPLETION_RING	0x180000000
#define XDP_UMEM_PGOFF_FILL_RING	0x100000000ULL
#define XDP_UMEM_PGOFF_COMPLETION_RING	0x180000000ULL

/* Rx/Tx descriptor */
struct xdp_desc {
+31 −17
Original line number Diff line number Diff line
@@ -1617,6 +1617,30 @@ static int get_callee_stack_depth(struct bpf_verifier_env *env,
}
#endif

static int check_ctx_reg(struct bpf_verifier_env *env,
			 const struct bpf_reg_state *reg, int regno)
{
	/* Access to ctx or passing it to a helper is only allowed in
	 * its original, unmodified form.
	 */

	if (reg->off) {
		verbose(env, "dereference of modified ctx ptr R%d off=%d disallowed\n",
			regno, reg->off);
		return -EACCES;
	}

	if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
		char tn_buf[48];

		tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
		verbose(env, "variable ctx access var_off=%s disallowed\n", tn_buf);
		return -EACCES;
	}

	return 0;
}

/* truncate register to smaller size (in bytes)
 * must be called with size < BPF_REG_SIZE
 */
@@ -1686,24 +1710,11 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
			verbose(env, "R%d leaks addr into ctx\n", value_regno);
			return -EACCES;
		}
		/* ctx accesses must be at a fixed offset, so that we can
		 * determine what type of data were returned.
		 */
		if (reg->off) {
			verbose(env,
				"dereference of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
				regno, reg->off, off - reg->off);
			return -EACCES;
		}
		if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
			char tn_buf[48];

			tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
			verbose(env,
				"variable ctx access var_off=%s off=%d size=%d",
				tn_buf, off, size);
			return -EACCES;
		}
		err = check_ctx_reg(env, reg, regno);
		if (err < 0)
			return err;

		err = check_ctx_access(env, insn_idx, off, size, t, &reg_type);
		if (!err && t == BPF_READ && value_regno >= 0) {
			/* ctx access returns either a scalar, or a
@@ -1984,6 +1995,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
		expected_type = PTR_TO_CTX;
		if (type != expected_type)
			goto err_type;
		err = check_ctx_reg(env, reg, regno);
		if (err < 0)
			return err;
	} else if (arg_type_is_mem_ptr(arg_type)) {
		expected_type = PTR_TO_STACK;
		/* One exception here. In case function allows for NULL to be
+4 −2
Original line number Diff line number Diff line
@@ -132,9 +132,11 @@ static void xdp_umem_unpin_pages(struct xdp_umem *umem)

static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
{
	if (umem->user) {
		atomic_long_sub(umem->npgs, &umem->user->locked_vm);
		free_uid(umem->user);
	}
}

static void xdp_umem_release(struct xdp_umem *umem)
{
+1 −1
Original line number Diff line number Diff line
@@ -643,7 +643,7 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname,
static int xsk_mmap(struct file *file, struct socket *sock,
		    struct vm_area_struct *vma)
{
	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
	loff_t offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
	unsigned long size = vma->vm_end - vma->vm_start;
	struct xdp_sock *xs = xdp_sk(sock->sk);
	struct xsk_queue *q = NULL;
+13 −1
Original line number Diff line number Diff line
@@ -11,12 +11,24 @@ struct bpf_map_def SEC("maps") cg_ids = {
	.max_entries = 1,
};

struct bpf_map_def SEC("maps") pidmap = {
	.type = BPF_MAP_TYPE_ARRAY,
	.key_size = sizeof(__u32),
	.value_size = sizeof(__u32),
	.max_entries = 1,
};

SEC("tracepoint/syscalls/sys_enter_nanosleep")
int trace(void *ctx)
{
	__u32 key = 0;
	__u32 pid = bpf_get_current_pid_tgid();
	__u32 key = 0, *expected_pid;
	__u64 *val;

	expected_pid = bpf_map_lookup_elem(&pidmap, &key);
	if (!expected_pid || *expected_pid != pid)
		return 0;

	val = bpf_map_lookup_elem(&cg_ids, &key);
	if (val)
		*val = bpf_get_current_cgroup_id();
Loading