Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Apr 1999 03:22:22 +0200 (CEST)
From:      dada@sbox.tu-graz.ac.at
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/11252: lite2 bugfixes missing in kern/uipc_socket.c
Message-ID:  <199904210122.DAA00732@localhost.kfunigraz.ac.at>

next in thread | raw e-mail | index | archive | help

>Number:         11252
>Category:       kern
>Synopsis:       lite2 bugfixes missing in kern/uipc_socket.c
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 20 18:50:00 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Martin Kammerhofer
>Release:        FreeBSD 2.2.8-STABLE i386
>Organization:
Graz University of Technology
>Environment:
>Description:

FreeBSD (all versions) is shipped with 2 bugs in get/setsockopt(2)

Bug #1:
Manpage setsockopt(2) says
	...
     decides it is unable to deliver the information (a timeout period, termed
     the linger interval, is specified in seconds in the setsockopt() call
     when SO_LINGER is requested).  If SO_LINGER is disabled and a close(2) is
	...

The problem is: You get exactly 1% of the requested linger time!
Why? The manpage says it is in seconds but it is used in soclose()
like this:
			while (so->so_state & SS_ISCONNECTED) {
				error = tsleep((caddr_t)&so->so_timeo,
				    PSOCK | PCATCH, "soclos", so->so_linger);

Unfortunately tsleep counts time in units of 1/HZ seconds. This is why
you get only one percent (with a HZ=100 kernel).

Bug #2:
Range checking for setsockopt(2) arguments SO_SNDTIMEO and SO_RCVTIMEO
is broken. This causes perfect reasonable timeouts to be rejected with
error EDOM. This problem is aggravated if your run a kernel with raised
HZ value (e.g. for ALTQ).

FreeBSD uses the buggy code from the original lite import. Both bugs
had been already fixed in lite2. It is in the repository but has never
been integrated.

>How-To-Repeat:

BUG #1:
struct linger l = {1, 1000};

setsockopt(s, SOL_SOCKET, SO_LINGER, &l, sizeof l);
...
close(s); // Will return after 10 seconds if still data queued for sending.
          // Achieve this by sending lots of data to an application that
	  // accept()s but doesn't read it's socket.

BUG #2:
Compile a kernel with HZ=1000 and find out that only negative send
and receive timeouts for sockets are acceptable. :)

>Fix:
cvs diff -r1.1.1.1 -r1.1.1.2 src/sys/kern/uipc_socket.c

Note that there's a small piece of code in sys/netinet/tcp_userreq.c
that relies on the bug:
	if ((so->so_options & SO_LINGER) && so->so_linger == 0)
		so->so_linger = TCP_LINGERTIME * hz;
                                              ^^^^^
See the commit of Revision 1.10  Thu Feb 16 01:42:45 1995 UTC by Wollman.
Since lite2 fixed soclose() this commit should be undone together with
the lite2 patch.

For a better fix change sb_timeo in struct sockbuf (socketvar.h) from
short to int! Even if long timeouts do not make sense this is much too
dependend on HZ. Bit saving mentality brought us all this Y2K issues...

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


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199904210122.DAA00732>