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

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

Merge branch 'bpf-misc-helper-verifier-improvements'



Daniel Borkmann says:

====================
Misc BPF helper/verifier improvements

Miscellanous improvements I still had in my queue, it adds a new
bpf_skb_adjust_room() helper for cls_bpf, exports to fdinfo whether
tail call array owner is JITed, so iproute2 error reporting can be
improved on that regard, a small cleanup and extension to trace
printk, two verifier patches, one to make the code around narrower
ctx access a bit more straight forward and one to allow for imm += x
operations, that we've seen LLVM generating and the verifier currently
rejecting. We've included the patch 6 given it's rather small and
we ran into it from LLVM side, it would be great if it could be
queued for stable as well after the merge window. Last but not least,
test cases are added also related to imm alu improvement.

Thanks a lot!
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a68491f8 6d191ed4
Loading
Loading
Loading
Loading
+7 −2
Original line number Original line Diff line number Diff line
@@ -156,9 +156,14 @@ struct bpf_prog;
struct bpf_insn_access_aux {
struct bpf_insn_access_aux {
	enum bpf_reg_type reg_type;
	enum bpf_reg_type reg_type;
	int ctx_field_size;
	int ctx_field_size;
	int converted_op_size;
};
};


static inline void
bpf_ctx_record_field_size(struct bpf_insn_access_aux *aux, u32 size)
{
	aux->ctx_field_size = size;
}

struct bpf_verifier_ops {
struct bpf_verifier_ops {
	/* return eBPF function prototype for verification */
	/* return eBPF function prototype for verification */
	const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id func_id);
	const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id func_id);
@@ -173,7 +178,7 @@ struct bpf_verifier_ops {
	u32 (*convert_ctx_access)(enum bpf_access_type type,
	u32 (*convert_ctx_access)(enum bpf_access_type type,
				  const struct bpf_insn *src,
				  const struct bpf_insn *src,
				  struct bpf_insn *dst,
				  struct bpf_insn *dst,
				  struct bpf_prog *prog);
				  struct bpf_prog *prog, u32 *target_size);
	int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
	int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
			union bpf_attr __user *uattr);
			union bpf_attr __user *uattr);
};
};
+47 −0
Original line number Original line Diff line number Diff line
@@ -337,6 +337,22 @@ struct bpf_prog_aux;
	bpf_size;						\
	bpf_size;						\
})
})


#define bpf_size_to_bytes(bpf_size)				\
({								\
	int bytes = -EINVAL;					\
								\
	if (bpf_size == BPF_B)					\
		bytes = sizeof(u8);				\
	else if (bpf_size == BPF_H)				\
		bytes = sizeof(u16);				\
	else if (bpf_size == BPF_W)				\
		bytes = sizeof(u32);				\
	else if (bpf_size == BPF_DW)				\
		bytes = sizeof(u64);				\
								\
	bytes;							\
})

#define BPF_SIZEOF(type)					\
#define BPF_SIZEOF(type)					\
	({							\
	({							\
		const int __size = bytes_to_bpf_size(sizeof(type)); \
		const int __size = bytes_to_bpf_size(sizeof(type)); \
@@ -351,6 +367,13 @@ struct bpf_prog_aux;
		__size;						\
		__size;						\
	})
	})


#define BPF_LDST_BYTES(insn)					\
	({							\
		const int __size = bpf_size_to_bytes(BPF_SIZE(insn->code)); \
		WARN_ON(__size < 0);				\
		__size;						\
	})

#define __BPF_MAP_0(m, v, ...) v
#define __BPF_MAP_0(m, v, ...) v
#define __BPF_MAP_1(m, v, t, a, ...) m(t, a)
#define __BPF_MAP_1(m, v, t, a, ...) m(t, a)
#define __BPF_MAP_2(m, v, t, a, ...) m(t, a), __BPF_MAP_1(m, v, __VA_ARGS__)
#define __BPF_MAP_2(m, v, t, a, ...) m(t, a), __BPF_MAP_1(m, v, __VA_ARGS__)
@@ -401,6 +424,18 @@ struct bpf_prog_aux;
#define BPF_CALL_4(name, ...)	BPF_CALL_x(4, name, __VA_ARGS__)
#define BPF_CALL_4(name, ...)	BPF_CALL_x(4, name, __VA_ARGS__)
#define BPF_CALL_5(name, ...)	BPF_CALL_x(5, name, __VA_ARGS__)
#define BPF_CALL_5(name, ...)	BPF_CALL_x(5, name, __VA_ARGS__)


#define bpf_ctx_range(TYPE, MEMBER)						\
	offsetof(TYPE, MEMBER) ... offsetofend(TYPE, MEMBER) - 1
#define bpf_ctx_range_till(TYPE, MEMBER1, MEMBER2)				\
	offsetof(TYPE, MEMBER1) ... offsetofend(TYPE, MEMBER2) - 1

#define bpf_target_off(TYPE, MEMBER, SIZE, PTR_SIZE)				\
	({									\
		BUILD_BUG_ON(FIELD_SIZEOF(TYPE, MEMBER) != (SIZE));		\
		*(PTR_SIZE) = (SIZE);						\
		offsetof(TYPE, MEMBER);						\
	})

#ifdef CONFIG_COMPAT
#ifdef CONFIG_COMPAT
/* A struct sock_filter is architecture independent. */
/* A struct sock_filter is architecture independent. */
struct compat_sock_fprog {
struct compat_sock_fprog {
@@ -564,6 +599,18 @@ static inline bool bpf_prog_was_classic(const struct bpf_prog *prog)
	return prog->type == BPF_PROG_TYPE_UNSPEC;
	return prog->type == BPF_PROG_TYPE_UNSPEC;
}
}


static inline bool
bpf_ctx_narrow_access_ok(u32 off, u32 size, const u32 size_default)
{
	bool off_ok;
#ifdef __LITTLE_ENDIAN
	off_ok = (off & (size_default - 1)) == 0;
#else
	off_ok = (off & (size_default - 1)) + size == size_default;
#endif
	return off_ok && size <= size_default && (size & (size - 1)) == 0;
}

#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))


#ifdef CONFIG_ARCH_HAS_SET_MEMORY
#ifdef CONFIG_ARCH_HAS_SET_MEMORY
+5 −0
Original line number Original line Diff line number Diff line
@@ -2206,6 +2206,11 @@ static inline int skb_mac_offset(const struct sk_buff *skb)
	return skb_mac_header(skb) - skb->data;
	return skb_mac_header(skb) - skb->data;
}
}


static inline u32 skb_mac_header_len(const struct sk_buff *skb)
{
	return skb->network_header - skb->mac_header;
}

static inline int skb_mac_header_was_set(const struct sk_buff *skb)
static inline int skb_mac_header_was_set(const struct sk_buff *skb)
{
{
	return skb->mac_header != (typeof(skb->mac_header))~0U;
	return skb->mac_header != (typeof(skb->mac_header))~0U;
+15 −1
Original line number Original line Diff line number Diff line
@@ -531,6 +531,14 @@ union bpf_attr {
 *     @optval: pointer to option value
 *     @optval: pointer to option value
 *     @optlen: length of optval in byes
 *     @optlen: length of optval in byes
 *     Return: 0 or negative error
 *     Return: 0 or negative error
 *
 * int bpf_skb_adjust_room(skb, len_diff, mode, flags)
 *     Grow or shrink room in sk_buff.
 *     @skb: pointer to skb
 *     @len_diff: (signed) amount of room to grow/shrink
 *     @mode: operation mode (enum bpf_adj_room_mode)
 *     @flags: reserved for future use
 *     Return: 0 on success or negative error code
 */
 */
#define __BPF_FUNC_MAPPER(FN)		\
#define __BPF_FUNC_MAPPER(FN)		\
	FN(unspec),			\
	FN(unspec),			\
@@ -582,7 +590,8 @@ union bpf_attr {
	FN(get_socket_cookie),		\
	FN(get_socket_cookie),		\
	FN(get_socket_uid),		\
	FN(get_socket_uid),		\
	FN(set_hash),			\
	FN(set_hash),			\
	FN(setsockopt),
	FN(setsockopt),			\
	FN(skb_adjust_room),


/* integer value in 'imm' field of BPF_CALL instruction selects which helper
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
 * function eBPF program intends to call
 * function eBPF program intends to call
@@ -632,6 +641,11 @@ enum bpf_func_id {
/* BPF_FUNC_perf_event_output for sk_buff input context. */
/* BPF_FUNC_perf_event_output for sk_buff input context. */
#define BPF_F_CTXLEN_MASK		(0xfffffULL << 32)
#define BPF_F_CTXLEN_MASK		(0xfffffULL << 32)


/* Mode for BPF_FUNC_skb_adjust_room helper. */
enum bpf_adj_room_mode {
	BPF_ADJ_ROOM_NET,
};

/* user accessible mirror of in-kernel sk_buff.
/* user accessible mirror of in-kernel sk_buff.
 * new fields can only be added to the end of this structure
 * new fields can only be added to the end of this structure
 */
 */
+6 −1
Original line number Original line Diff line number Diff line
@@ -216,10 +216,12 @@ static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
	const struct bpf_map *map = filp->private_data;
	const struct bpf_map *map = filp->private_data;
	const struct bpf_array *array;
	const struct bpf_array *array;
	u32 owner_prog_type = 0;
	u32 owner_prog_type = 0;
	u32 owner_jited = 0;


	if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
	if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
		array = container_of(map, struct bpf_array, map);
		array = container_of(map, struct bpf_array, map);
		owner_prog_type = array->owner_prog_type;
		owner_prog_type = array->owner_prog_type;
		owner_jited = array->owner_jited;
	}
	}


	seq_printf(m,
	seq_printf(m,
@@ -236,9 +238,12 @@ static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
		   map->map_flags,
		   map->map_flags,
		   map->pages * 1ULL << PAGE_SHIFT);
		   map->pages * 1ULL << PAGE_SHIFT);


	if (owner_prog_type)
	if (owner_prog_type) {
		seq_printf(m, "owner_prog_type:\t%u\n",
		seq_printf(m, "owner_prog_type:\t%u\n",
			   owner_prog_type);
			   owner_prog_type);
		seq_printf(m, "owner_jited:\t%u\n",
			   owner_jited);
	}
}
}
#endif
#endif


Loading