Commit 6da19356 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

Merge branch 'bpf-fix-wide-loads-sockaddr'

Stanislav Fomichev says:

====================
When fixing selftests by adding support for wide stores, Yonghong
reported that he had seen some examples where clang generates
single u64 loads for two adjacent u32s as well:

http://lore.kernel.org/netdev/a66c937f-94c0-eaf8-5b37-8587d66c0c62@fb.com



Fix this to support aligned u64 reads for some bpf_sock_addr fields
as well.
====================

Acked-by: default avatarAndrii Narkyiko <andriin@fb.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents 81f522f9 073a4834
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -747,7 +747,7 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
	return size <= size_default && (size & (size - 1)) == 0;
}

#define bpf_ctx_wide_store_ok(off, size, type, field)			\
#define bpf_ctx_wide_access_ok(off, size, type, field)			\
	(size == sizeof(__u64) &&					\
	off >= offsetof(type, field) &&					\
	off + sizeof(__u64) <= offsetofend(type, field) &&		\
+2 −2
Original line number Diff line number Diff line
@@ -3248,7 +3248,7 @@ struct bpf_sock_addr {
	__u32 user_ip4;		/* Allows 1,2,4-byte read and 4-byte write.
				 * Stored in network byte order.
				 */
	__u32 user_ip6[4];	/* Allows 1,2,4-byte read and 4,8-byte write.
	__u32 user_ip6[4];	/* Allows 1,2,4,8-byte read and 4,8-byte write.
				 * Stored in network byte order.
				 */
	__u32 user_port;	/* Allows 4-byte read and write.
@@ -3260,7 +3260,7 @@ struct bpf_sock_addr {
	__u32 msg_src_ip4;	/* Allows 1,2,4-byte read and 4-byte write.
				 * Stored in network byte order.
				 */
	__u32 msg_src_ip6[4];	/* Allows 1,2,4-byte read and 4,8-byte write.
	__u32 msg_src_ip6[4];	/* Allows 1,2,4,8-byte read and 4,8-byte write.
				 * Stored in network byte order.
				 */
	__bpf_md_ptr(struct bpf_sock *, sk);
+17 −7
Original line number Diff line number Diff line
@@ -6884,18 +6884,28 @@ static bool sock_addr_is_valid_access(int off, int size,
	case bpf_ctx_range(struct bpf_sock_addr, msg_src_ip4):
	case bpf_ctx_range_till(struct bpf_sock_addr, msg_src_ip6[0],
				msg_src_ip6[3]):
		/* Only narrow read access allowed for now. */
		if (type == BPF_READ) {
			bpf_ctx_record_field_size(info, size_default);

			if (bpf_ctx_wide_access_ok(off, size,
						   struct bpf_sock_addr,
						   user_ip6))
				return true;

			if (bpf_ctx_wide_access_ok(off, size,
						   struct bpf_sock_addr,
						   msg_src_ip6))
				return true;

			if (!bpf_ctx_narrow_access_ok(off, size, size_default))
				return false;
		} else {
			if (bpf_ctx_wide_store_ok(off, size,
			if (bpf_ctx_wide_access_ok(off, size,
						   struct bpf_sock_addr,
						   user_ip6))
				return true;

			if (bpf_ctx_wide_store_ok(off, size,
			if (bpf_ctx_wide_access_ok(off, size,
						   struct bpf_sock_addr,
						   msg_src_ip6))
				return true;
+2 −2
Original line number Diff line number Diff line
@@ -3245,7 +3245,7 @@ struct bpf_sock_addr {
	__u32 user_ip4;		/* Allows 1,2,4-byte read and 4-byte write.
				 * Stored in network byte order.
				 */
	__u32 user_ip6[4];	/* Allows 1,2,4-byte read and 4,8-byte write.
	__u32 user_ip6[4];	/* Allows 1,2,4,8-byte read and 4,8-byte write.
				 * Stored in network byte order.
				 */
	__u32 user_port;	/* Allows 4-byte read and write.
@@ -3257,7 +3257,7 @@ struct bpf_sock_addr {
	__u32 msg_src_ip4;	/* Allows 1,2,4-byte read and 4-byte write.
				 * Stored in network byte order.
				 */
	__u32 msg_src_ip6[4];	/* Allows 1,2,4-byte read and 4,8-byte write.
	__u32 msg_src_ip6[4];	/* Allows 1,2,4,8-byte read and 4,8-byte write.
				 * Stored in network byte order.
				 */
	__bpf_md_ptr(struct bpf_sock *, sk);
+73 −0
Original line number Diff line number Diff line
#define BPF_SOCK_ADDR_STORE(field, off, res, err) \
{ \
	"wide store to bpf_sock_addr." #field "[" #off "]", \
	.insns = { \
	BPF_MOV64_IMM(BPF_REG_0, 1), \
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, \
		    offsetof(struct bpf_sock_addr, field[off])), \
	BPF_EXIT_INSN(), \
	}, \
	.result = res, \
	.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, \
	.expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, \
	.errstr = err, \
}

/* user_ip6[0] is u64 aligned */
BPF_SOCK_ADDR_STORE(user_ip6, 0, ACCEPT,
		    NULL),
BPF_SOCK_ADDR_STORE(user_ip6, 1, REJECT,
		    "invalid bpf_context access off=12 size=8"),
BPF_SOCK_ADDR_STORE(user_ip6, 2, ACCEPT,
		    NULL),
BPF_SOCK_ADDR_STORE(user_ip6, 3, REJECT,
		    "invalid bpf_context access off=20 size=8"),

/* msg_src_ip6[0] is _not_ u64 aligned */
BPF_SOCK_ADDR_STORE(msg_src_ip6, 0, REJECT,
		    "invalid bpf_context access off=44 size=8"),
BPF_SOCK_ADDR_STORE(msg_src_ip6, 1, ACCEPT,
		    NULL),
BPF_SOCK_ADDR_STORE(msg_src_ip6, 2, REJECT,
		    "invalid bpf_context access off=52 size=8"),
BPF_SOCK_ADDR_STORE(msg_src_ip6, 3, REJECT,
		    "invalid bpf_context access off=56 size=8"),

#undef BPF_SOCK_ADDR_STORE

#define BPF_SOCK_ADDR_LOAD(field, off, res, err) \
{ \
	"wide load from bpf_sock_addr." #field "[" #off "]", \
	.insns = { \
	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, \
		    offsetof(struct bpf_sock_addr, field[off])), \
	BPF_MOV64_IMM(BPF_REG_0, 1), \
	BPF_EXIT_INSN(), \
	}, \
	.result = res, \
	.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, \
	.expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, \
	.errstr = err, \
}

/* user_ip6[0] is u64 aligned */
BPF_SOCK_ADDR_LOAD(user_ip6, 0, ACCEPT,
		   NULL),
BPF_SOCK_ADDR_LOAD(user_ip6, 1, REJECT,
		   "invalid bpf_context access off=12 size=8"),
BPF_SOCK_ADDR_LOAD(user_ip6, 2, ACCEPT,
		   NULL),
BPF_SOCK_ADDR_LOAD(user_ip6, 3, REJECT,
		   "invalid bpf_context access off=20 size=8"),

/* msg_src_ip6[0] is _not_ u64 aligned */
BPF_SOCK_ADDR_LOAD(msg_src_ip6, 0, REJECT,
		   "invalid bpf_context access off=44 size=8"),
BPF_SOCK_ADDR_LOAD(msg_src_ip6, 1, ACCEPT,
		   NULL),
BPF_SOCK_ADDR_LOAD(msg_src_ip6, 2, REJECT,
		   "invalid bpf_context access off=52 size=8"),
BPF_SOCK_ADDR_LOAD(msg_src_ip6, 3, REJECT,
		   "invalid bpf_context access off=56 size=8"),

#undef BPF_SOCK_ADDR_LOAD
Loading