From brandt@fokus.gmd.de  Fri Dec 14 03:08:45 2001
Return-Path: <brandt@fokus.gmd.de>
Received: from mailhub.fokus.gmd.de (mailhub.fokus.gmd.de [193.174.154.14])
	by hub.freebsd.org (Postfix) with ESMTP id D10FD37B416
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 14 Dec 2001 03:08:42 -0800 (PST)
Received: from fokus.gmd.de (beagle [193.175.132.100])
	by mailhub.fokus.gmd.de (8.11.6/8.11.6) with ESMTP id fBEB8f524200
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 14 Dec 2001 12:08:41 +0100 (MET)
Received: (from hbb@localhost)
	by fokus.gmd.de (8.11.6/8.11.0) id fBEB8fL69040;
	Fri, 14 Dec 2001 12:08:41 +0100 (CET)
	(envelope-from hbb)
Message-Id: <200112141108.fBEB8fL69040@fokus.gmd.de>
Date: Fri, 14 Dec 2001 12:08:41 +0100 (CET)
From: Hartmut Brandt <brandt@fokus.gmd.de>
Reply-To: Hartmut Brandt <brandt@fokus.gmd.de>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: small SO_RCVTIMEO values are taken to be zero
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         32827
>Category:       kern
>Synopsis:       small SO_RCVTIMEO values are taken to be zero
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    maxim
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Dec 14 03:10:01 PST 2001
>Closed-Date:    Sun Dec 15 01:26:30 PST 2002
>Last-Modified:  Sun Dec 15 01:26:30 PST 2002
>Originator:     Hartmut Brandt
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
FhG Fokus
>Environment:
System: FreeBSD beagle.fokus.gmd.de 5.0-CURRENT FreeBSD 5.0-CURRENT #3: Mon Dec 10 11:29:08 CET 2001 hbb@beagle.fokus.gmd.de:/opt/obj/usr/src/sys/BEAGLE i386


	
>Description:

If the receive timeout of a socket is set to a number of microseconds larger
than 0 but lesser than the value of 'tick', the code in uipc_socket.c 

			/* assert(tick > 0); */
			/* assert(ULONG_MAX - SHRT_MAX >= 1000000); */
1250:			val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick;
			if (val > SHRT_MAX) {
				error = EDOM;
				goto bad;

computes a timeout value for the socket of 0, causing subsequence receive
operations to block as if no timeout had been specified. This is unexpected
and not easily controllable by the application (one has to either fetch the
value of tick via sysctl or always make a getsockopt after the setsockopt).
Only timeout values with tv_sec==0 and tv_usec==0 should block indefinitely.

	
>How-To-Repeat:

Compile and run the following program and find it to timeout the first
receive after 1 second and to block forever on thesecond receive (given
no UDP packet is seen on 127.0.0.1:10000).

# include <sys/types.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <stdio.h>
# include <errno.h>
# include <string.h>
# include <err.h>
# include <netinet/in.h>

int
main(int argc, char *argv[])
{
	int s;
	struct timeval tv;
	struct sockaddr_in sin;
	u_char buf[1000];

	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
		err(1, "socket");

	sin.sin_len = sizeof(sin);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(10000);
	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
		err(1, "bind");

	tv.tv_sec = 1;
	tv.tv_usec = 0;
	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1)
		err(1, "setsockopt");

	printf("recv 1...\n");
	if (recv(s, buf, sizeof(buf), 0) == -1)
		warn("recv");

	tv.tv_sec = 0;
	tv.tv_usec = 100;
	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1)
		err(1, "setsockopt");

	printf("recv 2...\n");
	if (recv(s, buf, sizeof(buf), 0) == -1)
		warn("recv");

	return (0);
}
	

>Fix:

Apply the following patch to /usr/src/sys/kern/uipc_socket.c (this fixes
the same problem for the send case):

Index: uipc_socket.c
===================================================================
RCS file: /usr/ncvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.106
diff -r1.106 uipc_socket.c
1254a1255,1256
> 			if (val == 0 && (tv.tv_usec != 0 || tv.tv_sec != 0))
> 				val = 1;


	


>Release-Note:
>Audit-Trail:

From: Sheldon Hearn <sheldonh@starjuice.net>
To: Hartmut Brandt <brandt@fokus.gmd.de>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/32827: small SO_RCVTIMEO values are taken to be zero 
Date: Sun, 30 Dec 2001 14:41:15 +0200

 On Fri, 14 Dec 2001 12:08:41 +0100, Hartmut Brandt wrote:
 
 > >Category:       kern
 > >Synopsis:       small SO_RCVTIMEO values are taken to be zero
 
 I've asked for review on the freebsd-audit mailing list.  Hopefully,
 someone will take a look soon.
 
 Ciao,
 Sheldon.
State-Changed-From-To: open->patched 
State-Changed-By: maxim 
State-Changed-When: Wed Nov 27 05:37:53 PST 2002 
State-Changed-Why:  
Fixed in rev. 1.138 src/sys/kern/uipc_socket.c in -CURRENT. 
Thanks for the patch! 


Responsible-Changed-From-To: freebsd-bugs->maxim 
Responsible-Changed-By: maxim 
Responsible-Changed-When: Wed Nov 27 05:37:53 PST 2002 
Responsible-Changed-Why:  
Will MFC the diff in two weeks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=32827 
State-Changed-From-To: patched->closed 
State-Changed-By: maxim 
State-Changed-When: Sun Dec 15 01:24:56 PST 2002 
State-Changed-Why:  
Fixed in rev. 1.138 and rev. 1.68.2.22 src/sys/kern/uipc_socket.c in -CURRENT 
and -STABLE. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=32827 
>Unformatted:
