Scott Cheloha <scottchel...@gmail.com> wrote:

> There is one behavior change: in the setitimer(2) swap case it is now
> possible to EFAULT on copyout(9) *after* you have written the new
> timer value and (possibly) started the ITIMER_REAL timeout.
> 
> For example, the following code now yields EFAULT even though a new
> oneshot timer has been started successfully.
> 
>       struct itimerval new;
>       int error;
> 
>       new.it_value.tv_sec = 1;
>       new.it_value.tv_usec = 0;
>       timerclear(&new.it_interval);
>       error = setitimer(ITIMER_REAL, &new, 0xdeadbeef);
>       if (error)
>               warn("setitimer");
> 
> I don't think there is a way to avoid this without introducing a bunch
> of extra complexity.  The critical section is protected by a mutex and
> copyout(9) can sleep, so we have to wait until we leave the critical
> section to copyout(9).  If we leave the mutex to do the copyout(9)
> before writing the new timer value then the swap is no longer atomic.
> Of course, this is not an issue *now*, but when the syscalls are
> unlocked you will lose atomicity.
> 
> Personally I don't think this is a huge deal.  If you're getting
> EFAULT there is a bigger problem in your code.

Let's go back to this first mail.

I suspect it is OK to update the timout, even if the final copyout (and
syscall) then returns EFAULT.

It looks like historical 4.4BSD was "copyout then update".  FreeBSD is
"update them copyout".

I certainly don't think it is worthwhile creating a problem which
is somewhat similar to a TOCTOU.  Even your proposal to do the
address-space range check is a TOCTOU, it fixes nothing since the
address space can still be flipped).

What do other systems do?



Reply via email to