History

bpf: Add ingress_ifindex to bpf_sk_lookup

It may be helpful to have access to the ifindex during bpf socket lookup. An example may be to scope certain socket lookup logic to specific interfaces, i.e. an interface may be made exempt from custom lookup code. Add the ifindex of the arriving connection to the bpf_sk_lookup API.

Mark Pashmfouroush committed 5 years ago

Commit f8931561 parent 1a8b5978 files · +30 −18Browse files

Unified · Split

8 files
  1. include/linux/filter.h +5 −2
  2. include/uapi/linux/bpf.h +1 −0
  3. net/core/filter.c +7 −0
  4. net/ipv4/inet_hashtables.c +4 −4
  5. net/ipv4/udp.c +4 −4
  6. net/ipv6/inet6_hashtables.c +4 −4
  7. net/ipv6/udp.c +4 −4
  8. tools/include/uapi/linux/bpf.h +1 −0
include/linux/filter.h+5−2
@@ -1374,6 +1374,7 @@ struct bpf_sk_lookup_kern { · 1373 unmodified lines
1374 const struct in6_addr *daddr;1374 const struct in6_addr *daddr;
1375 } v6;1375 } v6;
1376 struct sock *selected_sk;1376 struct sock *selected_sk;
1377 u32 ingress_ifindex;
1377 bool no_reuseport;1378 bool no_reuseport;
1378};1379};
1379 1380
@@ -1436,7 +1437,7 @@ extern struct static_key_false bpf_sk_lookup_enabled; · 56 unmodified lines
1436static inline bool bpf_sk_lookup_run_v4(struct net *net, int protocol,1437static inline bool bpf_sk_lookup_run_v4(struct net *net, int protocol,
1437 const __be32 saddr, const __be16 sport,1438 const __be32 saddr, const __be16 sport,
1438 const __be32 daddr, const u16 dport,1439 const __be32 daddr, const u16 dport,
1439 struct sock **psk)1440 const int ifindex, struct sock **psk)
1440{1441{
1441 struct bpf_prog_array *run_array;1442 struct bpf_prog_array *run_array;
1442 struct sock *selected_sk = NULL;1443 struct sock *selected_sk = NULL;
@@ -1452,6 +1453,7 @@ static inline bool bpf_sk_lookup_run_v4(struct net *net, int protocol, · 9 unmodified lines
1452 .v4.daddr = daddr,1453 .v4.daddr = daddr,
1453 .sport = sport,1454 .sport = sport,
1454 .dport = dport,1455 .dport = dport,
1456 .ingress_ifindex = ifindex,
1455 };1457 };
1456 u32 act;1458 u32 act;
1457 1459
@@ -1474,7 +1476,7 @@ static inline bool bpf_sk_lookup_run_v6(struct net *net, int protocol, · 16 unmodified lines
1474 const __be16 sport,1476 const __be16 sport,
1475 const struct in6_addr *daddr,1477 const struct in6_addr *daddr,
1476 const u16 dport,1478 const u16 dport,
1477 struct sock **psk)1479 const int ifindex, struct sock **psk)
1478{1480{
1479 struct bpf_prog_array *run_array;1481 struct bpf_prog_array *run_array;
1480 struct sock *selected_sk = NULL;1482 struct sock *selected_sk = NULL;
@@ -1490,6 +1492,7 @@ static inline bool bpf_sk_lookup_run_v6(struct net *net, int protocol, · 9 unmodified lines
1490 .v6.daddr = daddr,1492 .v6.daddr = daddr,
1491 .sport = sport,1493 .sport = sport,
1492 .dport = dport,1494 .dport = dport,
1495 .ingress_ifindex = ifindex,
1493 };1496 };
1494 u32 act;1497 u32 act;
1495 1498
include/uapi/linux/bpf.h+1−0
@@ -6316,6 +6316,7 @@ struct bpf_sk_lookup { · 6315 unmodified lines
6316 __u32 local_ip4; /* Network byte order */6316 __u32 local_ip4; /* Network byte order */
6317 __u32 local_ip6[4]; /* Network byte order */6317 __u32 local_ip6[4]; /* Network byte order */
6318 __u32 local_port; /* Host byte order */6318 __u32 local_port; /* Host byte order */
6319 __u32 ingress_ifindex; /* The arriving interface. Determined by inet_iif. */
6319};6320};
6320 6321
6321/*6322/*
net/core/filter.c+7−0
@@ -10491,6 +10491,7 @@ static bool sk_lookup_is_valid_access(int off, int size, · 10490 unmodified lines
10491 case bpf_ctx_range_till(struct bpf_sk_lookup, local_ip6[0], local_ip6[3]):10491 case bpf_ctx_range_till(struct bpf_sk_lookup, local_ip6[0], local_ip6[3]):
10492 case bpf_ctx_range(struct bpf_sk_lookup, remote_port):10492 case bpf_ctx_range(struct bpf_sk_lookup, remote_port):
10493 case bpf_ctx_range(struct bpf_sk_lookup, local_port):10493 case bpf_ctx_range(struct bpf_sk_lookup, local_port):
10494 case bpf_ctx_range(struct bpf_sk_lookup, ingress_ifindex):
10494 bpf_ctx_record_field_size(info, sizeof(__u32));10495 bpf_ctx_record_field_size(info, sizeof(__u32));
10495 return bpf_ctx_narrow_access_ok(off, size, sizeof(__u32));10496 return bpf_ctx_narrow_access_ok(off, size, sizeof(__u32));
10496 10497
@@ -10580,6 +10581,12 @@ static u32 sk_lookup_convert_ctx_access(enum bpf_access_type type, · 83 unmodified lines
10580 bpf_target_off(struct bpf_sk_lookup_kern,10581 bpf_target_off(struct bpf_sk_lookup_kern,
10581 dport, 2, target_size));10582 dport, 2, target_size));
10582 break;10583 break;
10584
10585 case offsetof(struct bpf_sk_lookup, ingress_ifindex):
10586 *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
10587 bpf_target_off(struct bpf_sk_lookup_kern,
10588 ingress_ifindex, 4, target_size));
10589 break;
10583 }10590 }
10584 10591
10585 return insn - insn_buf;10592 return insn - insn_buf;
net/ipv4/inet_hashtables.c+4−4
@@ -307,7 +307,7 @@ static inline struct sock *inet_lookup_run_bpf(struct net *net, · 306 unmodified lines
307 struct inet_hashinfo *hashinfo,307 struct inet_hashinfo *hashinfo,
308 struct sk_buff *skb, int doff,308 struct sk_buff *skb, int doff,
309 __be32 saddr, __be16 sport,309 __be32 saddr, __be16 sport,
310 __be32 daddr, u16 hnum)310 __be32 daddr, u16 hnum, const int dif)
311{311{
312 struct sock *sk, *reuse_sk;312 struct sock *sk, *reuse_sk;
313 bool no_reuseport;313 bool no_reuseport;
@@ -315,8 +315,8 @@ static inline struct sock *inet_lookup_run_bpf(struct net *net, · 1 unmodified line
315 if (hashinfo != &tcp_hashinfo)315 if (hashinfo != &tcp_hashinfo)
316 return NULL; /* only TCP is supported */316 return NULL; /* only TCP is supported */
317 317
318 no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_TCP,318 no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_TCP, saddr, sport,
319 saddr, sport, daddr, hnum, &sk);319 daddr, hnum, dif, &sk);
320 if (no_reuseport || IS_ERR_OR_NULL(sk))320 if (no_reuseport || IS_ERR_OR_NULL(sk))
321 return sk;321 return sk;
322 322
@@ -340,7 +340,7 @@ struct sock *__inet_lookup_listener(struct net *net, · 17 unmodified lines
340 /* Lookup redirect from BPF */340 /* Lookup redirect from BPF */
341 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {341 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
342 result = inet_lookup_run_bpf(net, hashinfo, skb, doff,342 result = inet_lookup_run_bpf(net, hashinfo, skb, doff,
343 saddr, sport, daddr, hnum);343 saddr, sport, daddr, hnum, dif);
344 if (result)344 if (result)
345 goto done;345 goto done;
346 }346 }
net/ipv4/udp.c+4−4
@@ -460,7 +460,7 @@ static struct sock *udp4_lookup_run_bpf(struct net *net, · 459 unmodified lines
460 struct udp_table *udptable,460 struct udp_table *udptable,
461 struct sk_buff *skb,461 struct sk_buff *skb,
462 __be32 saddr, __be16 sport,462 __be32 saddr, __be16 sport,
463 __be32 daddr, u16 hnum)463 __be32 daddr, u16 hnum, const int dif)
464{464{
465 struct sock *sk, *reuse_sk;465 struct sock *sk, *reuse_sk;
466 bool no_reuseport;466 bool no_reuseport;
@@ -468,8 +468,8 @@ static struct sock *udp4_lookup_run_bpf(struct net *net, · 1 unmodified line
468 if (udptable != &udp_table)468 if (udptable != &udp_table)
469 return NULL; /* only UDP is supported */469 return NULL; /* only UDP is supported */
470 470
471 no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_UDP,471 no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_UDP, saddr, sport,
472 saddr, sport, daddr, hnum, &sk);472 daddr, hnum, dif, &sk);
473 if (no_reuseport || IS_ERR_OR_NULL(sk))473 if (no_reuseport || IS_ERR_OR_NULL(sk))
474 return sk;474 return sk;
475 475
@@ -505,7 +505,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, · 29 unmodified lines
505 /* Lookup redirect from BPF */505 /* Lookup redirect from BPF */
506 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {506 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
507 sk = udp4_lookup_run_bpf(net, udptable, skb,507 sk = udp4_lookup_run_bpf(net, udptable, skb,
508 saddr, sport, daddr, hnum);508 saddr, sport, daddr, hnum, dif);
509 if (sk) {509 if (sk) {
510 result = sk;510 result = sk;
511 goto done;511 goto done;
net/ipv6/inet6_hashtables.c+4−4
@@ -165,7 +165,7 @@ static inline struct sock *inet6_lookup_run_bpf(struct net *net, · 164 unmodified lines
165 const struct in6_addr *saddr,165 const struct in6_addr *saddr,
166 const __be16 sport,166 const __be16 sport,
167 const struct in6_addr *daddr,167 const struct in6_addr *daddr,
168 const u16 hnum)168 const u16 hnum, const int dif)
169{169{
170 struct sock *sk, *reuse_sk;170 struct sock *sk, *reuse_sk;
171 bool no_reuseport;171 bool no_reuseport;
@@ -173,8 +173,8 @@ static inline struct sock *inet6_lookup_run_bpf(struct net *net, · 1 unmodified line
173 if (hashinfo != &tcp_hashinfo)173 if (hashinfo != &tcp_hashinfo)
174 return NULL; /* only TCP is supported */174 return NULL; /* only TCP is supported */
175 175
176 no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP,176 no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP, saddr, sport,
177 saddr, sport, daddr, hnum, &sk);177 daddr, hnum, dif, &sk);
178 if (no_reuseport || IS_ERR_OR_NULL(sk))178 if (no_reuseport || IS_ERR_OR_NULL(sk))
179 return sk;179 return sk;
180 180
@@ -198,7 +198,7 @@ struct sock *inet6_lookup_listener(struct net *net, · 17 unmodified lines
198 /* Lookup redirect from BPF */198 /* Lookup redirect from BPF */
199 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {199 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
200 result = inet6_lookup_run_bpf(net, hashinfo, skb, doff,200 result = inet6_lookup_run_bpf(net, hashinfo, skb, doff,
201 saddr, sport, daddr, hnum);201 saddr, sport, daddr, hnum, dif);
202 if (result)202 if (result)
203 goto done;203 goto done;
204 }204 }
net/ipv6/udp.c+4−4
@@ -195,7 +195,7 @@ static inline struct sock *udp6_lookup_run_bpf(struct net *net, · 194 unmodified lines
195 const struct in6_addr *saddr,195 const struct in6_addr *saddr,
196 __be16 sport,196 __be16 sport,
197 const struct in6_addr *daddr,197 const struct in6_addr *daddr,
198 u16 hnum)198 u16 hnum, const int dif)
199{199{
200 struct sock *sk, *reuse_sk;200 struct sock *sk, *reuse_sk;
201 bool no_reuseport;201 bool no_reuseport;
@@ -203,8 +203,8 @@ static inline struct sock *udp6_lookup_run_bpf(struct net *net, · 1 unmodified line
203 if (udptable != &udp_table)203 if (udptable != &udp_table)
204 return NULL; /* only UDP is supported */204 return NULL; /* only UDP is supported */
205 205
206 no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP,206 no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP, saddr, sport,
207 saddr, sport, daddr, hnum, &sk);207 daddr, hnum, dif, &sk);
208 if (no_reuseport || IS_ERR_OR_NULL(sk))208 if (no_reuseport || IS_ERR_OR_NULL(sk))
209 return sk;209 return sk;
210 210
@@ -240,7 +240,7 @@ struct sock *__udp6_lib_lookup(struct net *net, · 29 unmodified lines
240 /* Lookup redirect from BPF */240 /* Lookup redirect from BPF */
241 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {241 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
242 sk = udp6_lookup_run_bpf(net, udptable, skb,242 sk = udp6_lookup_run_bpf(net, udptable, skb,
243 saddr, sport, daddr, hnum);243 saddr, sport, daddr, hnum, dif);
244 if (sk) {244 if (sk) {
245 result = sk;245 result = sk;
246 goto done;246 goto done;
tools/include/uapi/linux/bpf.h+1−0
@@ -6316,6 +6316,7 @@ struct bpf_sk_lookup { · 6315 unmodified lines
6316 __u32 local_ip4; /* Network byte order */6316 __u32 local_ip4; /* Network byte order */
6317 __u32 local_ip6[4]; /* Network byte order */6317 __u32 local_ip6[4]; /* Network byte order */
6318 __u32 local_port; /* Host byte order */6318 __u32 local_port; /* Host byte order */
6319 __u32 ingress_ifindex; /* The arriving interface. Determined by inet_iif. */
6319};6320};
6320 6321
6321/*6322/*