Skip to content

Commit 6342140

Browse files
avaginkees
authored andcommitted
selftests/timens: add a test for vfork+exit
* check that a child process is in parent's time namespace after vfork. * check that a child process is in the target namespace after exec. Output on success: $ ./vfork_exec 1..1 ok 1 exec Signed-off-by: Andrei Vagin <[email protected]> Signed-off-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 133e2d3 commit 6342140

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

tools/testing/selftests/timens/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec futex
1+
TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec futex vfork_exec
22
TEST_GEN_PROGS_EXTENDED := gettime_perf
33

44
CFLAGS := -Wall -Werror -pthread
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#define _GNU_SOURCE
3+
#include <errno.h>
4+
#include <fcntl.h>
5+
#include <sched.h>
6+
#include <stdio.h>
7+
#include <stdbool.h>
8+
#include <sys/stat.h>
9+
#include <sys/syscall.h>
10+
#include <sys/types.h>
11+
#include <sys/wait.h>
12+
#include <time.h>
13+
#include <unistd.h>
14+
#include <string.h>
15+
16+
#include "log.h"
17+
#include "timens.h"
18+
19+
#define OFFSET (36000)
20+
21+
int main(int argc, char *argv[])
22+
{
23+
struct timespec now, tst;
24+
int status, i;
25+
pid_t pid;
26+
27+
if (argc > 1) {
28+
if (sscanf(argv[1], "%ld", &now.tv_sec) != 1)
29+
return pr_perror("sscanf");
30+
31+
for (i = 0; i < 2; i++) {
32+
_gettime(CLOCK_MONOTONIC, &tst, i);
33+
if (abs(tst.tv_sec - now.tv_sec) > 5)
34+
return pr_fail("%ld %ld\n", now.tv_sec, tst.tv_sec);
35+
}
36+
return 0;
37+
}
38+
39+
nscheck();
40+
41+
ksft_set_plan(1);
42+
43+
clock_gettime(CLOCK_MONOTONIC, &now);
44+
45+
if (unshare_timens())
46+
return 1;
47+
48+
if (_settime(CLOCK_MONOTONIC, OFFSET))
49+
return 1;
50+
51+
for (i = 0; i < 2; i++) {
52+
_gettime(CLOCK_MONOTONIC, &tst, i);
53+
if (abs(tst.tv_sec - now.tv_sec) > 5)
54+
return pr_fail("%ld %ld\n",
55+
now.tv_sec, tst.tv_sec);
56+
}
57+
58+
pid = vfork();
59+
if (pid < 0)
60+
return pr_perror("fork");
61+
62+
if (pid == 0) {
63+
char now_str[64];
64+
char *cargv[] = {"exec", now_str, NULL};
65+
char *cenv[] = {NULL};
66+
67+
// Check that we are still in the source timens.
68+
for (i = 0; i < 2; i++) {
69+
_gettime(CLOCK_MONOTONIC, &tst, i);
70+
if (abs(tst.tv_sec - now.tv_sec) > 5)
71+
return pr_fail("%ld %ld\n",
72+
now.tv_sec, tst.tv_sec);
73+
}
74+
75+
/* Check for proper vvar offsets after execve. */
76+
snprintf(now_str, sizeof(now_str), "%ld", now.tv_sec + OFFSET);
77+
execve("/proc/self/exe", cargv, cenv);
78+
return pr_perror("execve");
79+
}
80+
81+
if (waitpid(pid, &status, 0) != pid)
82+
return pr_perror("waitpid");
83+
84+
if (status)
85+
ksft_exit_fail();
86+
87+
ksft_test_result_pass("exec\n");
88+
ksft_exit_pass();
89+
return 0;
90+
}

0 commit comments

Comments
 (0)