mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
commit
cfda06d736
|
@ -153,8 +153,15 @@ To signal this, gso_size is set to the special value GSO_BY_FRAGS.
|
|||
|
||||
Therefore, any code in the core networking stack must be aware of the
|
||||
possibility that gso_size will be GSO_BY_FRAGS and handle that case
|
||||
appropriately. (For size checks, the skb_gso_validate_*_len family of
|
||||
helpers do this automatically.)
|
||||
appropriately.
|
||||
|
||||
There are a couple of helpers to make this easier:
|
||||
|
||||
- For size checks, the skb_gso_validate_*_len family of helpers correctly
|
||||
considers GSO_BY_FRAGS.
|
||||
|
||||
- For manipulating packets, skb_increase_gso_size and skb_decrease_gso_size
|
||||
will check for GSO_BY_FRAGS and WARN if asked to manipulate these skbs.
|
||||
|
||||
This also affects drivers with the NETIF_F_FRAGLIST & NETIF_F_GSO_SCTP bits
|
||||
set. Note also that NETIF_F_GSO_SCTP is included in NETIF_F_GSO_SOFTWARE.
|
||||
|
|
|
@ -1188,7 +1188,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
|||
* may converge on the last pass. In such case do one more
|
||||
* pass to emit the final image
|
||||
*/
|
||||
for (pass = 0; pass < 10 || image; pass++) {
|
||||
for (pass = 0; pass < 20 || image; pass++) {
|
||||
proglen = do_jit(prog, addrs, image, oldproglen, &ctx);
|
||||
if (proglen <= 0) {
|
||||
image = NULL;
|
||||
|
@ -1215,6 +1215,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
|||
}
|
||||
}
|
||||
oldproglen = proglen;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (bpf_jit_enable > 1)
|
||||
|
|
|
@ -4037,6 +4037,12 @@ static inline bool skb_is_gso_v6(const struct sk_buff *skb)
|
|||
return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
|
||||
}
|
||||
|
||||
/* Note: Should be called only if skb_is_gso(skb) is true */
|
||||
static inline bool skb_is_gso_sctp(const struct sk_buff *skb)
|
||||
{
|
||||
return skb_shinfo(skb)->gso_type & SKB_GSO_SCTP;
|
||||
}
|
||||
|
||||
static inline void skb_gso_reset(struct sk_buff *skb)
|
||||
{
|
||||
skb_shinfo(skb)->gso_size = 0;
|
||||
|
@ -4044,6 +4050,22 @@ static inline void skb_gso_reset(struct sk_buff *skb)
|
|||
skb_shinfo(skb)->gso_type = 0;
|
||||
}
|
||||
|
||||
static inline void skb_increase_gso_size(struct skb_shared_info *shinfo,
|
||||
u16 increment)
|
||||
{
|
||||
if (WARN_ON_ONCE(shinfo->gso_size == GSO_BY_FRAGS))
|
||||
return;
|
||||
shinfo->gso_size += increment;
|
||||
}
|
||||
|
||||
static inline void skb_decrease_gso_size(struct skb_shared_info *shinfo,
|
||||
u16 decrement)
|
||||
{
|
||||
if (WARN_ON_ONCE(shinfo->gso_size == GSO_BY_FRAGS))
|
||||
return;
|
||||
shinfo->gso_size -= decrement;
|
||||
}
|
||||
|
||||
void __skb_warn_lro_forwarding(const struct sk_buff *skb);
|
||||
|
||||
static inline bool skb_warn_if_lro(const struct sk_buff *skb)
|
||||
|
|
|
@ -2087,6 +2087,10 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
|
|||
u32 off = skb_mac_header_len(skb);
|
||||
int ret;
|
||||
|
||||
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
|
||||
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = skb_cow(skb, len_diff);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
@ -2096,19 +2100,21 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
|
|||
return ret;
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
|
||||
/* SKB_GSO_TCPV4 needs to be changed into
|
||||
* SKB_GSO_TCPV6.
|
||||
*/
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
|
||||
skb_shinfo(skb)->gso_type &= ~SKB_GSO_TCPV4;
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV6;
|
||||
if (shinfo->gso_type & SKB_GSO_TCPV4) {
|
||||
shinfo->gso_type &= ~SKB_GSO_TCPV4;
|
||||
shinfo->gso_type |= SKB_GSO_TCPV6;
|
||||
}
|
||||
|
||||
/* Due to IPv6 header, MSS needs to be downgraded. */
|
||||
skb_shinfo(skb)->gso_size -= len_diff;
|
||||
skb_decrease_gso_size(shinfo, len_diff);
|
||||
/* Header must be checked, and gso_segs recomputed. */
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
|
||||
skb_shinfo(skb)->gso_segs = 0;
|
||||
shinfo->gso_type |= SKB_GSO_DODGY;
|
||||
shinfo->gso_segs = 0;
|
||||
}
|
||||
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
@ -2123,6 +2129,10 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
|
|||
u32 off = skb_mac_header_len(skb);
|
||||
int ret;
|
||||
|
||||
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
|
||||
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = skb_unclone(skb, GFP_ATOMIC);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
@ -2132,19 +2142,21 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
|
|||
return ret;
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
|
||||
/* SKB_GSO_TCPV6 needs to be changed into
|
||||
* SKB_GSO_TCPV4.
|
||||
*/
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
|
||||
skb_shinfo(skb)->gso_type &= ~SKB_GSO_TCPV6;
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
|
||||
if (shinfo->gso_type & SKB_GSO_TCPV6) {
|
||||
shinfo->gso_type &= ~SKB_GSO_TCPV6;
|
||||
shinfo->gso_type |= SKB_GSO_TCPV4;
|
||||
}
|
||||
|
||||
/* Due to IPv4 header, MSS can be upgraded. */
|
||||
skb_shinfo(skb)->gso_size += len_diff;
|
||||
skb_increase_gso_size(shinfo, len_diff);
|
||||
/* Header must be checked, and gso_segs recomputed. */
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
|
||||
skb_shinfo(skb)->gso_segs = 0;
|
||||
shinfo->gso_type |= SKB_GSO_DODGY;
|
||||
shinfo->gso_segs = 0;
|
||||
}
|
||||
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
@ -2243,6 +2255,10 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff)
|
|||
u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
|
||||
int ret;
|
||||
|
||||
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
|
||||
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = skb_cow(skb, len_diff);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
@ -2252,11 +2268,13 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff)
|
|||
return ret;
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
|
||||
/* Due to header grow, MSS needs to be downgraded. */
|
||||
skb_shinfo(skb)->gso_size -= len_diff;
|
||||
skb_decrease_gso_size(shinfo, len_diff);
|
||||
/* Header must be checked, and gso_segs recomputed. */
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
|
||||
skb_shinfo(skb)->gso_segs = 0;
|
||||
shinfo->gso_type |= SKB_GSO_DODGY;
|
||||
shinfo->gso_segs = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2267,6 +2285,10 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
|
|||
u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
|
||||
int ret;
|
||||
|
||||
/* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
|
||||
if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = skb_unclone(skb, GFP_ATOMIC);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
@ -2276,11 +2298,13 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
|
|||
return ret;
|
||||
|
||||
if (skb_is_gso(skb)) {
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
|
||||
/* Due to header shrink, MSS can be upgraded. */
|
||||
skb_shinfo(skb)->gso_size += len_diff;
|
||||
skb_increase_gso_size(shinfo, len_diff);
|
||||
/* Header must be checked, and gso_segs recomputed. */
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
|
||||
skb_shinfo(skb)->gso_segs = 0;
|
||||
shinfo->gso_type |= SKB_GSO_DODGY;
|
||||
shinfo->gso_segs = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
|
||||
#include "main.h"
|
||||
|
||||
#ifndef BPF_FS_MAGIC
|
||||
#define BPF_FS_MAGIC 0xcafe4a11
|
||||
#endif
|
||||
|
||||
void p_err(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
Loading…
Reference in New Issue