LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File glibc-2.3.90-bindresvport.blacklist.diff of Package glibc.i686 (Project Base:build)

Index: glibc-2.15/sunrpc/bindrsvprt.c
===================================================================
--- glibc-2.15.orig/sunrpc/bindrsvprt.c
+++ glibc-2.15/sunrpc/bindrsvprt.c
@@ -29,28 +29,108 @@
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdio.h>
+#include <ctype.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 
+#define STARTPORT 600
+#define LOWPORT 512
+#define ENDPORT (IPPORT_RESERVED - 1)
+#define NPORTS	(ENDPORT - STARTPORT + 1)
+
+/*
+ * Read the file /etc/rpc.blacklisted, so that we don't bind
+ * to this ports.
+ */
+
+static int blacklist_read;
+static int *list;
+static int list_size = 0;
+
+static void
+load_blacklist (void)
+{
+  FILE *fp;
+  char *buf = NULL;
+  size_t buflen = 0;
+  int size = 0, ptr = 0;
+
+  blacklist_read = 1;
+
+  fp = fopen ("/etc/bindresvport.blacklist", "r");
+  if (NULL == fp)
+    return;
+
+  while (!feof_unlocked (fp))
+    {
+      unsigned long port;
+      char *tmp, *cp;
+      ssize_t n = __getline (&buf, &buflen, fp);
+      if (n < 1)
+        break;
+
+      cp = buf;
+      tmp = strchr (cp, '#');  /* remove comments */
+      if (tmp)
+        *tmp = '\0';
+      while (isspace ((int)*cp))    /* remove spaces and tabs */
+        ++cp;
+      if (*cp == '\0')        /* ignore empty lines */
+        continue;
+      if (cp[strlen (cp) - 1] == '\n')
+        cp[strlen (cp) - 1] = '\0';
+
+      port = strtoul (cp, &tmp, 0);
+      while (isspace(*tmp))
+        ++tmp;
+      if (*tmp != '\0' || (port == ULONG_MAX && errno == ERANGE))
+	continue;
+
+      /* Don't bother with out-of-range ports */
+      if (port < LOWPORT || port > ENDPORT)
+        continue;
+
+      if (ptr >= size)
+	{
+	  size += 10;
+	  list = realloc (list, size * sizeof (int));
+	  if (list == NULL)
+	    {
+	      free (buf);
+	      return;
+	    }
+	}
+
+      list[ptr++] = port;
+    }
+
+  fclose (fp);
+
+  if (buf)
+    free (buf);
+
+  list_size = ptr;
+}
+
 /*
  * Bind a socket to a privileged IP port
  */
 int
 bindresvport (int sd, struct sockaddr_in *sin)
 {
+  static short startport = STARTPORT;
   static short port;
   struct sockaddr_in myaddr;
   int i;
 
-#define STARTPORT 600
-#define LOWPORT 512
-#define ENDPORT (IPPORT_RESERVED - 1)
-#define NPORTS	(ENDPORT - STARTPORT + 1)
-  static short startport = STARTPORT;
+  if (!blacklist_read)
+    load_blacklist ();
 
   if (sin == (struct sockaddr_in *) 0)
     {
@@ -69,6 +149,7 @@ bindresvport (int sd, struct sockaddr_in
       port = (__getpid () % NPORTS) + STARTPORT;
     }
 
+  __set_errno (EADDRINUSE);
   /* Initialize to make gcc happy.  */
   int res = -1;
 
@@ -77,12 +158,22 @@ bindresvport (int sd, struct sockaddr_in
  again:
   for (i = 0; i < nports; ++i)
     {
-      sin->sin_port = htons (port++);
-      if (port > endport)
-	port = startport;
+      int j;
+
+      sin->sin_port = htons (port);
+
+      /* Check, if this port is not blacklisted.  */
+      for (j = 0; j < list_size; j++)
+	if (port == list[j])
+	  goto try_next_port;
+
       res = __bind (sd, sin, sizeof (struct sockaddr_in));
       if (res >= 0 || errno != EADDRINUSE)
 	break;
+
+try_next_port:
+      if (++port > endport)
+	port = startport;
     }
 
   if (i == nports && startport != LOWPORT)