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: Andrii Narkyiko <andriin@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
commit
6da193569c
@ -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) && \
|
||||
|
@ -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);
|
||||
|
@ -6884,20 +6884,30 @@ 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,
|
||||
struct bpf_sock_addr,
|
||||
user_ip6))
|
||||
if (bpf_ctx_wide_access_ok(off, size,
|
||||
struct bpf_sock_addr,
|
||||
user_ip6))
|
||||
return true;
|
||||
|
||||
if (bpf_ctx_wide_store_ok(off, size,
|
||||
struct bpf_sock_addr,
|
||||
msg_src_ip6))
|
||||
if (bpf_ctx_wide_access_ok(off, size,
|
||||
struct bpf_sock_addr,
|
||||
msg_src_ip6))
|
||||
return true;
|
||||
|
||||
if (size != size_default)
|
||||
|
@ -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
tools/testing/selftests/bpf/verifier/wide_access.c
Normal file
73
tools/testing/selftests/bpf/verifier/wide_access.c
Normal file
@ -0,0 +1,73 @@
|
||||
#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
|
@ -1,36 +0,0 @@
|
||||
#define BPF_SOCK_ADDR(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(user_ip6, 0, ACCEPT,
|
||||
NULL),
|
||||
BPF_SOCK_ADDR(user_ip6, 1, REJECT,
|
||||
"invalid bpf_context access off=12 size=8"),
|
||||
BPF_SOCK_ADDR(user_ip6, 2, ACCEPT,
|
||||
NULL),
|
||||
BPF_SOCK_ADDR(user_ip6, 3, REJECT,
|
||||
"invalid bpf_context access off=20 size=8"),
|
||||
|
||||
/* msg_src_ip6[0] is _not_ u64 aligned */
|
||||
BPF_SOCK_ADDR(msg_src_ip6, 0, REJECT,
|
||||
"invalid bpf_context access off=44 size=8"),
|
||||
BPF_SOCK_ADDR(msg_src_ip6, 1, ACCEPT,
|
||||
NULL),
|
||||
BPF_SOCK_ADDR(msg_src_ip6, 2, REJECT,
|
||||
"invalid bpf_context access off=52 size=8"),
|
||||
BPF_SOCK_ADDR(msg_src_ip6, 3, REJECT,
|
||||
"invalid bpf_context access off=56 size=8"),
|
||||
|
||||
#undef BPF_SOCK_ADDR
|
Loading…
Reference in New Issue
Block a user