^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sys/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "log.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "timens.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Test shouldn't be run for a day, so add 10 days to child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * time and check parent's time to be in the same day.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MAX_TEST_TIME_SEC (60*5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DAY_IN_SEC (60*60*24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define TEN_DAYS_IN_SEC (10*DAY_IN_SEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int child_ns, parent_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int switch_ns(int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (setns(fd, CLONE_NEWTIME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return pr_perror("setns()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int init_namespaces(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) char path[] = "/proc/self/ns/time_for_children";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct stat st1, st2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) parent_ns = open(path, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (parent_ns <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return pr_perror("Unable to open %s", path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (fstat(parent_ns, &st1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return pr_perror("Unable to stat the parent timens");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (unshare_timens())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) child_ns = open(path, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (child_ns <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return pr_perror("Unable to open %s", path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (fstat(child_ns, &st2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return pr_perror("Unable to stat the timens");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (st1.st_ino == st2.st_ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return pr_err("The same child_ns after CLONE_NEWTIME");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (_settime(CLOCK_BOOTTIME, TEN_DAYS_IN_SEC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int read_proc_uptime(struct timespec *uptime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned long up_sec, up_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) FILE *proc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) proc = fopen("/proc/uptime", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (proc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pr_perror("Unable to open /proc/uptime");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (fscanf(proc, "%lu.%02lu", &up_sec, &up_nsec) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (errno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pr_perror("fscanf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pr_err("failed to parse /proc/uptime");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) fclose(proc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) uptime->tv_sec = up_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) uptime->tv_nsec = up_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static int check_uptime(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct timespec uptime_new, uptime_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) time_t uptime_expected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) double prec = MAX_TEST_TIME_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (switch_ns(parent_ns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return pr_err("switch_ns(%d)", parent_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (read_proc_uptime(&uptime_old))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (switch_ns(child_ns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return pr_err("switch_ns(%d)", child_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (read_proc_uptime(&uptime_new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) uptime_expected = uptime_old.tv_sec + TEN_DAYS_IN_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (fabs(difftime(uptime_new.tv_sec, uptime_expected)) > prec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pr_fail("uptime in /proc/uptime: old %ld, new %ld [%ld]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) uptime_old.tv_sec, uptime_new.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) uptime_old.tv_sec + TEN_DAYS_IN_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ksft_test_result_pass("Passed for /proc/uptime\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) nscheck();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ksft_set_plan(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (init_namespaces())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ret |= check_uptime();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ksft_exit_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }