kern/118154: pf(4) uses invalid timeout values for half-closed connections (fix included)

Jan Srzednicki w at wrzask.pl
Tue Nov 20 09:30:03 PST 2007


>Number:         118154
>Category:       kern
>Synopsis:       pf(4) uses invalid timeout values for half-closed connections (fix included)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 20 17:30:01 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator:     Jan Srzednicki
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
No, nay, never
>Environment:
System: FreeBSD oak.pl 6.2-STABLE FreeBSD 6.2-STABLE #12: Tue Jul 31 20:37:10 CEST 2007 root at oak.pl:/usr/obj/usr/src/sys/MISTLETOE i386

pf(4) from base system.

>Description:

The pf(4) packet filter in the RELENG_6 tree (this also affects 6.2-R and older releases)
contains a long-fixed in OpenBSD bug, which causes half-closed TCP connections (after
one side sends a FIN) to be timeouted by the "tcp.closed" timeout, instead of
"tcp.closing". This causes any subsequent packets to fall into "state mismatch", after
the "tcp.closing" timeout has passed.

HEAD has this thing fixed. OpenBSD had this fixed more than 2 years ago:

http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pf.c.diff?r1=1.493&r2=1.494&f=h

It would be good to have that fixed before 6.3-RELEASE is out.

Thanks to Daniel Hartmeier for helping me figuring the thing out.

>How-To-Repeat:

Set "tcp.closed" timeout to a very small value (eg. 5 seconds) and create a half-closed
connection. The connection will get cut off after the timeout.

>Fix:

--- src/sys/contrib/pf/net/pf.c.orig       Tue Nov 20 11:33:15 2007
+++ src/sys/contrib/pf/net/pf.c    Tue Nov 20 11:33:40 2007
@@ -4634,8 +4634,8 @@
                if (src->state >= TCPS_FIN_WAIT_2 &&
                    dst->state >= TCPS_FIN_WAIT_2)
                        (*state)->timeout = PFTM_TCP_CLOSED;
-               else if (src->state >= TCPS_FIN_WAIT_2 ||
-                   dst->state >= TCPS_FIN_WAIT_2)
+               else if (src->state >= TCPS_CLOSING &&
+                   dst->state >= TCPS_CLOSING)
                        (*state)->timeout = PFTM_TCP_FIN_WAIT;
                else if (src->state < TCPS_ESTABLISHED ||
                    dst->state < TCPS_ESTABLISHED)


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list