mirror of https://gitee.com/openkylin/linux.git
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: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
46f8bc9275
commit
aa65d6960a
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
#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,
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue