Commit a4f5759b authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Martin KaFai Lau says:

====================
pull-request: bpf-next 2025-07-24

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

The main changes are:

1) Improved verifier error message for incorrect narrower load from
   pointer field in ctx, from Paul Chaignon.

2) Disabled migration in nf_hook_run_bpf to address a syzbot report,
   from Kuniyuki Iwashima.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next:
  selftests/bpf: Test invalid narrower ctx load
  bpf: Reject narrower access to pointer ctx fields
  bpf: Disable migration in nf_hook_run_bpf().
====================

Link: https://patch.msgid.link/20250724173306.3578483-1-martin.lau@linux.dev


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7dba0cc9 ba578b87
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -2440,22 +2440,22 @@ static bool cg_sockopt_is_valid_access(int off, int size,
	}

	switch (off) {
	case offsetof(struct bpf_sockopt, sk):
	case bpf_ctx_range_ptr(struct bpf_sockopt, sk):
		if (size != sizeof(__u64))
			return false;
		info->reg_type = PTR_TO_SOCKET;
		break;
	case offsetof(struct bpf_sockopt, optval):
	case bpf_ctx_range_ptr(struct bpf_sockopt, optval):
		if (size != sizeof(__u64))
			return false;
		info->reg_type = PTR_TO_PACKET;
		break;
	case offsetof(struct bpf_sockopt, optval_end):
	case bpf_ctx_range_ptr(struct bpf_sockopt, optval_end):
		if (size != sizeof(__u64))
			return false;
		info->reg_type = PTR_TO_PACKET_END;
		break;
	case offsetof(struct bpf_sockopt, retval):
	case bpf_ctx_range(struct bpf_sockopt, retval):
		if (size != size_default)
			return false;
		return prog->expected_attach_type == BPF_CGROUP_GETSOCKOPT;
+10 −10
Original line number Diff line number Diff line
@@ -8699,7 +8699,7 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
		if (size != sizeof(__u64))
			return false;
		break;
	case offsetof(struct __sk_buff, sk):
	case bpf_ctx_range_ptr(struct __sk_buff, sk):
		if (type == BPF_WRITE || size != sizeof(__u64))
			return false;
		info->reg_type = PTR_TO_SOCK_COMMON_OR_NULL;
@@ -9277,7 +9277,7 @@ static bool sock_addr_is_valid_access(int off, int size,
				return false;
		}
		break;
	case offsetof(struct bpf_sock_addr, sk):
	case bpf_ctx_range_ptr(struct bpf_sock_addr, sk):
		if (type != BPF_READ)
			return false;
		if (size != sizeof(__u64))
@@ -9327,17 +9327,17 @@ static bool sock_ops_is_valid_access(int off, int size,
			if (size != sizeof(__u64))
				return false;
			break;
		case offsetof(struct bpf_sock_ops, sk):
		case bpf_ctx_range_ptr(struct bpf_sock_ops, sk):
			if (size != sizeof(__u64))
				return false;
			info->reg_type = PTR_TO_SOCKET_OR_NULL;
			break;
		case offsetof(struct bpf_sock_ops, skb_data):
		case bpf_ctx_range_ptr(struct bpf_sock_ops, skb_data):
			if (size != sizeof(__u64))
				return false;
			info->reg_type = PTR_TO_PACKET;
			break;
		case offsetof(struct bpf_sock_ops, skb_data_end):
		case bpf_ctx_range_ptr(struct bpf_sock_ops, skb_data_end):
			if (size != sizeof(__u64))
				return false;
			info->reg_type = PTR_TO_PACKET_END;
@@ -9346,7 +9346,7 @@ static bool sock_ops_is_valid_access(int off, int size,
			bpf_ctx_record_field_size(info, size_default);
			return bpf_ctx_narrow_access_ok(off, size,
							size_default);
		case offsetof(struct bpf_sock_ops, skb_hwtstamp):
		case bpf_ctx_range(struct bpf_sock_ops, skb_hwtstamp):
			if (size != sizeof(__u64))
				return false;
			break;
@@ -9416,17 +9416,17 @@ static bool sk_msg_is_valid_access(int off, int size,
		return false;

	switch (off) {
	case offsetof(struct sk_msg_md, data):
	case bpf_ctx_range_ptr(struct sk_msg_md, data):
		info->reg_type = PTR_TO_PACKET;
		if (size != sizeof(__u64))
			return false;
		break;
	case offsetof(struct sk_msg_md, data_end):
	case bpf_ctx_range_ptr(struct sk_msg_md, data_end):
		info->reg_type = PTR_TO_PACKET_END;
		if (size != sizeof(__u64))
			return false;
		break;
	case offsetof(struct sk_msg_md, sk):
	case bpf_ctx_range_ptr(struct sk_msg_md, sk):
		if (size != sizeof(__u64))
			return false;
		info->reg_type = PTR_TO_SOCKET;
@@ -11632,7 +11632,7 @@ static bool sk_lookup_is_valid_access(int off, int size,
		return false;

	switch (off) {
	case offsetof(struct bpf_sk_lookup, sk):
	case bpf_ctx_range_ptr(struct bpf_sk_lookup, sk):
		info->reg_type = PTR_TO_SOCKET_OR_NULL;
		return size == sizeof(__u64);

+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ static unsigned int nf_hook_run_bpf(void *bpf_prog, struct sk_buff *skb,
		.skb = skb,
	};

	return bpf_prog_run(prog, &ctx);
	return bpf_prog_run_pin_on_cpu(prog, &ctx);
}

struct bpf_nf_link {
+25 −0
Original line number Diff line number Diff line
@@ -218,4 +218,29 @@ __naked void null_check_8_null_bind(void)
	: __clobber_all);
}

#define narrow_load(type, ctx, field)					\
	SEC(type)							\
	__description("narrow load on field " #field " of " #ctx)	\
	__failure __msg("invalid bpf_context access")			\
	__naked void invalid_narrow_load##ctx##field(void)		\
	{								\
		asm volatile ("						\
		r1 = *(u32 *)(r1 + %[off]);				\
		r0 = 0;							\
		exit;"							\
		:							\
		: __imm_const(off, offsetof(struct ctx, field) + 4)	\
		: __clobber_all);					\
	}

narrow_load("cgroup/getsockopt", bpf_sockopt, sk);
narrow_load("cgroup/getsockopt", bpf_sockopt, optval);
narrow_load("cgroup/getsockopt", bpf_sockopt, optval_end);
narrow_load("tc", __sk_buff, sk);
narrow_load("cgroup/bind4", bpf_sock_addr, sk);
narrow_load("sockops", bpf_sock_ops, sk);
narrow_load("sockops", bpf_sock_ops, skb_data);
narrow_load("sockops", bpf_sock_ops, skb_data_end);
narrow_load("sockops", bpf_sock_ops, skb_hwtstamp);

char _license[] SEC("license") = "GPL";