On Wed, May 09, 2018 at 11:54:15AM +0300, Paul Irofti wrote: > On Wed, May 09, 2018 at 10:37:14AM +0200, Martin Pieuchot wrote: > > On 08/05/18(Tue) 14:57, Scott Cheloha wrote: > > > Hi, > > > > > > futex(2) doesn't do any range checking for timeout for FUTEX_WAIT, > > > though recent Linux does so. I assume we'd also want to validate > > > timeout before waiting. > > > > Could you use timespecfix() for that? Look how pselect(2) or ppoll(2) > > do it. Btw pirofti@ had a similar diff. > > [...] > > I was keeping that change for after the new semaphore implementation goes > in so I can more easily separate fallout sources if any. > > So I will commit this change afterwards if you guys don't mind or don't > see this crashing actual applications in the wild.
That works for me. One question below. > > > Index: sys/kern/sys_futex.c > > > =================================================================== > > > RCS file: /cvs/src/sys/kern/sys_futex.c,v > > > retrieving revision 1.7 > > > diff -u -p -r1.7 sys_futex.c > > > --- sys/kern/sys_futex.c 24 Apr 2018 17:19:35 -0000 1.7 > > > +++ sys/kern/sys_futex.c 8 May 2018 19:49:27 -0000 > > > @@ -214,6 +214,8 @@ futex_wait(uint32_t *uaddr, uint32_t val > > > if (KTRPOINT(p, KTR_STRUCT)) > > > ktrabstimespec(p, &ts); > > > #endif > > > + if (ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) > > > + return EINVAL; > > > to_ticks = (uint64_t)hz * ts.tv_sec + > > > (ts.tv_nsec + tick * 1000 - 1) / (tick * 1000) + 1; > > > if (to_ticks > INT_MAX) > > This is better: > > > Index: sys/kern/sys_futex.c > =================================================================== > RCS file: /cvs/src/sys/kern/sys_futex.c,v > retrieving revision 1.6 > diff -u -p -u -p -r1.6 sys_futex.c > --- sys/kern/sys_futex.c 8 Jan 2018 22:33:13 -0000 1.6 > +++ sys/kern/sys_futex.c 4 Apr 2018 11:53:59 -0000 > @@ -210,6 +210,8 @@ futex_wait(uint32_t *uaddr, uint32_t val > > if ((error = copyin(timeout, &ts, sizeof(ts)))) > return error; > + if ((error = timespecfix(&ts))) > + return error; > #ifdef KTRACE > if (KTRPOINT(p, KTR_STRUCT)) > ktrabstimespec(p, &ts); Is it better to filter for non-normal input before the trace? My thought was that it'd be useful to trace the input before returning EINVAL, but maybe I'm missing a drawback there. -Scott > > > Index: regress/sys/kern/futex/futex.c > > > =================================================================== > > > RCS file: /cvs/src/regress/sys/kern/futex/futex.c,v > > > retrieving revision 1.2 > > > diff -u -p -r1.2 futex.c > > > --- regress/sys/kern/futex/futex.c 30 Apr 2017 10:11:03 -0000 > > > 1.2 > > > +++ regress/sys/kern/futex/futex.c 8 May 2018 19:49:27 -0000 > > > @@ -37,7 +37,7 @@ int > > > main(int argc, char *argv[]) > > > { > > > struct sigaction sa; > > > - struct timespec abs = { 0, 5000 }; > > > + struct timespec abs = { 0, 5000 }, bogus; > > > pthread_t thread; > > > > > > /* Invalid operation */ > > > @@ -48,6 +48,17 @@ main(int argc, char *argv[]) > > > > > > /* If (lock != 1) return EAGAIN */ > > > assert(futex_twait(&lock, 1, 0, NULL) == EAGAIN); > > > + > > > + /* Invalid timeout */ > > > + bogus.tv_sec = -1; > > > + bogus.tv_nsec = 0; > > > + assert(futex(&lock, FUTEX_WAIT, lock, &bogus, NULL) == EINVAL); > > > + bogus.tv_sec = 0; > > > + bogus.tv_nsec = -1; > > > + assert(futex(&lock, FUTEX_WAIT, lock, &bogus, NULL) == EINVAL); > > > + bogus.tv_sec = 0; > > > + bogus.tv_nsec = 1000000001; > > > + assert(futex(&lock, FUTEX_WAIT, lock, &bogus, NULL) == EINVAL); > > > > > > /* Deadlock for 5000ns */ > > > assert(futex_twait(&lock, 0, CLOCK_REALTIME, &abs) == ETIMEDOUT); > > I like the regress test :)