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