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
517 bool sg_copy[MAX_SKB_FRAGS];517 bool sg_copy[MAX_SKB_FRAGS];
518 __u32 flags;518 __u32 flags;
519 struct sock *sk_redir;519 struct sock *sk_redir;
520 struct sock *sk;
520 struct sk_buff *skb;521 struct sk_buff *skb;
521 struct list_head list;522 struct list_head list;
522};523};
include/uapi/linux/bpf.h+8−0
@@ -2176,6 +2176,14 @@ enum sk_action { · 2175 unmodified lines
2176struct sk_msg_md {2176struct sk_msg_md {
2177 void *data;2177 void *data;
2178 void *data_end;2178 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 */
2179};2187};
2180 2188
2181#define BPF_TAG_SIZE 82189#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
523 }523 }
524 524
525 bpf_compute_data_pointers_sg(md);525 bpf_compute_data_pointers_sg(md);
526 md->sk = sk;
526 rc = (*prog->bpf_func)(md, prog->insnsi);527 rc = (*prog->bpf_func)(md, prog->insnsi);
527 psock->apply_bytes = md->apply_bytes;528 psock->apply_bytes = md->apply_bytes;
528 529
net/core/filter.c+111−3
@@ -5148,18 +5148,23 @@ static bool sk_msg_is_valid_access(int off, int size, · 5147 unmodified lines
5148 switch (off) {5148 switch (off) {
5149 case offsetof(struct sk_msg_md, data):5149 case offsetof(struct sk_msg_md, data):
5150 info->reg_type = PTR_TO_PACKET;5150 info->reg_type = PTR_TO_PACKET;
5151 if (size != sizeof(__u64))
5152 return false;
5151 break;5153 break;
5152 case offsetof(struct sk_msg_md, data_end):5154 case offsetof(struct sk_msg_md, data_end):
5153 info->reg_type = PTR_TO_PACKET_END;5155 info->reg_type = PTR_TO_PACKET_END;
5156 if (size != sizeof(__u64))
5157 return false;
5154 break;5158 break;
5159 default:
5160 if (size != sizeof(__u32))
5161 return false;
5155 }5162 }
5156 5163
5157 if (off < 0 || off >= sizeof(struct sk_msg_md))5164 if (off < 0 || off >= sizeof(struct sk_msg_md))
5158 return false;5165 return false;
5159 if (off % size != 0)5166 if (off % size != 0)
5160 return false;5167 return false;
5161 if (size != sizeof(__u64))
5162 return false;
5163 5168
5164 return true;5169 return true;
5165}5170}
@@ -5835,7 +5840,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, · 669 unmodified lines
5835 break;5840 break;
5836 5841
5837 case offsetof(struct bpf_sock_ops, local_ip4):5842 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);
5839 5845
5840 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(5846 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
5841 struct bpf_sock_ops_kern, sk),5847 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
6152 struct bpf_prog *prog, u32 *target_size)6158 struct bpf_prog *prog, u32 *target_size)
6153{6159{
6154 struct bpf_insn *insn = insn_buf;6160 struct bpf_insn *insn = insn_buf;
6161 int off;
6155 6162
6156 switch (si->off) {6163 switch (si->off) {
6157 case offsetof(struct sk_msg_md, data):6164 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
6164 si->dst_reg, si->src_reg,6171 si->dst_reg, si->src_reg,
6165 offsetof(struct sk_msg_buff, data_end));6172 offsetof(struct sk_msg_buff, data_end));
6166 break;6173 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;
6167 }6275 }
6168 6276
6169 return insn - insn_buf;6277 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