32
32
PIDFD_NS_NET ,
33
33
PIDFD_NS_CGROUP ,
34
34
PIDFD_NS_PIDCLD ,
35
+ PIDFD_NS_TIME ,
35
36
PIDFD_NS_MAX
36
37
};
37
38
@@ -47,6 +48,7 @@ const struct ns_info {
47
48
[PIDFD_NS_NET ] = { "net" , CLONE_NEWNET , },
48
49
[PIDFD_NS_CGROUP ] = { "cgroup" , CLONE_NEWCGROUP , },
49
50
[PIDFD_NS_PIDCLD ] = { "pid_for_children" , 0 , },
51
+ [PIDFD_NS_TIME ] = { "time" , CLONE_NEWTIME , },
50
52
};
51
53
52
54
FIXTURE (current_nsset )
@@ -83,9 +85,49 @@ pid_t create_child(int *pidfd, unsigned flags)
83
85
return sys_clone3 (& args , sizeof (struct clone_args ));
84
86
}
85
87
88
+ static bool switch_timens (void )
89
+ {
90
+ int fd , ret ;
91
+
92
+ if (unshare (CLONE_NEWTIME ))
93
+ return false;
94
+
95
+ fd = open ("/proc/self/ns/time_for_children" , O_RDONLY | O_CLOEXEC );
96
+ if (fd < 0 )
97
+ return false;
98
+
99
+ ret = setns (fd , CLONE_NEWTIME );
100
+ close (fd );
101
+ return ret == 0 ;
102
+ }
103
+
104
+ static ssize_t read_nointr (int fd , void * buf , size_t count )
105
+ {
106
+ ssize_t ret ;
107
+
108
+ do {
109
+ ret = read (fd , buf , count );
110
+ } while (ret < 0 && errno == EINTR );
111
+
112
+ return ret ;
113
+ }
114
+
115
+ static ssize_t write_nointr (int fd , const void * buf , size_t count )
116
+ {
117
+ ssize_t ret ;
118
+
119
+ do {
120
+ ret = write (fd , buf , count );
121
+ } while (ret < 0 && errno == EINTR );
122
+
123
+ return ret ;
124
+ }
125
+
86
126
FIXTURE_SETUP (current_nsset )
87
127
{
88
128
int i , proc_fd , ret ;
129
+ int ipc_sockets [2 ];
130
+ char c ;
89
131
90
132
for (i = 0 ; i < PIDFD_NS_MAX ; i ++ ) {
91
133
self -> nsfds [i ] = - EBADF ;
@@ -130,6 +172,9 @@ FIXTURE_SETUP(current_nsset)
130
172
TH_LOG ("%m - Failed to open pidfd for process %d" , self -> pid );
131
173
}
132
174
175
+ ret = socketpair (AF_LOCAL , SOCK_STREAM | SOCK_CLOEXEC , 0 , ipc_sockets );
176
+ EXPECT_EQ (ret , 0 );
177
+
133
178
/* Create tasks that will be stopped. */
134
179
self -> child_pid1 = create_child (& self -> child_pidfd1 ,
135
180
CLONE_NEWUSER | CLONE_NEWNS |
@@ -139,10 +184,27 @@ FIXTURE_SETUP(current_nsset)
139
184
EXPECT_GE (self -> child_pid1 , 0 );
140
185
141
186
if (self -> child_pid1 == 0 ) {
187
+ close (ipc_sockets [0 ]);
188
+
189
+ if (!switch_timens ())
190
+ _exit (EXIT_FAILURE );
191
+
192
+ if (write_nointr (ipc_sockets [1 ], "1" , 1 ) < 0 )
193
+ _exit (EXIT_FAILURE );
194
+
195
+ close (ipc_sockets [1 ]);
196
+
142
197
pause ();
143
198
_exit (EXIT_SUCCESS );
144
199
}
145
200
201
+ close (ipc_sockets [1 ]);
202
+ ASSERT_EQ (read_nointr (ipc_sockets [0 ], & c , 1 ), 1 );
203
+ close (ipc_sockets [0 ]);
204
+
205
+ ret = socketpair (AF_LOCAL , SOCK_STREAM | SOCK_CLOEXEC , 0 , ipc_sockets );
206
+ EXPECT_EQ (ret , 0 );
207
+
146
208
self -> child_pid2 = create_child (& self -> child_pidfd2 ,
147
209
CLONE_NEWUSER | CLONE_NEWNS |
148
210
CLONE_NEWCGROUP | CLONE_NEWIPC |
@@ -151,10 +213,24 @@ FIXTURE_SETUP(current_nsset)
151
213
EXPECT_GE (self -> child_pid2 , 0 );
152
214
153
215
if (self -> child_pid2 == 0 ) {
216
+ close (ipc_sockets [0 ]);
217
+
218
+ if (!switch_timens ())
219
+ _exit (EXIT_FAILURE );
220
+
221
+ if (write_nointr (ipc_sockets [1 ], "1" , 1 ) < 0 )
222
+ _exit (EXIT_FAILURE );
223
+
224
+ close (ipc_sockets [1 ]);
225
+
154
226
pause ();
155
227
_exit (EXIT_SUCCESS );
156
228
}
157
229
230
+ close (ipc_sockets [1 ]);
231
+ ASSERT_EQ (read_nointr (ipc_sockets [0 ], & c , 1 ), 1 );
232
+ close (ipc_sockets [0 ]);
233
+
158
234
for (i = 0 ; i < PIDFD_NS_MAX ; i ++ ) {
159
235
char p [100 ];
160
236
0 commit comments