~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/timens/procfs.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #define _GNU_SOURCE
  3 #include <errno.h>
  4 #include <fcntl.h>
  5 #include <math.h>
  6 #include <sched.h>
  7 #include <stdio.h>
  8 #include <stdbool.h>
  9 #include <stdlib.h>
 10 #include <sys/stat.h>
 11 #include <sys/syscall.h>
 12 #include <sys/types.h>
 13 #include <time.h>
 14 #include <unistd.h>
 15 
 16 #include "log.h"
 17 #include "timens.h"
 18 
 19 /*
 20  * Test shouldn't be run for a day, so add 10 days to child
 21  * time and check parent's time to be in the same day.
 22  */
 23 #define MAX_TEST_TIME_SEC               (60*5)
 24 #define DAY_IN_SEC                      (60*60*24)
 25 #define TEN_DAYS_IN_SEC                 (10*DAY_IN_SEC)
 26 
 27 static int child_ns, parent_ns;
 28 
 29 static int switch_ns(int fd)
 30 {
 31         if (setns(fd, CLONE_NEWTIME))
 32                 return pr_perror("setns()");
 33 
 34         return 0;
 35 }
 36 
 37 static int init_namespaces(void)
 38 {
 39         char path[] = "/proc/self/ns/time_for_children";
 40         struct stat st1, st2;
 41 
 42         parent_ns = open(path, O_RDONLY);
 43         if (parent_ns <= 0)
 44                 return pr_perror("Unable to open %s", path);
 45 
 46         if (fstat(parent_ns, &st1))
 47                 return pr_perror("Unable to stat the parent timens");
 48 
 49         if (unshare_timens())
 50                 return -1;
 51 
 52         child_ns = open(path, O_RDONLY);
 53         if (child_ns <= 0)
 54                 return pr_perror("Unable to open %s", path);
 55 
 56         if (fstat(child_ns, &st2))
 57                 return pr_perror("Unable to stat the timens");
 58 
 59         if (st1.st_ino == st2.st_ino)
 60                 return pr_err("The same child_ns after CLONE_NEWTIME");
 61 
 62         if (_settime(CLOCK_BOOTTIME, TEN_DAYS_IN_SEC))
 63                 return -1;
 64 
 65         return 0;
 66 }
 67 
 68 static int read_proc_uptime(struct timespec *uptime)
 69 {
 70         unsigned long up_sec, up_nsec;
 71         FILE *proc;
 72 
 73         proc = fopen("/proc/uptime", "r");
 74         if (proc == NULL) {
 75                 pr_perror("Unable to open /proc/uptime");
 76                 return -1;
 77         }
 78 
 79         if (fscanf(proc, "%lu.%02lu", &up_sec, &up_nsec) != 2) {
 80                 if (errno) {
 81                         pr_perror("fscanf");
 82                         return -errno;
 83                 }
 84                 pr_err("failed to parse /proc/uptime");
 85                 return -1;
 86         }
 87         fclose(proc);
 88 
 89         uptime->tv_sec = up_sec;
 90         uptime->tv_nsec = up_nsec;
 91         return 0;
 92 }
 93 
 94 static int read_proc_stat_btime(unsigned long long *boottime_sec)
 95 {
 96         FILE *proc;
 97         char line_buf[2048];
 98 
 99         proc = fopen("/proc/stat", "r");
100         if (proc == NULL) {
101                 pr_perror("Unable to open /proc/stat");
102                 return -1;
103         }
104 
105         while (fgets(line_buf, 2048, proc)) {
106                 if (sscanf(line_buf, "btime %llu", boottime_sec) != 1)
107                         continue;
108                 fclose(proc);
109                 return 0;
110         }
111         if (errno) {
112                 pr_perror("fscanf");
113                 fclose(proc);
114                 return -errno;
115         }
116         pr_err("failed to parse /proc/stat");
117         fclose(proc);
118         return -1;
119 }
120 
121 static int check_uptime(void)
122 {
123         struct timespec uptime_new, uptime_old;
124         time_t uptime_expected;
125         double prec = MAX_TEST_TIME_SEC;
126 
127         if (switch_ns(parent_ns))
128                 return pr_err("switch_ns(%d)", parent_ns);
129 
130         if (read_proc_uptime(&uptime_old))
131                 return 1;
132 
133         if (switch_ns(child_ns))
134                 return pr_err("switch_ns(%d)", child_ns);
135 
136         if (read_proc_uptime(&uptime_new))
137                 return 1;
138 
139         uptime_expected = uptime_old.tv_sec + TEN_DAYS_IN_SEC;
140         if (fabs(difftime(uptime_new.tv_sec, uptime_expected)) > prec) {
141                 pr_fail("uptime in /proc/uptime: old %ld, new %ld [%ld]",
142                         uptime_old.tv_sec, uptime_new.tv_sec,
143                         uptime_old.tv_sec + TEN_DAYS_IN_SEC);
144                 return 1;
145         }
146 
147         ksft_test_result_pass("Passed for /proc/uptime\n");
148         return 0;
149 }
150 
151 static int check_stat_btime(void)
152 {
153         unsigned long long btime_new, btime_old;
154         unsigned long long btime_expected;
155 
156         if (switch_ns(parent_ns))
157                 return pr_err("switch_ns(%d)", parent_ns);
158 
159         if (read_proc_stat_btime(&btime_old))
160                 return 1;
161 
162         if (switch_ns(child_ns))
163                 return pr_err("switch_ns(%d)", child_ns);
164 
165         if (read_proc_stat_btime(&btime_new))
166                 return 1;
167 
168         btime_expected = btime_old - TEN_DAYS_IN_SEC;
169         if (btime_new != btime_expected) {
170                 pr_fail("btime in /proc/stat: old %llu, new %llu [%llu]",
171                         btime_old, btime_new, btime_expected);
172                 return 1;
173         }
174 
175         ksft_test_result_pass("Passed for /proc/stat btime\n");
176         return 0;
177 }
178 
179 int main(int argc, char *argv[])
180 {
181         int ret = 0;
182 
183         nscheck();
184 
185         ksft_set_plan(2);
186 
187         if (init_namespaces())
188                 return 1;
189 
190         ret |= check_uptime();
191         ret |= check_stat_btime();
192 
193         if (ret)
194                 ksft_exit_fail();
195         ksft_exit_pass();
196         return ret;
197 }
198 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php