standards/149980: [libc] [patch] negative value integer to
nanosleep(2) should fail with EINVAL
arundel at freebsd.org
Wed Feb 23 23:27:06 UTC 2011
On Thu Feb 24 11, Bruce Evans wrote:
> On Wed, 23 Feb 2011, Alexander Best wrote:
> >The following reply was made to PR standards/149980; it has been noted by
> >From: Alexander Best <arundel at freebsd.org>
> >To: bug-followup at freebsd.org
> >Subject: Re: standards/149980: [libc] [patch] negative value integer to
> >nanosleep(2) should fail with EINVAL
> >Date: Wed, 23 Feb 2011 21:38:02 +0000
> >since this might break some ports or 3rd party applications, how about
> >something like kern.allow_negative_sleep?
> It shouldn't fail. POSIX doesn't require it to fail, at least in the old
> 2001 draft7:
yes. the same entry is in IEEE Std 1003.1-2008. however Garrett Cooper
mentioned in his PR that he talked to some POSIX people and so his information
might be different from the one in the specs. it might be possible that the
POSIX people expect time_t to be unsigned.
i think Garrett as the originator of this PR should clear things up.
> % 26886 ERRORS
> % 26887 The nanosleep( ) function shall fail if:
> % 26888 [EINTR] The nanosleep( ) function was
> interrupted by a signal.
> % 26889 [EINVAL] The rqtp argument specified a
> nanosecond value less than zero or greater than
> % 26890 or equal to 1000 million.
> It just specifies EINVAL for out-of-bounds nanoseconds values because those
> give an invalid timeval. Negative values for the seconds field are valid
> if they are representable.
> A negative sleep time is equally physically impossible as a sleep time
> of 0, but I haven't seen any proposals to break the latter. But if you
> want full breakage, be sure to disallow both negative timevals and ones
> longer than the lifetime of the universe ;-).
> In private or maybe public old mail about this, I pointed out bugs in
> itimerfix() and itimespecfix(). These functions do generate EINVAL
> for negative times and are very broken for large positive values
> considerably shorter than the lifetime of the universe for 32-bit
> time_t's but considerably longer than the lifetime of the universe for
> 64-bit time_t's. Callers depend on the time_t's being considerably
> less than the time until the time_t's wrap around. This used ti be
> avoided (until 2035 for 32-bit signed time_t's) by restricting the
> time_t's to 1000 million seconds (3+ years) in itimerfix(). This has
> been broken, so anyone who can make syscalls that use itimers can cause
> overflows in the kernel. Limiting the maximum itimer to 100 million
> seconds or even the lifetime of the univers is not supported by POSIX,
> but it is what BSD always did until FreeBSD broke it. itimerfix() and
> itimespecfix() also do bogus rounding up to a multiple of the timer
> granularity. This is mostly cosmetic, but breaks syscalls that return
> residual times. itimespecfix() also has a namespace error. It corresponds
> to itimerfix(). There is no itimevalfix(), but there is a confusingly
> similar timevalfix().
> These bugs don't directly affect nanosleep(), since it doesn't use
> itimespecfix(), perhaps intentionally to avoid breaking it for negative
> times. Its overflow bugs bugs are smaller in nanosleep(), since it
> loops internally to handle large times and its algorithm of comparing
> the current time with the end time in case it wakes up early is fairly
> robust. However, it blindly adds timespecs using timespecadd(&ts,
> rqt), where ts is initially the current time (spec) and *rqt is the
> arg, and ts is finally the end time. *rqt must be limited to prevent
> overflow of this. The usual (but broken) limit of 100 million seconds
> would work (until 2035) as elsewhere. When overflow occurs, the result
> is undefined. The actual behaviour is normally a garbage negative end
> time in ts, and although there are lots of compensating overflows
> (adding and subtracting the current time), I think the logic isn't all
> accidentally correct throughout.
More information about the freebsd-standards