Skip to content

Commit cfda06d

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2018-03-08 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Fix various BPF helpers which adjust the skb and its GSO information with regards to SCTP GSO. The latter is a special case where gso_size is of value GSO_BY_FRAGS, so mangling that will end up corrupting the skb, thus bail out when seeing SCTP GSO packets, from Daniel(s). 2) Fix a compilation error in bpftool where BPF_FS_MAGIC is not defined due to too old kernel headers in the system, from Jiri. 3) Increase the number of x64 JIT passes in order to allow larger images to converge instead of punting them to interpreter or having them rejected when the interpreter is not built into the kernel, from Daniel. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents b06ef18 + 6007b08 commit cfda06d

File tree

5 files changed

+79
-21
lines changed

5 files changed

+79
-21
lines changed

Documentation/networking/segmentation-offloads.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,15 @@ To signal this, gso_size is set to the special value GSO_BY_FRAGS.
153153

154154
Therefore, any code in the core networking stack must be aware of the
155155
possibility that gso_size will be GSO_BY_FRAGS and handle that case
156-
appropriately. (For size checks, the skb_gso_validate_*_len family of
157-
helpers do this automatically.)
156+
appropriately.
157+
158+
There are a couple of helpers to make this easier:
159+
160+
- For size checks, the skb_gso_validate_*_len family of helpers correctly
161+
considers GSO_BY_FRAGS.
162+
163+
- For manipulating packets, skb_increase_gso_size and skb_decrease_gso_size
164+
will check for GSO_BY_FRAGS and WARN if asked to manipulate these skbs.
158165

159166
This also affects drivers with the NETIF_F_FRAGLIST & NETIF_F_GSO_SCTP bits
160167
set. Note also that NETIF_F_GSO_SCTP is included in NETIF_F_GSO_SOFTWARE.

arch/x86/net/bpf_jit_comp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
11881188
* may converge on the last pass. In such case do one more
11891189
* pass to emit the final image
11901190
*/
1191-
for (pass = 0; pass < 10 || image; pass++) {
1191+
for (pass = 0; pass < 20 || image; pass++) {
11921192
proglen = do_jit(prog, addrs, image, oldproglen, &ctx);
11931193
if (proglen <= 0) {
11941194
image = NULL;
@@ -1215,6 +1215,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
12151215
}
12161216
}
12171217
oldproglen = proglen;
1218+
cond_resched();
12181219
}
12191220

12201221
if (bpf_jit_enable > 1)

include/linux/skbuff.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4037,13 +4037,35 @@ static inline bool skb_is_gso_v6(const struct sk_buff *skb)
40374037
return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
40384038
}
40394039

4040+
/* Note: Should be called only if skb_is_gso(skb) is true */
4041+
static inline bool skb_is_gso_sctp(const struct sk_buff *skb)
4042+
{
4043+
return skb_shinfo(skb)->gso_type & SKB_GSO_SCTP;
4044+
}
4045+
40404046
static inline void skb_gso_reset(struct sk_buff *skb)
40414047
{
40424048
skb_shinfo(skb)->gso_size = 0;
40434049
skb_shinfo(skb)->gso_segs = 0;
40444050
skb_shinfo(skb)->gso_type = 0;
40454051
}
40464052

4053+
static inline void skb_increase_gso_size(struct skb_shared_info *shinfo,
4054+
u16 increment)
4055+
{
4056+
if (WARN_ON_ONCE(shinfo->gso_size == GSO_BY_FRAGS))
4057+
return;
4058+
shinfo->gso_size += increment;
4059+
}
4060+
4061+
static inline void skb_decrease_gso_size(struct skb_shared_info *shinfo,
4062+
u16 decrement)
4063+
{
4064+
if (WARN_ON_ONCE(shinfo->gso_size == GSO_BY_FRAGS))
4065+
return;
4066+
shinfo->gso_size -= decrement;
4067+
}
4068+
40474069
void __skb_warn_lro_forwarding(const struct sk_buff *skb);
40484070

40494071
static inline bool skb_warn_if_lro(const struct sk_buff *skb)

net/core/filter.c

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,6 +2087,10 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
20872087
u32 off = skb_mac_header_len(skb);
20882088
int ret;
20892089

2090+
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2091+
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2092+
return -ENOTSUPP;
2093+
20902094
ret = skb_cow(skb, len_diff);
20912095
if (unlikely(ret < 0))
20922096
return ret;
@@ -2096,19 +2100,21 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
20962100
return ret;
20972101

20982102
if (skb_is_gso(skb)) {
2103+
struct skb_shared_info *shinfo = skb_shinfo(skb);
2104+
20992105
/* SKB_GSO_TCPV4 needs to be changed into
21002106
* SKB_GSO_TCPV6.
21012107
*/
2102-
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
2103-
skb_shinfo(skb)->gso_type &= ~SKB_GSO_TCPV4;
2104-
skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV6;
2108+
if (shinfo->gso_type & SKB_GSO_TCPV4) {
2109+
shinfo->gso_type &= ~SKB_GSO_TCPV4;
2110+
shinfo->gso_type |= SKB_GSO_TCPV6;
21052111
}
21062112

21072113
/* Due to IPv6 header, MSS needs to be downgraded. */
2108-
skb_shinfo(skb)->gso_size -= len_diff;
2114+
skb_decrease_gso_size(shinfo, len_diff);
21092115
/* Header must be checked, and gso_segs recomputed. */
2110-
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
2111-
skb_shinfo(skb)->gso_segs = 0;
2116+
shinfo->gso_type |= SKB_GSO_DODGY;
2117+
shinfo->gso_segs = 0;
21122118
}
21132119

21142120
skb->protocol = htons(ETH_P_IPV6);
@@ -2123,6 +2129,10 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
21232129
u32 off = skb_mac_header_len(skb);
21242130
int ret;
21252131

2132+
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2133+
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2134+
return -ENOTSUPP;
2135+
21262136
ret = skb_unclone(skb, GFP_ATOMIC);
21272137
if (unlikely(ret < 0))
21282138
return ret;
@@ -2132,19 +2142,21 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
21322142
return ret;
21332143

21342144
if (skb_is_gso(skb)) {
2145+
struct skb_shared_info *shinfo = skb_shinfo(skb);
2146+
21352147
/* SKB_GSO_TCPV6 needs to be changed into
21362148
* SKB_GSO_TCPV4.
21372149
*/
2138-
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
2139-
skb_shinfo(skb)->gso_type &= ~SKB_GSO_TCPV6;
2140-
skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
2150+
if (shinfo->gso_type & SKB_GSO_TCPV6) {
2151+
shinfo->gso_type &= ~SKB_GSO_TCPV6;
2152+
shinfo->gso_type |= SKB_GSO_TCPV4;
21412153
}
21422154

21432155
/* Due to IPv4 header, MSS can be upgraded. */
2144-
skb_shinfo(skb)->gso_size += len_diff;
2156+
skb_increase_gso_size(shinfo, len_diff);
21452157
/* Header must be checked, and gso_segs recomputed. */
2146-
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
2147-
skb_shinfo(skb)->gso_segs = 0;
2158+
shinfo->gso_type |= SKB_GSO_DODGY;
2159+
shinfo->gso_segs = 0;
21482160
}
21492161

21502162
skb->protocol = htons(ETH_P_IP);
@@ -2243,6 +2255,10 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff)
22432255
u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
22442256
int ret;
22452257

2258+
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2259+
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2260+
return -ENOTSUPP;
2261+
22462262
ret = skb_cow(skb, len_diff);
22472263
if (unlikely(ret < 0))
22482264
return ret;
@@ -2252,11 +2268,13 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff)
22522268
return ret;
22532269

22542270
if (skb_is_gso(skb)) {
2271+
struct skb_shared_info *shinfo = skb_shinfo(skb);
2272+
22552273
/* Due to header grow, MSS needs to be downgraded. */
2256-
skb_shinfo(skb)->gso_size -= len_diff;
2274+
skb_decrease_gso_size(shinfo, len_diff);
22572275
/* Header must be checked, and gso_segs recomputed. */
2258-
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
2259-
skb_shinfo(skb)->gso_segs = 0;
2276+
shinfo->gso_type |= SKB_GSO_DODGY;
2277+
shinfo->gso_segs = 0;
22602278
}
22612279

22622280
return 0;
@@ -2267,6 +2285,10 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
22672285
u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
22682286
int ret;
22692287

2288+
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
2289+
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
2290+
return -ENOTSUPP;
2291+
22702292
ret = skb_unclone(skb, GFP_ATOMIC);
22712293
if (unlikely(ret < 0))
22722294
return ret;
@@ -2276,11 +2298,13 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
22762298
return ret;
22772299

22782300
if (skb_is_gso(skb)) {
2301+
struct skb_shared_info *shinfo = skb_shinfo(skb);
2302+
22792303
/* Due to header shrink, MSS can be upgraded. */
2280-
skb_shinfo(skb)->gso_size += len_diff;
2304+
skb_increase_gso_size(shinfo, len_diff);
22812305
/* Header must be checked, and gso_segs recomputed. */
2282-
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
2283-
skb_shinfo(skb)->gso_segs = 0;
2306+
shinfo->gso_type |= SKB_GSO_DODGY;
2307+
shinfo->gso_segs = 0;
22842308
}
22852309

22862310
return 0;

tools/bpf/bpftool/common.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555

5656
#include "main.h"
5757

58+
#ifndef BPF_FS_MAGIC
59+
#define BPF_FS_MAGIC 0xcafe4a11
60+
#endif
61+
5862
void p_err(const char *fmt, ...)
5963
{
6064
va_list ap;

0 commit comments

Comments
 (0)