[LTP] [PATCH V8] syscalls: clock_settime: Add test around y2038 vulnerability

Cyril Hrubis chrubis@suse.cz
Wed Aug 5 17:11:45 CEST 2020


Hi!
> This adds a test around the y2038 vulnerability, it sets the system time
> to just before y2038 time (i.e. max value that can be stored in s32),
> and adds a timer to expire just after crossing it.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> V8:
> - Check compatibility issues for TST_KERN_OLD_TIMESPEC and not the new
>   timespec.
> - s/TFAIL/TCONF/ in setup()
> - Use kernel_timer_t
> - rearrange code and don't expect timer to fire before.
> 
>  runtest/syscalls                                   |   1 +
>  testcases/kernel/syscalls/clock_settime/.gitignore |   1 +
>  .../syscalls/clock_settime/clock_settime03.c       | 123 +++++++++++++++++++++
>  3 files changed, 125 insertions(+)
>  create mode 100644 testcases/kernel/syscalls/clock_settime/clock_settime03.c
> 
> diff --git a/runtest/syscalls b/runtest/syscalls
> index 3c6e78a4c6d0..3c2f5f6c0b37 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -99,6 +99,7 @@ leapsec01 leapsec01
>  
>  clock_settime01 clock_settime01
>  clock_settime02 clock_settime02
> +clock_settime03 clock_settime03
>  
>  clone01 clone01
>  clone02 clone02
> diff --git a/testcases/kernel/syscalls/clock_settime/.gitignore b/testcases/kernel/syscalls/clock_settime/.gitignore
> index 28121755006b..b66169b3eb7b 100644
> --- a/testcases/kernel/syscalls/clock_settime/.gitignore
> +++ b/testcases/kernel/syscalls/clock_settime/.gitignore
> @@ -1,2 +1,3 @@
>  clock_settime01
>  clock_settime02
> +clock_settime03
> diff --git a/testcases/kernel/syscalls/clock_settime/clock_settime03.c b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
> new file mode 100644
> index 000000000000..da062a8d0333
> --- /dev/null
> +++ b/testcases/kernel/syscalls/clock_settime/clock_settime03.c
> @@ -0,0 +1,123 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2020 Linaro Limited. All rights reserved.
> + * Author: Viresh Kumar<viresh.kumar@linaro.org>
> + *
> + * Check Year 2038 related vulnerabilities.
> + */
> +
> +#include <signal.h>
> +#include "config.h"
> +#include "tst_timer.h"
> +#include "tst_safe_clocks.h"
> +
> +#define TIMER_DELTA	3
> +#define ALLOWED_DELTA	(50 * 1000) /* 50 ms */
> +
> +static struct tst_ts start, end;
> +static struct tst_its its;
> +
> +static struct test_variants {
> +	int (*clock_gettime)(clockid_t clk_id, void *ts);
> +	int (*clock_settime)(clockid_t clk_id, void *ts);
> +	int (*timer_settime)(kernel_timer_t timerid, int flags, void *its,
> +			     void *old_its);
> +	enum tst_ts_type type;
> +	char *desc;
> +} variants[] = {
> +#if (__NR_clock_settime != __LTP__NR_INVALID_SYSCALL)
> +	{ .clock_gettime = sys_clock_gettime, .clock_settime = sys_clock_settime, .timer_settime = sys_timer_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
> +	{ .clock_gettime = sys_clock_gettime64, .clock_settime = sys_clock_settime64, .timer_settime = sys_timer_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
> +
> +static void setup(void)
> +{
> +	struct test_variants *tv = &variants[tst_variant];
> +
> +	tst_res(TINFO, "Testing variant: %s", tv->desc);
> +	start.type = end.type = its.type = tv->type;
> +
> +	/* Check if the kernel is y2038 safe */
> +	if (tv->type == TST_KERN_OLD_TIMESPEC &&
> +	    sizeof(start.ts.kern_old_ts) == 8)
> +		tst_brk(TCONF, "Not Y2038 safe to run test");

Thinking of this again, it may be safer to assert the size of the
kernel_old_ts.tv_sec, since the compiler is technically allowed to padd
the structure. So what about sizeof(start.ts.kernel_old_ts.tv_sec) == 4?

> +}
> +
> +static void run(void)
> +{
> +	struct test_variants *tv = &variants[tst_variant];
> +	unsigned long long time = 0x7FFFFFFE; /* Time just before y2038 */
> +	struct sigevent ev = {
> +		.sigev_notify = SIGEV_SIGNAL,
> +		.sigev_signo = SIGABRT,
> +	};
> +	long long diff;
> +	kernel_timer_t timer;
> +	sigset_t set;
> +	int sig, ret;
> +
> +	if (sigemptyset(&set) == -1)
> +		tst_brk(TBROK, "sigemptyset() failed");
> +
> +	if (sigaddset(&set, SIGABRT) == -1)
> +		tst_brk(TBROK, "sigaddset() failed");

We do have a safe macros for these two now.


Other than that these the code looks good. I can fix these two before
applying if you agree.

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list