opnsense-src/lib/libc
Gleb Smirnoff 1bda3fae78 tcp: don't ever return ECONNRESET on close(2)
The SUS doesn't mention this error code as a possible one [1]. The FreeBSD
manual page specifies a possible ECONNRESET for close(2):

[ECONNRESET]	The underlying object was a stream socket that was
		shut down by the peer before all pending data was
		delivered.

In the past it had been EINVAL (see 21367f630d), and this EINVAL was
added as a safety measure in 623dce13c6.  After conversion to
ECONNRESET it had been documented in the manual page in 78e3a7fdd5, but
I bet wasn't ever tested to actually be ever returned, cause the
tcp-testsuite[2] didn't exist back then.  So documentation is incorrect
since 2006, if my bet wins.  Anyway, in the modern FreeBSD the condition
described above doesn't end up with ECONNRESET error code from close(2).
The error condition is reported via SO_ERROR socket option, though.  This
can be checked using the tcp-testsuite, temporarily disabling the
getsockopt(SO_ERROR) lines using sed command [3].  Most of these
getsockopt(2)s are followed by '+0.00 close(3) = 0', which will confirm
that close(2) doesn't return ECONNRESET even on a socket that has the
error stored, neither it is returned in the case described in the manual
page.  The latter case is covered by multiple tests residing in tcp-
testsuite/state-event-engine/rcv-rst-*.

However, the deleted block of code could be entered in a race condition
between close(2) and processing of incoming packet, when connection had
already been half-closed with shutdown(SHUT_WR) and sits in TCPS_LAST_ACK.
This was reported in the bug 146845.  With the block deleted, we will
continue into tcp_disconnect() which has proper handling of INP_DROPPED.

The race explanation follows.  The connection is in TCPS_LAST_ACK.  The
network input thread acquires the tcpcb lock first, sets INP_DROPPED,
acquires the socket lock in soisdisconnected() and clears SS_ISCONNECTED.
Meanwhile, the syscall thread goes through sodisconnect() which checks for
SS_ISCONNECTED locklessly(!).  The check passes and the thread blocks on
the tcpcb lock in tcp_usr_disconnect().  Once input thread releases the
lock, the syscall thread observes INP_DROPPED and returns ECONNRESET.

- Thread 1: tcp_do_segment()->tcp_close()->in_pcbdrop(),soisdisconnected()
- Thread 2: sys_close()...->soclose()->sodisconnect()->tcp_usr_disconnect()

Note that the lockless operation in sodisconnect() isn't correct, but
enforcing the socket lock there will not fix the problem.

[1] https://pubs.opengroup.org/onlinepubs/9799919799/
[2] https://github.com/freebsd-net/tcp-testsuite
[3] sed -i "" -Ee '/\+0\.00 getsockopt\(3, SOL_SOCKET, SO_ERROR, \[ECONNRESET\]/d' $(grep -lr ECONNRESET tcp-testsuite)

PR:			146845
Reviewed by:		tuexen, rrs, imp
Differential Revision:	https://reviews.freebsd.org/D48148

(cherry picked from commit 053a988497342a6fd0a717cc097d09c23f83e103)
2025-03-31 10:31:21 -07:00
..
aarch64 libc/aarch64: Remove an unneeded weak symbol 2024-09-02 08:49:39 +00:00
amd64 lib/libc/amd64/string: fix overread condition in memccpy 2024-08-07 16:18:40 +02:00
arm libc: rename arm and i386 Ovfork.S to vfork.S 2024-01-02 16:58:42 +00:00
capability cap_rights_is_empty: add MLINK 2024-12-06 10:50:31 -05:00
compat-43 libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
csu libc: Purge unneeded cdefs.h 2023-11-26 21:20:09 -07:00
db libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
gdtoa libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
gen libc/gen/fts.c: fix assignment 2025-03-04 06:19:08 +02:00
gmon libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
i386 libc: rename arm and i386 Ovfork.S to vfork.S 2024-01-02 16:58:42 +00:00
iconv libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
include libc_private.h: use private namespace name for size_t 2024-04-30 04:14:52 +03:00
inet libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
isc libc: Purge unneeded cdefs.h 2023-11-26 21:20:09 -07:00
locale libc: remove some obsolete VCS data 2023-12-13 23:08:50 +00:00
md Remove $FreeBSD$: one-line sh pattern 2023-08-16 11:55:03 -06:00
nameser libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
net libc/getnameinfo: stop adding NI_NUMERICHOST where inappropriate 2024-09-28 10:35:11 +00:00
nls libc: remove some XXX for russian translations of errnos 2024-11-09 21:31:29 +02:00
posix1e manuals: Fix "missing end of block" errors 2024-11-04 12:07:50 -04:00
powerpc libc: centralize a few numeric symbols 2023-12-13 22:08:14 +00:00
powerpc64 libc: centralize a few numeric symbols 2023-12-13 22:08:14 +00:00
powerpcspe libc/<arch>/sys/Makefile.inc: remove cruft 2023-12-13 22:08:13 +00:00
quad libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
regex regex: mixed sets are misidentified as singletons 2024-09-25 15:42:25 -05:00
resolv libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
riscv libc: don't needlessly add vfork.o to NOASM 2024-01-02 16:58:54 +00:00
rpc libc: move NIS xdr_* symbols from rpc's to yp's Symbol.map 2024-05-29 11:40:18 -04:00
secure libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
softfloat libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
stdio libc/stdio: Increase BUF in vfprintf.c and vfwprintf.c 2025-03-25 19:28:39 -06:00
stdlib Revise qsort(3) reflect POSIX.1-2024 update. 2024-12-21 23:30:52 -08:00
stdtime strptime: Fix day-of-week calculation. 2024-12-16 10:37:08 +00:00
string libc: indicate existing functions that are POSIX 2024 2024-11-20 19:45:07 -05:00
sys tcp: don't ever return ECONNRESET on close(2) 2025-03-31 10:31:21 -07:00
tests Fix lib/libc/nss/getgr_test with large numbers of groups 2025-01-20 09:54:45 -07:00
uuid libc: Remove empty comments in Symbol.map 2023-12-13 22:08:13 +00:00
x86 Canonicalize the name of the FreeBSD Foundation 2025-02-19 09:58:47 -05:00
xdr rpc: Fix the definition of xdr_void() 2024-11-05 01:05:26 +00:00
yp libc: move NIS xdr_* symbols from rpc's to yp's Symbol.map 2024-05-29 11:40:18 -04:00
libc.ldscript Remove $FreeBSD$: one-line .c comment pattern 2023-08-16 11:54:29 -06:00
libc_nossp.ldscript Remove $FreeBSD$: one-line .c comment pattern 2023-08-16 11:54:29 -06:00
Makefile libc: enable initial-exec (IE) as default thread-local storage model on arm 2024-11-22 10:36:32 -05:00
Makefile.depend Remove $FreeBSD$: one-line sh pattern 2023-08-16 11:55:03 -06:00
Makefile.depend.options Remove $FreeBSD$: one-line sh pattern 2023-08-16 11:55:03 -06:00
Versions.def Create namespace for the symbols added during 15-CURRENT cycle 2024-01-31 01:14:38 -06:00