This is the mail archive of the libc-hacker@sourceware.org mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix bindresvport


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  <jakub@redhat.com>

	* 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]