Commit aa65d696 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Alexei Starovoitov

bpf: Add state, dst_ip4, dst_ip6 and dst_port to bpf_sock

This patch adds "state", "dst_ip4", "dst_ip6" and "dst_port" to the
bpf_sock.  The userspace has already been using "state",
e.g. inet_diag (ss -t) and getsockopt(TCP_INFO).

This patch also allows narrow load on the following existing fields:
"family", "type", "protocol" and "src_port".  Unlike IP address,
the load offset is resticted to the first byte for them but it
can be relaxed later if there is a use case.

This patch also folds __sock_filter_check_size() into
bpf_sock_is_valid_access() since it is not called
by any where else.  All bpf_sock checking is in
one place.
Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 46f8bc92
...@@ -2606,15 +2606,14 @@ struct bpf_sock { ...@@ -2606,15 +2606,14 @@ struct bpf_sock {
__u32 protocol; __u32 protocol;
__u32 mark; __u32 mark;
__u32 priority; __u32 priority;
__u32 src_ip4; /* Allows 1,2,4-byte read. /* IP address also allows 1 and 2 bytes access */
* Stored in network byte order. __u32 src_ip4;
*/ __u32 src_ip6[4];
__u32 src_ip6[4]; /* Allows 1,2,4-byte read. __u32 src_port; /* host byte order */
* Stored in network byte order. __u32 dst_port; /* network byte order */
*/ __u32 dst_ip4;
__u32 src_port; /* Allows 4-byte read. __u32 dst_ip6[4];
* Stored in host byte order __u32 state;
*/
}; };
struct bpf_sock_tuple { struct bpf_sock_tuple {
......
...@@ -5958,21 +5958,6 @@ static bool __sock_filter_check_attach_type(int off, ...@@ -5958,21 +5958,6 @@ static bool __sock_filter_check_attach_type(int off,
return true; return true;
} }
static bool __sock_filter_check_size(int off, int size,
struct bpf_insn_access_aux *info)
{
const int size_default = sizeof(__u32);
switch (off) {
case bpf_ctx_range(struct bpf_sock, src_ip4):
case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
bpf_ctx_record_field_size(info, size_default);
return bpf_ctx_narrow_access_ok(off, size, size_default);
}
return size == size_default;
}
bool bpf_sock_common_is_valid_access(int off, int size, bool bpf_sock_common_is_valid_access(int off, int size,
enum bpf_access_type type, enum bpf_access_type type,
struct bpf_insn_access_aux *info) struct bpf_insn_access_aux *info)
...@@ -5988,13 +5973,29 @@ bool bpf_sock_common_is_valid_access(int off, int size, ...@@ -5988,13 +5973,29 @@ bool bpf_sock_common_is_valid_access(int off, int size,
bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type, bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
struct bpf_insn_access_aux *info) struct bpf_insn_access_aux *info)
{ {
const int size_default = sizeof(__u32);
if (off < 0 || off >= sizeof(struct bpf_sock)) if (off < 0 || off >= sizeof(struct bpf_sock))
return false; return false;
if (off % size != 0) if (off % size != 0)
return false; return false;
if (!__sock_filter_check_size(off, size, info))
return false; switch (off) {
return true; case offsetof(struct bpf_sock, state):
case offsetof(struct bpf_sock, family):
case offsetof(struct bpf_sock, type):
case offsetof(struct bpf_sock, protocol):
case offsetof(struct bpf_sock, dst_port):
case offsetof(struct bpf_sock, src_port):
case bpf_ctx_range(struct bpf_sock, src_ip4):
case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
case bpf_ctx_range(struct bpf_sock, dst_ip4):
case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
bpf_ctx_record_field_size(info, size_default);
return bpf_ctx_narrow_access_ok(off, size, size_default);
}
return size == size_default;
} }
static bool sock_filter_is_valid_access(int off, int size, static bool sock_filter_is_valid_access(int off, int size,
...@@ -6838,24 +6839,32 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, ...@@ -6838,24 +6839,32 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
break; break;
case offsetof(struct bpf_sock, family): case offsetof(struct bpf_sock, family):
BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_family) != 2); *insn++ = BPF_LDX_MEM(
BPF_FIELD_SIZEOF(struct sock_common, skc_family),
*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg, si->dst_reg, si->src_reg,
offsetof(struct sock, sk_family)); bpf_target_off(struct sock_common,
skc_family,
FIELD_SIZEOF(struct sock_common,
skc_family),
target_size));
break; break;
case offsetof(struct bpf_sock, type): case offsetof(struct bpf_sock, type):
BUILD_BUG_ON(HWEIGHT32(SK_FL_TYPE_MASK) != BITS_PER_BYTE * 2);
*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg, *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
offsetof(struct sock, __sk_flags_offset)); offsetof(struct sock, __sk_flags_offset));
*insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK); *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK);
*insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT); *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT);
*target_size = 2;
break; break;
case offsetof(struct bpf_sock, protocol): case offsetof(struct bpf_sock, protocol):
BUILD_BUG_ON(HWEIGHT32(SK_FL_PROTO_MASK) != BITS_PER_BYTE);
*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg, *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
offsetof(struct sock, __sk_flags_offset)); offsetof(struct sock, __sk_flags_offset));
*insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK); *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK);
*insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_PROTO_SHIFT); *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_PROTO_SHIFT);
*target_size = 1;
break; break;
case offsetof(struct bpf_sock, src_ip4): case offsetof(struct bpf_sock, src_ip4):
...@@ -6867,6 +6876,15 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, ...@@ -6867,6 +6876,15 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
target_size)); target_size));
break; break;
case offsetof(struct bpf_sock, dst_ip4):
*insn++ = BPF_LDX_MEM(
BPF_SIZE(si->code), si->dst_reg, si->src_reg,
bpf_target_off(struct sock_common, skc_daddr,
FIELD_SIZEOF(struct sock_common,
skc_daddr),
target_size));
break;
case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]): case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
off = si->off; off = si->off;
...@@ -6885,6 +6903,23 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, ...@@ -6885,6 +6903,23 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
#endif #endif
break; break;
case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
#if IS_ENABLED(CONFIG_IPV6)
off = si->off;
off -= offsetof(struct bpf_sock, dst_ip6[0]);
*insn++ = BPF_LDX_MEM(
BPF_SIZE(si->code), si->dst_reg, si->src_reg,
bpf_target_off(struct sock_common,
skc_v6_daddr.s6_addr32[0],
FIELD_SIZEOF(struct sock_common,
skc_v6_daddr.s6_addr32[0]),
target_size) + off);
#else
*insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
*target_size = 4;
#endif
break;
case offsetof(struct bpf_sock, src_port): case offsetof(struct bpf_sock, src_port):
*insn++ = BPF_LDX_MEM( *insn++ = BPF_LDX_MEM(
BPF_FIELD_SIZEOF(struct sock_common, skc_num), BPF_FIELD_SIZEOF(struct sock_common, skc_num),
...@@ -6894,6 +6929,26 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type, ...@@ -6894,6 +6929,26 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
skc_num), skc_num),
target_size)); target_size));
break; break;
case offsetof(struct bpf_sock, dst_port):
*insn++ = BPF_LDX_MEM(
BPF_FIELD_SIZEOF(struct sock_common, skc_dport),
si->dst_reg, si->src_reg,
bpf_target_off(struct sock_common, skc_dport,
FIELD_SIZEOF(struct sock_common,
skc_dport),
target_size));
break;
case offsetof(struct bpf_sock, state):
*insn++ = BPF_LDX_MEM(
BPF_FIELD_SIZEOF(struct sock_common, skc_state),
si->dst_reg, si->src_reg,
bpf_target_off(struct sock_common, skc_state,
FIELD_SIZEOF(struct sock_common,
skc_state),
target_size));
break;
} }
return insn - insn_buf; return insn - insn_buf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment