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 :)

Reply via email to