This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v2] sysdeps/nanosleep: Use clock_nanosleep_time64 if avaliable
- From: Joseph Myers <joseph at codesourcery dot com>
- To: Alistair Francis <alistair dot francis at wdc dot com>
- Cc: <libc-alpha at sourceware dot org>, <alistair23 at gmail dot com>
- Date: Fri, 25 Oct 2019 21:44:33 +0000
- Subject: Re: [PATCH v2] sysdeps/nanosleep: Use clock_nanosleep_time64 if avaliable
- Ironport-sdr: jq1FMG9jpT7OA5p8x3bsmix253Gi71Dt85hJqvs49P7bQxwQ+17d9egNXIsFgmBFflOwBUYr+o 2hmOq7JxpGTZz0L+3nZuwLKzBvDcVJpZcQVd7jwlx5lDTZM1FDmW+gsGd+9ea8nxuujausrnNc sJk1n1KAI7K2w4dQZeBA9yTEp8oOGoYZGMU/hob+5NjRCcAjlFtykXnzbn+S+HD61iLKJcdqj4 3+5wx2vNzRCKPKqyHN1AZtZiR095fsHK4aCFmiA6DdCYnKHd55DcwoU77t3plgr/I7ZJgyjPET 57A=
- Ironport-sdr: kuFPPXYNrT4AFvXYwZUu0Rv1GxCD/gXIPwes4uMH15+tKg/IA2mfQjobmlxAj38z/YruJtQQMz f15c3LAdFy2usw03W3QzTwseG7XeS7LAgA/wldlTXnErlkyRrFUetK2LeojQP5SkQCUfUQBCWn crE82Yj6Mhcwvw/14jp4W7+HXo9TBOoi+AfZh4pFNIKWfw4PGDo71OhbKjZKC9O0twwMF6d3cG dKLjZVY32EUCtbhx4bjOesu48tjjXRKyxJAwzY1JQB1r9RjIrNmJbyslpmMD9Dhcceiy5XaXD2 xU8=
- References: <20191024234106.27081-1-alistair.francis@wdc.com>
On Thu, 24 Oct 2019, Alistair Francis wrote:
> +# ifdef __NR_clock_nanosleep_time64
> + long int ret_64;
> +
> + ret_64 = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, CLOCK_REALTIME,
> + 0, time_point, remaining);
> +
> + if (ret_64 == 0 || errno != ENOSYS)
> + ret = ret_64;
> +# endif /* __NR_clock_nanosleep_time64 */
> + if (ret < 0)
> + {
> + struct timespec tp32, tr32;
> +
> + if (! in_time_t_range (time_point->tv_sec))
> + {
> + __set_errno (EOVERFLOW);
> + return -1;
> + }
> +
> + tp32 = valid_timespec64_to_timespec (*time_point);
> + ret = INTERNAL_SYSCALL_CANCEL (nanosleep, err, &tp32, &tr32);
This looks like it would call the nanosleep syscall if
clock_nanosleep_time64 failed for some non-ENOSYS reason. That doesn't
seem right.
> + if ((ret == 0 || errno != ENOSYS) && remaining)
> + *remaining = valid_timespec_to_timespec64 (tr32);
And if nanosleep fails for a non-EINTR reason, it won't have filled in
tr32, so this could be copying uninitialized data.
> +#if __TIMESIZE != 64
> +int
> +thrd_sleep (const struct timespec* time_point, struct timespec* remaining)
> +{
> + int ret;
> + struct __timespec64 tp64, tr64;
> +
> + tp64 = valid_timespec_to_timespec64 (*time_point);
> + ret = __thrd_sleep_time64 (&tp64, &tr64);
> +
> + if (ret == 0 || errno != ENOSYS)
> + {
> + if (! in_time_t_range (tr64.tv_sec))
> + {
> + __set_errno (EOVERFLOW);
> + return -1;
This could not only be copying uninitialized data for such a failure (e.g.
a failure for an invalid nanoseconds value), it could actually produce a
spurious EOVERFLOW error if that uninitialized data is out of range.
As far as I know the remaining amount can't exceed the amount passed in,
so when it's copied it shouldn't actually be necessary to check for
overflow.
I think similar issues apply for other functions in the patch.
Do we have test coverage in the testsuite for invalid nanoseconds
arguments to all these functions, making sure they produce proper EINVAL
errors? That might not cover many of these bugs (it wouldn't detect
simply reading uninitialized memory, or calling more syscalls than
necessary, and detecting the spurious EOVERFLOW would depend on what
values were in that memory). But it would seem a good idea to make sure
we do have such test coverage for functions using time arguments.
--
Joseph S. Myers
joseph@codesourcery.com