Date: Tue, 28 Jun 2016 11:58:56 +0200 From: Julien Charbon <jch@freebsd.org> To: Randall Stewart <rrs@netflix.com>, current@freebsd.org Cc: hselasky@FreeBSD.org, net@FreeBSD.org Subject: Re: panic with tcp timers Message-ID: <ae21858a-e162-6aad-1597-eeff614624c9@freebsd.org> In-Reply-To: <6E52CA6A-2153-4EF9-A3E1-97CB0D07EB28@freebsd.org> References: <20160617045319.GE1076@FreeBSD.org> <1f28844b-b4ea-b544-3892-811f2be327b9@freebsd.org> <20160620073917.GI1076@FreeBSD.org> <1d18d0e2-3e42-cb26-928c-2989d0751884@freebsd.org> <20160620095822.GJ1076@FreeBSD.org> <74bb31b7-a9f5-3d0c-eea0-681872e6f09b@freebsd.org> <18D94615-810E-4E79-A889-4B0CC70F9E45@netflix.com> <6E52CA6A-2153-4EF9-A3E1-97CB0D07EB28@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --V2vxqg2bse8BDAiFdbkRFrXdAgQxIDLnB Content-Type: multipart/mixed; boundary="VSScAOvNUr1ikVRhBTpmu42CTd9EplESr" From: Julien Charbon <jch@freebsd.org> To: Randall Stewart <rrs@netflix.com>, current@freebsd.org Cc: hselasky@FreeBSD.org, net@FreeBSD.org Message-ID: <ae21858a-e162-6aad-1597-eeff614624c9@freebsd.org> Subject: Re: panic with tcp timers References: <20160617045319.GE1076@FreeBSD.org> <1f28844b-b4ea-b544-3892-811f2be327b9@freebsd.org> <20160620073917.GI1076@FreeBSD.org> <1d18d0e2-3e42-cb26-928c-2989d0751884@freebsd.org> <20160620095822.GJ1076@FreeBSD.org> <74bb31b7-a9f5-3d0c-eea0-681872e6f09b@freebsd.org> <18D94615-810E-4E79-A889-4B0CC70F9E45@netflix.com> <6E52CA6A-2153-4EF9-A3E1-97CB0D07EB28@freebsd.org> In-Reply-To: <6E52CA6A-2153-4EF9-A3E1-97CB0D07EB28@freebsd.org> --VSScAOvNUr1ikVRhBTpmu42CTd9EplESr Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Hi Randall, On 6/25/16 4:41 PM, Randall Stewart via freebsd-net wrote: > Ok >=20 > Lets try this again with my source changed to my @freebsd.net :-) >=20 > Now I am also attaching a patch for you Gleb, this will take some pokin= g to > get in to your NF-head since it incorporates some changes we made earli= er. >=20 > I think this will fix the problem.. i.e. dealing with two locks in the = callout system (which it was > never meant to have done).. >=20 > Note we probably can move the code to use the callout lock init now.. b= ut lets see if this works > on your setup on c096 and if so we can think about doing that. Thanks for proposing a patch. I believe your patch will work with callout lock init, but not without: You still have a use-after-free issue on the tcpcb without callout lock init. The case being subtle as usual, let me try to describe that could happen= : With your patch we have: void tcp_timer_keep(void *xtp) { struct tcpcb *tp =3D xtp; struct tcptemp *t_template; struct inpcb *inp; CURVNET_SET(tp->t_vnet); #ifdef TCPDEBUG int ostate; ostate =3D tp->t_state; #endif inp =3D tp->t_inpcb; KASSERT(inp !=3D NULL, ("%s: tp %p tp->t_inpcb =3D=3D NULL", __fu= nc__, tp)); INP_WLOCK(inp); if (callout_pending(&tp->t_timers->tt_keep) ### Use after free of tp here !callout_active(&tp->t_timers->tt_keep)) { INP_WUNLOCK(inp); CURVNET_RESTORE(); return; } ... The use-after-free scenario: [CPU 1] the callout fires, tcp_timer_keep entered [CPU 1] blocks on INP_WLOCK(inp); [CPU 2] schedules tcp_timer_keep with callout_reset() [CPU 2] tcp_discardcb called [CPU 2] tcp_timer_keep callout successfully canceled [CPU 2] tcpcb freed [CPU 1] unblocks, the tcpcb is used Then the tcpcb will used just after being freed... Might also crash or not depending in the case. Extra notes: o The invariant I see here is: The "callout successfully canceled" step should never happen when "the callout is currently being executed". o Solutions I see to enforce this invariant: - First solution: Use callout lock init with inp lock, your patch seems to permit that now. - Second solution: Change callout_async_drain() behavior: It can return 0 (fail) when the callout is currently being executed (no matter what). - Third solution: Don't trust callout_async_drain(callout) return value of 1 (success) if the previous call of callout_reset(callout) returned 0 (fail). That was the exact purpose of r284261 change, but this solution is also step backward in modernization of TCP timers/callout... https://svnweb.freebsd.org/base/stable/10/sys/netinet/tcp_timer.c?r1=3D28= 4261&r2=3D284260&pathrev=3D284261 Hopefully my description is clear enough... -- Julien --VSScAOvNUr1ikVRhBTpmu42CTd9EplESr-- --V2vxqg2bse8BDAiFdbkRFrXdAgQxIDLnB Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Comment: GPGTools - https://gpgtools.org iQEcBAEBCgAGBQJXckpqAAoJEKVlQ5Je6dhxbn8IAK+iSIVBRUUwNNolJFmSx47O Y1qySRcEb04Q8qxTZrT72/0FDRyFdMydhTTKh3yifXnTEGeg+wWKomkDNP8RDhgX 96xwXhzos+Y50PEbeKy78/kAZG8UmFaSGRMCDyvUHeTBI9TIRdDjZzJzCgrVqLot a54sCW/+Ud1tXYUO0HEdJqaMWMdAre4Xsn7QNGFF7eY0ewmFj6vbA7VST35SbRnw vP+Oy2VBPb2otqKY+FYYHeUi6gRMs+Nsen0K+hegbokWxBRXWPhft9WuSiz3heTI juMOCALkH/D2lrHTxVkoR3+4+1fTZ9LkmBIaoA8mgH6UbeCvLJLcaODIpvwsVYA= =j5ic -----END PGP SIGNATURE----- --V2vxqg2bse8BDAiFdbkRFrXdAgQxIDLnB--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?ae21858a-e162-6aad-1597-eeff614624c9>