18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#define _GNU_SOURCE
38c2ecf20Sopenharmony_ci#include <errno.h>
48c2ecf20Sopenharmony_ci#include <fcntl.h>
58c2ecf20Sopenharmony_ci#include <sched.h>
68c2ecf20Sopenharmony_ci#include <stdio.h>
78c2ecf20Sopenharmony_ci#include <stdbool.h>
88c2ecf20Sopenharmony_ci#include <sys/stat.h>
98c2ecf20Sopenharmony_ci#include <sys/syscall.h>
108c2ecf20Sopenharmony_ci#include <sys/types.h>
118c2ecf20Sopenharmony_ci#include <sys/wait.h>
128c2ecf20Sopenharmony_ci#include <time.h>
138c2ecf20Sopenharmony_ci#include <unistd.h>
148c2ecf20Sopenharmony_ci#include <string.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "log.h"
178c2ecf20Sopenharmony_ci#include "timens.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define OFFSET (36000)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciint main(int argc, char *argv[])
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	struct timespec now, tst;
248c2ecf20Sopenharmony_ci	int status, i;
258c2ecf20Sopenharmony_ci	pid_t pid;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	if (argc > 1) {
288c2ecf20Sopenharmony_ci		if (sscanf(argv[1], "%ld", &now.tv_sec) != 1)
298c2ecf20Sopenharmony_ci			return pr_perror("sscanf");
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci		for (i = 0; i < 2; i++) {
328c2ecf20Sopenharmony_ci			_gettime(CLOCK_MONOTONIC, &tst, i);
338c2ecf20Sopenharmony_ci			if (abs(tst.tv_sec - now.tv_sec) > 5)
348c2ecf20Sopenharmony_ci				return pr_fail("%ld %ld\n", now.tv_sec, tst.tv_sec);
358c2ecf20Sopenharmony_ci		}
368c2ecf20Sopenharmony_ci		return 0;
378c2ecf20Sopenharmony_ci	}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	nscheck();
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	ksft_set_plan(1);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	clock_gettime(CLOCK_MONOTONIC, &now);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (unshare_timens())
468c2ecf20Sopenharmony_ci		return 1;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (_settime(CLOCK_MONOTONIC, OFFSET))
498c2ecf20Sopenharmony_ci		return 1;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++) {
528c2ecf20Sopenharmony_ci		_gettime(CLOCK_MONOTONIC, &tst, i);
538c2ecf20Sopenharmony_ci		if (abs(tst.tv_sec - now.tv_sec) > 5)
548c2ecf20Sopenharmony_ci			return pr_fail("%ld %ld\n",
558c2ecf20Sopenharmony_ci					now.tv_sec, tst.tv_sec);
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (argc > 1)
598c2ecf20Sopenharmony_ci		return 0;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	pid = fork();
628c2ecf20Sopenharmony_ci	if (pid < 0)
638c2ecf20Sopenharmony_ci		return pr_perror("fork");
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	if (pid == 0) {
668c2ecf20Sopenharmony_ci		char now_str[64];
678c2ecf20Sopenharmony_ci		char *cargv[] = {"exec", now_str, NULL};
688c2ecf20Sopenharmony_ci		char *cenv[] = {NULL};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci		/* Check that a child process is in the new timens. */
718c2ecf20Sopenharmony_ci		for (i = 0; i < 2; i++) {
728c2ecf20Sopenharmony_ci			_gettime(CLOCK_MONOTONIC, &tst, i);
738c2ecf20Sopenharmony_ci			if (abs(tst.tv_sec - now.tv_sec - OFFSET) > 5)
748c2ecf20Sopenharmony_ci				return pr_fail("%ld %ld\n",
758c2ecf20Sopenharmony_ci						now.tv_sec + OFFSET, tst.tv_sec);
768c2ecf20Sopenharmony_ci		}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci		/* Check for proper vvar offsets after execve. */
798c2ecf20Sopenharmony_ci		snprintf(now_str, sizeof(now_str), "%ld", now.tv_sec + OFFSET);
808c2ecf20Sopenharmony_ci		execve("/proc/self/exe", cargv, cenv);
818c2ecf20Sopenharmony_ci		return pr_perror("execve");
828c2ecf20Sopenharmony_ci	}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	if (waitpid(pid, &status, 0) != pid)
858c2ecf20Sopenharmony_ci		return pr_perror("waitpid");
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (status)
888c2ecf20Sopenharmony_ci		ksft_exit_fail();
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	ksft_test_result_pass("exec\n");
918c2ecf20Sopenharmony_ci	ksft_exit_pass();
928c2ecf20Sopenharmony_ci	return 0;
938c2ecf20Sopenharmony_ci}
94