7
7
#include <inttypes.h>
8
8
#include <linux/types.h>
9
9
#include <linux/sched.h>
10
+ #include <stdbool.h>
10
11
#include <stdint.h>
11
12
#include <stdio.h>
12
13
#include <stdlib.h>
@@ -103,8 +104,8 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
103
104
return 0 ;
104
105
}
105
106
106
- static void test_clone3 (uint64_t flags , size_t size , int expected ,
107
- enum test_mode test_mode )
107
+ static bool test_clone3 (uint64_t flags , size_t size , int expected ,
108
+ enum test_mode test_mode )
108
109
{
109
110
int ret ;
110
111
@@ -114,92 +115,210 @@ static void test_clone3(uint64_t flags, size_t size, int expected,
114
115
ret = call_clone3 (flags , size , test_mode );
115
116
ksft_print_msg ("[%d] clone3() with flags says: %d expected %d\n" ,
116
117
getpid (), ret , expected );
117
- if (ret != expected )
118
- ksft_test_result_fail (
118
+ if (ret != expected ) {
119
+ ksft_print_msg (
119
120
"[%d] Result (%d) is different than expected (%d)\n" ,
120
121
getpid (), ret , expected );
121
- else
122
- ksft_test_result_pass (
123
- "[%d] Result (%d) matches expectation (%d)\n" ,
124
- getpid (), ret , expected );
125
- }
126
-
127
- int main (int argc , char * argv [])
128
- {
129
- uid_t uid = getuid ();
130
-
131
- ksft_print_header ();
132
- ksft_set_plan (19 );
133
- test_clone3_supported ();
134
-
135
- /* Just a simple clone3() should return 0.*/
136
- test_clone3 (0 , 0 , 0 , CLONE3_ARGS_NO_TEST );
137
-
138
- /* Do a clone3() in a new PID NS.*/
139
- if (uid == 0 )
140
- test_clone3 (CLONE_NEWPID , 0 , 0 , CLONE3_ARGS_NO_TEST );
141
- else
142
- ksft_test_result_skip ("Skipping clone3() with CLONE_NEWPID\n" );
143
-
144
- /* Do a clone3() with CLONE_ARGS_SIZE_VER0. */
145
- test_clone3 (0 , CLONE_ARGS_SIZE_VER0 , 0 , CLONE3_ARGS_NO_TEST );
146
-
147
- /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 */
148
- test_clone3 (0 , CLONE_ARGS_SIZE_VER0 - 8 , - EINVAL , CLONE3_ARGS_NO_TEST );
149
-
150
- /* Do a clone3() with sizeof(struct clone_args) + 8 */
151
- test_clone3 (0 , sizeof (struct __clone_args ) + 8 , 0 , CLONE3_ARGS_NO_TEST );
152
-
153
- /* Do a clone3() with exit_signal having highest 32 bits non-zero */
154
- test_clone3 (0 , 0 , - EINVAL , CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG );
122
+ return false;
123
+ }
155
124
156
- /* Do a clone3() with negative 32-bit exit_signal */
157
- test_clone3 ( 0 , 0 , - EINVAL , CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG );
125
+ return true;
126
+ }
158
127
159
- /* Do a clone3() with exit_signal not fitting into CSIGNAL mask */
160
- test_clone3 ( 0 , 0 , - EINVAL , CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG );
128
+ typedef bool ( * filter_function )( void );
129
+ typedef size_t ( * size_function )( void );
161
130
162
- /* Do a clone3() with NSIG < exit_signal < CSIG */
163
- test_clone3 (0 , 0 , - EINVAL , CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG );
131
+ static bool not_root (void )
132
+ {
133
+ if (getuid () != 0 ) {
134
+ ksft_print_msg ("Not running as root\n" );
135
+ return true;
136
+ }
164
137
165
- test_clone3 (0 , sizeof (struct __clone_args ) + 8 , 0 , CLONE3_ARGS_ALL_0 );
138
+ return false;
139
+ }
166
140
167
- test_clone3 (0 , sizeof (struct __clone_args ) + 16 , - E2BIG ,
168
- CLONE3_ARGS_ALL_0 );
141
+ static size_t page_size_plus_8 (void )
142
+ {
143
+ return getpagesize () + 8 ;
144
+ }
169
145
170
- test_clone3 (0 , sizeof (struct __clone_args ) * 2 , - E2BIG ,
171
- CLONE3_ARGS_ALL_0 );
146
+ struct test {
147
+ const char * name ;
148
+ uint64_t flags ;
149
+ size_t size ;
150
+ size_function size_function ;
151
+ int expected ;
152
+ enum test_mode test_mode ;
153
+ filter_function filter ;
154
+ };
172
155
173
- /* Do a clone3() with > page size */
174
- test_clone3 (0 , getpagesize () + 8 , - E2BIG , CLONE3_ARGS_NO_TEST );
156
+ static const struct test tests [] = {
157
+ {
158
+ .name = "simple clone3()" ,
159
+ .flags = 0 ,
160
+ .size = 0 ,
161
+ .expected = 0 ,
162
+ .test_mode = CLONE3_ARGS_NO_TEST ,
163
+ },
164
+ {
165
+ .name = "clone3() in a new PID_NS" ,
166
+ .flags = CLONE_NEWPID ,
167
+ .size = 0 ,
168
+ .expected = 0 ,
169
+ .test_mode = CLONE3_ARGS_NO_TEST ,
170
+ .filter = not_root ,
171
+ },
172
+ {
173
+ .name = "CLONE_ARGS_SIZE_VER0" ,
174
+ .flags = 0 ,
175
+ .size = CLONE_ARGS_SIZE_VER0 ,
176
+ .expected = 0 ,
177
+ .test_mode = CLONE3_ARGS_NO_TEST ,
178
+ },
179
+ {
180
+ .name = "CLONE_ARGS_SIZE_VER0 - 8" ,
181
+ .flags = 0 ,
182
+ .size = CLONE_ARGS_SIZE_VER0 - 8 ,
183
+ .expected = - EINVAL ,
184
+ .test_mode = CLONE3_ARGS_NO_TEST ,
185
+ },
186
+ {
187
+ .name = "sizeof(struct clone_args) + 8" ,
188
+ .flags = 0 ,
189
+ .size = sizeof (struct __clone_args ) + 8 ,
190
+ .expected = 0 ,
191
+ .test_mode = CLONE3_ARGS_NO_TEST ,
192
+ },
193
+ {
194
+ .name = "exit_signal with highest 32 bits non-zero" ,
195
+ .flags = 0 ,
196
+ .size = 0 ,
197
+ .expected = - EINVAL ,
198
+ .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG ,
199
+ },
200
+ {
201
+ .name = "negative 32-bit exit_signal" ,
202
+ .flags = 0 ,
203
+ .size = 0 ,
204
+ .expected = - EINVAL ,
205
+ .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG ,
206
+ },
207
+ {
208
+ .name = "exit_signal not fitting into CSIGNAL mask" ,
209
+ .flags = 0 ,
210
+ .size = 0 ,
211
+ .expected = - EINVAL ,
212
+ .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG ,
213
+ },
214
+ {
215
+ .name = "NSIG < exit_signal < CSIG" ,
216
+ .flags = 0 ,
217
+ .size = 0 ,
218
+ .expected = - EINVAL ,
219
+ .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG ,
220
+ },
221
+ {
222
+ .name = "Arguments sizeof(struct clone_args) + 8" ,
223
+ .flags = 0 ,
224
+ .size = sizeof (struct __clone_args ) + 8 ,
225
+ .expected = 0 ,
226
+ .test_mode = CLONE3_ARGS_ALL_0 ,
227
+ },
228
+ {
229
+ .name = "Arguments sizeof(struct clone_args) + 16" ,
230
+ .flags = 0 ,
231
+ .size = sizeof (struct __clone_args ) + 16 ,
232
+ .expected = - E2BIG ,
233
+ .test_mode = CLONE3_ARGS_ALL_0 ,
234
+ },
235
+ {
236
+ .name = "Arguments sizeof(struct clone_arg) * 2" ,
237
+ .flags = 0 ,
238
+ .size = sizeof (struct __clone_args ) + 16 ,
239
+ .expected = - E2BIG ,
240
+ .test_mode = CLONE3_ARGS_ALL_0 ,
241
+ },
242
+ {
243
+ .name = "Arguments > page size" ,
244
+ .flags = 0 ,
245
+ .size_function = page_size_plus_8 ,
246
+ .expected = - E2BIG ,
247
+ .test_mode = CLONE3_ARGS_NO_TEST ,
248
+ },
249
+ {
250
+ .name = "CLONE_ARGS_SIZE_VER0 in a new PID NS" ,
251
+ .flags = CLONE_NEWPID ,
252
+ .size = CLONE_ARGS_SIZE_VER0 ,
253
+ .expected = 0 ,
254
+ .test_mode = CLONE3_ARGS_NO_TEST ,
255
+ .filter = not_root ,
256
+ },
257
+ {
258
+ .name = "CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS" ,
259
+ .flags = CLONE_NEWPID ,
260
+ .size = CLONE_ARGS_SIZE_VER0 - 8 ,
261
+ .expected = - EINVAL ,
262
+ .test_mode = CLONE3_ARGS_NO_TEST ,
263
+ },
264
+ {
265
+ .name = "sizeof(struct clone_args) + 8 in a new PID NS" ,
266
+ .flags = CLONE_NEWPID ,
267
+ .size = sizeof (struct __clone_args ) + 8 ,
268
+ .expected = 0 ,
269
+ .test_mode = CLONE3_ARGS_NO_TEST ,
270
+ .filter = not_root ,
271
+ },
272
+ {
273
+ .name = "Arguments > page size in a new PID NS" ,
274
+ .flags = CLONE_NEWPID ,
275
+ .size_function = page_size_plus_8 ,
276
+ .expected = - E2BIG ,
277
+ .test_mode = CLONE3_ARGS_NO_TEST ,
278
+ },
279
+ {
280
+ .name = "New time NS" ,
281
+ .flags = CLONE_NEWTIME ,
282
+ .size = 0 ,
283
+ .expected = 0 ,
284
+ .test_mode = CLONE3_ARGS_NO_TEST ,
285
+ },
286
+ {
287
+ .name = "exit signal (SIGCHLD) in flags" ,
288
+ .flags = SIGCHLD ,
289
+ .size = 0 ,
290
+ .expected = - EINVAL ,
291
+ .test_mode = CLONE3_ARGS_NO_TEST ,
292
+ },
293
+ };
175
294
176
- /* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */
177
- if (uid == 0 )
178
- test_clone3 (CLONE_NEWPID , CLONE_ARGS_SIZE_VER0 , 0 ,
179
- CLONE3_ARGS_NO_TEST );
180
- else
181
- ksft_test_result_skip ("Skipping clone3() with CLONE_NEWPID\n" );
295
+ int main (int argc , char * argv [])
296
+ {
297
+ size_t size ;
298
+ int i ;
182
299
183
- /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS */
184
- test_clone3 ( CLONE_NEWPID , CLONE_ARGS_SIZE_VER0 - 8 , - EINVAL ,
185
- CLONE3_ARGS_NO_TEST );
300
+ ksft_print_header ();
301
+ ksft_set_plan ( ARRAY_SIZE ( tests ));
302
+ test_clone3_supported ( );
186
303
187
- /* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */
188
- if (uid == 0 )
189
- test_clone3 (CLONE_NEWPID , sizeof (struct __clone_args ) + 8 , 0 ,
190
- CLONE3_ARGS_NO_TEST );
191
- else
192
- ksft_test_result_skip ("Skipping clone3() with CLONE_NEWPID\n" );
304
+ for (i = 0 ; i < ARRAY_SIZE (tests ); i ++ ) {
305
+ if (tests [i ].filter && tests [i ].filter ()) {
306
+ ksft_test_result_skip ("%s\n" , tests [i ].name );
307
+ continue ;
308
+ }
193
309
194
- /* Do a clone3() with > page size in a new PID NS */
195
- test_clone3 (CLONE_NEWPID , getpagesize () + 8 , - E2BIG ,
196
- CLONE3_ARGS_NO_TEST );
310
+ if (tests [i ].size_function )
311
+ size = tests [i ].size_function ();
312
+ else
313
+ size = tests [i ].size ;
197
314
198
- /* Do a clone3() in a new time namespace */
199
- test_clone3 (CLONE_NEWTIME , 0 , 0 , CLONE3_ARGS_NO_TEST );
315
+ ksft_print_msg ("Running test '%s'\n" , tests [i ].name );
200
316
201
- /* Do a clone3() with exit signal (SIGCHLD) in flags */
202
- test_clone3 (SIGCHLD , 0 , - EINVAL , CLONE3_ARGS_NO_TEST );
317
+ ksft_test_result (test_clone3 (tests [i ].flags , size ,
318
+ tests [i ].expected ,
319
+ tests [i ].test_mode ),
320
+ "%s\n" , tests [i ].name );
321
+ }
203
322
204
323
ksft_finished ();
205
324
}
0 commit comments