NetBSD Problem Report #3770

Received: (qmail 21081 invoked from network); 22 Jun 1997 13:47:04 -0000
Message-Id: <199706221345.PAA03007@vader.runit.sintef.no>
Date: Sun, 22 Jun 1997 15:45:56 +0200 (MEST)
From: Havard Eidnes <he@vader.runit.sintef.no>
Reply-To: he@vader.runit.sintef.no
To: gnats-bugs@gnats.netbsd.org
Cc: Jarle.Greipsland@runit.sintef.no, sthaug@nethelp.no
Subject: Setting SO_SNDLOWAT to 0 causes busy-wait inside kernel
X-Send-Pr-Version: 3.95

>Number:         3770
>Category:       kern
>Synopsis:       Setting SO_SNDLOWAT to 0 causes busy-wait inside kernel
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 22 06:50:00 +0000 1997
>Closed-Date:    Tue Jun 24 20:05:23 +0000 1997
>Last-Modified:  Tue Jun 24 20:06:13 +0000 1997
>Originator:     Havard Eidnes
>Release:        NetBSD-1.2.1 (and newer versions too)
>Organization:
	SINTEF RUNIT
>Environment:
System: NetBSD vader.runit.sintef.no 1.2G NetBSD 1.2G (VADER) #2: Mon Jun 16 21:58:48 MEST 1997 he@vader.runit.sintef.no:/usr/src/sys/arch/i386/compile/VADER i386


>Description:
	Setting SO_SNDLOWAT to 0 on a TCP socket and sending to a non-
	local host (reachable with some delay and/or with limited bandwidth)
	will cause the sending machine to go into busy-wait inside the kernel.

	What appears to happen is this:

	 o select() will always return that the socket is writable, even when
	   sbspace() returns 0 due to the >= comparison in the sowritable()
	   macro.

	 o once the user writes, it appears that sosend() will loop internally
	   since sbspace() is 0, no data will be added to the outgoing buffer,
	   and the residue for each turn of the loop stays the same.  The test
	   for the low-water mark does not kick in, so sbwait() will not be
	   called.

	It can clearly be argued that the program setting SO_SNDLOWAT to 0
	is buggy, but the robustness against this mis-setting should be better
	to prevent denial-of-service attacks by local users.

>How-To-Repeat:
	Run the attached program towards a non-local host reachable via
	a "thin" line or over some delay by calling it:

	% tstlowat low-water-mark number-of-buffers ip-address

	and trying low-water-mark of 0.

--- snip, snip --
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

main(int argc, char *argv[])
{
	struct sockaddr_in sin;
	int i, n, s, sndlowat;
	char buf[65536];

	sndlowat = atoi(argv[1]);
	n = atoi(argv[2]);

	if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
		perror("socket"); exit(1);
	}
	if (setsockopt(s, SOL_SOCKET, SO_SNDLOWAT, (char *)&sndlowat,
		       sizeof sndlowat) < 0) {
		perror("setsockopt"); exit(1);
	}
	sin.sin_port = htons(9);	/* Discard port */
	sin.sin_family = AF_INET;
	if (inet_aton(argv[3], &sin.sin_addr) == 0) {
		fprintf(stderr, "inet_aton"); exit(1);
	}
	if (connect(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
		perror("connect"); exit(1);
	}

	for (i=0; i<n; i++) {
		if (write(s, buf, sizeof buf) < 0) {
			perror("write"); exit(1);
		}
	}
}
--- snip, snip ---

>Fix:
	Sorry, I don't know.

	Does a socket low-water mark of 0 really make sense?
	If not, return EINVAL or something like that on an attempt at
	setting it to 0?
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: thorpej 
State-Changed-When: Tue Jun 24 13:05:23 PDT 1997 
State-Changed-Why:  
low-water marks less than 1 are now disallowed, thus addressing this problem. 
However, the logic for determining socket buffer writability may want a 
lookthrough. 
>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.49 2026/05/14 01:52:41 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.