nmap hang due to BADF ioctl inside select call is returning good rc
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
glibc (Ubuntu) |
New
|
Undecided
|
Unassigned | ||
nmap (Ubuntu) |
Incomplete
|
Undecided
|
Unassigned |
Bug Description
Hi,
the reproducibility of this is hard, but I've seen it twice in a week now so it is not a stray cosmic ray after all.
I've seen nmap hang that was running with a timeout already which made me wonder.
$ nmap -Pn 192.168.122.0/24 --host-timeout 10
In PS the output looks normal usually in a wchan with a timeout:
$ ps axlf
...
4 0 10155 0 20 0 25372 17320 poll_s S ? 0:07 nmap -Pn 192.168.122.0/24 --host-timeout 10
Full wchan:
cat /proc/10155/wchan
poll_schedule_
I found that nmap isn't dead, it is looping it seems.
Obviously on GDB you always find it at the timeout
0x00007fe5b73a725a in __GI___select (nfds=nfds@entry=5, readfds=
timeout=
41 ../sysdeps/
(gdb) bt
#0 0x00007fe5b73a725a in __GI___select (nfds=nfds@entry=5, readfds=
timeout=
#1 0x000055900ff4f838 in pcap_select (p=p@entry=
#2 0x000055900ff4fa15 in pcap_select (usecs=999993, p=0x55901131ec10) at netutil.cc:1031
#3 read_reply_pcap (pd=0x55901131ec10, to_usec=999993, accept_
p=p@
#4 0x000055900ff56014 in read_arp_reply_pcap (pd=<optimized out>, sendermac=
rcvdtime=
#5 0x000055900fefce80 in get_arp_result (USI=0x7ffec6db
#6 0x000055900fef5e67 in ultra_scan(
#7 0x000055900ff0e1cc in arpping (hostbatch=
#8 0x000055900ff0ed00 in refresh_hostbatch (hs=<optimized out>, exclude_
#9 0x000055900ff0ee5d in nexthost (hs=hs@
at targets.cc:644
#10 0x000055900fec8ec3 in nmap_main (argc=<optimized out>, argv=0x7ffec6db
#11 0x000055900fe9e215 in main (argc=5, argv=0x7ffec6db
But strace has shown that the syscall is bad
# strace -rT -p 10155
strace: Process 10155 attached
0.000000 select(5, [4], NULL, NULL, {tv_sec=0, tv_usec=438201}) = 0 (Timeout) <0.438773>
0.439032 ioctl(-1, TIOCGPGRP, 0x7ffec6db1784) = -1 EBADF (Bad file descriptor) <0.000028>
0.000170 getpgrp() = 0 <0.000021>
0.000092 select(5, [4], NULL, NULL, {tv_sec=0, tv_usec=999992}) = 0 (Timeout) <1.001123>
1.001253 ioctl(-1, TIOCGPGRP, 0x7ffec6db1784) = -1 EBADF (Bad file descriptor) <0.000019>
0.000075 getpgrp() = 0 <0.000018>
I expected nmap to give up if the select call went bad - and indeed the code would:
1008 FD_SET(fd, &rfds);
1009
1010 do {
1011 errno = 0;
1012 ret = select(fd + 1, &rfds, NULL, NULL, timeout);
1013 if (ret == -1) {
1014 if (errno == EINTR)
1015 netutil_error("%s: %s", __func__, strerror(errno));
1016 else
1017 netutil_fatal("Your system does not support select()ing on pcap devices (%s). PLEASE REPORT THIS ALONG WITH DETAILED SYSTEM INFORMATION TO THE nmap-dev MAILING LIST!", strerror(errno));
But glibc returns a good RC on this ioctl error:
1012 ret = select(fd + 1, &rfds, NULL, NULL, timeout);
(gdb) n
1013 if (ret == -1) {
(gdb) p ret
$1 = 1
There isn't much more code in glbic shown in GDB
Breakpoint 1, pcap_select (p=p@entry=
976 in netutil.cc
(gdb) c
Continuing.
Breakpoint 2, __GI___select (nfds=nfds@entry=5, readfds=
at ../sysdeps/
39 {
(gdb) n
41 return SYSCALL_CANCEL (select, nfds, readfds, writefds, exceptfds,
(gdb) s
Is it a bug in glibc, would it need to return -1 in that case?
Note: it also is a bug in nmap to loop on it but they could say "but the answer fromt he socket call is wrong", so lets sort that out first.
nmap task is incomplete until we know a hard reason glibc is returning rc=1 on a underlying EBADF ioctl.