[Toybox] sleep overflow

Rob Landley rob at landley.net
Fri Aug 17 17:04:06 PDT 2012


On 08/15/2012 07:48 AM, Elie De Brauwer wrote:
> Hello all,
> 
> Found a little bug in sleep, for insanely large values (so insane people
> might use them to sleep forever and they will be disappointed when
> forever means zero) sleep might return immediately ( config SLEEP_FLOAT
> is impact, config SLEEP and config USLEEP are not affected).
> 
> Now sleep (with floating point support) functions as follows:
> 
> edb at lapedb:~/edb-stuff/toybox/toybox$ strace -e nanosleep  ./toybox
> sleep 24855d
> nanosleep({2147472000, 0}, ^C <unfinished ...>
> edb at lapedb:~/edb-stuff/toybox/toybox$ strace -e nanosleep  ./toybox
> sleep 24856d
> nanosleep({2147558400, 2147483648}, NULL) = -1 EINVAL (Invalid argument)
> 
> So it'd better not sleep longer than 68 years :D.

Your patch is actually a workaround for a glibc bug.  On uClibc:

$ strace ./toybox sleep 24855d
execve("./toybox", ["./toybox", "sleep", "24855d"], [/* 37 vars */]) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo
...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo
...}) = 0
umask(0)                                = 022
umask(022)                              = 0
brk(0)                                  = 0x24c1000
brk(0x24c2000)                          = 0x24c2000
umask(0)                                = 022
umask(022)                              = 0
nanosleep({2147472000, 0},

And it sits there.

> This is caused by an overflow in the argument parsing, if it exceeds
> INT_MAX (0x80000000 on 32 bit) nanosleep will start to consider certain
> variables as negative.

Actually the overflow is being caught, the problem is that glibc is then
maxing out the nanoseconds field, and the kernel only accepts a certain
maximum value in the nanoseconds before barfing. (You should never
_need_ to specify more than 1 billion in there, because that's what the
seconds field is for.)

> I've attached a patch which just tops this off
> to INT_MAX. With it, it behaves more or less  as 'real' sleep:
> 
> edb at lapedb:~/edb-stuff/toybox/toybox$ strace -e nanosleep  ./toybox
> sleep 24856d
> nanosleep({2147483647, 0}, ^C <unfinished ...>

Ooh, decisions, decisions.

Anybody know how bionic or musl handles this? (I need to finish
migrating to my new nebook so I have space to set up test environments.
This old netbook only has 3 gigs free.)

In _theory_ time_t is a long for a reason. In practice, 60 year waits
might as well be "forever"...

Rob
-- 
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code.
Either it's "mere aggregation", or a license violation.  Pick one.

 1345248246.0


More information about the Toybox mailing list