diff options
-rw-r--r-- | include/net/dst.h | 12 | ||||
-rw-r--r-- | include/net/ip_tunnels.h | 7 | ||||
-rw-r--r-- | net/core/filter.c | 30 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel_core.c | 6 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 2 |
5 files changed, 35 insertions, 22 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index c7329dcd90cc..5c98443c1c9e 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -398,6 +398,18 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, | |||
398 | __skb_tunnel_rx(skb, dev, net); | 398 | __skb_tunnel_rx(skb, dev, net); |
399 | } | 399 | } |
400 | 400 | ||
401 | static inline u32 dst_tclassid(const struct sk_buff *skb) | ||
402 | { | ||
403 | #ifdef CONFIG_IP_ROUTE_CLASSID | ||
404 | const struct dst_entry *dst; | ||
405 | |||
406 | dst = skb_dst(skb); | ||
407 | if (dst) | ||
408 | return dst->tclassid; | ||
409 | #endif | ||
410 | return 0; | ||
411 | } | ||
412 | |||
401 | int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); | 413 | int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
402 | static inline int dst_discard(struct sk_buff *skb) | 414 | static inline int dst_discard(struct sk_buff *skb) |
403 | { | 415 | { |
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 5dc2e454f866..c35dda9ec991 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <linux/socket.h> | 7 | #include <linux/socket.h> |
8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
9 | #include <linux/u64_stats_sync.h> | 9 | #include <linux/u64_stats_sync.h> |
10 | #include <linux/bitops.h> | ||
11 | |||
10 | #include <net/dsfield.h> | 12 | #include <net/dsfield.h> |
11 | #include <net/gro_cells.h> | 13 | #include <net/gro_cells.h> |
12 | #include <net/inet_ecn.h> | 14 | #include <net/inet_ecn.h> |
@@ -57,6 +59,11 @@ struct ip_tunnel_key { | |||
57 | #define IP_TUNNEL_INFO_TX 0x01 /* represents tx tunnel parameters */ | 59 | #define IP_TUNNEL_INFO_TX 0x01 /* represents tx tunnel parameters */ |
58 | #define IP_TUNNEL_INFO_IPV6 0x02 /* key contains IPv6 addresses */ | 60 | #define IP_TUNNEL_INFO_IPV6 0x02 /* key contains IPv6 addresses */ |
59 | 61 | ||
62 | /* Maximum tunnel options length. */ | ||
63 | #define IP_TUNNEL_OPTS_MAX \ | ||
64 | GENMASK((FIELD_SIZEOF(struct ip_tunnel_info, \ | ||
65 | options_len) * BITS_PER_BYTE) - 1, 0) | ||
66 | |||
60 | struct ip_tunnel_info { | 67 | struct ip_tunnel_info { |
61 | struct ip_tunnel_key key; | 68 | struct ip_tunnel_key key; |
62 | #ifdef CONFIG_DST_CACHE | 69 | #ifdef CONFIG_DST_CACHE |
diff --git a/net/core/filter.c b/net/core/filter.c index 6fc3893a6170..b7177d01ecb0 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -1682,14 +1682,7 @@ static const struct bpf_func_proto bpf_get_cgroup_classid_proto = { | |||
1682 | 1682 | ||
1683 | static u64 bpf_get_route_realm(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) | 1683 | static u64 bpf_get_route_realm(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) |
1684 | { | 1684 | { |
1685 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1685 | return dst_tclassid((struct sk_buff *) (unsigned long) r1); |
1686 | const struct dst_entry *dst; | ||
1687 | |||
1688 | dst = skb_dst((struct sk_buff *) (unsigned long) r1); | ||
1689 | if (dst) | ||
1690 | return dst->tclassid; | ||
1691 | #endif | ||
1692 | return 0; | ||
1693 | } | 1686 | } |
1694 | 1687 | ||
1695 | static const struct bpf_func_proto bpf_get_route_realm_proto = { | 1688 | static const struct bpf_func_proto bpf_get_route_realm_proto = { |
@@ -1911,8 +1904,6 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = { | |||
1911 | .arg4_type = ARG_ANYTHING, | 1904 | .arg4_type = ARG_ANYTHING, |
1912 | }; | 1905 | }; |
1913 | 1906 | ||
1914 | #define BPF_TUNLEN_MAX 255 | ||
1915 | |||
1916 | static u64 bpf_skb_set_tunnel_opt(u64 r1, u64 r2, u64 size, u64 r4, u64 r5) | 1907 | static u64 bpf_skb_set_tunnel_opt(u64 r1, u64 r2, u64 size, u64 r4, u64 r5) |
1917 | { | 1908 | { |
1918 | struct sk_buff *skb = (struct sk_buff *) (long) r1; | 1909 | struct sk_buff *skb = (struct sk_buff *) (long) r1; |
@@ -1922,7 +1913,7 @@ static u64 bpf_skb_set_tunnel_opt(u64 r1, u64 r2, u64 size, u64 r4, u64 r5) | |||
1922 | 1913 | ||
1923 | if (unlikely(info != &md->u.tun_info || (size & (sizeof(u32) - 1)))) | 1914 | if (unlikely(info != &md->u.tun_info || (size & (sizeof(u32) - 1)))) |
1924 | return -EINVAL; | 1915 | return -EINVAL; |
1925 | if (unlikely(size > BPF_TUNLEN_MAX)) | 1916 | if (unlikely(size > IP_TUNNEL_OPTS_MAX)) |
1926 | return -ENOMEM; | 1917 | return -ENOMEM; |
1927 | 1918 | ||
1928 | ip_tunnel_info_opts_set(info, from, size); | 1919 | ip_tunnel_info_opts_set(info, from, size); |
@@ -1943,13 +1934,10 @@ static const struct bpf_func_proto * | |||
1943 | bpf_get_skb_set_tunnel_proto(enum bpf_func_id which) | 1934 | bpf_get_skb_set_tunnel_proto(enum bpf_func_id which) |
1944 | { | 1935 | { |
1945 | if (!md_dst) { | 1936 | if (!md_dst) { |
1946 | BUILD_BUG_ON(FIELD_SIZEOF(struct ip_tunnel_info, | ||
1947 | options_len) != 1); | ||
1948 | |||
1949 | /* Race is not possible, since it's called from verifier | 1937 | /* Race is not possible, since it's called from verifier |
1950 | * that is holding verifier mutex. | 1938 | * that is holding verifier mutex. |
1951 | */ | 1939 | */ |
1952 | md_dst = metadata_dst_alloc_percpu(BPF_TUNLEN_MAX, | 1940 | md_dst = metadata_dst_alloc_percpu(IP_TUNNEL_OPTS_MAX, |
1953 | GFP_KERNEL); | 1941 | GFP_KERNEL); |
1954 | if (!md_dst) | 1942 | if (!md_dst) |
1955 | return NULL; | 1943 | return NULL; |
@@ -2069,16 +2057,14 @@ static bool sk_filter_is_valid_access(int off, int size, | |||
2069 | static bool tc_cls_act_is_valid_access(int off, int size, | 2057 | static bool tc_cls_act_is_valid_access(int off, int size, |
2070 | enum bpf_access_type type) | 2058 | enum bpf_access_type type) |
2071 | { | 2059 | { |
2072 | if (off == offsetof(struct __sk_buff, tc_classid)) | ||
2073 | return type == BPF_WRITE ? true : false; | ||
2074 | |||
2075 | if (type == BPF_WRITE) { | 2060 | if (type == BPF_WRITE) { |
2076 | switch (off) { | 2061 | switch (off) { |
2077 | case offsetof(struct __sk_buff, mark): | 2062 | case offsetof(struct __sk_buff, mark): |
2078 | case offsetof(struct __sk_buff, tc_index): | 2063 | case offsetof(struct __sk_buff, tc_index): |
2079 | case offsetof(struct __sk_buff, priority): | 2064 | case offsetof(struct __sk_buff, priority): |
2080 | case offsetof(struct __sk_buff, cb[0]) ... | 2065 | case offsetof(struct __sk_buff, cb[0]) ... |
2081 | offsetof(struct __sk_buff, cb[4]): | 2066 | offsetof(struct __sk_buff, cb[4]): |
2067 | case offsetof(struct __sk_buff, tc_classid): | ||
2082 | break; | 2068 | break; |
2083 | default: | 2069 | default: |
2084 | return false; | 2070 | return false; |
@@ -2195,8 +2181,10 @@ static u32 bpf_net_convert_ctx_access(enum bpf_access_type type, int dst_reg, | |||
2195 | ctx_off -= offsetof(struct __sk_buff, tc_classid); | 2181 | ctx_off -= offsetof(struct __sk_buff, tc_classid); |
2196 | ctx_off += offsetof(struct sk_buff, cb); | 2182 | ctx_off += offsetof(struct sk_buff, cb); |
2197 | ctx_off += offsetof(struct qdisc_skb_cb, tc_classid); | 2183 | ctx_off += offsetof(struct qdisc_skb_cb, tc_classid); |
2198 | WARN_ON(type != BPF_WRITE); | 2184 | if (type == BPF_WRITE) |
2199 | *insn++ = BPF_STX_MEM(BPF_H, dst_reg, src_reg, ctx_off); | 2185 | *insn++ = BPF_STX_MEM(BPF_H, dst_reg, src_reg, ctx_off); |
2186 | else | ||
2187 | *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg, ctx_off); | ||
2200 | break; | 2188 | break; |
2201 | 2189 | ||
2202 | case offsetof(struct __sk_buff, tc_index): | 2190 | case offsetof(struct __sk_buff, tc_index): |
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index eaca2449a09a..d27276f6f8dd 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
@@ -398,6 +398,12 @@ static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = { | |||
398 | 398 | ||
399 | void __init ip_tunnel_core_init(void) | 399 | void __init ip_tunnel_core_init(void) |
400 | { | 400 | { |
401 | /* If you land here, make sure whether increasing ip_tunnel_info's | ||
402 | * options_len is a reasonable choice with its usage in front ends | ||
403 | * (f.e., it's part of flow keys, etc). | ||
404 | */ | ||
405 | BUILD_BUG_ON(IP_TUNNEL_OPTS_MAX != 255); | ||
406 | |||
401 | lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP); | 407 | lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP); |
402 | lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6); | 408 | lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6); |
403 | } | 409 | } |
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 1d055c559eaf..03378e75a67c 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
@@ -55,7 +55,7 @@ struct ovs_tunnel_info { | |||
55 | FIELD_SIZEOF(struct sw_flow_key, recirc_id)) | 55 | FIELD_SIZEOF(struct sw_flow_key, recirc_id)) |
56 | 56 | ||
57 | struct sw_flow_key { | 57 | struct sw_flow_key { |
58 | u8 tun_opts[255]; | 58 | u8 tun_opts[IP_TUNNEL_OPTS_MAX]; |
59 | u8 tun_opts_len; | 59 | u8 tun_opts_len; |
60 | struct ip_tunnel_key tun_key; /* Encapsulating tunnel key. */ | 60 | struct ip_tunnel_key tun_key; /* Encapsulating tunnel key. */ |
61 | struct { | 61 | struct { |