162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define _GNU_SOURCE 362306a36Sopenharmony_ci#include <errno.h> 462306a36Sopenharmony_ci#include <fcntl.h> 562306a36Sopenharmony_ci#include <sched.h> 662306a36Sopenharmony_ci#include <stdio.h> 762306a36Sopenharmony_ci#include <stdbool.h> 862306a36Sopenharmony_ci#include <sys/stat.h> 962306a36Sopenharmony_ci#include <sys/syscall.h> 1062306a36Sopenharmony_ci#include <sys/types.h> 1162306a36Sopenharmony_ci#include <sys/wait.h> 1262306a36Sopenharmony_ci#include <time.h> 1362306a36Sopenharmony_ci#include <unistd.h> 1462306a36Sopenharmony_ci#include <string.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "log.h" 1762306a36Sopenharmony_ci#include "timens.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define OFFSET (36000) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciint main(int argc, char *argv[]) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci struct timespec now, tst; 2462306a36Sopenharmony_ci int status, i; 2562306a36Sopenharmony_ci pid_t pid; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if (argc > 1) { 2862306a36Sopenharmony_ci if (sscanf(argv[1], "%ld", &now.tv_sec) != 1) 2962306a36Sopenharmony_ci return pr_perror("sscanf"); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 3262306a36Sopenharmony_ci _gettime(CLOCK_MONOTONIC, &tst, i); 3362306a36Sopenharmony_ci if (abs(tst.tv_sec - now.tv_sec) > 5) 3462306a36Sopenharmony_ci return pr_fail("%ld %ld\n", now.tv_sec, tst.tv_sec); 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci return 0; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci nscheck(); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci ksft_set_plan(1); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &now); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (unshare_timens()) 4662306a36Sopenharmony_ci return 1; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci if (_settime(CLOCK_MONOTONIC, OFFSET)) 4962306a36Sopenharmony_ci return 1; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 5262306a36Sopenharmony_ci _gettime(CLOCK_MONOTONIC, &tst, i); 5362306a36Sopenharmony_ci if (abs(tst.tv_sec - now.tv_sec) > 5) 5462306a36Sopenharmony_ci return pr_fail("%ld %ld\n", 5562306a36Sopenharmony_ci now.tv_sec, tst.tv_sec); 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (argc > 1) 5962306a36Sopenharmony_ci return 0; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci pid = fork(); 6262306a36Sopenharmony_ci if (pid < 0) 6362306a36Sopenharmony_ci return pr_perror("fork"); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (pid == 0) { 6662306a36Sopenharmony_ci char now_str[64]; 6762306a36Sopenharmony_ci char *cargv[] = {"exec", now_str, NULL}; 6862306a36Sopenharmony_ci char *cenv[] = {NULL}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* Check that a child process is in the new timens. */ 7162306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 7262306a36Sopenharmony_ci _gettime(CLOCK_MONOTONIC, &tst, i); 7362306a36Sopenharmony_ci if (abs(tst.tv_sec - now.tv_sec - OFFSET) > 5) 7462306a36Sopenharmony_ci return pr_fail("%ld %ld\n", 7562306a36Sopenharmony_ci now.tv_sec + OFFSET, tst.tv_sec); 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* Check for proper vvar offsets after execve. */ 7962306a36Sopenharmony_ci snprintf(now_str, sizeof(now_str), "%ld", now.tv_sec + OFFSET); 8062306a36Sopenharmony_ci execve("/proc/self/exe", cargv, cenv); 8162306a36Sopenharmony_ci return pr_perror("execve"); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci if (waitpid(pid, &status, 0) != pid) 8562306a36Sopenharmony_ci return pr_perror("waitpid"); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (status) 8862306a36Sopenharmony_ci ksft_exit_fail(); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci ksft_test_result_pass("exec\n"); 9162306a36Sopenharmony_ci ksft_exit_pass(); 9262306a36Sopenharmony_ci return 0; 9362306a36Sopenharmony_ci} 94