chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / debian / patches / any / local-bindresvport_blacklist.diff
1 Patch from the OpenSUSE glibc
2
3 ---
4  sunrpc/bindrsvprt.c |  107 ++++++++++++++++++++++++++++++++++++++++++++++++----
5  1 file changed, 99 insertions(+), 8 deletions(-)
6
7 --- a/sunrpc/bindrsvprt.c
8 +++ b/sunrpc/bindrsvprt.c
9 @@ -29,28 +29,108 @@
10   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11   */
12  
13 +#include <stdio.h>
14 +#include <ctype.h>
15  #include <errno.h>
16 +#include <stdlib.h>
17  #include <unistd.h>
18  #include <string.h>
19  #include <sys/types.h>
20  #include <sys/socket.h>
21  #include <netinet/in.h>
22  
23 +#define STARTPORT 600
24 +#define LOWPORT 512
25 +#define ENDPORT (IPPORT_RESERVED - 1)
26 +#define NPORTS (ENDPORT - STARTPORT + 1)
27 +
28 +/*
29 + * Read the file /etc/rpc.blacklisted, so that we don't bind
30 + * to this ports.
31 + */
32 +
33 +static int blacklist_read;
34 +static int *list;
35 +static int list_size = 0;
36 +
37 +static void
38 +load_blacklist (void)
39 +{
40 +  FILE *fp;
41 +  char *buf = NULL;
42 +  size_t buflen = 0;
43 +  int size = 0, ptr = 0;
44 +
45 +  blacklist_read = 1;
46 +
47 +  fp = fopen ("/etc/bindresvport.blacklist", "r");
48 +  if (NULL == fp)
49 +    return;
50 +
51 +  while (!feof (fp))
52 +    {
53 +      unsigned long port;
54 +      char *tmp, *cp;
55 +      ssize_t n = __getline (&buf, &buflen, fp);
56 +      if (n < 1)
57 +        break;
58 +
59 +      cp = buf;
60 +      tmp = strchr (cp, '#');  /* remove comments */
61 +      if (tmp)
62 +        *tmp = '\0';
63 +      while (isspace ((int)*cp))    /* remove spaces and tabs */
64 +        ++cp;
65 +      if (*cp == '\0')        /* ignore empty lines */
66 +        continue;
67 +      if (cp[strlen (cp) - 1] == '\n')
68 +        cp[strlen (cp) - 1] = '\0';
69 +
70 +      port = strtoul (cp, &tmp, 0);
71 +      while (isspace(*tmp))
72 +        ++tmp;
73 +      if (*tmp != '\0' || (port == ULONG_MAX && errno == ERANGE))
74 +       continue;
75 +
76 +      /* Don't bother with out-of-range ports */
77 +      if (port < LOWPORT || port > ENDPORT)
78 +        continue;
79 +
80 +      if (ptr >= size)
81 +       {
82 +         size += 10;
83 +         list = realloc (list, size * sizeof (int));
84 +         if (list == NULL)
85 +           {
86 +             free (buf);
87 +             return;
88 +           }
89 +       }
90 +
91 +      list[ptr++] = port;
92 +    }
93 +
94 +  fclose (fp);
95 +
96 +  if (buf)
97 +    free (buf);
98 +
99 +  list_size = ptr;
100 +}
101 +
102  /*
103   * Bind a socket to a privileged IP port
104   */
105  int
106  bindresvport (int sd, struct sockaddr_in *sin)
107  {
108 +  static short startport = STARTPORT;
109    static short port;
110    struct sockaddr_in myaddr;
111    int i;
112  
113 -#define STARTPORT 600
114 -#define LOWPORT 512
115 -#define ENDPORT (IPPORT_RESERVED - 1)
116 -#define NPORTS (ENDPORT - STARTPORT + 1)
117 -  static short startport = STARTPORT;
118 +  if (!blacklist_read)
119 +    load_blacklist ();
120  
121    if (sin == (struct sockaddr_in *) 0)
122      {
123 @@ -69,6 +149,7 @@
124        port = (__getpid () % NPORTS) + STARTPORT;
125      }
126  
127 +  __set_errno (EADDRINUSE);
128    /* Initialize to make gcc happy.  */
129    int res = -1;
130  
131 @@ -77,12 +158,22 @@
132   again:
133    for (i = 0; i < nports; ++i)
134      {
135 -      sin->sin_port = htons (port++);
136 -      if (port > endport)
137 -       port = startport;
138 +      int j;
139 +
140 +      sin->sin_port = htons (port);
141 +
142 +      /* Check, if this port is not blacklisted.  */
143 +      for (j = 0; j < list_size; j++)
144 +       if (port == list[j])
145 +         goto try_next_port;
146 +
147        res = __bind (sd, sin, sizeof (struct sockaddr_in));
148        if (res >= 0 || errno != EADDRINUSE)
149         break;
150 +
151 +try_next_port:
152 +      if (++port > endport)
153 +       port = startport;
154      }
155  
156    if (i == nports && startport != LOWPORT)