On Thu, Jan 09, 2020 at 04:10:03PM +0100, Martin Pieuchot wrote:
> case SO_RCVTIMEO:
> {
> struct timeval tv;
> - int val;
> + uint64_t nsecs;
>
> if (m == NULL || m->m_len < sizeof (tv))
> return (EINVAL);
> memcpy(&tv, mtod(m, struct timeval *), sizeof tv);
> - val = tvtohz(&tv);
> - if (val > USHRT_MAX)
> - return (EDOM);
> -
> + nsecs = TIMEVAL_TO_NSEC(&tv);
There was a range check before, I would like to keep that.
And tv is user data, we should be more paranoid.
Something like this, or a new macro TIMEVAL_ISVALID() ?
if (tv->tv_usec < 0 || tv->tv_usec >= 1000000 ||
TIMEVAL_TO_NSEC(&tv) == UINT64_MAX)
return (EDOM);
> case SO_SNDTIMEO:
> - so->so_snd.sb_timeo = val;
> + so->so_snd.sb_nsecs = nsecs;
The send buffer field is stil a timeout and not some nanoseconds.
Can we call it sb_timeo_nsec ?
> - memset(&tv, 0, sizeof(tv));
> - tv.tv_sec = val / hz;
> - tv.tv_usec = (val % hz) * tick;
> + NSEC_TO_TIMEVAL(nsecs, &tv);
The memset is here to clear padding bytes and to prevent kernel
memory leakage to userland. Please keep it.
> +static inline uint64_t
> +TIMEVAL_TO_NSEC(const struct timeval *tv)
> +{
> + if (tv->tv_sec > (UINT64_MAX - tv->tv_usec * 1000ULL) / 1000000000ULL)
> + return UINT64_MAX;
> + return tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL;
> +}
I think this overflow check is correct under the assumption that
tv_usec is in a valid range.
bluhm