linux/net/ipv4
Eric Dumazet 7ec318feee tcp: gso: avoid refcount_t warning from tcp_gso_segment()
When a GSO skb of truesize O is segmented into 2 new skbs of truesize N1
and N2, we want to transfer socket ownership to the new fresh skbs.

In order to avoid expensive atomic operations on a cache line subject to
cache bouncing, we replace the sequence :

refcount_add(N1, &sk->sk_wmem_alloc);
refcount_add(N2, &sk->sk_wmem_alloc); // repeated by number of segments

refcount_sub(O, &sk->sk_wmem_alloc);

by a single

refcount_add(sum_of(N) - O, &sk->sk_wmem_alloc);

Problem is :

In some pathological cases, sum(N) - O might be a negative number, and
syzkaller bot was apparently able to trigger this trace [1]

atomic_t was ok with this construct, but we need to take care of the
negative delta with refcount_t

[1]
refcount_t: saturated; leaking memory.
------------[ cut here ]------------
WARNING: CPU: 0 PID: 8404 at lib/refcount.c:77 refcount_add_not_zero+0x198/0x200 lib/refcount.c:77
Kernel panic - not syncing: panic_on_warn set ...

CPU: 0 PID: 8404 Comm: syz-executor2 Not tainted 4.14.0-rc5-mm1+ #20
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:16 [inline]
 dump_stack+0x194/0x257 lib/dump_stack.c:52
 panic+0x1e4/0x41c kernel/panic.c:183
 __warn+0x1c4/0x1e0 kernel/panic.c:546
 report_bug+0x211/0x2d0 lib/bug.c:183
 fixup_bug+0x40/0x90 arch/x86/kernel/traps.c:177
 do_trap_no_signal arch/x86/kernel/traps.c:211 [inline]
 do_trap+0x260/0x390 arch/x86/kernel/traps.c:260
 do_error_trap+0x120/0x390 arch/x86/kernel/traps.c:297
 do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:310
 invalid_op+0x18/0x20 arch/x86/entry/entry_64.S:905
RIP: 0010:refcount_add_not_zero+0x198/0x200 lib/refcount.c:77
RSP: 0018:ffff8801c606e3a0 EFLAGS: 00010282
RAX: 0000000000000026 RBX: 0000000000001401 RCX: 0000000000000000
RDX: 0000000000000026 RSI: ffffc900036fc000 RDI: ffffed0038c0dc68
RBP: ffff8801c606e430 R08: 0000000000000001 R09: 0000000000000000
R10: ffff8801d97f5eba R11: 0000000000000000 R12: ffff8801d5acf73c
R13: 1ffff10038c0dc75 R14: 00000000ffffffff R15: 00000000fffff72f
 refcount_add+0x1b/0x60 lib/refcount.c:101
 tcp_gso_segment+0x10d0/0x16b0 net/ipv4/tcp_offload.c:155
 tcp4_gso_segment+0xd4/0x310 net/ipv4/tcp_offload.c:51
 inet_gso_segment+0x60c/0x11c0 net/ipv4/af_inet.c:1271
 skb_mac_gso_segment+0x33f/0x660 net/core/dev.c:2749
 __skb_gso_segment+0x35f/0x7f0 net/core/dev.c:2821
 skb_gso_segment include/linux/netdevice.h:3971 [inline]
 validate_xmit_skb+0x4ba/0xb20 net/core/dev.c:3074
 __dev_queue_xmit+0xe49/0x2070 net/core/dev.c:3497
 dev_queue_xmit+0x17/0x20 net/core/dev.c:3538
 neigh_hh_output include/net/neighbour.h:471 [inline]
 neigh_output include/net/neighbour.h:479 [inline]
 ip_finish_output2+0xece/0x1460 net/ipv4/ip_output.c:229
 ip_finish_output+0x85e/0xd10 net/ipv4/ip_output.c:317
 NF_HOOK_COND include/linux/netfilter.h:238 [inline]
 ip_output+0x1cc/0x860 net/ipv4/ip_output.c:405
 dst_output include/net/dst.h:459 [inline]
 ip_local_out+0x95/0x160 net/ipv4/ip_output.c:124
 ip_queue_xmit+0x8c6/0x18e0 net/ipv4/ip_output.c:504
 tcp_transmit_skb+0x1ab7/0x3840 net/ipv4/tcp_output.c:1137
 tcp_write_xmit+0x663/0x4de0 net/ipv4/tcp_output.c:2341
 __tcp_push_pending_frames+0xa0/0x250 net/ipv4/tcp_output.c:2513
 tcp_push_pending_frames include/net/tcp.h:1722 [inline]
 tcp_data_snd_check net/ipv4/tcp_input.c:5050 [inline]
 tcp_rcv_established+0x8c7/0x18a0 net/ipv4/tcp_input.c:5497
 tcp_v4_do_rcv+0x2ab/0x7d0 net/ipv4/tcp_ipv4.c:1460
 sk_backlog_rcv include/net/sock.h:909 [inline]
 __release_sock+0x124/0x360 net/core/sock.c:2264
 release_sock+0xa4/0x2a0 net/core/sock.c:2776
 tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1462
 inet_sendmsg+0x11f/0x5e0 net/ipv4/af_inet.c:763
 sock_sendmsg_nosec net/socket.c:632 [inline]
 sock_sendmsg+0xca/0x110 net/socket.c:642
 ___sys_sendmsg+0x31c/0x890 net/socket.c:2048
 __sys_sendmmsg+0x1e6/0x5f0 net/socket.c:2138

Fixes: 14afee4b60 ("net: convert sock.sk_wmem_alloc from atomic_t to refcount_t")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-11-10 18:07:15 +09:00
..
netfilter Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-11-03 09:09:21 -07:00
af_inet.c net: Add comment that early_demux can change via sysctl 2017-08-28 15:17:29 -07:00
ah4.c Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next 2017-06-23 14:17:31 -04:00
arp.c neigh: increase queue_len_bytes to match wmem_default 2017-08-29 16:10:50 -07:00
cipso_ipv4.c tcp/dccp: fix ireq->opt races 2017-10-21 01:33:19 +01:00
datagram.c
devinet.c rtnetlink: make rtnl_register accept a flags parameter 2017-08-09 16:57:38 -07:00
esp4_offload.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-09-01 17:42:05 -07:00
esp4.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-09-01 17:42:05 -07:00
fib_frontend.c rtnetlink: make rtnl_register accept a flags parameter 2017-08-09 16:57:38 -07:00
fib_lookup.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
fib_notifier.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
fib_rules.c net: fib_rules: Implement notification logic in core 2017-08-03 15:35:59 -07:00
fib_semantics.c fib: fib_dump_info can no longer use __in_dev_get_rtnl 2017-11-03 14:27:46 +09:00
fib_trie.c ipv4: do metrics match when looking up and deleting a route 2017-08-23 20:37:10 -07:00
fou.c gue: fix remcsum when GRO on and CHECKSUM_PARTIAL boundary is outer UDP 2017-08-01 16:09:14 -07:00
gre_demux.c
gre_offload.c gso: fix payload length when gso_size is zero 2017-10-08 10:12:15 -07:00
icmp.c ip/options: explicitly provide net ns to __ip_options_echo() 2017-08-06 20:51:12 -07:00
igmp.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-08-21 17:06:42 -07:00
inet_connection_sock.c tcp/dccp: fix other lockdep splats accessing ireq_opt 2017-10-26 17:41:32 +09:00
inet_diag.c inet_diag: allow protocols to provide additional data 2017-09-01 18:38:09 -07:00
inet_fragment.c Revert "net: use lib/percpu_counter API for fragmentation mem accounting" 2017-09-03 11:01:05 -07:00
inet_hashtables.c soreuseport: fix initialization race 2017-10-22 02:03:51 +01:00
inet_timewait_sock.c net: convert sock.sk_refcnt from atomic_t to refcount_t 2017-07-01 07:39:08 -07:00
inetpeer.c inetpeer: fix RCU lookup() again 2017-09-28 09:39:34 -07:00
ip_forward.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ip_fragment.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ip_gre.c ip_gre: erspan device should keep dst 2017-10-01 22:30:32 -07:00
ip_input.c IPv4: early demux can return an error code 2017-10-01 03:55:47 +01:00
ip_options.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ip_output.c udp: remove unreachable ufo branches 2017-08-22 14:27:18 -07:00
ip_sockglue.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ip_tunnel_core.c net: store port/representator id in metadata_dst 2017-06-25 11:42:01 -04:00
ip_tunnel.c ip_tunnel: fix ip tunnel lookup in collect_md mode 2017-09-12 20:45:31 -07:00
ip_vti.c vti: fix use after free in vti_tunnel_xmit/vti6_tnl_xmit 2017-09-26 09:58:21 -07:00
ipcomp.c
ipconfig.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ipip.c ipip: only increase err_count for some certain type icmp in ipip_err 2017-10-27 23:43:31 +09:00
ipmr.c rtnetlink: make rtnl_register accept a flags parameter 2017-08-09 16:57:38 -07:00
Kconfig ip: update policy routing config help 2017-10-12 22:57:11 -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
netfilter.c netfilter: use skb_to_full_sk in ip_route_me_harder 2017-02-28 12:49:36 +01:00
ping.c net: convert sock.sk_refcnt from atomic_t to refcount_t 2017-07-01 07:39:08 -07:00
proc.c tcp: Revert "tcp: remove header prediction" 2017-08-30 11:20:09 -07:00
protocol.c net: Add sysctl to toggle early demux for tcp and udp 2017-03-24 13:17:07 -07:00
raw_diag.c net: ipv6: add second dif to raw socket lookups 2017-08-07 11:39:22 -07:00
raw.c net: ipv4: add second dif to multicast source filter 2017-08-07 11:39:22 -07:00
route.c ipv4: Fix traffic triggered IPsec connections. 2017-10-09 09:39:50 -07:00
syncookies.c tcp/dccp: fix ireq->opt races 2017-10-21 01:33:19 +01:00
sysctl_net_ipv4.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tcp_bbr.c tcp_bbr: init pacing rate on first RTT sample 2017-07-15 14:43:29 -07:00
tcp_bic.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_cdg.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_cong.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-09-01 17:42:05 -07:00
tcp_cubic.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_dctcp.c
tcp_diag.c tcp_diag: report TCP MD5 signing keys and addresses 2017-09-01 18:38:09 -07:00
tcp_fastopen.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tcp_highspeed.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_htcp.c tcp: fix cwnd undo in Reno and HTCP congestion controls 2017-08-06 21:25:10 -07:00
tcp_hybla.c
tcp_illinois.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_input.c tcp: fix DSACK-based undo on non-duplicate ACK 2017-11-05 23:16:50 +09:00
tcp_ipv4.c tcp/dccp: fix other lockdep splats accessing ireq_opt 2017-10-26 17:41:32 +09:00
tcp_lp.c tcp: switch TCP TS option (RFC 7323) to 1ms clock 2017-05-17 16:06:01 -04:00
tcp_metrics.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tcp_minisocks.c tcp: Revert "tcp: remove header prediction" 2017-08-30 11:20:09 -07:00
tcp_nv.c tcp_nv: fix division by zero in tcpnv_acked() 2017-11-02 16:16:27 +09:00
tcp_offload.c tcp: gso: avoid refcount_t warning from tcp_gso_segment() 2017-11-10 18:07:15 +09:00
tcp_output.c tcp: do not mangle skb->cb[] in tcp_make_synack() 2017-11-03 14:29:01 +09:00
tcp_probe.c tcp: remove redundant argument from tcp_rcv_established() 2017-07-24 17:28:12 -07:00
tcp_rate.c tcp: export do_tcp_sendpages and tcp_rate_check_app_limited functions 2017-06-15 12:12:40 -04:00
tcp_recovery.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tcp_scalable.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_timer.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-08-09 16:28:45 -07:00
tcp_ulp.c tcp: ulp: avoid module refcnt leak in tcp_set_ulp 2017-08-14 22:17:05 -07:00
tcp_vegas.c
tcp_vegas.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tcp_veno.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp_westwood.c tcp: Revert "tcp: remove CA_ACK_SLOWPATH" 2017-08-30 11:20:08 -07:00
tcp_yeah.c tcp: consolidate congestion control undo functions 2017-08-06 21:25:10 -07:00
tcp.c net: prepare (struct ubuf_info)->refcnt conversion 2017-09-01 20:22:03 -07:00
tunnel4.c
udp_diag.c net: ipv6: add second dif to udp socket lookups 2017-08-07 11:39:22 -07:00
udp_impl.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
udp_offload.c gso: fix payload length when gso_size is zero 2017-10-08 10:12:15 -07:00
udp_tunnel.c net: add infrastructure to un-offload UDP tunnel port 2017-07-24 13:52:59 -07:00
udp.c soreuseport: fix initialization race 2017-10-22 02:03:51 +01:00
udplite.c
xfrm4_input.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
xfrm4_mode_beet.c networking: make skb_pull & friends return void pointers 2017-06-16 11:48:39 -04:00
xfrm4_mode_transport.c xfrm: Add encapsulation header offsets while SKB is not encrypted 2017-04-14 10:07:39 +02:00
xfrm4_mode_tunnel.c xfrm: Add encapsulation header offsets while SKB is not encrypted 2017-04-14 10:07:39 +02:00
xfrm4_output.c xfrm: Add an IPsec hardware offloading API 2017-04-14 10:06:10 +02:00
xfrm4_policy.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
xfrm4_protocol.c xfrm: input: constify xfrm_input_afinfo 2017-02-09 10:22:17 +01:00
xfrm4_state.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
xfrm4_tunnel.c