Bug#588144: libc6: As shipped /etc/bindresvport.blacklist lines are ignored due to tabs
>From lenny's glibc-2.7/debian/patches/any/local-bindresvport_blacklist.diff
the code to read and parse a single line is:
+ 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);
+ if (*tmp != '\0' || (port == ULONG_MAX && errno == ERANGE))
+ continue;
This has a couple of issues.
The one that causes a problem is that it skips leading but not trailing
spaces. If the last digit of the number is followed by anything other
than '\0', '#', or '\n', the line will be skipped.
Code should be added after strtoul() to skip the spaces:
while (isspace ((int)*tmp)) /* remove spaces and tabs */
++tmp;
Also, a comment purports to "ignore empty lines" by checking for a null
character, but it does this *before* replacing a newline at the end with
a null character. As it happens, lines consisting solely of a newline
will be ignored, but only because of this code:
+ /* Don't bother with out-of-range ports */
+ if (port < LOWPORT || port > ENDPORT)
+ continue;
Therefore, the "ignore empty lines" comment is misleading.
In an Ubuntu bug report, I gave good directions for testing this.
https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/306007
I have confirmed the directions work on lenny (I have an Ubuntu desktop
and a lenny server). (Of course, I got different port numbers, but still
in the 600-999 range I reserved.)
0. Backup the file:
$ sudo mv /etc/bindresvport.blacklist /etc/bindresvport.blacklist.bak
1. Reserve all ports 600-999, with the format used for shipped
bindresvport.blacklist (e.g., "631\t# cups")
$ perl -e 'for ($i=600; $i<1000; $i++) {print "$i\t# foo\n";}' | sudo
dd of=/etc/bindresvport.blacklist
7+1 records in
7+1 records out
4011 bytes (4.0 kB) copied, 6.5962e-05 s, 60.8 MB/s
2. Restart nis (or a different service as available).
$ sudo /etc/init.d/nis restart
* Starting NIS service
3. Check what port it got:
$ sudo netstat --inet -nap | grep ypbind
tcp 0 0 0.0.0.0:724 0.0.0.0:* LISTEN 29803/ypbind
udp 0 0 0.0.0.0:723 0.0.0.0:* 29803/ypbind
udp 0 0 0.0.0.0:724 0.0.0.0:* 29803/ypbind
4. Note that it falls in the range 600-999 (there is a small 24 out of
424 chance it will not -- try again).
This also fails with spaces, substituting the perl command in step 1:
$ perl -e 'for ($i=600; $i<1000; $i++) {print "$i # foo\n";}' | sudo
dd of=/etc/bindresvport.blacklist
It works with the '#' character directly following the port number:
$ perl -e 'for ($i=600; $i<1000; $i++) {print "$i# foo\n";}' | sudo dd
of=/etc/bindresvport.blacklist
or with the port number on the line by itself:
$ perl -e 'for ($i=600; $i<1000; $i++) {print "$i\n";}' | sudo dd
of=/etc/bindresvport.blacklist
In the last two cases I get:
tcp 0 0 0.0.0.0:1001 0.0.0.0:* LISTEN 29923/ypbind
udp 0 0 0.0.0.0:1000 0.0.0.0:* 29923/ypbind
udp 0 0 0.0.0.0:1001 0.0.0.0:* 29923/ypbind
Reply to: