strace seg with select and -ve nfds

Dr. David Alan Gilbert dave at treblig.org
Tue Nov 5 18:27:38 UTC 2013


* Denys Vlasenko (dvlasenk at redhat.com) wrote:
> On 11/05/2013 01:33 PM, Dr. David Alan Gilbert wrote:

> > That still fails (this is FORTIFY detecting the fail).
> 
> Please elaborate. You get a warning about access to fd_set->[__]fds_bits
> array past its declared bounds? How it looks? Does strace abort or what?

$ ./strace test/select
.....

select(3, [2], [2], [2], NULL)          = 1 ()
select(-1, [], NULL, NULL, NULL)        = -1 EINVAL (Invalid argument)
*** buffer overflow detected ***: /home/dg/git/strace-code/./strace terminated

......
select(10000, [2
Program received signal SIGABRT, Aborted.
0x00007ffff7a48f77 in __GI_raise (sig=sig at entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) where
#0  0x00007ffff7a48f77 in __GI_raise (sig=sig at entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff7a4c5e8 in __GI_abort () at abort.c:90
#2  0x00007ffff7a864fb in __libc_message (do_abort=do_abort at entry=2, fmt=fmt at entry=0x7ffff7b97f10 "*** %s ***: %s terminated\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:199
#3  0x00007ffff7b2408c in __GI___fortify_fail (msg=<optimised out>, msg at entry=0x7ffff7b97ea7 "buffer overflow detected") at fortify_fail.c:37
#4  0x00007ffff7b23020 in __GI___chk_fail () at chk_fail.c:28
#5  0x00007ffff7b23fd7 in __fdelt_chk (d=d at entry=1024) at fdelt_chk.c:25
#6  0x0000000000403b19 in decode_select (tcp=0x66b030, args=0x66b048, bitness=BITNESS_CURRENT) at desc.c:522
#7  0x0000000000415b88 in trace_syscall_entering (tcp=0x66b030) at syscall.c:2050
#8  trace_syscall (tcp=tcp at entry=0x66b030) at syscall.c:2722
#9  0x0000000000413f50 in trace () at strace.c:2332
#10 0x00000000004023af in main (argc=<optimised out>, argv=<optimised out>) at strace.c:2362
(gdb) up
#1  0x00007ffff7a4c5e8 in __GI_abort () at abort.c:90
90      abort.c: No such file or directory.
(gdb) 
#2  0x00007ffff7a864fb in __libc_message (do_abort=do_abort at entry=2, fmt=fmt at entry=0x7ffff7b97f10 "*** %s ***: %s terminated\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:199
199     ../sysdeps/unix/sysv/linux/libc_fatal.c: No such file or directory.
(gdb) 
#3  0x00007ffff7b2408c in __GI___fortify_fail (msg=<optimised out>, msg at entry=0x7ffff7b97ea7 "buffer overflow detected") at fortify_fail.c:37
37      fortify_fail.c: No such file or directory.
(gdb) 
#4  0x00007ffff7b23020 in __GI___chk_fail () at chk_fail.c:28
28      chk_fail.c: No such file or directory.
(gdb) 
#5  0x00007ffff7b23fd7 in __fdelt_chk (d=d at entry=1024) at fdelt_chk.c:25
25      fdelt_chk.c: No such file or directory.
(gdb) 
#6  0x0000000000403b19 in decode_select (tcp=0x66b030, args=0x66b048, bitness=BITNESS_CURRENT) at desc.c:522
522                                     if (FD_ISSET(j, fds)) {

So it does look like the FD_ISSET is blowing up.

(For ref this is an Ubuntu Trusty x86-64 linux VM - but I don't see anything specific about
it other than the fact they have fortify on)

> > I can see two things potentially; the simple one is that the types are still
> > wrong so that the -1 starts out as 2^32-1 and goes through the route of being
> > corrected to be 1024*1024 rather than 0.
> 
> Okay, let's do this.
> 
> > However, the other thing I think is being caught here is that fortify is 
> > catching FD_ISSET on a value greater than the size of the fd_set,
> > so the added test below causes it to hit that failure - I guess the
> > only solution there is not to use FD_ISSET or to cap at max-fds rather than
> > the arbitrary 1024*1024 ?
> 
> There can be legitimate programs which use select() in excess of glibc-imposed
> artificial limit on bit array sizes.

> > (I guess you could argue that's a false positive from fortify, but there
> > again I think it is an illegal use of FD_ISSET).
> 
> Do you see a reasonably portable way to check FD_ISSET?

Nope; I think as soon as we go beyond sizeof(fd_set) all bets are off
and even that seems to be an evil way of telling.

> On the related note, how are we doing in "stracing 32-bit app
> with 64-bit strace on a big-endian machine" case?
> In that case, sizeof(long) is important...
> I dread to think about that:(

Yeh that's kind of related to the question I asked in my 1st post;
since we're getting passed args here as long* and this is actually
an int does this work at all on BE machines?
Is there GET_ARG_INT thing in strace this routine should be using?

Yeh mixed ABI is hard - and things mix ABI in different ways,
some systems have to have it in different processes (in which
case two strace binaries might do it) and some can
mix and match in the one (in which case an strace lib built in 
the other endianness and called with libffi might work?)

Dave
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\ gro.gilbert @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/




More information about the Strace-devel mailing list