Skip to content

Commit aa65d69

Browse files
iamkafaiAlexei Starovoitov
authored andcommitted
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 <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 46f8bc9 commit aa65d69

2 files changed

Lines changed: 85 additions & 31 deletions

File tree

include/uapi/linux/bpf.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,15 +2606,14 @@ struct bpf_sock {
26062606
__u32 protocol;
26072607
__u32 mark;
26082608
__u32 priority;
2609-
__u32 src_ip4; /* Allows 1,2,4-byte read.
2610-
* Stored in network byte order.
2611-
*/
2612-
__u32 src_ip6[4]; /* Allows 1,2,4-byte read.
2613-
* Stored in network byte order.
2614-
*/
2615-
__u32 src_port; /* Allows 4-byte read.
2616-
* Stored in host byte order
2617-
*/
2609+
/* IP address also allows 1 and 2 bytes access */
2610+
__u32 src_ip4;
2611+
__u32 src_ip6[4];
2612+
__u32 src_port; /* host byte order */
2613+
__u32 dst_port; /* network byte order */
2614+
__u32 dst_ip4;
2615+
__u32 dst_ip6[4];
2616+
__u32 state;
26182617
};
26192618

26202619
struct bpf_sock_tuple {

net/core/filter.c

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5958,21 +5958,6 @@ static bool __sock_filter_check_attach_type(int off,
59585958
return true;
59595959
}
59605960

5961-
static bool __sock_filter_check_size(int off, int size,
5962-
struct bpf_insn_access_aux *info)
5963-
{
5964-
const int size_default = sizeof(__u32);
5965-
5966-
switch (off) {
5967-
case bpf_ctx_range(struct bpf_sock, src_ip4):
5968-
case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
5969-
bpf_ctx_record_field_size(info, size_default);
5970-
return bpf_ctx_narrow_access_ok(off, size, size_default);
5971-
}
5972-
5973-
return size == size_default;
5974-
}
5975-
59765961
bool bpf_sock_common_is_valid_access(int off, int size,
59775962
enum bpf_access_type type,
59785963
struct bpf_insn_access_aux *info)
@@ -5988,13 +5973,29 @@ bool bpf_sock_common_is_valid_access(int off, int size,
59885973
bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
59895974
struct bpf_insn_access_aux *info)
59905975
{
5976+
const int size_default = sizeof(__u32);
5977+
59915978
if (off < 0 || off >= sizeof(struct bpf_sock))
59925979
return false;
59935980
if (off % size != 0)
59945981
return false;
5995-
if (!__sock_filter_check_size(off, size, info))
5996-
return false;
5997-
return true;
5982+
5983+
switch (off) {
5984+
case offsetof(struct bpf_sock, state):
5985+
case offsetof(struct bpf_sock, family):
5986+
case offsetof(struct bpf_sock, type):
5987+
case offsetof(struct bpf_sock, protocol):
5988+
case offsetof(struct bpf_sock, dst_port):
5989+
case offsetof(struct bpf_sock, src_port):
5990+
case bpf_ctx_range(struct bpf_sock, src_ip4):
5991+
case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
5992+
case bpf_ctx_range(struct bpf_sock, dst_ip4):
5993+
case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
5994+
bpf_ctx_record_field_size(info, size_default);
5995+
return bpf_ctx_narrow_access_ok(off, size, size_default);
5996+
}
5997+
5998+
return size == size_default;
59985999
}
59996000

60006001
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,
68386839
break;
68396840

68406841
case offsetof(struct bpf_sock, family):
6841-
BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_family) != 2);
6842-
6843-
*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg,
6844-
offsetof(struct sock, sk_family));
6842+
*insn++ = BPF_LDX_MEM(
6843+
BPF_FIELD_SIZEOF(struct sock_common, skc_family),
6844+
si->dst_reg, si->src_reg,
6845+
bpf_target_off(struct sock_common,
6846+
skc_family,
6847+
FIELD_SIZEOF(struct sock_common,
6848+
skc_family),
6849+
target_size));
68456850
break;
68466851

68476852
case offsetof(struct bpf_sock, type):
6853+
BUILD_BUG_ON(HWEIGHT32(SK_FL_TYPE_MASK) != BITS_PER_BYTE * 2);
68486854
*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
68496855
offsetof(struct sock, __sk_flags_offset));
68506856
*insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK);
68516857
*insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT);
6858+
*target_size = 2;
68526859
break;
68536860

68546861
case offsetof(struct bpf_sock, protocol):
6862+
BUILD_BUG_ON(HWEIGHT32(SK_FL_PROTO_MASK) != BITS_PER_BYTE);
68556863
*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
68566864
offsetof(struct sock, __sk_flags_offset));
68576865
*insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK);
68586866
*insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_PROTO_SHIFT);
6867+
*target_size = 1;
68596868
break;
68606869

68616870
case offsetof(struct bpf_sock, src_ip4):
@@ -6867,6 +6876,15 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
68676876
target_size));
68686877
break;
68696878

6879+
case offsetof(struct bpf_sock, dst_ip4):
6880+
*insn++ = BPF_LDX_MEM(
6881+
BPF_SIZE(si->code), si->dst_reg, si->src_reg,
6882+
bpf_target_off(struct sock_common, skc_daddr,
6883+
FIELD_SIZEOF(struct sock_common,
6884+
skc_daddr),
6885+
target_size));
6886+
break;
6887+
68706888
case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
68716889
#if IS_ENABLED(CONFIG_IPV6)
68726890
off = si->off;
@@ -6885,6 +6903,23 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
68856903
#endif
68866904
break;
68876905

6906+
case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
6907+
#if IS_ENABLED(CONFIG_IPV6)
6908+
off = si->off;
6909+
off -= offsetof(struct bpf_sock, dst_ip6[0]);
6910+
*insn++ = BPF_LDX_MEM(
6911+
BPF_SIZE(si->code), si->dst_reg, si->src_reg,
6912+
bpf_target_off(struct sock_common,
6913+
skc_v6_daddr.s6_addr32[0],
6914+
FIELD_SIZEOF(struct sock_common,
6915+
skc_v6_daddr.s6_addr32[0]),
6916+
target_size) + off);
6917+
#else
6918+
*insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
6919+
*target_size = 4;
6920+
#endif
6921+
break;
6922+
68886923
case offsetof(struct bpf_sock, src_port):
68896924
*insn++ = BPF_LDX_MEM(
68906925
BPF_FIELD_SIZEOF(struct sock_common, skc_num),
@@ -6894,6 +6929,26 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
68946929
skc_num),
68956930
target_size));
68966931
break;
6932+
6933+
case offsetof(struct bpf_sock, dst_port):
6934+
*insn++ = BPF_LDX_MEM(
6935+
BPF_FIELD_SIZEOF(struct sock_common, skc_dport),
6936+
si->dst_reg, si->src_reg,
6937+
bpf_target_off(struct sock_common, skc_dport,
6938+
FIELD_SIZEOF(struct sock_common,
6939+
skc_dport),
6940+
target_size));
6941+
break;
6942+
6943+
case offsetof(struct bpf_sock, state):
6944+
*insn++ = BPF_LDX_MEM(
6945+
BPF_FIELD_SIZEOF(struct sock_common, skc_state),
6946+
si->dst_reg, si->src_reg,
6947+
bpf_target_off(struct sock_common, skc_state,
6948+
FIELD_SIZEOF(struct sock_common,
6949+
skc_state),
6950+
target_size));
6951+
break;
68976952
}
68986953

68996954
return insn - insn_buf;

0 commit comments

Comments
 (0)