linux-stable/net/core
Shmulik Ladkani 55fb612bef net: gso: Fix skb_segment splat when splitting gso_size mangled skb having linear-headed frag_list
[ Upstream commit 3dcbdb134f ]

Historically, support for frag_list packets entering skb_segment() was
limited to frag_list members terminating on exact same gso_size
boundaries. This is verified with a BUG_ON since commit 89319d3801
("net: Add frag_list support to skb_segment"), quote:

    As such we require all frag_list members terminate on exact MSS
    boundaries.  This is checked using BUG_ON.
    As there should only be one producer in the kernel of such packets,
    namely GRO, this requirement should not be difficult to maintain.

However, since commit 6578171a7f ("bpf: add bpf_skb_change_proto helper"),
the "exact MSS boundaries" assumption no longer holds:
An eBPF program using bpf_skb_change_proto() DOES modify 'gso_size', but
leaves the frag_list members as originally merged by GRO with the
original 'gso_size'. Example of such programs are bpf-based NAT46 or
NAT64.

This lead to a kernel BUG_ON for flows involving:
 - GRO generating a frag_list skb
 - bpf program performing bpf_skb_change_proto() or bpf_skb_adjust_room()
 - skb_segment() of the skb

See example BUG_ON reports in [0].

In commit 13acc94eff ("net: permit skb_segment on head_frag frag_list skb"),
skb_segment() was modified to support the "gso_size mangling" case of
a frag_list GRO'ed skb, but *only* for frag_list members having
head_frag==true (having a page-fragment head).

Alas, GRO packets having frag_list members with a linear kmalloced head
(head_frag==false) still hit the BUG_ON.

This commit adds support to skb_segment() for a 'head_skb' packet having
a frag_list whose members are *non* head_frag, with gso_size mangled, by
disabling SG and thus falling-back to copying the data from the given
'head_skb' into the generated segmented skbs - as suggested by Willem de
Bruijn [1].

Since this approach involves the penalty of skb_copy_and_csum_bits()
when building the segments, care was taken in order to enable this
solution only when required:
 - untrusted gso_size, by testing SKB_GSO_DODGY is set
   (SKB_GSO_DODGY is set by any gso_size mangling functions in
    net/core/filter.c)
 - the frag_list is non empty, its item is a non head_frag, *and* the
   headlen of the given 'head_skb' does not match the gso_size.

[0]
https://lore.kernel.org/netdev/20190826170724.25ff616f@pixies/
https://lore.kernel.org/netdev/9265b93f-253d-6b8c-f2b8-4b54eff1835c@fb.com/

[1]
https://lore.kernel.org/netdev/CA+FuTSfVsgNDi7c=GUU8nMg2hWxF2SjCNLXetHeVPdnxAW5K-w@mail.gmail.com/

Fixes: 6578171a7f ("bpf: add bpf_skb_change_proto helper")
Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Alexander Duyck <alexander.duyck@gmail.com>
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Alexander Duyck <alexander.h.duyck@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-09-19 09:08:01 +02:00
..
datagram.c net: datagram: fix unbounded loop in __skb_try_recv_datagram() 2019-04-03 06:25:08 +02:00
dev.c net: Fix null de-reference of device refcount 2019-09-19 09:08:00 +02:00
dev_addr_lists.c net: fix uninit-value in __hw_addr_add_ex() 2018-05-16 10:10:23 +02:00
dev_ioctl.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
devlink.c devlink: Remove redundant free on error path 2018-03-31 18:10:39 +02:00
drop_monitor.c drop_monitor: use setup_timer 2017-03-12 23:47:16 -07:00
dst.c net: check type when freeing metadata dst 2017-08-21 10:57:38 -07:00
dst_cache.c
ethtool.c ethtool: check the return value of get_regs_len 2019-06-11 12:21:51 +02:00
fib_notifier.c net: Add module reference to FIB notifiers 2017-09-01 20:33:42 -07:00
fib_rules.c Revert "fib_rules: return 0 directly if an exactly same rule exists when NLM_F_EXCL not supplied" 2019-06-11 12:21:47 +02:00
filter.c tcp: fix tcp_set_congestion_control() use from bpf hook 2019-07-31 07:28:46 +02:00
flow_dissector.c flow_dissector: do not dissect l4 ports for fragments 2018-11-23 08:19:25 +01:00
gen_estimator.c net_sched: gen_estimator: fix broken estimators based on percpu stats 2018-03-08 22:41:13 -08:00
gen_stats.c gen_stats: Fix netlink stats dumping in the presence of padding 2018-07-25 11:25:09 +02:00
gro_cells.c gro_cells: make sure device is up in gro_cells_receive() 2019-03-19 13:13:21 +01:00
hwbm.c
link_watch.c
lwt_bpf.c bpf: in __bpf_redirect_no_mac pull mac only if present 2019-01-23 08:09:50 +01:00
lwtunnel.c ipv6: sr: define core operations for seg6local lightweight tunnel 2017-08-07 14:16:22 -07:00
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
neighbour.c net: neigh: fix multiple neigh timer scheduling 2019-07-31 07:28:45 +02:00
net-procfs.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
net-sysfs.c net-sysfs: call dev_hold if kobject_init_and_add success 2019-04-03 06:25:09 +02:00
net-sysfs.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
net-traces.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
net_namespace.c netns: provide pure entropy for net_hash_mix() 2019-04-17 08:37:50 +02:00
netclassid_cgroup.c cgroup, netclassid: add a preemption point to write_classid 2018-11-13 11:14:56 -08:00
netevent.c
netpoll.c net: fix skb use after free in netpoll 2019-09-10 10:32:20 +01:00
netprio_cgroup.c net: break include loop netdevice.h, dsa.h, devlink.h 2017-03-28 22:46:04 -07:00
pktgen.c pktgen: do not sleep with the thread lock held. 2019-06-11 12:21:45 +02:00
ptp_classifier.c
request_sock.c ipv4: Namespaceify tcp_max_syn_backlog knob 2016-12-29 11:38:31 -05:00
rtnetlink.c rtnetlink: ndo_dflt_fdb_dump() only work for ARPHRD_ETHER devices 2018-12-17 09:28:47 +01:00
scm.c sched/headers: Prepare for new header dependencies before moving code to <linux/sched/user.h> 2017-03-02 08:42:29 +01:00
secure_seq.c tcp: Namespaceify sysctl_tcp_timestamps 2017-06-08 10:53:29 -04:00
skbuff.c net: gso: Fix skb_segment splat when splitting gso_size mangled skb having linear-headed frag_list 2019-09-19 09:08:01 +02:00
sock.c net: remove duplicate fetch in sock_getsockopt 2019-07-03 13:16:01 +02:00
sock_diag.c net: core: fix module type in sock_diag_bind 2018-01-17 09:45:21 +01:00
sock_reuseport.c soreuseport: fix mem leak in reuseport_add_sock() 2018-02-13 10:19:48 +01:00
stream.c tcp: make sure EPOLLOUT wont be missed 2019-09-06 10:20:50 +02:00
sysctl_net_core.c bpf: fix bpf_jit_limit knob for PAGE_SIZE >= 64K 2019-08-25 10:50:23 +02:00
timestamping.c
tso.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
utils.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2017-05-02 16:40:27 -07:00