From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1944 invoked by alias); 21 Nov 2005 20:18:45 -0000 Received: (qmail 1928 invoked by uid 22791); 21 Nov 2005 20:18:44 -0000 X-Spam-Check-By: sourceware.org Received: from sunsite.ms.mff.cuni.cz (HELO sunsite.mff.cuni.cz) (195.113.15.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 21 Nov 2005 20:18:41 +0000 Received: from sunsite.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.mff.cuni.cz (8.13.1/8.13.1) with ESMTP id jALKIbGh004371; Mon, 21 Nov 2005 21:18:37 +0100 Received: (from jakub@localhost) by sunsite.mff.cuni.cz (8.13.1/8.13.1/Submit) id jALKIbqX004370; Mon, 21 Nov 2005 21:18:37 +0100 Date: Mon, 21 Nov 2005 20:18:00 -0000 From: Jakub Jelinek To: Ulrich Drepper , Roland McGrath Cc: Glibc hackers Subject: [PATCH] Fix bindresvport Message-ID: <20051121201837.GS16723@sunsite.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i Mailing-List: contact libc-hacker-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sourceware.org X-SW-Source: 2005-11/txt/msg00022.txt.bz2 Hi! Unless the caller of bindresvport is lucky, the first bindresvport that sees all STARTPORT .. ENDPORT ports (i.e. 600 .. 1023) used will fail. While subsequent bindresvport calls would probably succeed again (as 512 .. 1023 range would be scanned next time), most programs bail out on the first failure. The reason why the bindresvport call that changes startport variable usually fails is that unless port ends with a value > (ENDPORT - (STARTPORT - LOWPORT)) == 935, after jumping to again label it will try all ports in the range portN .. portN+87 (where portN is value of port variable on the startport = LOWPORT; statement), but those usually have been already checked previously to be already bound. The fix can be either to set nports not to STARTPORT - LOWPORT, but ENDPORT - LOWPORT + 1 (guess solution shortest for code size, but might scan up to 423 ports unnecessarily again), or startport = LOWPORT: nports = STARTPORT - 1; port = LOWPORT; (the disadvantage would be that in case of overflowing the 600 .. 1023 area it would always start with port 512), or as done in the patch below, setting port to something in between LOWPORT and STARTPORT - 1 and making sure that wrapping in that loop will be when port >= STARTPORT. 2005-11-21 Jakub Jelinek * sunrpc/bindrsvprt.c (bindresvport): Wrap around to startport in the loop if port is bigger than endport, initially set to ENDPORT. When changing startport, set endport and port appropriately. --- libc/sunrpc/bindrsvprt.c 23 May 2005 19:03:43 -0000 1.11 +++ libc/sunrpc/bindrsvprt.c 21 Nov 2005 19:52:27 -0000 @@ -74,14 +74,13 @@ bindresvport (int sd, struct sockaddr_in int res = -1; int nports = ENDPORT - startport + 1; + int endport = ENDPORT; again: for (i = 0; i < nports; ++i) { sin->sin_port = htons (port++); - if (port > ENDPORT) - { - port = startport; - } + if (port > endport) + port = startport; res = __bind (sd, sin, sizeof (struct sockaddr_in)); if (res >= 0 || errno != EADDRINUSE) break; @@ -90,7 +89,9 @@ bindresvport (int sd, struct sockaddr_in if (i == nports && startport != LOWPORT) { startport = LOWPORT; + endport = STARTPORT - 1; nports = STARTPORT - LOWPORT; + port = LOWPORT + port % (STARTPORT - LOWPORT); goto again; } Jakub