aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-08-07 11:02:05 -0700
committerDavid S. Miller <davem@davemloft.net>2018-08-07 11:02:05 -0700
commit1ba982806ce58baac44c52e6c7812245afad27c8 (patch)
treeb0a8061a496c3d01eed36eadf22cea845a2a995b /net/ipv6
parentieee802154: hwsim: fix rcu address annotation (diff)
parentbpf: introduce update_effective_progs() (diff)
downloadwireguard-linux-1ba982806ce58baac44c52e6c7812245afad27c8.tar.xz
wireguard-linux-1ba982806ce58baac44c52e6c7812245afad27c8.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2018-08-07 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Add cgroup local storage for BPF programs, which provides a fast accessible memory for storing various per-cgroup data like number of transmitted packets, etc, from Roman. 2) Support bpf_get_socket_cookie() BPF helper in several more program types that have a full socket available, from Andrey. 3) Significantly improve the performance of perf events which are reported from BPF offload. Also convert a couple of BPF AF_XDP samples overto use libbpf, both from Jakub. 4) seg6local LWT provides the End.DT6 action, which allows to decapsulate an outer IPv6 header containing a Segment Routing Header. Adds this action now to the seg6local BPF interface, from Mathieu. 5) Do not mark dst register as unbounded in MOV64 instruction when both src and dst register are the same, from Arthur. 6) Define u_smp_rmb() and u_smp_wmb() to their respective barrier instructions on arm64 for the AF_XDP sample code, from Brian. 7) Convert the tcp_client.py and tcp_server.py BPF selftest scripts over from Python 2 to Python 3, from Jeremy. 8) Enable BTF build flags to the BPF sample code Makefile, from Taeung. 9) Remove an unnecessary rcu_read_lock() in run_lwt_bpf(), from Taehee. 10) Several improvements to the README.rst from the BPF documentation to make it more consistent with RST format, from Tobin. 11) Replace all occurrences of strerror() by calls to strerror_r() in libbpf and fix a FORTIFY_SOURCE build error along with it, from Thomas. 12) Fix a bug in bpftool's get_btf() function to correctly propagate an error via PTR_ERR(), from Yue. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/seg6_local.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index e1025b493a18..60325dbfe88b 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -459,36 +459,57 @@ drop:
DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states);
+bool seg6_bpf_has_valid_srh(struct sk_buff *skb)
+{
+ struct seg6_bpf_srh_state *srh_state =
+ this_cpu_ptr(&seg6_bpf_srh_states);
+ struct ipv6_sr_hdr *srh = srh_state->srh;
+
+ if (unlikely(srh == NULL))
+ return false;
+
+ if (unlikely(!srh_state->valid)) {
+ if ((srh_state->hdrlen & 7) != 0)
+ return false;
+
+ srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
+ if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))
+ return false;
+
+ srh_state->valid = true;
+ }
+
+ return true;
+}
+
static int input_action_end_bpf(struct sk_buff *skb,
struct seg6_local_lwt *slwt)
{
struct seg6_bpf_srh_state *srh_state =
this_cpu_ptr(&seg6_bpf_srh_states);
- struct seg6_bpf_srh_state local_srh_state;
struct ipv6_sr_hdr *srh;
- int srhoff = 0;
int ret;
srh = get_and_validate_srh(skb);
- if (!srh)
- goto drop;
+ if (!srh) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
/* preempt_disable is needed to protect the per-CPU buffer srh_state,
* which is also accessed by the bpf_lwt_seg6_* helpers
*/
preempt_disable();
+ srh_state->srh = srh;
srh_state->hdrlen = srh->hdrlen << 3;
- srh_state->valid = 1;
+ srh_state->valid = true;
rcu_read_lock();
bpf_compute_data_pointers(skb);
ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb);
rcu_read_unlock();
- local_srh_state = *srh_state;
- preempt_enable();
-
switch (ret) {
case BPF_OK:
case BPF_REDIRECT:
@@ -500,24 +521,17 @@ static int input_action_end_bpf(struct sk_buff *skb,
goto drop;
}
- if (unlikely((local_srh_state.hdrlen & 7) != 0))
- goto drop;
-
- if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
- goto drop;
- srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
- srh->hdrlen = (u8)(local_srh_state.hdrlen >> 3);
-
- if (!local_srh_state.valid &&
- unlikely(!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3)))
+ if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
goto drop;
+ preempt_enable();
if (ret != BPF_REDIRECT)
seg6_lookup_nexthop(skb, NULL, 0);
return dst_input(skb);
drop:
+ preempt_enable();
kfree_skb(skb);
return -EINVAL;
}