master
c 570 lines 12.6 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 auxv.c
8
9 Abstract:
10
11 This file is a test for the auxiliary vector functionality.
12
13 --*/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/auxv.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include "lxtcommon.h"
23 #include "unittests.h"
24
25 #define AUXV_UID 1004
26 #define AUXV_GID 1004
27
28 #define LXT_NAME "auxv"
29
30 #define AUXV_TEST_SCRIPT "auxv_test_script.sh"
31 #define AUXV_TEST_SCRIPT_SOURCE "#!" AUXV_TEST_PROGRAM_PATH
32 #define AUXV_TEST_PROGRAM "auxv_test_program"
33 #define AUXV_TEST_PROGRAM_PATH "/data/test/" AUXV_TEST_PROGRAM
34 #define AUXV_TEST_PROGRAM_SOURCE_FILE "auxv_test_program.c"
35 #define AUXV_TEST_PROGRAM_SOURCE \
36 "#include <stdio.h>\n" \
37 "#include <string.h>\n" \
38 "#include <stdlib.h>\n" \
39 "#include <sys/auxv.h>\n" \
40 "\n" \
41 "int main(int Argc, char** Argv)\n" \
42 "{\n" \
43 " int Index;\n" \
44 " char* Filename = (char*)getauxval(AT_EXECFN);\n" \
45 " char* Platform = (char*)getauxval(AT_PLATFORM);\n" \
46 " printf(\"AT_EXECFN: %%s {%%p}\\n\", Filename, Filename);\n" \
47 " printf(\"AT_PLATFORM: %%s {%%p}\\n\", Platform, Platform);\n" \
48 " for (Index = 0; Index < Argc; Index += 1) {\n" \
49 " printf(\"Argv[%%d] = %%s\\n\", Index, Argv[Index]);\n" \
50 " }\n" \
51 " if (Platform > Filename) {\n" \
52 " return -1;\n" \
53 " }\n" \
54 " if ((strcmp(Platform, \"%s\") != 0) ||\n" \
55 " (strcmp(Filename, \"%s\") != 0)) {\n" \
56 " return -1;\n" \
57 " }\n" \
58 " return 0;\n" \
59 "}"
60
61 int AuxvAtExecfn(PLXT_ARGS Args);
62
63 int AuxvGetAuxv(PLXT_ARGS Args);
64
65 int AuxvGetAuxvChild(void);
66
67 static const LXT_VARIATION g_LxtVariations[] = {{"getauxv", AuxvGetAuxv}, {"AT_EXECFN", AuxvAtExecfn}};
68
69 int AuxvTestEntry(int Argc, char* Argv[])
70 {
71
72 LXT_ARGS Args;
73 int ArgvIndex;
74 int Result;
75
76 Result = LXT_RESULT_FAILURE;
77
78 //
79 // Parse the arguments.
80 //
81
82 for (ArgvIndex = 1; ArgvIndex < Argc; ++ArgvIndex)
83 {
84 if (Argv[ArgvIndex][0] != '-')
85 {
86 printf("Unexpected character %s", Argv[ArgvIndex]);
87 goto ErrorExit;
88 }
89
90 switch (Argv[ArgvIndex][1])
91 {
92 case 'c':
93
94 //
95 // Run the getauxv child variation.
96 //
97
98 return AuxvGetAuxvChild();
99
100 //
101 // The below arguments are taken care of by LxtInitialize.
102 //
103
104 case 'a':
105 break;
106
107 case 'v':
108 case 'l':
109 ++ArgvIndex;
110
111 break;
112
113 default:
114 goto ErrorExit;
115 }
116 }
117
118 //
119 // If -c was not specified, just run the tests
120 //
121
122 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
123 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
124
125 ErrorExit:
126 LxtUninitialize();
127 return 0;
128 }
129
130 int AuxvGetAuxv(PLXT_ARGS Args)
131
132 {
133
134 char* Argv[4];
135 struct stat Buffer;
136 int ChildPid;
137 int Mode;
138 int OriginalMode;
139 gid_t OriginalGid;
140 uid_t OriginalUid;
141 int Result;
142 unsigned long Value;
143
144 ChildPid = -1;
145 OriginalMode = 0;
146 OriginalUid = 0;
147 OriginalGid = 0;
148 Value = getauxval(AT_SECURE);
149 LxtLogInfo("Parent AT_SECURE = %u", Value);
150 LxtCheckEqual(Value, 0, "%u");
151
152 // change Args->Argv[0] so that it points to the new single test binary design
153 Args->Argv[0] = Argv[0] = WSL_UNIT_TEST_BINARY;
154 LxtLogInfo("calling stat(%s)", Args->Argv[0]);
155 LxtCheckErrno(stat(Args->Argv[0], &Buffer));
156 OriginalMode = Buffer.st_mode;
157 OriginalGid = Buffer.st_gid;
158 OriginalUid = Buffer.st_uid;
159
160 LxtLogInfo("Setting the set-user-ID bit");
161 Mode = OriginalMode | S_ISUID;
162
163 LxtCheckErrno(chown(Args->Argv[0], AUXV_UID, AUXV_UID));
164 LxtCheckErrno(chmod(Args->Argv[0], Mode));
165
166 //
167 // Start a child process to verify the value of AT_SECURE.
168 //
169
170 LxtCheckErrno(ChildPid = fork());
171 if (ChildPid == 0)
172 {
173 Argv[1] = "auxv";
174 Argv[2] = "-c";
175 Argv[3] = NULL;
176 execve(Args->Argv[0], Argv, NULL);
177 LxtLogError("Execve failed, errno: %d (%s)", errno, strerror(errno));
178 _exit(LXT_RESULT_FAILURE);
179 }
180
181 //
182 // Wait for the child to exit.
183 //
184
185 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
186
187 LxtLogInfo("Setting the set-group-ID bit");
188 Mode = OriginalMode | S_ISGID;
189 LxtCheckErrno(chmod(Args->Argv[0], Mode));
190
191 //
192 // Start a child process to verify the value of AT_SECURE.
193 //
194
195 LxtCheckErrno(ChildPid = fork());
196 if (ChildPid == 0)
197 {
198 Argv[1] = "auxv";
199 Argv[2] = "-c";
200 Argv[3] = NULL;
201 execve(Argv[0], Argv, NULL);
202 LxtLogError("Execve failed, errno: %d (%s)", errno, strerror(errno));
203 _exit(LXT_RESULT_FAILURE);
204 }
205
206 //
207 // Wait for the child to exit.
208 //
209
210 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
211 Result = LXT_RESULT_SUCCESS;
212
213 ErrorExit:
214 if (OriginalMode != 0)
215 {
216 chmod(Args->Argv[0], OriginalMode);
217 chown(Args->Argv[0], OriginalUid, OriginalGid);
218 }
219
220 if (ChildPid == 0)
221 {
222 _exit(Result);
223 }
224
225 return Result;
226 }
227
228 int AuxvGetAuxvChild(void)
229
230 {
231
232 int ChildPid;
233 int Result;
234 unsigned long Value;
235
236 ChildPid = -1;
237 Value = getauxval(AT_SECURE);
238 LxtLogInfo("child AT_SECURE = %u", Value);
239 LxtCheckEqual(Value, 1, "%u");
240
241 //
242 // Start a child process to verify the value of AT_SECURE.
243 //
244
245 LxtCheckErrno(ChildPid = fork());
246 if (ChildPid == 0)
247 {
248 Value = getauxval(AT_SECURE);
249 LxtLogInfo("child fork AT_SECURE = %u", Value);
250 LxtCheckEqual(Value, 1, "%u");
251 Result = LXT_RESULT_SUCCESS;
252 goto ErrorExit;
253 }
254
255 //
256 // Wait for the child to exit.
257 //
258
259 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
260 Result = LXT_RESULT_SUCCESS;
261
262 ErrorExit:
263 if (ChildPid == 0)
264 {
265 _exit(Result);
266 }
267
268 return Result;
269 }
270
271 int AuxvAtExecfnCompile(char* Filename)
272
273 {
274
275 char* Argv[5];
276 char Buffer[1024];
277 int ByteCount;
278 int ChildPid;
279 int Fd;
280 char* Platform;
281 int Result;
282
283 ChildPid = -1;
284 Fd = -1;
285 Platform = (char*)getauxval(AT_PLATFORM);
286
287 ByteCount = snprintf(Buffer, sizeof(Buffer), AUXV_TEST_PROGRAM_SOURCE, Platform, Filename);
288
289 if (ByteCount < 0)
290 {
291 Result = LXT_RESULT_FAILURE;
292 LxtLogError("Formatting test source failed %d", errno);
293 goto ErrorExit;
294 }
295
296 //
297 // Create the source file to be compiled.
298 //
299
300 LxtCheckErrno(Fd = creat(AUXV_TEST_PROGRAM_SOURCE_FILE, 0755));
301 LxtCheckErrno(ByteCount = write(Fd, Buffer, ByteCount));
302
303 //
304 // Compile the binary
305 //
306
307 LxtCheckErrno(ChildPid = fork());
308 if (ChildPid == 0)
309 {
310 Filename = "/usr/bin/gcc";
311 Argv[0] = "gcc";
312 Argv[1] = AUXV_TEST_PROGRAM_SOURCE_FILE;
313 Argv[2] = "-o";
314 Argv[3] = AUXV_TEST_PROGRAM_PATH;
315 Argv[4] = NULL;
316 LxtCheckErrno(execv(Filename, Argv));
317 goto ErrorExit;
318 }
319
320 //
321 // Wait for the child to exit.
322 //
323
324 LxtCheckResult(LxtWaitPidPollOptions(ChildPid, LXT_RESULT_SUCCESS, 0, 30));
325
326 Result = LXT_RESULT_SUCCESS;
327
328 ErrorExit:
329 if (Fd != -1)
330 {
331 LxtClose(Fd);
332 }
333
334 if (ChildPid == 0)
335 {
336 _exit(Result);
337 }
338
339 unlink(AUXV_TEST_PROGRAM_SOURCE_FILE);
340 return Result;
341 }
342
343 int AuxvAtExecfn(PLXT_ARGS Args)
344
345 {
346
347 char* Argv[2];
348 int ByteCount;
349 int ChildPid;
350 char* Environment[2];
351 int Fd;
352 char* Filename;
353 int Result;
354
355 ChildPid = -1;
356 Fd = -1;
357 Filename = AUXV_TEST_PROGRAM_PATH;
358 LxtCheckResult(AuxvAtExecfnCompile(Filename));
359
360 //
361 // Run the binary with a non-null argument array.
362 //
363
364 LxtCheckErrno(ChildPid = fork());
365 if (ChildPid == 0)
366 {
367 Argv[0] = AUXV_TEST_PROGRAM_PATH;
368 Argv[1] = NULL;
369 LxtCheckErrno(execv(Filename, Argv));
370 goto ErrorExit;
371 }
372
373 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
374
375 //
376 // Run the binary with a null argument array.
377 //
378
379 LxtCheckErrno(ChildPid = fork());
380 if (ChildPid == 0)
381 {
382 Environment[0] = "FOO=bar";
383 Environment[1] = NULL;
384 LxtCheckErrno(LxtExecve(Filename, NULL, Environment));
385 goto ErrorExit;
386 }
387
388 //
389 // Wait for the child to exit.
390 //
391
392 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
393
394 //
395 // Run the binary with an Argv[0] that does not match the filename.
396 //
397
398 LxtCheckErrno(ChildPid = fork());
399 if (ChildPid == 0)
400 {
401 Argv[0] = "FOO";
402 Argv[1] = NULL;
403 LxtCheckErrno(execv(Filename, Argv));
404 goto ErrorExit;
405 }
406
407 //
408 // Wait for the child to exit.
409 //
410
411 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
412
413 //
414 // Run the binary with an empty command line.
415 //
416
417 LxtCheckErrno(ChildPid = fork());
418 if (ChildPid == 0)
419 {
420 Environment[0] = "FOO=bar";
421 Environment[1] = NULL;
422 LxtCheckErrno(LxtExecve(Filename, NULL, Environment));
423 goto ErrorExit;
424 }
425
426 //
427 // Wait for the child to exit.
428 //
429
430 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
431
432 //
433 // Run the binary with null argument and environment arrays.
434 //
435
436 LxtCheckErrno(ChildPid = fork());
437 if (ChildPid == 0)
438 {
439 LxtCheckErrno(LxtExecve(Filename, NULL, NULL));
440 goto ErrorExit;
441 }
442
443 //
444 // Wait for the child to exit.
445 //
446
447 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
448
449 //
450 // Create a script that uses #! to launch the test binary.
451 //
452
453 LxtCheckErrno(Fd = creat(AUXV_TEST_SCRIPT, 0755));
454 LxtCheckErrno(ByteCount = write(Fd, AUXV_TEST_SCRIPT_SOURCE, sizeof(AUXV_TEST_SCRIPT_SOURCE)));
455 LxtClose(Fd);
456 Fd = -1;
457
458 //
459 // Recompile the binary with the script as the expected AT_EXECFN.
460 //
461
462 Filename = AUXV_TEST_SCRIPT;
463 LxtCheckResult(AuxvAtExecfnCompile(Filename));
464
465 //
466 // Run the script with a non-null argument array.
467 //
468
469 LxtCheckErrno(ChildPid = fork());
470 if (ChildPid == 0)
471 {
472 Argv[0] = Filename;
473 Argv[1] = NULL;
474 LxtCheckErrno(execv(Filename, Argv));
475 goto ErrorExit;
476 }
477
478 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
479
480 //
481 // Run the script with a null argument array.
482 //
483
484 LxtCheckErrno(ChildPid = fork());
485 if (ChildPid == 0)
486 {
487 Environment[0] = "FOO=bar";
488 Environment[1] = NULL;
489 LxtCheckErrno(LxtExecve(Filename, NULL, Environment));
490 goto ErrorExit;
491 }
492
493 //
494 // Wait for the child to exit.
495 //
496
497 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
498
499 //
500 // Run the script with an Argv[0] that does not match the filename.
501 //
502
503 LxtCheckErrno(ChildPid = fork());
504 if (ChildPid == 0)
505 {
506 Argv[0] = "FOO";
507 Argv[1] = NULL;
508 LxtCheckErrno(execv(Filename, Argv));
509 goto ErrorExit;
510 }
511
512 //
513 // Wait for the child to exit.
514 //
515
516 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
517
518 //
519 // Run the script with an empty command line.
520 //
521
522 LxtCheckErrno(ChildPid = fork());
523 if (ChildPid == 0)
524 {
525 Environment[0] = "FOO=bar";
526 Environment[1] = NULL;
527 LxtCheckErrno(LxtExecve(Filename, NULL, Environment));
528 goto ErrorExit;
529 }
530
531 //
532 // Wait for the child to exit.
533 //
534
535 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
536
537 //
538 // Run the script with null argument and environment arrays.
539 //
540
541 LxtCheckErrno(ChildPid = fork());
542 if (ChildPid == 0)
543 {
544 LxtCheckErrno(LxtExecve(Filename, NULL, NULL));
545 goto ErrorExit;
546 }
547
548 //
549 // Wait for the child to exit.
550 //
551
552 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
553
554 Result = LXT_RESULT_SUCCESS;
555
556 ErrorExit:
557 if (Fd != -1)
558 {
559 LxtClose(Fd);
560 }
561
562 if (ChildPid == 0)
563 {
564 _exit(Result);
565 }
566
567 unlink(AUXV_TEST_PROGRAM_PATH);
568 unlink(AUXV_TEST_SCRIPT);
569 return Result;
570 }