History

bpf: allow sk_msg programs to read sock fields

Currently sk_msg programs only have access to the raw data. However, it is often useful when building policies to have the policies specific to the socket endpoint. This allows using the socket tuple as input into filters, etc. This patch adds ctx access to the sock fields.

John Fastabend committed 8 years ago

Commit 303def31 parent 1cb61384 files · +121 −3Browse files

Unified · Split

4 files
  1. include/linux/filter.h +1 −0
  2. include/uapi/linux/bpf.h +8 −0
  3. kernel/bpf/sockmap.c +1 −0
  4. net/core/filter.c +111 −3
include/linux/filter.h+1−0
@@ -517,6 +517,7 @@ struct sk_msg_buff { · 516 unmodified lines
517517 bool sg_copy[MAX_SKB_FRAGS];
518518 __u32 flags;
519519 struct sock *sk_redir;
520+ struct sock *sk;
520521 struct sk_buff *skb;
521522 struct list_head list;
522523 };
include/uapi/linux/bpf.h+8−0
@@ -2176,6 +2176,14 @@ enum sk_action { · 2175 unmodified lines
21762176 struct sk_msg_md {
21772177 void *data;
21782178 void *data_end;
2179+
2180+ __u32 family;
2181+ __u32 remote_ip4; /* Stored in network byte order */
2182+ __u32 local_ip4; /* Stored in network byte order */
2183+ __u32 remote_ip6[4]; /* Stored in network byte order */
2184+ __u32 local_ip6[4]; /* Stored in network byte order */
2185+ __u32 remote_port; /* Stored in network byte order */
2186+ __u32 local_port; /* stored in host byte order */
21792187 };
21802188
21812189 #define BPF_TAG_SIZE 8
kernel/bpf/sockmap.c+1−0
@@ -523,6 +523,7 @@ static unsigned int smap_do_tx_msg(struct sock *sk, · 522 unmodified lines
523523 }
524524
525525 bpf_compute_data_pointers_sg(md);
526+ md->sk = sk;
526527 rc = (*prog->bpf_func)(md, prog->insnsi);
527528 psock->apply_bytes = md->apply_bytes;
528529
net/core/filter.c+111−3
@@ -5148,18 +5148,23 @@ static bool sk_msg_is_valid_access(int off, int size, · 5147 unmodified lines
51485148 switch (off) {
51495149 case offsetof(struct sk_msg_md, data):
51505150 info->reg_type = PTR_TO_PACKET;
5151+ if (size != sizeof(__u64))
5152+ return false;
51515153 break;
51525154 case offsetof(struct sk_msg_md, data_end):
51535155 info->reg_type = PTR_TO_PACKET_END;
5156+ if (size != sizeof(__u64))
5157+ return false;
51545158 break;
5159+ default:
5160+ if (size != sizeof(__u32))
5161+ return false;
51555162 }
51565163
51575164 if (off < 0 || off >= sizeof(struct sk_msg_md))
51585165 return false;
51595166 if (off % size != 0)
51605167 return false;
5161− if (size != sizeof(__u64))
5162− return false;
51635168
51645169 return true;
51655170 }
@@ -5835,7 +5840,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, · 669 unmodified lines
58355840 break;
58365841
58375842 case offsetof(struct bpf_sock_ops, local_ip4):
5838− BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_rcv_saddr) != 4);
5843+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
5844+ skc_rcv_saddr) != 4);
58395845
58405846 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
58415847 struct bpf_sock_ops_kern, sk),
@@ -6152,6 +6158,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type, · 310 unmodified lines
61526158 struct bpf_prog *prog, u32 *target_size)
61536159 {
61546160 struct bpf_insn *insn = insn_buf;
6161+ int off;
61556162
61566163 switch (si->off) {
61576164 case offsetof(struct sk_msg_md, data):
@@ -6164,6 +6171,107 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type, · 6 unmodified lines
61646171 si->dst_reg, si->src_reg,
61656172 offsetof(struct sk_msg_buff, data_end));
61666173 break;
6174+ case offsetof(struct sk_msg_md, family):
6175+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
6176+
6177+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6178+ struct sk_msg_buff, sk),
6179+ si->dst_reg, si->src_reg,
6180+ offsetof(struct sk_msg_buff, sk));
6181+ *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
6182+ offsetof(struct sock_common, skc_family));
6183+ break;
6184+
6185+ case offsetof(struct sk_msg_md, remote_ip4):
6186+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
6187+
6188+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6189+ struct sk_msg_buff, sk),
6190+ si->dst_reg, si->src_reg,
6191+ offsetof(struct sk_msg_buff, sk));
6192+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
6193+ offsetof(struct sock_common, skc_daddr));
6194+ break;
6195+
6196+ case offsetof(struct sk_msg_md, local_ip4):
6197+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
6198+ skc_rcv_saddr) != 4);
6199+
6200+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6201+ struct sk_msg_buff, sk),
6202+ si->dst_reg, si->src_reg,
6203+ offsetof(struct sk_msg_buff, sk));
6204+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
6205+ offsetof(struct sock_common,
6206+ skc_rcv_saddr));
6207+ break;
6208+
6209+ case offsetof(struct sk_msg_md, remote_ip6[0]) ...
6210+ offsetof(struct sk_msg_md, remote_ip6[3]):
6211+#if IS_ENABLED(CONFIG_IPV6)
6212+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
6213+ skc_v6_daddr.s6_addr32[0]) != 4);
6214+
6215+ off = si->off;
6216+ off -= offsetof(struct sk_msg_md, remote_ip6[0]);
6217+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6218+ struct sk_msg_buff, sk),
6219+ si->dst_reg, si->src_reg,
6220+ offsetof(struct sk_msg_buff, sk));
6221+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
6222+ offsetof(struct sock_common,
6223+ skc_v6_daddr.s6_addr32[0]) +
6224+ off);
6225+#else
6226+ *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
6227+#endif
6228+ break;
6229+
6230+ case offsetof(struct sk_msg_md, local_ip6[0]) ...
6231+ offsetof(struct sk_msg_md, local_ip6[3]):
6232+#if IS_ENABLED(CONFIG_IPV6)
6233+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
6234+ skc_v6_rcv_saddr.s6_addr32[0]) != 4);
6235+
6236+ off = si->off;
6237+ off -= offsetof(struct sk_msg_md, local_ip6[0]);
6238+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6239+ struct sk_msg_buff, sk),
6240+ si->dst_reg, si->src_reg,
6241+ offsetof(struct sk_msg_buff, sk));
6242+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
6243+ offsetof(struct sock_common,
6244+ skc_v6_rcv_saddr.s6_addr32[0]) +
6245+ off);
6246+#else
6247+ *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
6248+#endif
6249+ break;
6250+
6251+ case offsetof(struct sk_msg_md, remote_port):
6252+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
6253+
6254+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6255+ struct sk_msg_buff, sk),
6256+ si->dst_reg, si->src_reg,
6257+ offsetof(struct sk_msg_buff, sk));
6258+ *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
6259+ offsetof(struct sock_common, skc_dport));
6260+#ifndef __BIG_ENDIAN_BITFIELD
6261+ *insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
6262+#endif
6263+ break;
6264+
6265+ case offsetof(struct sk_msg_md, local_port):
6266+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
6267+
6268+ *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
6269+ struct sk_msg_buff, sk),
6270+ si->dst_reg, si->src_reg,
6271+ offsetof(struct sk_msg_buff, sk));
6272+ *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
6273+ offsetof(struct sock_common, skc_num));
6274+ break;
61676275 }
61686276
61696277 return insn - insn_buf;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t