]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/tests.c
8d1e8f460fa733a885f8f53e6965811bf3562e1a
[apple/xnu.git] / tools / tests / xnu_quick_test / tests.c
1 /*
2 * tests.c
3 * xnu_quick_test
4 *
5 * Created by Jerry Cottingham on 3/25/05.
6 * Copyright 2008 Apple Inc. All rights reserved.
7 *
8 */
9
10 #include "tests.h"
11 #include <sys/ipc.h> /* for message queue tests */
12 #include <sys/msg.h> /* for message queue tests */
13 #include <sys/syscall.h> /* for get / settid */
14 #include <sys/sysctl.h> /* for determining hw */
15 #include <sys/kas_info.h> /* for kas_info() */
16 #include <AvailabilityMacros.h> /* for determination of Mac OS X version (tiger, leopard, etc.) */
17 #include <libkern/OSByteOrder.h> /* for OSSwap32() */
18 #include <mach/mach.h>
19
20
21 extern char g_target_path[ PATH_MAX ];
22 extern int g_skip_setuid_tests;
23 extern int g_is_single_user;
24
25
26 void print_acct_debug_strings( char * my_ac_comm );
27
28
29 #if TEST_SYSTEM_CALLS /* system calls to do */
30 "reboot", /* 55 = reboot */
31 "revoke", /* 56 = revoke */
32 "sbrk", /* 69 = sbrk */
33 "sstk", /* 70 = sstk */
34 "mount", /* 167 = mount */
35 "unmount", /* 159 = unmount */
36 "undelete", /* 205 = undelete */
37 "watchevent", /* 231 = watchevent */
38 "waitevent", /* 232 = waitevent */
39 "modwatch", /* 233 = modwatch */
40 "fsctl", /* 242 = fsctl */
41 "initgroups", /* 243 = initgroups */
42 "semsys", /* 251 = semsys */
43 "semconfig", /* 257 = semconfig */
44 "msgsys", /* 252 = msgsys */
45 "shmsys", /* 253 = shmsys */
46 "load_shared_file", /* 296 = load_shared_file */
47 "reset_shared_file", /* 297 = reset_shared_file */
48 "new_system_shared_regions", /* 298 = new_system_shared_regions */
49 "shared_region_map_file_np", /* 299 = shared_region_map_file_np */
50 "shared_region_make_private_np", /* 300 = shared_region_make_private_np */
51 "__pthread_kill", /* 328 = __pthread_kill */
52 "pthread_sigmask", /* 329 = pthread_sigmask */
53 "__disable_threadsignal", /* 331 = __disable_threadsignal */
54 "__pthread_markcancel", /* 332 = __pthread_markcancel */
55 "__pthread_canceled", /* 333 = __pthread_canceled */
56 "__semwait_signal", /* 334 = __semwait_signal */
57 "audit", /* 350 = audit */
58 "auditon", /* 351 = auditon */
59 "getaudit", /* 355 = getaudit */
60 "setaudit", /* 356 = setaudit */
61 "getaudit_addr", /* 357 = getaudit_addr */
62 "setaudit_addr", /* 358 = setaudit_addr */
63 "auditctl", /* 359 = auditctl */
64 #endif
65
66 /* **************************************************************************************************************
67 * Test the syscall system call.
68 * **************************************************************************************************************
69 */
70 int syscall_test( void * the_argp )
71 {
72 int my_err;
73 int my_fd = -1;
74 char * my_pathp;
75 kern_return_t my_kr;
76
77 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
78 if(my_kr != KERN_SUCCESS){
79 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
80 goto test_failed_exit;
81 }
82
83 *my_pathp = 0x00;
84 strcpy( my_pathp, &g_target_path[0] );
85 strcat( my_pathp, "/" );
86
87 /* create a test file */
88 my_err = create_random_name( my_pathp, 1 );
89 if ( my_err != 0 ) {
90 goto test_failed_exit;
91 }
92
93 /* use an indirect system call to open our test file.
94 * I picked open since it uses a path pointer which grows to 64 bits in an LP64 environment.
95 */
96 my_fd = syscall( SYS_open, my_pathp, (O_RDWR | O_EXCL), 0 );
97 if ( my_fd == -1 ) {
98 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
99 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
100 goto test_failed_exit;
101 }
102
103 my_err = 0;
104 goto test_passed_exit;
105
106 test_failed_exit:
107 my_err = -1;
108
109 test_passed_exit:
110 if ( my_fd != -1 )
111 close( my_fd );
112 if ( my_pathp != NULL ) {
113 remove( my_pathp );
114 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
115 }
116 return( my_err );
117 }
118
119 /* **************************************************************************************************************
120 * Test fork wait4, and exit system calls.
121 * **************************************************************************************************************
122 */
123 int fork_wait4_exit_test( void * the_argp )
124 {
125 int my_err, my_status;
126 pid_t my_pid, my_wait_pid;
127 struct rusage my_usage;
128
129 /* spin off another process */
130 my_pid = fork( );
131 if ( my_pid == -1 ) {
132 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
133 return( -1 );
134 }
135 else if ( my_pid == 0 ) {
136 struct stat my_sb;
137
138 /* child process does very little then exits */
139 my_err = stat( &g_target_path[0], &my_sb );
140 if ( my_err != 0 ) {
141 printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
142 printf( "\t path we stated \"%s\" \n", &g_target_path[0] );
143 exit( -1 );
144 }
145 exit( 44 );
146 }
147
148 /* parent process waits for child to exit */
149 my_wait_pid = wait4( my_pid, &my_status, 0, &my_usage );
150 if ( my_wait_pid == -1 ) {
151 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
152 return( -1 );
153 }
154
155 /* wait4 should return our child's pid when it exits */
156 if ( my_wait_pid != my_pid ) {
157 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
158 return( -1 );
159 }
160
161 /* kind of just guessing on these values so if this fails we should take a closer
162 * look at the returned rusage structure.
163 */
164 if ( my_usage.ru_utime.tv_sec > 1 || my_usage.ru_stime.tv_sec > 1 ||
165 my_usage.ru_majflt > 1000 || my_usage.ru_msgsnd > 100 ) {
166 printf( "wait4 returned an odd looking rusage structure \n" );
167 return( -1 );
168 }
169
170 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) == 44 ) {
171 }
172 else {
173 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status );
174 return( -1 );
175 }
176
177 return( 0 );
178 }
179
180 /* **************************************************************************************************************
181 * Test fsync, ftruncate, lseek, pread, pwrite, read, readv, truncate, write, writev system calls.
182 * **************************************************************************************************************
183 */
184 int read_write_test( void * the_argp )
185 {
186 int my_fd = -1;
187 int my_err;
188 char * my_pathp = NULL;
189 char * my_bufp = NULL;
190 ssize_t my_result;
191 off_t my_current_offset;
192 struct iovec my_iovs[2];
193 struct stat my_sb;
194 kern_return_t my_kr;
195
196 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
197 if(my_kr != KERN_SUCCESS){
198 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
199 goto test_failed_exit;
200 }
201
202 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufp, MY_BUFFER_SIZE, VM_FLAGS_ANYWHERE);
203 if(my_kr != KERN_SUCCESS){
204 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
205 goto test_failed_exit;
206 }
207
208 *my_pathp = 0x00;
209 strcat( my_pathp, &g_target_path[0] );
210 strcat( my_pathp, "/" );
211
212 /* create a test file */
213 my_err = create_random_name( my_pathp, 1 );
214 if ( my_err != 0 ) {
215 goto test_failed_exit;
216 }
217
218 my_fd = open( my_pathp, O_RDONLY, 0 );
219 if ( my_fd == -1 ) {
220 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
221 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
222 goto test_failed_exit;
223 }
224
225 /* should get EOF since the file is empty at this point */
226 my_result = read( my_fd, my_bufp, 10);
227 if ( my_result == -1 ) {
228 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
229 goto test_failed_exit;
230 }
231 if ( my_result != 0 ) {
232 if ( sizeof( ssize_t ) > sizeof( int ) ) {
233 printf( "read call failed - should have read 0 bytes on empty file - read %ld \n", (long int) my_result );
234 }
235 else {
236 printf( "read call failed - should have read 0 bytes on empty file - read %d \n", (int) my_result );
237 }
238 goto test_failed_exit;
239 }
240
241 /* this write should fail since we opened for read only */
242 my_result = write( my_fd, my_bufp, 10 );
243 my_err = errno;
244 if ( my_result != -1 ) {
245 if ( sizeof( ssize_t ) > sizeof( int ) ) {
246 printf( "write should have failed for read only fd - %ld \n", (long int) my_result );
247 }
248 else {
249 printf( "write should have failed for read only fd - %d \n", (int) my_result );
250 }
251 goto test_failed_exit;
252 }
253 if ( my_err != EBADF ) {
254 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
255 printf( "should have failed with EBADF error %d \n", EBADF );
256 goto test_failed_exit;
257 }
258
259 /* now really write some data */
260 close( my_fd );
261 my_fd = open( my_pathp, O_RDWR, 0 );
262 if ( my_fd == -1 ) {
263 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
264 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
265 goto test_failed_exit;
266 }
267
268 memset( my_bufp, 'j', MY_BUFFER_SIZE );
269 my_result = write( my_fd, my_bufp, MY_BUFFER_SIZE );
270 if ( my_result == -1 ) {
271 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
272 goto test_failed_exit;
273 }
274 if ( my_result != MY_BUFFER_SIZE ) {
275 printf( "write failed to write out all the data \n" );
276 goto test_failed_exit;
277 }
278
279 /* push data to disk */
280 my_err = fsync( my_fd );
281 if ( my_err == -1 ) {
282 printf( "fsync failed with errno %d - %s \n", errno, strerror( errno ) );
283 goto test_failed_exit;
284 }
285
286 /* now verify the write worked OK using readv */
287 lseek( my_fd, 0, SEEK_SET );
288 bzero( (void *)my_bufp, MY_BUFFER_SIZE );
289 my_iovs[0].iov_base = my_bufp;
290 my_iovs[0].iov_len = 16;
291 my_iovs[1].iov_base = (my_bufp + MY_BUFFER_SIZE - 16) ;
292 my_iovs[1].iov_len = 16;
293
294 my_result = readv( my_fd, &my_iovs[0], 2 );
295 if ( my_result == -1 ) {
296 printf( "readv call failed with error %d - \"%s\" \n", errno, strerror( errno) );
297 goto test_failed_exit;
298 }
299 if ( my_result != 32 ) {
300 printf( "readv failed to get all the data - asked for %d got back %d\n", MY_BUFFER_SIZE, (int) my_result );
301 goto test_failed_exit;
302 }
303 if ( *my_bufp != 'j' || *(my_bufp + (MY_BUFFER_SIZE - 1)) != 'j' ) {
304 printf( "readv failed to get correct data \n" );
305 goto test_failed_exit;
306 }
307
308 /* test ftruncate */
309 my_err = ftruncate( my_fd, 0 );
310 if ( my_err == -1 ) {
311 printf( "ftruncate call failed with error %d - \"%s\" \n", errno, strerror( errno) );
312 goto test_failed_exit;
313 }
314
315 my_err = fstat( my_fd, &my_sb );
316 if ( my_err == -1 ) {
317 printf( "fstat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
318 goto test_failed_exit;
319 }
320 if ( my_sb.st_size != 0 ) {
321 printf( "ftruncate call failed - file size is wrong \n" );
322 goto test_failed_exit;
323 }
324
325 /* test writev */
326 lseek( my_fd, 0, SEEK_SET );
327 memset( my_bufp, 'z', MY_BUFFER_SIZE );
328 my_iovs[0].iov_base = my_bufp;
329 my_iovs[0].iov_len = 8;
330 my_iovs[1].iov_base = (my_bufp + MY_BUFFER_SIZE - 8) ;
331 my_iovs[1].iov_len = 8;
332 my_result = writev( my_fd, &my_iovs[0], 2 );
333 if ( my_result == -1 ) {
334 printf( "writev call failed with error %d - \"%s\" \n", errno, strerror( errno) );
335 goto test_failed_exit;
336 }
337 if ( my_result != 16 ) {
338 printf( "writev failed to get all the data - asked for %d got back %d\n", MY_BUFFER_SIZE, (int) my_result );
339 goto test_failed_exit;
340 }
341
342 /* now verify the writev worked OK */
343 lseek( my_fd, 0, SEEK_SET );
344 bzero( (void *)my_bufp, MY_BUFFER_SIZE );
345 my_iovs[0].iov_base = my_bufp;
346 my_iovs[0].iov_len = 8;
347 my_iovs[1].iov_base = (my_bufp + MY_BUFFER_SIZE - 8) ;
348 my_iovs[1].iov_len = 8;
349
350 my_result = readv( my_fd, &my_iovs[0], 2 );
351 if ( my_result == -1 ) {
352 printf( "readv call failed with error %d - \"%s\" \n", errno, strerror( errno) );
353 goto test_failed_exit;
354 }
355 if ( my_result != 16 ) {
356 printf( "readv failed to get all the data - asked for %d got back %d\n", MY_BUFFER_SIZE, (int) my_result );
357 goto test_failed_exit;
358 }
359 if ( *my_bufp != 'z' || *(my_bufp + (MY_BUFFER_SIZE - 1)) != 'z' ) {
360 printf( "readv failed to get correct data \n" );
361 goto test_failed_exit;
362 }
363
364 /* test pread and pwrite */
365 my_current_offset = lseek( my_fd, 0, SEEK_CUR );
366 if ( my_current_offset == -1 ) {
367 printf( "lseek call failed with error %d - \"%s\" \n", errno, strerror( errno) );
368 goto test_failed_exit;
369 }
370
371 my_result = pwrite( my_fd, "jer", 3, my_current_offset );
372 if ( my_result == -1 ) {
373 printf( "pwrite call failed with error %d - \"%s\" \n", errno, strerror( errno) );
374 goto test_failed_exit;
375 }
376 if ( my_result != 3 ) {
377 printf( "pwrite failed to write all the data \n" );
378 goto test_failed_exit;
379 }
380
381 /* make sure file position did not advance */
382 if ( my_current_offset != lseek( my_fd, 0, SEEK_CUR ) ) {
383 printf( "pwrite advanced file positiion \n" );
384 goto test_failed_exit;
385 }
386
387 bzero( (void *)my_bufp, MY_BUFFER_SIZE );
388 my_result = pread( my_fd, my_bufp, 3, my_current_offset );
389 if ( my_result == -1 ) {
390 printf( "pread call failed with error %d - \"%s\" \n", errno, strerror( errno) );
391 goto test_failed_exit;
392 }
393 if ( my_result != 3 ) {
394 printf( "pread failed to write all the data \n" );
395 goto test_failed_exit;
396 }
397
398 /* make sure file position did not advance */
399 if ( my_current_offset != lseek( my_fd, 0, SEEK_CUR ) ) {
400 printf( "pread advanced file positiion \n" );
401 goto test_failed_exit;
402 }
403
404 /* make sure pread and pwrite transferred correct data */
405 if ( strcmp( my_bufp, "jer" ) != 0 ) {
406 printf( "pread or pwrite failed to read / write correct data \n" );
407 goto test_failed_exit;
408 }
409
410 /* test truncate */
411 my_err = truncate( my_pathp, 0 );
412 if ( my_err == -1 ) {
413 printf( "truncate call failed with error %d - \"%s\" \n", errno, strerror( errno) );
414 goto test_failed_exit;
415 }
416
417 my_err = stat( my_pathp, &my_sb );
418 if ( my_err == -1 ) {
419 printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
420 goto test_failed_exit;
421 }
422 if ( my_sb.st_size != 0 ) {
423 printf( "truncate call failed - file size is wrong \n" );
424 goto test_failed_exit;
425 }
426
427 my_err = 0;
428 goto test_passed_exit;
429
430 test_failed_exit:
431 my_err = -1;
432
433 test_passed_exit:
434 if ( my_fd != -1 )
435 close( my_fd );
436 if ( my_pathp != NULL ) {
437 remove( my_pathp );
438 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
439 }
440 if ( my_bufp != NULL )
441 vm_deallocate(mach_task_self(), (vm_address_t)my_bufp, MY_BUFFER_SIZE);
442 return( my_err );
443 }
444
445 /* **************************************************************************************************************
446 * Test close, fpathconf, fstat, open, pathconf system calls.
447 * **************************************************************************************************************
448 */
449 int open_close_test( void * the_argp )
450 {
451 int my_err;
452 int my_fd = -1;
453 char * my_pathp = NULL;
454 ssize_t my_result;
455 long my_pconf_result;
456 struct stat my_sb;
457 char my_buffer[32];
458 kern_return_t my_kr;
459
460 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
461 if(my_kr != KERN_SUCCESS){
462 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
463 goto test_failed_exit;
464 }
465
466 *my_pathp = 0x00;
467 strcat( my_pathp, &g_target_path[0] );
468 strcat( my_pathp, "/" );
469
470 /* create a test file */
471 my_err = create_random_name( my_pathp, 1 );
472 if ( my_err != 0 ) {
473 goto test_failed_exit;
474 }
475
476 /* test O_WRONLY case */
477 my_fd = open( my_pathp, O_WRONLY, 0 );
478 if ( my_fd == -1 ) {
479 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
480 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
481 goto test_failed_exit;
482 }
483
484 /* test pathconf and fpathconf */
485 my_pconf_result = pathconf( my_pathp, _PC_PATH_MAX );
486 if ( my_pconf_result == -1 ) {
487 printf( "pathconf - _PC_PATH_MAX - failed with error %d - \"%s\" \n", errno, strerror( errno) );
488 goto test_failed_exit;
489 }
490 // printf( "_PC_PATH_MAX %ld \n", my_pconf_result );
491 /* results look OK? */
492 if ( my_pconf_result < PATH_MAX ) {
493 printf( "pathconf - _PC_PATH_MAX - looks like wrong results \n" );
494 goto test_failed_exit;
495 }
496
497 my_pconf_result = fpathconf( my_fd, _PC_NAME_MAX );
498 if ( my_pconf_result == -1 ) {
499 printf( "fpathconf - _PC_PATH_MAX - failed with error %d - \"%s\" \n", errno, strerror( errno) );
500 goto test_failed_exit;
501 }
502 // printf( "_PC_NAME_MAX %ld \n", my_pconf_result );
503 /* results look OK? */
504 if ( my_pconf_result < 6 ) {
505 printf( "fpathconf - _PC_NAME_MAX - looks like wrong results \n" );
506 goto test_failed_exit;
507 }
508
509 /* write some data then try to read it */
510 my_result = write( my_fd, "kat", 3 );
511 my_err = errno;
512 if ( my_result != 3 ) {
513 if ( sizeof( ssize_t ) > sizeof( int ) ) {
514 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
515 }
516 else {
517 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
518 }
519 goto test_failed_exit;
520 }
521
522 /* Try to read - this should fail since we opened file with O_WRONLY */
523 my_result = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
524 my_err = errno;
525 if ( my_result != -1 ) {
526 printf( "read call should have failed with errno 9 (EBADF) \n" );
527 goto test_failed_exit;
528 }
529 else if ( my_err != EBADF ) {
530 printf( "read call should have failed with errno 9 (EBADF). actually failed with %d - \"%s\" \n", my_err, strerror( my_err) );
531 goto test_failed_exit;
532 }
533
534 close( my_fd );
535
536 /* test O_TRUNC and O_APPEND case */
537 my_fd = open( my_pathp, (O_RDWR | O_TRUNC | O_APPEND), 0 );
538 if ( my_fd == -1 ) {
539 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
540 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
541 goto test_failed_exit;
542 }
543
544 my_result = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
545 if ( my_result == -1 ) {
546 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
547 goto test_failed_exit;
548 }
549 if ( my_result != 0 ) {
550 printf( "read failed - should have read 0 bytes. \n" );
551 goto test_failed_exit;
552 }
553
554 my_result = write( my_fd, "kat", 3 );
555 my_err = errno;
556 if ( my_result != 3 ) {
557 if ( sizeof( ssize_t ) > sizeof( int ) ) {
558 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
559 }
560 else {
561 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
562 }
563 goto test_failed_exit;
564 }
565
566 /* add some more data to the test file - this should be appended */
567 lseek( my_fd, 0, SEEK_SET );
568 my_result = write( my_fd, "zzz", 3 );
569 my_err = errno;
570 if ( my_result != 3 ) {
571 if ( sizeof( ssize_t ) > sizeof( int ) ) {
572 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
573 }
574 else {
575 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
576 }
577 goto test_failed_exit;
578 }
579
580 /* now verify the writes */
581 bzero( (void *)&my_buffer[0], sizeof(my_buffer) );
582 lseek( my_fd, 0, SEEK_SET );
583 my_result = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
584 if ( my_result == -1 ) {
585 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
586 goto test_failed_exit;
587 }
588 if ( my_buffer[0] != 'k' || my_buffer[5] != 'z' ) {
589 printf( "read failed to get correct data \n" );
590 goto test_failed_exit;
591 }
592
593 /* test fstat */
594 my_err = fstat( my_fd, &my_sb );
595 if ( my_err == -1 ) {
596 printf( "fstat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
597 goto test_failed_exit;
598 }
599 if ( my_sb.st_size != 6 ) {
600 printf( "fstat call failed - st_size is wrong \n" );
601 goto test_failed_exit;
602 }
603 if ( !S_ISREG( my_sb.st_mode ) ) {
604 printf( "fstat call failed - st_mode does not indicate regular file \n" );
605 goto test_failed_exit;
606 }
607
608 my_err = 0;
609 goto test_passed_exit;
610
611 test_failed_exit:
612 my_err = -1;
613
614 test_passed_exit:
615 if ( my_fd != -1 )
616 close( my_fd );
617 if ( my_pathp != NULL ) {
618 remove( my_pathp );
619 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
620 }
621 return( my_err );
622 }
623
624 /* **************************************************************************************************************
625 * Test link, stat and unlink system calls.
626 * **************************************************************************************************************
627 */
628 int link_stat_unlink_test( void * the_argp )
629 {
630 int my_err;
631 int my_fd = -1;
632 char * my_pathp = NULL;
633 char * my_path2p = NULL;
634 nlink_t my_link_count;
635 ssize_t my_result;
636 struct stat my_sb;
637 kern_return_t my_kr;
638
639 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
640 if(my_kr != KERN_SUCCESS){
641 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
642 goto test_failed_exit;
643 }
644
645 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_path2p, PATH_MAX, VM_FLAGS_ANYWHERE);
646 if(my_kr != KERN_SUCCESS){
647 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
648 goto test_failed_exit;
649 }
650
651 *my_pathp = 0x00;
652 *my_path2p = 0x00;
653 strcat( my_pathp, &g_target_path[0] );
654 strcat( my_pathp, "/" );
655
656 /* create a test file */
657 my_err = create_random_name( my_pathp, 1 );
658 if ( my_err != 0 ) {
659 goto test_failed_exit;
660 }
661
662 /* now create a name for the link file */
663 strcat( my_path2p, my_pathp );
664 strcat( my_path2p, "link" );
665
666 /* get the current link count */
667 my_err = stat( my_pathp, &my_sb );
668 if ( my_err != 0 ) {
669 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
670 goto test_failed_exit;
671 }
672 my_link_count = my_sb.st_nlink;
673
674 /* check file size (should be 0) */
675 if ( my_sb.st_size != 0 ) {
676 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
677 printf( "st_size is not 0 \n" );
678 goto test_failed_exit;
679 }
680
681 /* change file size */
682 my_fd = open( my_pathp, O_RDWR, 0 );
683 if ( my_fd == -1 ) {
684 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
685 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
686 goto test_failed_exit;
687 }
688 my_result = write( my_fd, "kat", 3 );
689 my_err = errno;
690 if ( my_result != 3 ) {
691 if ( sizeof( ssize_t ) > sizeof( int ) ) {
692 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
693 }
694 else {
695 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
696 }
697 goto test_failed_exit;
698 }
699 close( my_fd );
700 my_fd = -1;
701
702 /* now link another file to our test file and recheck link count */
703 my_err = link( my_pathp, my_path2p );
704 if ( my_err != 0 ) {
705 printf( "link call failed. got errno %d - %s. \n", errno, strerror( errno ) );
706 goto test_failed_exit;
707 }
708 my_err = stat( my_pathp, &my_sb );
709 if ( my_err != 0 ) {
710 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
711 goto test_failed_exit;
712 }
713 if ( (my_link_count + 1) != my_sb.st_nlink ) {
714 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
715 printf( "incorrect st_nlink \n" );
716 goto test_failed_exit;
717 }
718
719 /* check file size (should be 3) */
720 if ( my_sb.st_size != 3 ) {
721 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
722 printf( "st_size is not 3 \n" );
723 goto test_failed_exit;
724 }
725
726 /* now make sure unlink works OK */
727 my_err = unlink( my_path2p );
728 if ( my_err != 0 ) {
729 printf( "unlink call failed. got errno %d - %s. \n", errno, strerror( errno ) );
730 goto test_failed_exit;
731 }
732 my_err = stat( my_pathp, &my_sb );
733 if ( my_err != 0 ) {
734 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
735 goto test_failed_exit;
736 }
737 if ( my_link_count != my_sb.st_nlink ) {
738 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
739 printf( "incorrect st_nlink \n" );
740 goto test_failed_exit;
741 }
742
743 my_err = 0;
744 goto test_passed_exit;
745
746 test_failed_exit:
747 my_err = -1;
748
749 test_passed_exit:
750 if ( my_fd != -1 )
751 close( my_fd );
752 if ( my_pathp != NULL ) {
753 remove( my_pathp );
754 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
755 }
756 if ( my_path2p != NULL ) {
757 remove( my_path2p );
758 vm_deallocate(mach_task_self(), (vm_address_t)my_path2p, PATH_MAX);
759 }
760 return( my_err );
761 }
762
763 /* **************************************************************************************************************
764 * Test chdir and fchdir system calls.
765 * **************************************************************************************************************
766 */
767 int chdir_fchdir_test( void * the_argp )
768 {
769 int my_err;
770 int my_fd = -1;
771 char * my_pathp = NULL;
772 char * my_file_namep;
773 struct stat my_sb;
774 struct stat my_sb2;
775 kern_return_t my_kr;
776
777 char *cwd = getwd(NULL); /* Save current working directory so we can restore later */
778
779 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
780 if(my_kr != KERN_SUCCESS){
781 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
782 goto test_failed_exit;
783 }
784
785 *my_pathp = 0x00;
786 strcat( my_pathp, &g_target_path[0] );
787 strcat( my_pathp, "/" );
788
789 /* create a test file */
790 my_err = create_random_name( my_pathp, 1 );
791 if ( my_err != 0 ) {
792 goto test_failed_exit;
793 }
794
795 /* test by doing a stat on the test file using a full path and a partial path.
796 * get full path first.
797 */
798 my_err = stat( my_pathp, &my_sb );
799 if ( my_err != 0 ) {
800 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
801 goto test_failed_exit;
802 }
803
804 /* now do the chdir to our test directory and then do the stat relative to that location */
805 my_err = chdir( &g_target_path[0] );
806 if ( my_err != 0 ) {
807 printf( "chdir call failed. got errno %d - %s. \n", errno, strerror( errno ) );
808 goto test_failed_exit;
809 }
810
811 my_file_namep = strrchr( my_pathp, '/' );
812 my_file_namep++;
813 my_err = stat( my_file_namep, &my_sb2 );
814 if ( my_err != 0 ) {
815 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
816 goto test_failed_exit;
817 }
818
819 /* both stat buffers should contain the same data since they should be referencing the same
820 * file.
821 */
822 if ( my_sb.st_ino != my_sb2.st_ino || my_sb.st_size != my_sb2.st_size ||
823 my_sb.st_mtimespec.tv_sec != my_sb2.st_mtimespec.tv_sec ||
824 my_sb.st_mtimespec.tv_nsec != my_sb2.st_mtimespec.tv_nsec ) {
825 printf( "chdir call appears to have failed. stat buffer contents do not match! \n" );
826 goto test_failed_exit;
827 }
828
829 /* now change our current directory to "/" and use fchdir to get back to our test directory */
830 my_err = chdir( "/" );
831 if ( my_err != 0 ) {
832 printf( "chdir call failed. got errno %d - %s. \n", errno, strerror( errno ) );
833 goto test_failed_exit;
834 }
835
836 /* we should not find our test file at the root of the volume */
837 my_err = stat( my_file_namep, &my_sb2 );
838 if ( my_err == 0 ) {
839 printf( "chdir to root volume has failed \n" );
840 goto test_failed_exit;
841 }
842
843 /* get a file descriptor to the test directory for use with fchdir */
844 my_fd = open( &g_target_path[0], O_RDONLY, 0 );
845 if ( my_fd == -1 ) {
846 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
847 printf( "\t we attempted to open -> \"%s\" \n", &g_target_path[0] );
848 goto test_failed_exit;
849 }
850
851 my_err = fchdir( my_fd );
852 if ( my_err == -1 ) {
853 printf( "fchdir call failed. got errno %d - %s. \n", errno, strerror( errno ) );
854 goto test_failed_exit;
855 }
856
857 my_err = stat( my_file_namep, &my_sb2 );
858 if ( my_err != 0 ) {
859 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
860 goto test_failed_exit;
861 }
862
863 /* both stat buffers should contain the same data since they should be referencing the same
864 * file.
865 */
866 if ( my_sb.st_ino != my_sb2.st_ino || my_sb.st_size != my_sb2.st_size ||
867 my_sb.st_mtimespec.tv_sec != my_sb2.st_mtimespec.tv_sec ||
868 my_sb.st_mtimespec.tv_nsec != my_sb2.st_mtimespec.tv_nsec ) {
869 printf( "chdir call appears to have failed. stat buffer contents do not match! \n" );
870 goto test_failed_exit;
871 }
872
873 my_err = 0;
874 goto test_passed_exit;
875
876 test_failed_exit:
877 my_err = -1;
878
879 test_passed_exit:
880 if ( my_fd != -1 )
881 close( my_fd );
882 if ( my_pathp != NULL ) {
883 remove( my_pathp );
884 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
885 }
886 if ( chdir(cwd) != 0) /* Changes back to original directory, don't screw up the env. */
887 my_err = -1;
888 return( my_err );
889 }
890
891 /* **************************************************************************************************************
892 * Test access, chmod and fchmod system calls.
893 * **************************************************************************************************************
894 */
895 int access_chmod_fchmod_test( void * the_argp )
896 {
897 int error_occurred;
898 int my_err;
899 int my_fd = -1;
900
901 char * my_pathp = NULL;
902
903 uid_t ruid;
904 struct stat my_sb;
905
906 FILE * file_handle;
907
908 kern_return_t my_kr;
909
910
911 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
912 if(my_kr != KERN_SUCCESS){
913 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
914 goto test_failed_exit;
915 }
916
917 *my_pathp = 0x00;
918 strcat( my_pathp, &g_target_path[0] );
919 strcat( my_pathp, "/" );
920
921 /* create a test file */
922 my_err = create_random_name( my_pathp, 1 );
923 if ( my_err != 0 ) {
924 goto test_failed_exit;
925 }
926
927
928 /* test chmod */
929 my_err = chmod( my_pathp, S_IRWXU );
930 if ( my_err == -1 ) {
931 printf( "chmod call failed. got errno %d - %s. \n", errno, strerror( errno ) );
932 goto test_failed_exit;
933 }
934
935 my_err = chmod( my_pathp, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) );
936 if ( my_err == -1 ) {
937 printf( "chmod call failed. got errno %d - %s. \n", errno, strerror( errno ) );
938 goto test_failed_exit;
939 }
940
941 /* test access - this should fail */
942 my_err = access( my_pathp, (X_OK) );
943 if ( my_err == 0 ) {
944 printf( "access call should have failed, but did not. \n" );
945 goto test_failed_exit;
946 }
947 else if ( my_err == -1 ) {
948 int tmp = 0;
949 tmp = getuid( );
950
951 /* special case when running as root - we get back EPERM when running as root */
952 my_err = errno;
953 if ( ( tmp == 0 && my_err != EPERM) || (tmp != 0 && my_err != EACCES) ) {
954 printf( "access failed with errno %d - %s. \n", my_err, strerror( my_err ) );
955 goto test_failed_exit;
956 }
957 }
958
959 /* verify correct modes are set */
960 my_err = stat( my_pathp, &my_sb );
961 if ( my_err != 0 ) {
962 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
963 goto test_failed_exit;
964 }
965
966 if ( (my_sb.st_mode & (S_IRWXO | S_IXGRP)) != 0 ||
967 (my_sb.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == 0 ) {
968 printf( "chmod call appears to have failed. stat shows incorrect values in st_mode! \n" );
969 goto test_failed_exit;
970 }
971
972
973 /* another test for the access system call -- refer ro radar# 6725311 */
974
975
976 /*
977 * This test makes sure that the access system call does not give the current user extra
978 * permissions on files the current user does not own. From radar #6725311, this could
979 * happen when the current user calls access() on a file owned by the current user in
980 * the same directory as the other files not owned by the current user.
981 *
982 * Note: This test expects that the effective uid (euid) is set to root.
983 *
984 */
985
986 /* Create a file that root owns */
987 file_handle = fopen(FILE_NOTME, "w");
988 fclose(file_handle);
989
990 /* Currently running as root (through settid manipulation), switch to running as the current user. */
991 ruid = getuid();
992 my_err = syscall(SYS_settid, ruid, KAUTH_GID_NONE);
993 if (my_err != 0) {
994 printf("Failed to settid to non-root with error %d:%s\n", errno, strerror(errno));
995 goto test_failed_exit;
996 }
997
998 /* Create a file that the current user owns */
999 file_handle = fopen(FILE_ME, "w");
1000 fclose(file_handle);
1001
1002 error_occurred = 0;
1003
1004 /* Try to remove the file owned by root (this should fail). */
1005 my_err = unlink(FILE_NOTME);
1006
1007 if (my_err < 0) {
1008 my_err = errno;
1009 }
1010
1011 if (my_err == 0) {
1012 printf("Unresolved: First attempt deleted '" FILE_NOTME "'! \n");
1013 error_occurred = 1;
1014 } else {
1015 printf("Status: First attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
1016
1017 /* Set _DELETE_OK on a file that the current user owns */
1018 access(FILE_ME, _DELETE_OK);
1019
1020 /* Try to remove the file owned by root again (should give us: EPERM [13]) */
1021 my_err = unlink(FILE_NOTME);
1022
1023 if (my_err < 0) {
1024 my_err = errno;
1025 }
1026
1027 if (my_err == 0) {
1028 printf("Failed: Second attempt deleted '" FILE_NOTME "'!\n");
1029 error_occurred = 1;
1030 } else if (my_err == 13) {
1031 printf("Passed: Second attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
1032 } else {
1033 printf("Failed: Second attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
1034 error_occurred = 1;
1035 }
1036 }
1037
1038 /* Reset to running as root */
1039 my_err = syscall(SYS_settid, KAUTH_UID_NONE, KAUTH_GID_NONE);
1040 if (my_err != 0) {
1041 printf("Failed to revert to root using settid with error %d:%s\n", errno, strerror(errno));
1042 goto test_failed_exit;
1043 }
1044 if(error_occurred == 1) {
1045 goto test_failed_exit;
1046 }
1047
1048
1049 /* end of test*/
1050
1051
1052 /* test fchmod */
1053 my_fd = open( my_pathp, O_RDONLY, 0 );
1054 if ( my_fd == -1 ) {
1055 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1056 printf( "\t we attempted to open -> \"%s\" \n", &g_target_path[0] );
1057 goto test_failed_exit;
1058 }
1059
1060 my_err = fchmod( my_fd, S_IRWXU );
1061 if ( my_err == -1 ) {
1062 printf( "fchmod call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1063 goto test_failed_exit;
1064 }
1065
1066 my_err = stat( my_pathp, &my_sb );
1067 if ( my_err != 0 ) {
1068 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1069 goto test_failed_exit;
1070 }
1071
1072 /* verify correct modes are set */
1073 if ( (my_sb.st_mode & (S_IRWXG | S_IRWXO)) != 0 ||
1074 (my_sb.st_mode & (S_IRWXU)) == 0 ) {
1075 printf( "fchmod call appears to have failed. stat shows incorrect values in st_mode! \n" );
1076 goto test_failed_exit;
1077 }
1078
1079 my_err = 0;
1080 goto test_passed_exit;
1081
1082 test_failed_exit:
1083 my_err = -1;
1084
1085 test_passed_exit:
1086 if ( my_fd != -1 )
1087 close( my_fd );
1088 if ( my_pathp != NULL ) {
1089 remove( my_pathp );
1090 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
1091 }
1092 return( my_err );
1093 }
1094
1095 static bool _prime_groups(void)
1096 {
1097 /*
1098 * prime groups with a known list to ensure consistent test behavior
1099 */
1100
1101 gid_t my_exp_groups[] = { getegid(), 20, 61, 12 };
1102 int my_err;
1103
1104 my_err = setgroups( ( sizeof(my_exp_groups) / sizeof(*my_exp_groups) ), &my_exp_groups[0] );
1105 if ( my_err == -1 ) {
1106 printf( "initial setgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1107 return false;
1108 }
1109
1110 return true;
1111 }
1112
1113 /* **************************************************************************************************************
1114 * Test chown, fchown, lchown, lstat, readlink, symlink system calls.
1115 * **************************************************************************************************************
1116 */
1117 int chown_fchown_lchown_lstat_symlink_test( void * the_argp )
1118 {
1119 int my_err, my_group_count, i;
1120 int my_fd = -1;
1121 char * my_pathp = NULL;
1122 char * my_link_pathp = NULL;
1123 uid_t my_orig_uid;
1124 gid_t my_orig_gid, my_new_gid1 = 0, my_new_gid2 = 0;
1125 ssize_t my_result;
1126 struct stat my_sb;
1127 gid_t my_groups[ NGROUPS_MAX ];
1128 char my_buffer[ 64 ];
1129 kern_return_t my_kr;
1130
1131 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
1132 if(my_kr != KERN_SUCCESS){
1133 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
1134 goto test_failed_exit;
1135 }
1136
1137 *my_pathp = 0x00;
1138 strcat( my_pathp, &g_target_path[0] );
1139 strcat( my_pathp, "/" );
1140
1141 /* create a test file */
1142 my_err = create_random_name( my_pathp, 1 );
1143 if ( my_err != 0 ) {
1144 goto test_failed_exit;
1145 }
1146
1147 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_link_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
1148 if(my_kr != KERN_SUCCESS){
1149 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
1150 goto test_failed_exit;
1151 }
1152
1153 *my_link_pathp = 0x00;
1154 strcat( my_link_pathp, &g_target_path[0] );
1155 strcat( my_link_pathp, "/" );
1156
1157 /* get a test file name for the link */
1158 my_err = create_random_name( my_link_pathp, 0 );
1159 if ( my_err != 0 ) {
1160 goto test_failed_exit;
1161 }
1162
1163 if ( !_prime_groups() ) {
1164 goto test_failed_exit;
1165 }
1166
1167 /* set up by getting a list of groups */
1168 my_group_count = getgroups( NGROUPS_MAX, &my_groups[0] );
1169
1170 if ( my_group_count == -1 || my_group_count < 1 ) {
1171 printf( "getgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1172 goto test_failed_exit;
1173 }
1174
1175 my_err = stat( my_pathp, &my_sb );
1176 if ( my_err != 0 ) {
1177 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1178 goto test_failed_exit;
1179 }
1180
1181 /* now change group owner to something other than current value */
1182 my_orig_gid = my_sb.st_gid;
1183 my_orig_uid = my_sb.st_uid;
1184
1185 for ( i = 0; i < my_group_count; i++ ) {
1186 if ( my_orig_gid != my_groups[ i ] ) {
1187 if ( my_new_gid1 == 0 ) {
1188 my_new_gid1 = my_groups[ i ];
1189 }
1190 else if( my_new_gid1 != my_groups[ i ] ) {
1191 my_new_gid2 = my_groups[ i ];
1192 break;
1193 }
1194 }
1195 }
1196 if ( i >= my_group_count ) {
1197 printf( "not enough groups to choose from. st_gid is the same as current groups! \n" );
1198 goto test_failed_exit;
1199 }
1200
1201 my_err = chown( my_pathp, my_orig_uid, my_new_gid1 );
1202 if ( my_err != 0 ) {
1203 printf( "chown call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1204 goto test_failed_exit;
1205 }
1206
1207 /* make sure the group owner was changed */
1208 my_err = stat( my_pathp, &my_sb );
1209 if ( my_err != 0 ) {
1210 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1211 goto test_failed_exit;
1212 }
1213 if ( my_sb.st_gid == my_orig_gid ) {
1214 printf( "chown call failed. st_gid is not correct! \n" );
1215 goto test_failed_exit;
1216 }
1217
1218 /* change group owner back using fchown */
1219 my_fd = open( my_pathp, O_RDWR, 0 );
1220 if ( my_fd == -1 ) {
1221 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1222 printf( "\t we attempted to open -> \"%s\" \n", &g_target_path[0] );
1223 goto test_failed_exit;
1224 }
1225
1226 my_err = fchown( my_fd, my_orig_uid, my_new_gid2 );
1227 if ( my_err != 0 ) {
1228 printf( "fchown call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1229 goto test_failed_exit;
1230 }
1231
1232 /* make sure the group owner was changed back to the original value */
1233 my_err = stat( my_pathp, &my_sb );
1234 if ( my_err != 0 ) {
1235 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1236 goto test_failed_exit;
1237 }
1238 if ( my_sb.st_gid == my_new_gid1 ) {
1239 printf( "fchown call failed. st_gid is not correct! \n" );
1240 goto test_failed_exit;
1241 }
1242
1243 /* create a link file and test lchown */
1244 my_err = symlink( my_pathp, my_link_pathp );
1245 if ( my_err != 0 ) {
1246 printf( "symlink call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1247 goto test_failed_exit;
1248 }
1249
1250 my_err = lstat( my_link_pathp, &my_sb );
1251 if ( my_err != 0 ) {
1252 printf( "lstat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1253 goto test_failed_exit;
1254 }
1255
1256 /* now change group owner to something other than current value */
1257 my_orig_gid = my_sb.st_gid;
1258 my_orig_uid = my_sb.st_uid;
1259 my_err = lchown( my_link_pathp, my_orig_uid, my_new_gid1 );
1260 if ( my_err != 0 ) {
1261 printf( "lchown call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1262 goto test_failed_exit;
1263 }
1264
1265 /* make sure the group owner was changed to new value */
1266 my_err = lstat( my_link_pathp, &my_sb );
1267 if ( my_err != 0 ) {
1268 printf( "lstat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1269 goto test_failed_exit;
1270 }
1271 if ( my_sb.st_gid == my_new_gid2 ) {
1272 printf( "lchown call failed. st_gid is not correct! \n" );
1273 goto test_failed_exit;
1274 }
1275
1276 /* make sure we can read the symlink file */
1277 my_result = readlink( my_link_pathp, &my_buffer[0], sizeof(my_buffer) );
1278 if ( my_result == -1 ) {
1279 printf( "readlink call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1280 goto test_failed_exit;
1281 }
1282 /* make sure we read some data */
1283 if ( my_result < 1 ) {
1284 printf( "readlink failed to read any data. \n" );
1285 goto test_failed_exit;
1286 }
1287
1288 my_err = 0;
1289 goto test_passed_exit;
1290
1291 test_failed_exit:
1292 my_err = -1;
1293
1294 test_passed_exit:
1295 if ( my_fd != -1 )
1296 close( my_fd );
1297 if ( my_pathp != NULL ) {
1298 remove( my_pathp );
1299 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
1300 }
1301 if ( my_link_pathp != NULL ) {
1302 unlink( my_link_pathp );
1303 vm_deallocate(mach_task_self(), (vm_address_t)my_link_pathp, PATH_MAX);
1304 }
1305 return( my_err );
1306 }
1307
1308 /* **************************************************************************************************************
1309 * Test fstatfs, getattrlist, getfsstat, statfs, getfsstat64, statfs64, fstatfs64 system calls.
1310 * **************************************************************************************************************
1311 */
1312
1313 #pragma pack(4)
1314 struct vol_attr_buf {
1315 u_int32_t length;
1316 off_t volume_size;
1317 u_int32_t io_blksize;
1318 };
1319 #pragma pack()
1320 typedef struct vol_attr_buf vol_attr_buf;
1321
1322 #define STATFS_TEST_PATH "/tmp"
1323
1324 int fs_stat_tests( void * the_argp )
1325 {
1326 int my_err, my_count, i;
1327 int my_buffer_size, my_buffer64_size;
1328 int my_fd = -1;
1329 int is_ufs = 0;
1330 long my_io_size;
1331 fsid_t my_fsid;
1332 struct attrlist my_attrlist;
1333 vol_attr_buf my_attr_buf;
1334 void * my_bufferp = NULL;
1335 struct statfs * my_statfsp;
1336 kern_return_t my_kr;
1337
1338 void * my_buffer64p = NULL;
1339 struct statfs64 * my_statfs64p;
1340
1341 my_buffer64_size = (sizeof(struct statfs64) * 10);
1342
1343 my_kr = vm_allocate((vm_map_t) mach_task_self(),(vm_address_t*) &my_buffer64p, my_buffer64_size, VM_FLAGS_ANYWHERE);
1344 if(my_kr != KERN_SUCCESS){
1345 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
1346 goto test_failed_exit;
1347 }
1348
1349 my_buffer_size = (sizeof(struct statfs) * 10);
1350
1351 my_kr = vm_allocate((vm_map_t) mach_task_self(),(vm_address_t*) &my_bufferp, my_buffer_size, VM_FLAGS_ANYWHERE);
1352 if(my_kr != KERN_SUCCESS){
1353 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
1354 goto test_failed_exit;
1355 }
1356
1357 my_statfsp = (struct statfs *) my_bufferp;
1358 my_err = statfs( STATFS_TEST_PATH, my_statfsp );
1359 if ( my_err == -1 ) {
1360 printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1361 goto test_failed_exit;
1362 }
1363 if ( memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 ) {
1364 is_ufs = 1;
1365 }
1366
1367 my_count = getfsstat( (struct statfs *)my_bufferp, my_buffer_size, MNT_NOWAIT );
1368 if ( my_count == -1 ) {
1369 printf( "getfsstat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1370 goto test_failed_exit;
1371 }
1372
1373 /* validate results */
1374 my_statfsp = (struct statfs *) my_bufferp;
1375 for ( i = 0; i < my_count; i++, my_statfsp++ ) {
1376 if ( memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 ||
1377 memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0 ||
1378 memcmp( &my_statfsp->f_fstypename[0], "devfs", 5 ) == 0 ||
1379 memcmp( &my_statfsp->f_fstypename[0], "volfs", 5 ) == 0 ) {
1380 /* found a valid entry */
1381 break;
1382 }
1383 }
1384 if ( i >= my_count ) {
1385 printf( "getfsstat call failed. could not find valid f_fstypename! \n" );
1386 goto test_failed_exit;
1387 }
1388
1389 /* now try statfs64 */
1390 my_statfs64p = (struct statfs64 *) my_buffer64p;
1391 my_err = statfs64( STATFS_TEST_PATH, my_statfs64p );
1392 if ( my_err == -1 ) {
1393 printf( "statfs64 call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1394 goto test_failed_exit;
1395 }
1396 if ( my_statfs64p->f_fsid.val[0] != my_statfsp->f_fsid.val[0] ||
1397 my_statfs64p->f_fsid.val[1] != my_statfsp->f_fsid.val[1] ) {
1398 printf( "statfs64 call failed. wrong f_fsid! \n" );
1399 goto test_failed_exit;
1400 }
1401
1402 my_count = getfsstat64( (struct statfs64 *)my_buffer64p, my_buffer64_size, MNT_NOWAIT );
1403 if ( my_count == -1 ) {
1404 printf( "getfsstat64 call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1405 goto test_failed_exit;
1406 }
1407
1408 /* validate results */
1409 my_statfs64p = (struct statfs64 *) my_buffer64p;
1410 for ( i = 0; i < my_count; i++, my_statfs64p++ ) {
1411 if ( memcmp( &my_statfs64p->f_fstypename[0], "hfs", 3 ) == 0 ||
1412 memcmp( &my_statfs64p->f_fstypename[0], "ufs", 3 ) == 0 ||
1413 memcmp( &my_statfs64p->f_fstypename[0], "devfs", 5 ) == 0 ||
1414 memcmp( &my_statfs64p->f_fstypename[0], "volfs", 5 ) == 0 ) {
1415 /* found a valid entry */
1416 break;
1417 }
1418 }
1419 if ( i >= my_count ) {
1420 printf( "getfsstat64 call failed. could not find valid f_fstypename! \n" );
1421 goto test_failed_exit;
1422 }
1423
1424 /* set up to validate results via multiple sources. we use getattrlist to get volume
1425 * related attributes to verify against results from fstatfs and statfs - but only if
1426 * we are not targeting ufs volume since it doesn't support getattr calls
1427 */
1428 if ( is_ufs == 0 ) {
1429 memset( &my_attrlist, 0, sizeof(my_attrlist) );
1430 my_attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
1431 my_attrlist.volattr = (ATTR_VOL_SIZE | ATTR_VOL_IOBLOCKSIZE);
1432 my_err = getattrlist( "/", &my_attrlist, &my_attr_buf, sizeof(my_attr_buf), 0 );
1433 if ( my_err != 0 ) {
1434 printf( "getattrlist call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1435 goto test_failed_exit;
1436 }
1437 }
1438
1439 /* open to use as test file for fstatfs */
1440 my_fd = open( STATFS_TEST_PATH, O_RDONLY, 0 );
1441 if ( my_fd == -1 ) {
1442 printf( "open call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1443 goto test_failed_exit;
1444 }
1445
1446 /* testing fstatfs64 */
1447 my_statfs64p = (struct statfs64 *) my_buffer64p;
1448 my_err = fstatfs64( my_fd, my_statfs64p );
1449 if ( my_err == -1 ) {
1450 printf( "fstatfs64 call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1451 goto test_failed_exit;
1452 }
1453
1454 /* validate results - assumes we only boot from hfs or ufs */
1455 if ( !(memcmp( &my_statfs64p->f_fstypename[0], "hfs", 3 ) == 0 ||
1456 memcmp( &my_statfs64p->f_fstypename[0], "ufs", 3 ) == 0) ) {
1457 printf( "fstatfs64 call failed. could not find valid f_fstypename! \n" );
1458 goto test_failed_exit;
1459 }
1460
1461 /* testing fstatfs */
1462 my_statfsp = (struct statfs *) my_bufferp;
1463 my_err = fstatfs( my_fd, my_statfsp );
1464 if ( my_err == -1 ) {
1465 printf( "fstatfs call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1466 goto test_failed_exit;
1467 }
1468
1469 /* validate results */
1470 if ( !(memcmp( &my_statfsp->f_fstypename[0], "hfs", 3 ) == 0 ||
1471 memcmp( &my_statfsp->f_fstypename[0], "ufs", 3 ) == 0) ) {
1472 printf( "fstatfs call failed. could not find valid f_fstypename! \n" );
1473 goto test_failed_exit;
1474 }
1475 my_io_size = my_statfsp->f_iosize;
1476 my_fsid = my_statfsp->f_fsid;
1477 if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) {
1478 printf( "fstatfs and getattrlist results do not match for volume block size \n" );
1479 goto test_failed_exit;
1480 }
1481
1482 /* try again with statfs */
1483 my_err = statfs( STATFS_TEST_PATH , my_statfsp );
1484 if ( my_err == -1 ) {
1485 printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1486 goto test_failed_exit;
1487 }
1488
1489 /* validate results */
1490 if ( my_io_size != my_statfsp->f_iosize || my_fsid.val[0] != my_statfsp->f_fsid.val[0] ||
1491 my_fsid.val[1] != my_statfsp->f_fsid.val[1] ) {
1492 printf( "statfs call failed. wrong f_iosize or f_fsid! \n" );
1493 goto test_failed_exit;
1494 }
1495 if ( is_ufs == 0 && my_statfsp->f_iosize != my_attr_buf.io_blksize ) {
1496 printf( "statfs and getattrlist results do not match for volume block size \n" );
1497 goto test_failed_exit;
1498 }
1499
1500 my_err = 0;
1501 goto test_passed_exit;
1502
1503 test_failed_exit:
1504 my_err = -1;
1505
1506 test_passed_exit:
1507 if ( my_fd != -1 )
1508 close( my_fd );
1509 if ( my_bufferp != NULL ) {
1510 vm_deallocate(mach_task_self(), (vm_address_t)my_bufferp, my_buffer_size);
1511 }
1512 if ( my_buffer64p != NULL ) {
1513 vm_deallocate(mach_task_self(), (vm_address_t)my_buffer64p, my_buffer64_size);
1514 }
1515
1516 return( my_err );
1517 }
1518
1519 /* **************************************************************************************************************
1520 * Test getpid, getppid, and pipe system calls.
1521 * **************************************************************************************************************
1522 */
1523 int getpid_getppid_pipe_test( void * the_argp )
1524 {
1525 int my_err, my_status;
1526 pid_t my_pid, my_wait_pid;
1527 ssize_t my_count;
1528 int my_fildes[2] = {-1, -1};
1529 off_t my_current_offset;
1530 char my_pid_string[64];
1531
1532 my_err = pipe( &my_fildes[0] );
1533 if ( my_err != 0 ) {
1534 printf( "pipe call failed. got errno %d - %s. \n", errno, strerror( errno ) );
1535 goto test_failed_exit;
1536 }
1537
1538 /* make sure we can't seek on a pipe */
1539 my_current_offset = lseek( my_fildes[0], 0, SEEK_CUR );
1540 if ( my_current_offset != -1 ) {
1541 printf( "lseek on pipe should fail but did not \n" );
1542 goto test_failed_exit;
1543 }
1544
1545 /* fork here and use pipe to communicate */
1546 my_pid = fork( );
1547 if ( my_pid == -1 ) {
1548 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
1549 goto test_failed_exit;
1550 }
1551 else if ( my_pid == 0 ) {
1552 /* child process */
1553 unsigned long my_ppid;
1554 char my_buffer[64];
1555
1556 close( my_fildes[1] ); /* close write end of pipe */
1557 my_fildes[1] = -1;
1558
1559 /* get the parent's pid using getppid and from the parent (using getpid in porent) */
1560 my_count = read( my_fildes[0], &my_buffer[0], sizeof(my_buffer) );
1561 if ( my_count == -1 ) {
1562 printf( "read from pipe failed. got errno %d - %s. \n", errno, strerror( errno ) );
1563 exit(-1);
1564 }
1565
1566 /* parent wrote (to our pipe) its pid as character string */
1567 my_ppid = strtoul( &my_buffer[0], NULL, 10 );
1568 if ( my_ppid == 0 ) {
1569 printf( "strtoul failed. got errno %d - %s. \n", errno, strerror( errno ) );
1570 exit(-1);
1571 }
1572
1573 if ( getppid( ) != my_ppid ) {
1574 printf( "getppid failed. pid we got from parent does not match getppid result. \n" );
1575 exit(-1);
1576 }
1577 exit(0);
1578 }
1579
1580 /* parent process - get our pid using getpid and send it to child for verification */
1581 close( my_fildes[0] ); /* close read end of pipe */
1582 my_fildes[0] = -1;
1583
1584 sprintf( &my_pid_string[0], "%d\n", getpid( ) );
1585
1586 my_count = write( my_fildes[1], &my_pid_string[0], sizeof(my_pid_string) );
1587 if ( my_count == -1 ) {
1588 printf( "write to pipe failed. got errno %d - %s. \n", errno, strerror( errno ) );
1589 goto test_failed_exit;
1590 }
1591
1592 /* wait for child to exit */
1593 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
1594 if ( my_wait_pid == -1 ) {
1595 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
1596 goto test_failed_exit;
1597 }
1598
1599 /* wait4 should return our child's pid when it exits */
1600 if ( my_wait_pid != my_pid ) {
1601 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
1602 goto test_failed_exit;
1603 }
1604
1605 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
1606 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status );
1607 goto test_failed_exit;
1608 }
1609
1610 my_err = 0;
1611 goto test_passed_exit;
1612
1613 test_failed_exit:
1614 my_err = -1;
1615
1616 test_passed_exit:
1617 if ( my_fildes[0] != -1 )
1618 close( my_fildes[0] );
1619 if ( my_fildes[1] != -1 )
1620 close( my_fildes[1] );
1621 return( my_err );
1622 }
1623
1624
1625 /* **************************************************************************************************************
1626 * Test getauid, gettid, getuid, geteuid, issetugid, setaudit_addr, seteuid, settid, settid_with_pid, setuid system calls.
1627 * **************************************************************************************************************
1628 */
1629 int uid_tests( void * the_argp )
1630 {
1631 int my_err, my_status;
1632 pid_t my_pid, my_wait_pid;
1633
1634 if ( g_skip_setuid_tests != 0 ) {
1635 printf("\t skipping this test \n");
1636 my_err = 0;
1637 goto test_passed_exit;
1638 }
1639
1640 /* test issetugid - should return 1 when not root and 0 when root
1641 * Figuring out setugid will not work in single-user mode; skip
1642 * this test in that case.
1643 */
1644 if (!g_is_single_user) {
1645 my_err = issetugid( );
1646 if ( getuid( ) == 0 ) {
1647 if ( my_err == 1 ) {
1648 printf( "issetugid should return false \n" );
1649 goto test_failed_exit;
1650 }
1651 }
1652 else {
1653 if ( my_err == 0 ) {
1654 printf( "issetugid should return true \n" );
1655 goto test_failed_exit;
1656 }
1657 }
1658 }
1659
1660 /*
1661 * fork here and do the setuid work in the child
1662 */
1663 my_pid = fork( );
1664 if ( my_pid == -1 ) {
1665 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
1666 goto test_failed_exit;
1667 }
1668 else if ( my_pid == 0 ) {
1669 /*
1670 * child process
1671 */
1672 uid_t my_ruid, my_euid;
1673 uid_t my_uid, my_temp_uid;
1674 gid_t my_gid, my_temp_gid;
1675 auditinfo_addr_t my_aia;
1676
1677 my_ruid = getuid( );
1678 my_euid = geteuid( );
1679 if ( my_ruid == my_euid ) {
1680 exit( 0 );
1681 }
1682
1683 /* Test getauid, gettid, setaudit_addr, settid, settid_with_pid */
1684 /* get our current uid and gid for comparison later */
1685 my_uid = getuid( );
1686 my_gid = getgid( );
1687
1688 my_err = syscall( SYS_settid, 4444, 5555 );
1689 //my_err = settid( 4444, 5555 );
1690 if (my_err != 0) {
1691 printf( "settid call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1692 exit( -1 );
1693 }
1694
1695 my_err = syscall( SYS_gettid, &my_temp_uid, &my_temp_gid );
1696 //my_err = gettid( &my_temp_uid, &my_temp_gid );
1697 if (my_err != 0) {
1698 printf( "gettid call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1699 exit( -1 );
1700 }
1701 if (my_temp_uid != 4444) {
1702 printf("get / settid test failed - wrong uid was set - %d \n", my_temp_uid);
1703 exit( -1 );
1704 }
1705 if (my_temp_gid != 5555) {
1706 printf("get / settid test failed - wrong gid was set - %d \n", my_temp_gid);
1707 exit( -1 );
1708 }
1709
1710 /* resume original identity */
1711 my_err = syscall( SYS_settid, KAUTH_UID_NONE, KAUTH_GID_NONE );
1712 //my_err = settid( KAUTH_UID_NONE, KAUTH_GID_NONE );
1713 if (my_err != 0) {
1714 printf( "settid revert - failed with error %d - \"%s\" \n", errno, strerror( errno) );
1715 exit( -1 );
1716 }
1717
1718 /* values should be returned to original settings */
1719 my_temp_uid = getuid( );
1720 if (my_temp_uid == 4444) {
1721 printf("test failed - wrong uid was set - %d \n", my_temp_uid);
1722 exit( -1 );
1723 }
1724 my_temp_gid = getgid( );
1725 if (my_temp_gid == 5555) {
1726 printf("test failed - wrong gid was set - %d \n", my_temp_gid);
1727 exit( -1 );
1728 }
1729
1730 /*
1731 * Assume the identity of our parent.
1732 */
1733 my_err = syscall( SYS_settid_with_pid, getppid( ), 1 );
1734 //my_err = settid_with_pid, my_target_pid, 1 );
1735 if (my_err != 0) {
1736 printf( "settid_with_pid assume - failed with error %d - \"%s\" \n", errno, strerror( errno) );
1737 exit( -1 );
1738 }
1739
1740 /*
1741 * Resume our identity.
1742 */
1743 my_err = syscall( SYS_settid_with_pid, 0, 0 );
1744 //my_err = settid_with_pid( my_target_pid, 0 );
1745 if (my_err != 0) {
1746 printf( "settid_with_pid resume - failed with error %d - \"%s\" \n", errno, strerror( errno) );
1747 exit( -1 );
1748 }
1749
1750 /*
1751 * test to make sure setaudit_addr doesn't cause audit info to get lost from
1752 * the credential.
1753 */
1754 bzero( &my_aia, sizeof(my_aia) );
1755 my_aia.ai_auid = 442344;
1756 my_aia.ai_asid = AU_ASSIGN_ASID;
1757 my_aia.ai_termid.at_type = AU_IPv4;
1758 my_err = setaudit_addr( &my_aia, sizeof(my_aia) );
1759 if (my_err != 0) {
1760 printf( "setaudit_addr - failed with error %d - \"%s\" \n", errno, strerror( errno) );
1761 exit( -1 );
1762 }
1763
1764 my_aia.ai_auid = 0;
1765 my_err = getaudit_addr( &my_aia, sizeof(my_aia) );
1766 if (my_err != 0) {
1767 printf( "getaudit_addr - failed with error %d - \"%s\" \n", errno, strerror( errno) );
1768 exit( -1 );
1769 }
1770 //printf("new audit ID is %d \n", my_aia.ai_auid);
1771
1772 if (my_aia.ai_auid != 442344) {
1773 printf("test failed - wrong audit ID was set - %d \n", my_aia.ai_auid);
1774 exit( -1 );
1775 }
1776
1777 /* change real uid and effective uid to current euid */
1778 my_err = setuid( my_euid );
1779 if ( my_err == -1 ) {
1780 printf( "setuid call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1781 exit( -1 );
1782 }
1783 if ( getuid( ) != my_euid ) {
1784 printf( "setuid call failed to set the real uid \n" );
1785 exit( -1 );
1786 }
1787
1788 /* change effective uid to current euid - really a NOP */
1789 my_err = seteuid( my_euid );
1790 if ( my_err == -1 ) {
1791 printf( "seteuid call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1792 exit( -1 );
1793 }
1794 if ( geteuid( ) != my_euid ) {
1795 printf( "seteuid call failed to set the original euid \n" );
1796 exit( -1 );
1797 }
1798
1799 /* change real uid and effective uid to original real uid */
1800 my_err = setuid( my_ruid );
1801 if ( my_err == -1 ) {
1802 printf( "setuid call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1803 exit( -1 );
1804 }
1805 if ( getuid( ) != my_ruid ) {
1806 printf( "setuid call failed to set the real uid \n" );
1807 exit( -1 );
1808 }
1809
1810 exit(0);
1811 }
1812
1813 /*
1814 * parent process -
1815 * wait for child to exit
1816 */
1817 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
1818 if ( my_wait_pid == -1 ) {
1819 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
1820 goto test_failed_exit;
1821 }
1822
1823 /* wait4 should return our child's pid when it exits */
1824 if ( my_wait_pid != my_pid ) {
1825 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
1826 goto test_failed_exit;
1827 }
1828
1829 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
1830 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status );
1831 goto test_failed_exit;
1832 }
1833
1834 my_err = 0;
1835 goto test_passed_exit;
1836
1837 test_failed_exit:
1838 my_err = -1;
1839
1840 test_passed_exit:
1841 return( my_err );
1842 }
1843
1844 /* **************************************************************************************************************
1845 * Test mknod, sync system calls.
1846 * **************************************************************************************************************
1847 */
1848 int mknod_sync_test( void * the_argp )
1849 {
1850 int my_err;
1851 char * my_pathp = NULL;
1852 kern_return_t my_kr;
1853
1854 if ( g_skip_setuid_tests != 0 ) {
1855 printf("\t skipping this test \n");
1856 my_err = 0;
1857 goto test_passed_exit;
1858 }
1859
1860 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
1861 if(my_kr != KERN_SUCCESS){
1862 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
1863 goto test_failed_exit;
1864 }
1865
1866 *my_pathp = 0x00;
1867 strcat( my_pathp, "/dev/" );
1868
1869 /* get a unique name for our test file */
1870 my_err = create_random_name( my_pathp, 0 );
1871 if ( my_err != 0 ) {
1872 goto test_failed_exit;
1873 }
1874
1875 my_err = mknod( my_pathp, (S_IFCHR | S_IRWXU), 0 );
1876 if ( my_err == -1 ) {
1877 printf( "mknod failed with errno %d - %s \n", errno, strerror( errno ) );
1878 printf( "path \"%s\" \n", my_pathp );
1879 goto test_failed_exit;
1880 }
1881
1882 /* not really sure what to do with sync call test */
1883 sync( );
1884 my_err = 0;
1885 goto test_passed_exit;
1886
1887 test_failed_exit:
1888 my_err = -1;
1889
1890 test_passed_exit:
1891 if ( my_pathp != NULL ) {
1892 remove( my_pathp );
1893 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
1894 }
1895 return( my_err );
1896 }
1897
1898 /* **************************************************************************************************************
1899 * Test chflags, fchflags system calls.
1900 * **************************************************************************************************************
1901 */
1902 int chflags_fchflags_test( void * the_argp )
1903 {
1904 int my_err;
1905 int my_fd = -1;
1906 u_int my_flags;
1907 char * my_pathp = NULL;
1908 struct stat my_sb;
1909 kern_return_t my_kr;
1910
1911 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
1912 if(my_kr != KERN_SUCCESS){
1913 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
1914 goto test_failed_exit;
1915 }
1916
1917 *my_pathp = 0x00;
1918 strcat( my_pathp, &g_target_path[0] );
1919 strcat( my_pathp, "/" );
1920
1921 /* create a test file */
1922 my_err = create_random_name( my_pathp, 1 );
1923 if ( my_err != 0 ) {
1924 goto test_failed_exit;
1925 }
1926
1927 /* make test file unchangable */
1928 my_err = stat( my_pathp, &my_sb );
1929 if ( my_err != 0 ) {
1930 printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1931 goto test_failed_exit;
1932 }
1933
1934 my_flags = (my_sb.st_flags | UF_IMMUTABLE);
1935 my_err = chflags( my_pathp, my_flags );
1936 if ( my_err != 0 ) {
1937 printf( "chflags call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1938 goto test_failed_exit;
1939 }
1940
1941 /* should fail with EPERM since we cannot change the file now */
1942 my_fd = open( my_pathp, O_RDWR, 0 );
1943 if ( my_fd == -1 && errno != EPERM ) {
1944 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1945 printf( "open failed with wrong error - should be EPERM \n" );
1946 goto test_failed_exit;
1947 }
1948
1949 /* this open should work OK */
1950 my_fd = open( my_pathp, O_RDONLY, 0 );
1951 if ( my_fd == -1 ) {
1952 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1953 goto test_failed_exit;
1954 }
1955
1956 my_err = stat( my_pathp, &my_sb );
1957 if ( my_err != 0 ) {
1958 printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1959 goto test_failed_exit;
1960 }
1961
1962 my_flags = (my_sb.st_flags & ~UF_IMMUTABLE);
1963 my_err = fchflags( my_fd, my_flags );
1964 if ( my_err != 0 ) {
1965 printf( "chflags call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1966 goto test_failed_exit;
1967 }
1968
1969 close( my_fd );
1970 my_fd = -1;
1971
1972 /* should now work */
1973 my_fd = open( my_pathp, O_RDWR, 0 );
1974 if ( my_fd == -1 ) {
1975 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
1976 goto test_failed_exit;
1977 }
1978
1979 my_err = 0;
1980 goto test_passed_exit;
1981
1982 test_failed_exit:
1983 my_err = -1;
1984
1985 test_passed_exit:
1986 if ( my_fd != -1 )
1987 close( my_fd );
1988 if ( my_pathp != NULL ) {
1989 remove( my_pathp );
1990 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
1991 }
1992 return( my_err );
1993 }
1994
1995
1996 /* **************************************************************************************************************
1997 * Test kill, vfork, execve system calls.
1998 * **************************************************************************************************************
1999 */
2000 /* There are many new exec() situations to test now that 64-bit is in. These extra tests are in response to
2001 * rdar://4606399 and rdar://4607285. It should cover every permutation of the following variables.
2002 *
2003 * - Current Process "Bitness": 64 or 32
2004 * - exec()'ed process "bitness": 64 or 32
2005 * (if 64 bit, size of page zero:) (4GB or 4KB)
2006 * - Parent Process "Bitness": 64 or 32
2007
2008 * Test to make sure certain inheritance properties of fork()'ed children
2009 * are correctly set.
2010 * 1. 64 bit process forking() 64-bit child, child execing() 64-bit file (4GB pagezero)
2011 * 2. 64 bit process forking() 64-bit child, child execing() 64-bit file (4KB pagezero)
2012 * 3. 64 bit process forking() 64-bit child, child execing() 32-bit file
2013 * 4. 32 bit process forking() 32-bit child, child execing() 32-bit file
2014 * 5. 32 bit process forking() 32-bit child, child execing() 64 bit file (4GB pagezero)
2015 * 6. 32 bit process forking() 32-bit child, child execing() 64 bit file (4KB pagezero)
2016 *
2017 */
2018
2019
2020 int execve_kill_vfork_test( void * the_argp )
2021 {
2022 int my_err, my_status;
2023 pid_t my_pid, my_wait_pid;
2024 char * errmsg = NULL;
2025 char * argvs[2] = {"", NULL};
2026 int bits = get_bits(); /* Gets actual processor bit-ness. */
2027
2028 if (bits != 32 && bits != 64) {
2029 printf("Determination of processor bit-ness failed, get_bits() returned %d.\n", get_bits());
2030 return(-1);
2031 }
2032
2033 if (get_architecture() == -1) {
2034 errmsg = "get_architecture() could not determine the CPU architecture.\n";
2035 goto test_failed_exit;
2036 }
2037
2038 if (get_architecture() == INTEL) {
2039 struct stat sb;
2040
2041 if (bits == 64 && sizeof(long) == 8) {
2042 /*
2043 * Running on x86_64 hardware and running in 64-bit mode.
2044 * Check cases 1, 2, 3 and fork a child to check 4, 5, 6.
2045 */
2046 errmsg = "execve failed: from x86_64 forking and exec()ing 64-bit x86_64 process w/ 4G pagezero.\n";
2047 argvs[0] = "sleep-x86_64-4G";
2048 if (do_execve_test("helpers/sleep-x86_64-4G", argvs, NULL, 1)) goto test_failed_exit;
2049
2050 errmsg = "execve failed: from x86_64 forking and exec()ing 64-bit x86_64 process w/ 4K Pagezero.\n";
2051 argvs[0] = "sleep-x86_64-4K";
2052 if (do_execve_test("helpers/sleep-x86_64-4K", argvs, NULL, 1)) goto test_failed_exit;
2053
2054 errmsg = "execve failed: from x64_64 forking and exec()ing 32-bit i386 process.\n";
2055 argvs[0] = "sleep-i386";
2056 if (do_execve_test("helpers/sleep-i386", argvs, NULL, 1)) goto test_failed_exit;
2057
2058 /* Fork off a helper process and load a 32-bit program in it to test 32->64 bit exec(). */
2059 errmsg = "execve failed to exec the helper process.\n";
2060 argvs[0] = "launch-i386";
2061 if (do_execve_test("helpers/launch-i386", argvs, NULL, 1) != 0) goto test_failed_exit;
2062
2063 /* Test posix_spawn for i386, x86_64 (should succeed) */
2064 errmsg = NULL;
2065 if (do_spawn_test(CPU_TYPE_I386, 0))
2066 goto test_failed_exit;
2067 if (do_spawn_test(CPU_TYPE_X86_64, 0))
2068 goto test_failed_exit;
2069 }
2070 else if (bits == 64 && sizeof(long) == 4) {
2071 /*
2072 * Running on x86_64 hardware, but actually running in 32-bit mode.
2073 * Check cases 4, 5, 6 and fork a child to check 1, 2, 3.
2074 */
2075 errmsg = "execve failed: from i386 forking and exec()ing i386 process.\n";
2076 argvs[0] = "sleep-i386";
2077 if (do_execve_test("helpers/sleep-i386", argvs, NULL, 0)) goto test_failed_exit;
2078
2079 errmsg = "execve failed: from i386 forking and exec()ing x86_64 process w/ 4G pagezero.\n";
2080 argvs[0] = "sleep-x86_64-4G";
2081 if (do_execve_test("helpers/sleep-x86_64-4G", argvs, NULL, 0)) goto test_failed_exit;
2082
2083 errmsg = "execve failed: from i386 forking and exec()ing x86_64 process w/ 4K pagezero.\n";
2084 argvs[0] = "sleep-x86_64-4K";
2085 if (do_execve_test("helpers/sleep-x86_64-4K", argvs, NULL, 0)) goto test_failed_exit;
2086
2087 /* Fork off a helper process and load a 64-bit program in it to test 64->32 bit exec(). */
2088 errmsg = "execve failed to exec the helper process.\n";
2089 argvs[0] = "launch-x86_64";
2090 if (do_execve_test("helpers/launch-x86_64", argvs, NULL, 1) != 0) goto test_failed_exit;
2091
2092 /* Test posix_spawn for i386, x86_64 (should succeed) */
2093 errmsg = NULL;
2094 if (do_spawn_test(CPU_TYPE_I386, 0))
2095 goto test_failed_exit;
2096 if (do_spawn_test(CPU_TYPE_X86_64, 0))
2097 goto test_failed_exit;
2098 }
2099 else if (bits == 32) {
2100 /* Running on i386 hardware. Check cases 4. */
2101 errmsg = "execve failed: from i386 forking and exec()ing 32-bit i386 process.\n";
2102 argvs[0] = "sleep-i386";
2103 if (do_execve_test("helpers/sleep-i386", argvs, NULL, 1)) goto test_failed_exit;
2104
2105 /* Test posix_spawn for x86_64 (should fail), i386 (should succeed) */
2106 errmsg = NULL;
2107 if (do_spawn_test(CPU_TYPE_X86_64, 1))
2108 goto test_failed_exit;
2109 if (do_spawn_test(CPU_TYPE_I386, 0))
2110 goto test_failed_exit;
2111 }
2112 } else if(get_architecture() == ARM) {
2113
2114 #ifdef CPU_TYPE_ARM64
2115 if (bits == 64) {
2116 /* Running on arm64 hardware. */
2117 errmsg = "execve failed: from arm64 forking and exec()ing 64-bit arm process.\n";
2118 argvs[0] = "sleep-arm";
2119 if (do_execve_test("helpers/sleep-arm64", argvs, NULL, 1))
2120 goto test_failed_exit;
2121
2122 /* Test posix_spawn for arm64 (should succeed) */
2123 errmsg = NULL;
2124 if (do_spawn_test(CPU_TYPE_ARM64, 0))
2125 goto test_failed_exit;
2126 }
2127 #endif
2128
2129 /* Exec arm test on both arm and arm64 */
2130 errmsg = "execve failed: from arm forking and exec()ing 32-bit arm process.\n";
2131 argvs[0] = "sleep-arm";
2132 if (do_execve_test("helpers/sleep-arm", argvs, NULL, 1))
2133 goto test_failed_exit;
2134
2135 /* Test posix_spawn for arm (should succeed) */
2136 errmsg = NULL;
2137 if (do_spawn_test(CPU_TYPE_ARM, 0))
2138 goto test_failed_exit;
2139
2140 }
2141 else {
2142 /* Just in case someone decides we need more architectures in the future */
2143 printf("get_architecture() returned unknown architecture");
2144 return(-1);
2145 }
2146
2147 return 0;
2148
2149 test_failed_exit:
2150 if (errmsg)
2151 printf("%s", errmsg);
2152 return -1;
2153 }
2154
2155
2156 /* **************************************************************************************************************
2157 * Test getegid, getgid, getgroups, setegid, setgid, setgroups system calls.
2158 * **************************************************************************************************************
2159 */
2160 int groups_test( void * the_argp )
2161 {
2162 int my_err, i;
2163 int my_group_count, my_orig_group_count;
2164 gid_t my_real_gid;
2165 gid_t my_effective_gid;
2166 gid_t my_removed_gid;
2167 gid_t my_new_gid;
2168 gid_t my_groups[ NGROUPS_MAX ];
2169
2170 if ( g_skip_setuid_tests != 0 ) {
2171 printf("\t skipping this test \n");
2172 my_err = 0;
2173 goto test_passed_exit;
2174 }
2175
2176 my_real_gid = getgid( );
2177 my_effective_gid = getegid( );
2178
2179 if ( !_prime_groups() ) {
2180 goto test_failed_exit;
2181 }
2182
2183 /* start by getting list of groups the current user belongs to */
2184 my_orig_group_count = getgroups( NGROUPS_MAX, &my_groups[0] );
2185
2186 if ( my_orig_group_count == -1 || my_orig_group_count < 1 ) {
2187 printf( "getgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2188 goto test_failed_exit;
2189 }
2190
2191 /* make sure real and effective gids are correct */
2192 for ( i = 0; i < my_orig_group_count; i++ ) {
2193 if ( my_groups[i] == my_real_gid )
2194 break;
2195 }
2196 if ( i >= my_orig_group_count ) {
2197 printf( "getgid or getgroups call failed. could not find real gid in list of groups. \n" );
2198 goto test_failed_exit;
2199 }
2200 for ( i = 0; i < my_orig_group_count; i++ ) {
2201 if ( my_groups[i] == my_effective_gid )
2202 break;
2203 }
2204 if ( i >= my_orig_group_count ) {
2205 printf( "getegid or getgroups call failed. could not find effective gid in list of groups. \n" );
2206 goto test_failed_exit;
2207 }
2208
2209 /* remove the last group */
2210 my_removed_gid = my_groups[ (my_orig_group_count - 1) ];
2211 my_err = setgroups( (my_orig_group_count - 1), &my_groups[0] );
2212 if ( my_err == -1 ) {
2213 printf( "setgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2214 goto test_failed_exit;
2215 }
2216
2217 my_group_count = getgroups( NGROUPS_MAX, &my_groups[0] );
2218
2219 if ( my_group_count == -1 || my_group_count < 1 ) {
2220 printf( "getgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2221 goto test_failed_exit;
2222 }
2223
2224 /* make sure setgroups dropped one */
2225 if ( my_orig_group_count <= my_group_count ) {
2226 printf( "setgroups call failed. current group count is too high. \n" );
2227 goto test_failed_exit;
2228 }
2229
2230 /* now put removed gid back */
2231 my_groups[ (my_orig_group_count - 1) ] = my_removed_gid;
2232 my_err = setgroups( my_orig_group_count, &my_groups[0] );
2233 if ( my_err == -1 ) {
2234 printf( "setgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2235 goto test_failed_exit;
2236 }
2237
2238 /* find a group to change real and effective gid to then do it */
2239 my_new_gid = -1;
2240 for ( i = 0; i < my_orig_group_count; i++ ) {
2241 if ( my_groups[i] == my_effective_gid || my_groups[i] == my_real_gid )
2242 continue;
2243 my_new_gid = my_groups[i];
2244 }
2245
2246 if ( my_new_gid == -1 ) {
2247 printf( "could not find a gid to switch to. \n" );
2248 goto test_failed_exit;
2249 }
2250
2251 /* test setegid */
2252 my_err = setegid( my_new_gid );
2253 if ( my_err == -1 ) {
2254 printf( "setegid call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2255 goto test_failed_exit;
2256 }
2257 /* verify it changed */
2258 if ( getegid( ) != my_new_gid ) {
2259 printf( "setegid failed to change the effective gid. \n" );
2260 goto test_failed_exit;
2261 }
2262 /* change it back to original value */
2263 my_err = setegid( my_effective_gid );
2264 if ( my_err == -1 ) {
2265 printf( "setegid call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2266 goto test_failed_exit;
2267 }
2268
2269 /* test setgid */
2270 my_err = setgid( my_new_gid );
2271 if ( my_err == -1 ) {
2272 printf( "setgid call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2273 goto test_failed_exit;
2274 }
2275 /* verify it changed */
2276 if ( getgid( ) != my_new_gid ) {
2277 printf( "setgid failed to change the real gid. \n" );
2278 goto test_failed_exit;
2279 }
2280 /* change it back to original value */
2281 my_err = setgid( my_real_gid );
2282 if ( my_err == -1 ) {
2283 printf( "setegid call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2284 goto test_failed_exit;
2285 }
2286
2287 my_err = 0;
2288 goto test_passed_exit;
2289
2290 test_failed_exit:
2291 my_err = -1;
2292
2293 test_passed_exit:
2294 return( my_err );
2295 }
2296
2297
2298 /* **************************************************************************************************************
2299 * Test dup, dup2, getdtablesize system calls.
2300 * **************************************************************************************************************
2301 */
2302 int dup_test( void * the_argp )
2303 {
2304 int my_err;
2305 int my_fd = -1;
2306 int my_newfd = -1;
2307 int my_table_size, my_loop_counter = 0;
2308 char * my_pathp = NULL;
2309 ssize_t my_count;
2310 char my_buffer[64];
2311 kern_return_t my_kr;
2312
2313 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
2314 if(my_kr != KERN_SUCCESS){
2315 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
2316 goto test_failed_exit;
2317 }
2318
2319 *my_pathp = 0x00;
2320 strcat( my_pathp, &g_target_path[0] );
2321 strcat( my_pathp, "/" );
2322
2323 /* create a test file */
2324 my_err = create_random_name( my_pathp, 1 );
2325 if ( my_err != 0 ) {
2326 goto test_failed_exit;
2327 }
2328
2329 /* test dup, dup2, getdtablesize */
2330 my_table_size = getdtablesize( );
2331 if ( my_table_size < 20 ) {
2332 printf( "getdtablesize should return at least 20, returned %d \n", my_table_size );
2333 goto test_failed_exit;
2334 }
2335
2336 my_fd = open( my_pathp, O_RDWR, 0 );
2337 if ( my_fd == -1 ) {
2338 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2339 goto test_failed_exit;
2340 }
2341
2342 my_newfd = dup( my_fd );
2343 if ( my_newfd == -1 ) {
2344 printf( "dup call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2345 goto test_failed_exit;
2346 }
2347
2348 redo:
2349 /* now write somne data to the orginal and new fd */
2350 /* make sure test file is empty */
2351 my_err = ftruncate( my_fd, 0 );
2352 if ( my_err == -1 ) {
2353 printf( "ftruncate call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2354 goto test_failed_exit;
2355 }
2356
2357 lseek( my_fd, 0, SEEK_SET );
2358 my_count = write( my_fd, "aa", 2 );
2359 if ( my_count == -1 ) {
2360 printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2361 goto test_failed_exit;
2362 }
2363
2364 my_count = write( my_newfd, "xx", 2 );
2365 if ( my_count == -1 ) {
2366 printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) );
2367 goto test_failed_exit;
2368 }
2369
2370 /* now read it back and make sure data is correct */
2371 lseek( my_fd, 0, SEEK_SET );
2372 my_count = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
2373 if ( my_count == -1 ) {
2374 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2375 goto test_failed_exit;
2376 }
2377 if ( my_buffer[0] != 'a' || my_buffer[1] != 'a' || my_buffer[2] != 'x' || my_buffer[3] != 'x' ) {
2378 printf( "wrong data in test file. \n" );
2379 goto test_failed_exit;
2380 }
2381
2382 bzero( &my_buffer[0], sizeof(my_buffer) );
2383 lseek( my_newfd, 0, SEEK_SET );
2384 my_count = read( my_newfd, &my_buffer[0], sizeof(my_buffer) );
2385 if ( my_count == -1 ) {
2386 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2387 goto test_failed_exit;
2388 }
2389 if ( my_buffer[0] != 'a' || my_buffer[1] != 'a' || my_buffer[2] != 'x' || my_buffer[3] != 'x' ) {
2390 printf( "wrong data in test file. \n" );
2391 goto test_failed_exit;
2392 }
2393
2394 /* we do the above tests twice - once for dup and once for dup2 */
2395 if ( my_loop_counter < 1 ) {
2396 my_loop_counter++;
2397 close( my_newfd );
2398
2399 my_err = dup2( my_fd, my_newfd );
2400 if ( my_err == -1 ) {
2401 printf( "dup2 call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2402 goto test_failed_exit;
2403 }
2404
2405 goto redo;
2406 }
2407
2408 my_err = 0;
2409 goto test_passed_exit;
2410
2411 test_failed_exit:
2412 my_err = -1;
2413
2414 test_passed_exit:
2415 if ( my_fd != -1 )
2416 close( my_fd );
2417 if ( my_newfd != -1 )
2418 close( my_newfd );
2419 if ( my_pathp != NULL ) {
2420 remove( my_pathp );
2421 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
2422 }
2423 return( my_err );
2424 }
2425
2426
2427 /* **************************************************************************************************************
2428 * Test getrusage system call.
2429 * **************************************************************************************************************
2430 */
2431 int getrusage_test( void * the_argp )
2432 {
2433 int my_err;
2434 struct rusage my_rusage;
2435
2436 my_err = getrusage( RUSAGE_SELF, &my_rusage );
2437 if ( my_err == -1 ) {
2438 printf( "getrusage failed with error %d - \"%s\" \n", errno, strerror( errno) );
2439 goto test_failed_exit;
2440 }
2441
2442 /* do a sanity check on the getrusage results */
2443 if ( my_rusage.ru_msgrcv > 1000 || my_rusage.ru_msgrcv < 0 ) {
2444 printf( "getrusage seems to report wrong data - ru_msgrcv looks odd. \n" );
2445 goto test_failed_exit;
2446 }
2447 if ( my_rusage.ru_nsignals > 1000 || my_rusage.ru_nsignals < 0 ) {
2448 printf( "getrusage seems to report wrong data - ru_nsignals looks odd. \n" );
2449 goto test_failed_exit;
2450 }
2451
2452 my_err = 0;
2453 goto test_passed_exit;
2454
2455 test_failed_exit:
2456 my_err = -1;
2457
2458 test_passed_exit:
2459 return( my_err );
2460 }
2461
2462 /* **************************************************************************************************************
2463 * Test getitimer, setitimer, sigaction, sigpending, sigprocmask, sigsuspend, sigwait system calls.
2464 * **************************************************************************************************************
2465 */
2466
2467 int alarm_global = 0;
2468 void test_alarm_handler( int the_arg );
2469 void test_alarm_handler( int the_arg )
2470 {
2471 alarm_global = 4;
2472 //printf( "test_alarm_handler - got here \n" );
2473 if ( the_arg == 0 ) {
2474 }
2475 return;
2476 }
2477
2478 void test_signal_handler( int the_arg );
2479 void test_signal_handler( int the_arg )
2480 {
2481 //printf( "test_signal_handler - got here \n" );
2482 if ( the_arg == 0 ) {
2483 }
2484 return;
2485 }
2486
2487 int signals_test( void * the_argp )
2488 {
2489 int my_err, my_status;
2490 int my_fd = -1;
2491 char * my_pathp = NULL;
2492 pid_t my_pid, my_wait_pid;
2493 kern_return_t my_kr;
2494
2495 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
2496 if(my_kr != KERN_SUCCESS){
2497 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
2498 goto test_failed_exit;
2499 }
2500
2501 *my_pathp = 0x00;
2502 strcat( my_pathp, &g_target_path[0] );
2503 strcat( my_pathp, "/" );
2504
2505 /* create a test file */
2506 my_err = create_random_name( my_pathp, 1 );
2507 if ( my_err != 0 ) {
2508 goto test_failed_exit;
2509 }
2510
2511 /*
2512 * spin off a child process that we will use for signal related testing.
2513 */
2514 my_pid = fork( );
2515 if ( my_pid == -1 ) {
2516 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
2517 goto test_failed_exit;
2518 }
2519 if ( my_pid == 0 ) {
2520 /*
2521 * child process - test signal related system calls.
2522 */
2523 //int my_counter;
2524 int my_signal;
2525 sigset_t my_sigset;
2526 struct sigaction my_sigaction;
2527 #ifdef MAC_OS_X_VERSION_10_5
2528 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
2529 /* If this is Leopard. To allow compiling for Inca x86_64 this definition cannot
2530 * be included. But it is needed to compile on Leopard.
2531 */
2532 struct __darwin_sigaltstack my_sigaltstack;
2533 #endif
2534 #else
2535 struct sigaltstack my_sigaltstack;
2536 #endif
2537 struct itimerval my_timer;
2538
2539
2540 /* test getting the current signal stack context */
2541 my_err = sigaltstack( NULL, &my_sigaltstack );
2542 if ( my_err == -1 ) {
2543 printf( "sigaction failed with errno %d - %s \n", errno, strerror( errno ) );
2544 exit( -1 );
2545 }
2546 if ( (my_sigaltstack.ss_flags & SS_DISABLE) == 0 ) {
2547 printf( "sigaction must have failed - SS_DISABLE is cleared \n" );
2548 exit( -1 );
2549 }
2550
2551 /* set up to catch SIGUSR1 */
2552 my_sigaction.sa_handler = test_signal_handler;
2553 my_sigaction.sa_flags = SA_RESTART;
2554 my_sigaction.sa_mask = 0;
2555
2556 my_err = sigaction( SIGUSR1, &my_sigaction, NULL );
2557 if ( my_err == -1 ) {
2558 printf( "sigaction failed with errno %d - %s \n", errno, strerror( errno ) );
2559 exit( -1 );
2560 }
2561
2562 /* now suspend until signal SIGUSR1 is sent */
2563 sigemptyset( &my_sigset );
2564 my_err = sigsuspend( &my_sigset );
2565 if ( my_err == -1 ) {
2566 if ( errno != EINTR ) {
2567 printf( "sigsuspend should have returned with errno EINTR \n" );
2568 exit( -1 );
2569 }
2570 }
2571
2572 /* block SIGUSR1 */
2573 sigemptyset( &my_sigset );
2574 sigaddset( &my_sigset, SIGUSR1 );
2575 if ( sigismember( &my_sigset, SIGUSR1 ) == 0 ) {
2576 printf( "sigaddset call failed to add SIGUSR1 to signal set \n" );
2577 exit( -1 );
2578 }
2579 my_err = sigprocmask( SIG_BLOCK, &my_sigset, NULL );
2580 if ( my_err == -1 ) {
2581 printf( "sigprocmask failed with errno %d - %s \n", errno, strerror( errno ) );
2582 exit( -1 );
2583 }
2584
2585 /* make sure we are blocking SIGUSR1 */
2586 sigemptyset( &my_sigset );
2587 my_err = sigprocmask( 0, NULL, &my_sigset );
2588 if ( my_err == -1 ) {
2589 printf( "sigprocmask failed with errno %d - %s \n", errno, strerror( errno ) );
2590 exit( -1 );
2591 }
2592 if ( sigismember( &my_sigset, SIGUSR1 ) == 0 ) {
2593 printf( "sigaddset call failed to add SIGUSR1 to signal set \n" );
2594 exit( -1 );
2595 }
2596
2597 /* our parent will send a 2nd SIGUSR1 signal which we should now see getting
2598 * blocked.
2599 */
2600 sigemptyset( &my_sigset );
2601 sigaddset( &my_sigset, SIGUSR1 );
2602 my_err = sigwait( &my_sigset, &my_signal );
2603 if ( my_err == -1 ) {
2604 printf( "sigwait failed with errno %d - %s \n", errno, strerror( errno ) );
2605 exit( -1 );
2606 }
2607 //printf( "%s - %d - signal 0x%02X %d \n", __FUNCTION__, __LINE__, my_signal, my_signal );
2608 if ( my_signal != SIGUSR1 ) {
2609 printf( "sigwait failed to catch a pending SIGUSR1 signal. \n" );
2610 exit( -1 );
2611 }
2612
2613 /* now unblock SIGUSR1 */
2614 sigfillset( &my_sigset );
2615 sigdelset( &my_sigset, SIGUSR1 );
2616 my_err = sigprocmask( SIG_UNBLOCK, &my_sigset, NULL );
2617 if ( my_err == -1 ) {
2618 printf( "sigprocmask failed with errno %d - %s \n", errno, strerror( errno ) );
2619 exit( -1 );
2620 }
2621 if ( sigismember( &my_sigset, SIGUSR1 ) != 0 ) {
2622 printf( "sigprocmask call failed to unblock SIGUSR1 \n" );
2623 exit( -1 );
2624 }
2625
2626 /* test get / setitimer */
2627 timerclear( &my_timer.it_interval );
2628 timerclear( &my_timer.it_value );
2629 my_err = setitimer( ITIMER_VIRTUAL, &my_timer, NULL );
2630 if ( my_err == -1 ) {
2631 printf( "setitimer - ITIMER_VIRTUAL - failed with errno %d - %s \n", errno, strerror( errno ) );
2632 exit( -1 );
2633 }
2634 my_err = setitimer( ITIMER_PROF, &my_timer, NULL );
2635 if ( my_err == -1 ) {
2636 printf( "setitimer - ITIMER_PROF - failed with errno %d - %s \n", errno, strerror( errno ) );
2637 exit( -1 );
2638 }
2639
2640 /* set up to catch SIGALRM */
2641 alarm_global = 0;
2642 my_sigaction.sa_handler = test_alarm_handler;
2643 my_sigaction.sa_flags = SA_RESTART;
2644 my_sigaction.sa_mask = 0;
2645
2646 my_err = sigaction( SIGALRM, &my_sigaction, NULL );
2647 if ( my_err == -1 ) {
2648 printf( "sigaction - SIGALRM - failed with errno %d - %s \n", errno, strerror( errno ) );
2649 exit( -1 );
2650 }
2651
2652 /* set timer for half a second */
2653 my_timer.it_value.tv_usec = (1000000 / 2);
2654 my_err = setitimer( ITIMER_REAL, &my_timer, NULL );
2655 if ( my_err == -1 ) {
2656 printf( "setitimer - ITIMER_REAL - failed with errno %d - %s \n", errno, strerror( errno ) );
2657 exit( -1 );
2658 }
2659
2660 /* now suspend until signal SIGALRM is sent */
2661 sigfillset( &my_sigset );
2662 sigdelset( &my_sigset, SIGALRM );
2663 my_err = sigsuspend( &my_sigset );
2664 if ( my_err == -1 ) {
2665 if ( errno != EINTR ) {
2666 printf( "sigsuspend should have returned with errno EINTR \n" );
2667 exit( -1 );
2668 }
2669 }
2670 if ( alarm_global != 4 ) {
2671 printf( "setitimer test failed - did not catch SIGALRM \n" );
2672 exit( -1 );
2673 }
2674
2675 /* make sure ITIMER_REAL is now clear */
2676 my_timer.it_value.tv_sec = 44;
2677 my_timer.it_value.tv_usec = 44;
2678 my_err = getitimer( ITIMER_REAL, &my_timer );
2679 if ( my_err == -1 ) {
2680 printf( "getitimer - ITIMER_REAL - failed with errno %d - %s \n", errno, strerror( errno ) );
2681 exit( -1 );
2682 }
2683 if ( timerisset( &my_timer.it_value ) || timerisset( &my_timer.it_interval ) ) {
2684 printf( "ITIMER_REAL is set, but should not be \n" );
2685 exit( -1 );
2686 }
2687
2688 exit(0);
2689 }
2690
2691 /*
2692 * parent process - let child set up to suspend then signal it with SIGUSR1
2693 */
2694 sleep( 1 );
2695 my_err = kill( my_pid, SIGUSR1 );
2696 if ( my_err == -1 ) {
2697 printf( "kill call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2698 goto test_failed_exit;
2699 }
2700
2701 /* send 2nd signal to suspended child - which should be blocking SIGUSR1 signals */
2702 sleep( 1 );
2703 my_err = kill( my_pid, SIGUSR1 );
2704 if ( my_err == -1 ) {
2705 printf( "kill call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2706 goto test_failed_exit;
2707 }
2708
2709 /* wait for child to exit */
2710 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
2711 if ( my_wait_pid == -1 ) {
2712 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
2713 goto test_failed_exit;
2714 }
2715
2716 if ( WIFSIGNALED( my_status ) || ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) ) {
2717 goto test_failed_exit;
2718 }
2719
2720 my_err = 0;
2721 goto test_passed_exit;
2722
2723 test_failed_exit:
2724 my_err = -1;
2725
2726 test_passed_exit:
2727 if ( my_fd != -1 )
2728 close( my_fd );
2729 if ( my_pathp != NULL ) {
2730 remove( my_pathp );
2731 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
2732 }
2733 return( my_err );
2734 }
2735
2736 /* **************************************************************************************************************
2737 * Test getlogin, setlogin system calls.
2738 * **************************************************************************************************************
2739 */
2740 int getlogin_setlogin_test( void * the_argp )
2741 {
2742 int my_err, my_status;
2743 pid_t my_pid, my_wait_pid;
2744 kern_return_t my_kr;
2745
2746 if ( g_skip_setuid_tests != 0 ) {
2747 printf("\t skipping this test \n");
2748 my_err = 0;
2749 goto test_passed_exit;
2750 }
2751
2752 /*
2753 * spin off a child process that we will use for testing.
2754 */
2755 my_pid = fork( );
2756 if ( my_pid == -1 ) {
2757 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
2758 goto test_failed_exit;
2759 }
2760 if ( my_pid == 0 ) {
2761 /*
2762 * child process - do getlogin and setlogin testing.
2763 */
2764 char * my_namep = NULL;
2765 int my_len;
2766 char * my_new_namep = NULL;
2767
2768 my_namep = getlogin( );
2769 if ( my_namep == NULL ) {
2770 printf( "getlogin returned NULL name pointer \n" );
2771 my_err = -1;
2772 goto exit_child;
2773 }
2774
2775 my_len = strlen( my_namep ) + 4;
2776
2777 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_new_namep, my_len, VM_FLAGS_ANYWHERE);
2778 if(my_kr != KERN_SUCCESS){
2779 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
2780 my_err = -1;
2781 goto exit_child;
2782 }
2783
2784 bzero( (void *)my_new_namep, my_len );
2785
2786 strcat( my_new_namep, my_namep );
2787 strcat( my_new_namep, "2" );
2788
2789
2790 /* set new name */
2791 my_err = setlogin( my_new_namep );
2792 if ( my_err == -1 ) {
2793 printf( "When setting new login name, setlogin failed with error %d - \"%s\" \n", errno, strerror( errno) );
2794 my_err = -1;
2795 goto exit_child;
2796 }
2797
2798 /* make sure we set new name */
2799 my_namep = getlogin( );
2800 if ( my_namep == NULL ) {
2801 printf( "getlogin returned NULL name pointer \n" );
2802 my_err = -1;
2803 goto exit_child;
2804 }
2805
2806 if ( memcmp( my_namep, my_new_namep, strlen( my_new_namep ) ) != 0 ) {
2807 printf( "setlogin failed to set the new name \n" );
2808 my_err = -1;
2809 goto exit_child;
2810 }
2811
2812 /* reset to original name */
2813 my_len = strlen ( my_namep );
2814 my_namep[ my_len - 1 ] = '\0';
2815
2816 my_err = setlogin( my_namep );
2817 if ( my_err == -1 ) {
2818 printf( "When resetting login name, setlogin failed with error %d - \"%s\" \n", errno, strerror( errno) );
2819 my_err = -1;
2820 goto exit_child;
2821 }
2822
2823
2824 my_err = 0;
2825 exit_child:
2826 if ( my_new_namep != NULL ) {
2827 vm_deallocate(mach_task_self(), (vm_address_t)my_new_namep, my_len);
2828 }
2829 exit( my_err );
2830 }
2831
2832 /* parent process -
2833 * wait for child to exit
2834 */
2835 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
2836 if ( my_wait_pid == -1 ) {
2837 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
2838 goto test_failed_exit;
2839 }
2840
2841 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
2842 goto test_failed_exit;
2843 }
2844 my_err = 0;
2845 goto test_passed_exit;
2846
2847 test_failed_exit:
2848 my_err = -1;
2849
2850 test_passed_exit:
2851 return( my_err );
2852 }
2853
2854 /* **************************************************************************************************************
2855 * Test acct system call.
2856 * **************************************************************************************************************
2857 */
2858 int acct_test( void * the_argp )
2859 {
2860 int my_err, my_status;
2861 int my_fd = -1;
2862 char * my_pathp = NULL;
2863 struct acct * my_acctp;
2864 pid_t my_pid, my_wait_pid;
2865 ssize_t my_count;
2866 char my_buffer[ (sizeof(struct acct) + 32) ];
2867 kern_return_t my_kr;
2868 int acct_record_found;
2869 char * test_bin_name = NULL;
2870
2871 if ( g_skip_setuid_tests != 0 ) {
2872 printf("\t skipping this test \n");
2873 my_err = 0;
2874 goto test_passed_exit;
2875 }
2876
2877 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
2878 if(my_kr != KERN_SUCCESS){
2879 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
2880 goto test_failed_exit;
2881 }
2882
2883 *my_pathp = 0x00;
2884 strcat( my_pathp, &g_target_path[0] );
2885 strcat( my_pathp, "/" );
2886
2887 /* create a test file */
2888 my_err = create_random_name( my_pathp, 1 );
2889 if ( my_err != 0 ) {
2890 goto test_failed_exit;
2891 }
2892
2893 /* enable process accounting */
2894 my_err = acct( my_pathp );
2895 if ( my_err == -1 ) {
2896 printf( "acct failed with error %d - \"%s\" \n", errno, strerror( errno) );
2897 goto test_failed_exit;
2898 }
2899
2900 /*
2901 * spin off a child process that we will use for testing.
2902 */
2903 my_pid = fork( );
2904 if ( my_pid == -1 ) {
2905 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
2906 goto test_failed_exit;
2907 }
2908 if ( my_pid == 0 ) {
2909 char *argv[2]; /* supply valid argv array to execv() */
2910 argv[0] = "/usr/bin/true";
2911 argv[1] = 0;
2912
2913 /*
2914 * child process - do a little work then exit.
2915 */
2916 my_err = execv( argv[0], argv);
2917 exit( 0 );
2918 }
2919
2920 /* parent process -
2921 * wait for child to exit
2922 */
2923 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
2924 if ( my_wait_pid == -1 ) {
2925 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
2926 goto test_failed_exit;
2927 }
2928
2929 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
2930 printf("unexpected child exit status for accounting test load: %d\n", WEXITSTATUS( my_status));
2931 goto test_failed_exit;
2932 }
2933
2934 /* disable process accounting */
2935 my_err = acct( NULL );
2936 if ( my_err == -1 ) {
2937 printf( "acct failed with error %d - \"%s\" \n", errno, strerror( errno) );
2938 goto test_failed_exit;
2939 }
2940
2941 /* now verify that there is accounting info in the log file */
2942 my_fd = open( my_pathp, O_RDONLY, 0 );
2943 if ( my_fd == -1 ) {
2944 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2945 goto test_failed_exit;
2946 }
2947
2948 lseek( my_fd, 0, SEEK_SET );
2949 bzero( (void *)&my_buffer[0], sizeof(my_buffer) );
2950 acct_record_found = 0;
2951 test_bin_name = "true";
2952
2953 while(1) {
2954
2955 my_count = read( my_fd, &my_buffer[0], sizeof(struct acct) );
2956
2957 if ( my_count == -1 ) {
2958 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
2959 goto test_failed_exit;
2960 }
2961
2962 if ( my_count < sizeof(struct acct)) {
2963 /* Indicates EOF or misaligned file size */
2964 printf("Reached end of accounting records with last read count: %d\n", my_count);
2965 break;
2966 }
2967
2968 my_acctp = (struct acct *) &my_buffer[0];
2969 /* first letters in ac_comm should match the name of the executable */
2970 if ( (getuid() == my_acctp->ac_uid) && (getgid() == my_acctp->ac_gid) &&
2971 (!strncmp(my_acctp->ac_comm, test_bin_name, strlen(test_bin_name))) ) {
2972 /* Expected accounting record found */
2973 acct_record_found = 1;
2974 break;
2975 }
2976
2977 }
2978
2979 if (acct_record_found) {
2980 my_err = 0;
2981 goto test_passed_exit;
2982 } else {
2983 printf( "------------------------\n" );
2984 printf( "Expected Accounting Record for child process %s not found\n", test_bin_name );
2985 printf( "Expected uid: %lu Expected gid: %lu\n" , (unsigned long) getuid(), (unsigned long) getgid() );
2986 printf( "Account file path: %s\n", my_pathp );
2987 goto test_failed_exit;
2988 }
2989
2990 test_failed_exit:
2991 my_err = -1;
2992
2993 test_passed_exit:
2994 if ( my_fd != -1 )
2995 close( my_fd );
2996 if ( my_pathp != NULL ) {
2997 remove( my_pathp );
2998 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
2999 }
3000 return( my_err );
3001 }
3002
3003 void print_acct_debug_strings( char * my_ac_comm )
3004 {
3005 char my_cmd_str[11]; /* sizeof(acct_cmd) + 1 for '\0' if acct_cmd is bogus */
3006 char my_hex_str[128];
3007 int i;
3008
3009 my_hex_str[0] = '\0';
3010 for(i = 0; i < 10; i++)
3011 {
3012 sprintf( my_hex_str, "%s \'0x%x\' ", my_hex_str, my_ac_comm[i]);
3013 }
3014
3015 memccpy(my_cmd_str, my_ac_comm, '\0', 10);
3016 my_cmd_str[10] = '\0'; /* In case ac_comm was bogus */
3017
3018
3019 printf( "my_acctp->ac_comm = \"%s\" (should begin with: \"tr\")\n", my_cmd_str);
3020 printf( "my_acctp->ac_comm = \"%s\"\n", my_hex_str);
3021 printf( "------------------------\n" );
3022 }
3023
3024
3025 /* **************************************************************************************************************
3026 * Test ioctl system calls.
3027 * **************************************************************************************************************
3028 */
3029 int ioctl_test( void * the_argp )
3030 {
3031 int my_err, my_result;
3032 int my_fd = -1;
3033 struct statfs * my_infop;
3034 char * my_ptr;
3035 int my_blksize;
3036 long long my_block_count;
3037 char my_name[ 128 ];
3038
3039 my_result = getmntinfo( &my_infop, MNT_NOWAIT );
3040 if ( my_result < 1 ) {
3041 printf( "getmntinfo failed with error %d - \"%s\" \n", errno, strerror( errno) );
3042 goto test_failed_exit;
3043 }
3044
3045 /* make this a raw device */
3046 strcpy( &my_name[0], &my_infop->f_mntfromname[0] );
3047 if ( (my_ptr = strrchr( &my_name[0], '/' )) != 0 ) {
3048 if ( my_ptr[1] != 'r' ) {
3049 my_ptr[ strlen( my_ptr ) ] = 0x00;
3050 memmove( &my_ptr[2], &my_ptr[1], (strlen( &my_ptr[1] ) + 1) );
3051 my_ptr[1] = 'r';
3052 }
3053 }
3054
3055 my_fd = open(&my_name[0], O_RDONLY );
3056 if ( my_fd == -1 ) {
3057 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3058 goto test_failed_exit;
3059 }
3060
3061 /* obtain the size of the media (in blocks) */
3062 my_err = ioctl( my_fd, DKIOCGETBLOCKCOUNT, &my_block_count );
3063 if ( my_err == -1 ) {
3064 printf( "ioctl DKIOCGETBLOCKCOUNT failed with error %d - \"%s\" \n", errno, strerror( errno) );
3065 goto test_failed_exit;
3066 }
3067
3068 /* obtain the block size of the media */
3069 my_err = ioctl( my_fd, DKIOCGETBLOCKSIZE, &my_blksize );
3070 if ( my_err == -1 ) {
3071 printf( "ioctl DKIOCGETBLOCKSIZE failed with error %d - \"%s\" \n", errno, strerror( errno) );
3072 goto test_failed_exit;
3073 }
3074 //printf( "my_block_count %qd my_blksize %d \n", my_block_count, my_blksize );
3075
3076 /* make sure the returned data looks somewhat valid */
3077 if ( my_blksize < 0 || my_blksize > (1024 * 1000) ) {
3078 printf( "ioctl appears to have returned incorrect block size data \n" );
3079 goto test_failed_exit;
3080 }
3081
3082 my_err = 0;
3083 goto test_passed_exit;
3084
3085 test_failed_exit:
3086 my_err = -1;
3087
3088 test_passed_exit:
3089 if ( my_fd != -1 )
3090 close( my_fd );
3091 return( my_err );
3092 }
3093
3094 /* **************************************************************************************************************
3095 * Test mkdir, rmdir, umask system calls.
3096 * **************************************************************************************************************
3097 */
3098 int mkdir_rmdir_umask_test( void * the_argp )
3099 {
3100 int my_err;
3101 int my_fd = -1;
3102 int did_umask = 0;
3103 char * my_pathp = NULL;
3104 mode_t my_orig_mask;
3105 struct stat my_sb;
3106 kern_return_t my_kr;
3107
3108 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3109 if(my_kr != KERN_SUCCESS){
3110 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3111 goto test_failed_exit;
3112 }
3113
3114 *my_pathp = 0x00;
3115 strcat( my_pathp, &g_target_path[0] );
3116 strcat( my_pathp, "/" );
3117
3118 /* get a unique name to use with mkdir */
3119 my_err = create_random_name( my_pathp, 0 );
3120 if ( my_err != 0 ) {
3121 printf( "create_random_name failed with error %d\n", my_err );
3122 goto test_failed_exit;
3123 }
3124
3125 /* set umask to clear WX for other and group and clear X for user */
3126 my_orig_mask = umask( (S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH) );
3127 did_umask = 1;
3128
3129 /* create a directory with RWX for user, group, other (which should be limited by umask) */
3130 my_err = mkdir( my_pathp, (S_IRWXU | S_IRWXG | S_IRWXO) );
3131 if ( my_err == -1 ) {
3132 printf( "mkdir failed with error %d - \"%s\" \n", errno, strerror( errno) );
3133 goto test_failed_exit;
3134 }
3135
3136 /* verify results - (S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH) should be clear*/
3137 my_err = stat( my_pathp, &my_sb );
3138 if ( my_err != 0 ) {
3139 printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3140 goto test_failed_exit;
3141 }
3142 if ( (my_sb.st_mode & (S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH)) != 0 ) {
3143 printf( "umask did not limit modes as it should have \n" );
3144 goto test_failed_exit;
3145 }
3146
3147 /* get rid of our test directory */
3148 my_err = rmdir( my_pathp );
3149 if ( my_err == -1 ) {
3150 printf( "rmdir failed with error %d - \"%s\" \n", errno, strerror( errno) );
3151 goto test_failed_exit;
3152 }
3153 my_err = 0;
3154 goto test_passed_exit;
3155
3156 test_failed_exit:
3157 my_err = -1;
3158
3159 test_passed_exit:
3160 if ( my_fd != -1 )
3161 close( my_fd );
3162 if ( my_pathp != NULL ) {
3163 rmdir( my_pathp );
3164 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
3165 }
3166 if ( did_umask != 0 ) {
3167 umask( my_orig_mask );
3168 }
3169
3170 return( my_err );
3171 }
3172
3173 /* **************************************************************************************************************
3174 * Test chroot system call.
3175 * **************************************************************************************************************
3176 */
3177 int chroot_test( void * the_argp )
3178 {
3179 int my_err, my_status;
3180 pid_t my_pid, my_wait_pid;
3181 char * my_pathp = NULL;
3182 kern_return_t my_kr;
3183
3184 if ( g_skip_setuid_tests != 0 ) {
3185 printf("\t skipping this test \n");
3186 my_err = 0;
3187 goto test_passed_exit;
3188 }
3189
3190 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3191 if(my_kr != KERN_SUCCESS){
3192 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3193 goto test_failed_exit;
3194 }
3195
3196 *my_pathp = 0x00;
3197 strcat( my_pathp, &g_target_path[0] );
3198 strcat( my_pathp, "/" );
3199
3200 /* get a unique name for our test directory */
3201 my_err = create_random_name( my_pathp, 0 );
3202 if ( my_err != 0 ) {
3203 goto test_failed_exit;
3204 }
3205
3206 /* create a test directory */
3207 my_err = mkdir( my_pathp, (S_IRWXU | S_IRWXG | S_IRWXO) );
3208 if ( my_err == -1 ) {
3209 printf( "mkdir failed with error %d - \"%s\" \n", errno, strerror( errno) );
3210 goto test_failed_exit;
3211 }
3212
3213 /*
3214 * spin off a child process that we will use for testing.
3215 */
3216 my_pid = fork( );
3217 if ( my_pid == -1 ) {
3218 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
3219 goto test_failed_exit;
3220 }
3221 if ( my_pid == 0 ) {
3222 /*
3223 * child process - do getlogin and setlogin testing.
3224 */
3225 struct stat my_sb;
3226
3227 /* change our root to our new test directory */
3228 my_err = chroot( my_pathp );
3229 if ( my_err != 0 ) {
3230 printf( "chroot failed with error %d - \"%s\" \n", errno, strerror( errno) );
3231 exit( -1 );
3232 }
3233
3234 /* verify root directory is now an empty directory */
3235 my_err = stat( "/", &my_sb );
3236 if ( my_err != 0 ) {
3237 printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3238 exit( -1 );
3239 }
3240 if ( my_sb.st_nlink > 2 ) {
3241 printf( "root dir should be emnpty! \n" );
3242 exit( -1 );
3243 }
3244 exit( 0 );
3245 }
3246
3247 /* parent process -
3248 * wait for child to exit
3249 */
3250 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
3251 if ( my_wait_pid == -1 ) {
3252 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
3253 goto test_failed_exit;
3254 }
3255
3256 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
3257 printf( "bad exit status\n" );
3258 goto test_failed_exit;
3259 }
3260
3261 my_err = 0;
3262 goto test_passed_exit;
3263
3264 test_failed_exit:
3265 my_err = -1;
3266
3267 test_passed_exit:
3268 if ( my_pathp != NULL ) {
3269 my_err = rmdir( my_pathp );
3270 if ( my_err != 0 ) {
3271 printf( "rmdir failed with error %d - \"%s\" path %p\n", errno, strerror( errno), my_pathp );
3272 }
3273 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
3274 }
3275 return( my_err );
3276 }
3277
3278 /* **************************************************************************************************************
3279 * Test getpgrp, getpgid, getsid, setpgid, setpgrp, setsid system calls.
3280 * **************************************************************************************************************
3281 */
3282 int process_group_test( void * the_argp )
3283 {
3284 int my_err = 0, i = 0;
3285 pid_t my_session_id, my_pid, my_process_group;
3286
3287 /* get current session ID, pgid, and pid */
3288 my_session_id = getsid( 0 );
3289 if ( my_session_id == -1 ) {
3290 printf( "getsid call failed with error %d - \"%s\" \n",
3291 errno, strerror( errno ) );
3292 goto test_failed_exit;
3293 }
3294
3295 my_pid = getpid( );
3296 my_process_group = getpgrp( );
3297
3298 /* test getpgrp and getpgid - they should return the same results when 0 is passed to getpgid */
3299 if ( my_process_group != getpgid( 0 ) ) {
3300 printf( "getpgrp and getpgid did not return the same process group ID \n" );
3301 printf( "getpgid: %d, my_process_group: %d\n", getpgid( 0 ), my_process_group );
3302 goto test_failed_exit;
3303 }
3304
3305 if ( my_pid == my_process_group ) {
3306 /* we are process group leader */
3307 my_err = setsid( );
3308 if ( my_err == 0 || errno != EPERM ) {
3309 printf( "setsid call should have failed with EPERM\n" );
3310 goto test_failed_exit;
3311 }
3312 } else {
3313 /* we are not process group leader: try creating new session */
3314 my_err = setsid( );
3315 if ( my_err == -1 ) {
3316 printf( "setsid call failed with error %d - \"%s\" \n",
3317 errno, strerror( errno ) );
3318 goto test_failed_exit;
3319 }
3320
3321 if ( my_process_group == getpgid( 0 ) ) {
3322 printf( "process group was not reset \n" );
3323 goto test_failed_exit;
3324 }
3325 }
3326
3327 /* find an unused process group ID */
3328 for ( i = 10000; i < 1000000; i++ ) {
3329 my_process_group = getpgid( i );
3330 if ( my_process_group == -1 ) {
3331 break;
3332 }
3333 }
3334
3335 /* this should fail */
3336 my_err = setpgid( 0, my_process_group );
3337 if ( my_err != -1 ) {
3338 printf( "setpgid should have failed, but did not \n" );
3339 goto test_failed_exit;
3340 }
3341
3342 my_err = 0;
3343 goto test_passed_exit;
3344
3345 test_failed_exit:
3346 my_err = -1;
3347
3348 test_passed_exit:
3349 return( my_err );
3350 }
3351
3352 /* **************************************************************************************************************
3353 * Test fcntl system calls.
3354 * **************************************************************************************************************
3355 */
3356 int fcntl_test( void * the_argp )
3357 {
3358 int my_err, my_result, my_tmep;
3359 int my_fd = -1;
3360 int my_newfd = -1;
3361 char * my_pathp = NULL;
3362 kern_return_t my_kr;
3363
3364 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3365 if(my_kr != KERN_SUCCESS){
3366 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3367 goto test_failed_exit;
3368 }
3369
3370 *my_pathp = 0x00;
3371 strcat( my_pathp, &g_target_path[0] );
3372 strcat( my_pathp, "/" );
3373
3374 /* create a test file */
3375 my_err = create_random_name( my_pathp, 1 );
3376 if ( my_err != 0 ) {
3377 goto test_failed_exit;
3378 }
3379
3380 /* open our test file and use fcntl to get / set file descriptor flags */
3381 my_fd = open( my_pathp, O_RDONLY, 0 );
3382 if ( my_fd == -1 ) {
3383 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3384 goto test_failed_exit;
3385 }
3386
3387 my_result = fcntl( my_fd, F_GETFD, 0 );
3388 if ( my_result == -1 ) {
3389 printf( "fcntl - F_GETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3390 goto test_failed_exit;
3391 }
3392
3393 my_tmep = (my_result & FD_CLOEXEC);
3394 if ( my_tmep ) {
3395 /* FD_CLOEXEC is on, let's turn it off */
3396 my_result = fcntl( my_fd, F_SETFD, 0 );
3397 }
3398 else {
3399 /* FD_CLOEXEC is off, let's turn it on */
3400 my_result = fcntl( my_fd, F_SETFD, 1 );
3401 }
3402 if ( my_result == -1 ) {
3403 printf( "fcntl - F_SETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3404 goto test_failed_exit;
3405 }
3406
3407 /* now check to see if it is set correctly */
3408 my_result = fcntl( my_fd, F_GETFD, 0 );
3409 if ( my_result == -1 ) {
3410 printf( "fcntl - F_GETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3411 goto test_failed_exit;
3412 }
3413 if ( my_tmep == (my_result & 0x01) ) {
3414 printf( "fcntl - F_SETFD failed to set FD_CLOEXEC correctly!!! \n" );
3415 goto test_failed_exit;
3416 }
3417
3418 /* dup it to a new fd with FD_CLOEXEC forced on */
3419
3420 my_result = fcntl( my_fd, F_DUPFD_CLOEXEC, 0);
3421 if ( my_result == -1 ) {
3422 printf( "fcntl - F_DUPFD_CLOEXEC - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3423 goto test_failed_exit;
3424 }
3425 my_newfd = my_result;
3426
3427 /* check to see that it too is marked with FD_CLOEXEC */
3428
3429 my_result = fcntl( my_newfd, F_GETFD, 0);
3430 if ( my_result == -1 ) {
3431 printf( "fcntl - F_GETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3432 goto test_failed_exit;
3433 }
3434 if ( (my_result & FD_CLOEXEC) == 0 ) {
3435 printf( "fcntl - F_DUPFD_CLOEXEC failed to set FD_CLOEXEC!!! \n" );
3436 goto test_failed_exit;
3437 }
3438
3439 close( my_newfd );
3440 my_newfd = -1;
3441
3442 /* While we're here, dup it via an open of /dev/fd/<fd> .. */
3443
3444 {
3445 char devfdpath[PATH_MAX];
3446
3447 (void) snprintf( devfdpath, sizeof (devfdpath),
3448 "/dev/fd/%u", my_fd );
3449 my_result = open( devfdpath, O_RDONLY | O_CLOEXEC );
3450 }
3451 if ( my_result == -1 ) {
3452 printf( "open call failed on /dev/fd/%u with error %d - \"%s\" \n", my_fd, errno, strerror( errno) );
3453 goto test_failed_exit;
3454 }
3455 my_newfd = my_result;
3456
3457 /* check to see that it too is marked with FD_CLOEXEC */
3458
3459 my_result = fcntl( my_newfd, F_GETFD, 0);
3460 if ( my_result == -1 ) {
3461 printf( "fcntl - F_GETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3462 goto test_failed_exit;
3463 }
3464 if ( (my_result & FD_CLOEXEC) == 0 ) {
3465 printf( "fcntl - O_CLOEXEC open of /dev/fd/%u failed to set FD_CLOEXEC!!! \n", my_fd );
3466 goto test_failed_exit;
3467 }
3468 close ( my_newfd );
3469 my_newfd = -1;
3470 my_err = 0;
3471 goto test_passed_exit;
3472
3473 test_failed_exit:
3474 my_err = -1;
3475
3476 test_passed_exit:
3477 if ( my_newfd != -1)
3478 close ( my_newfd );
3479 if ( my_fd != -1 )
3480 close( my_fd );
3481 if ( my_pathp != NULL ) {
3482 remove( my_pathp );
3483 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
3484 }
3485 return( my_err );
3486 }
3487
3488 /* **************************************************************************************************************
3489 * Test getpriority, setpriority system calls.
3490 * **************************************************************************************************************
3491 */
3492 int getpriority_setpriority_test( void * the_argp )
3493 {
3494 int my_err;
3495 int my_priority;
3496 int my_new_priority;
3497
3498 /* getpriority returns scheduling priority so -1 is a valid value */
3499 errno = 0;
3500 my_priority = getpriority( PRIO_PROCESS, 0 );
3501 if ( my_priority == -1 && errno != 0 ) {
3502 printf( "getpriority - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3503 goto test_failed_exit;
3504 }
3505
3506 /* change scheduling priority */
3507 my_new_priority = (my_priority == PRIO_MIN) ? (my_priority + 10) : (PRIO_MIN);
3508 my_err = setpriority( PRIO_PROCESS, 0, my_new_priority );
3509 if ( my_err == -1 ) {
3510 printf( "setpriority - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3511 goto test_failed_exit;
3512 }
3513
3514 /* verify change */
3515 errno = 0;
3516 my_priority = getpriority( PRIO_PROCESS, 0 );
3517 if ( my_priority == -1 && errno != 0 ) {
3518 printf( "getpriority - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3519 goto test_failed_exit;
3520 }
3521
3522 if ( my_priority != my_new_priority ) {
3523 printf( "setpriority - failed to set correct scheduling priority \n" );
3524 goto test_failed_exit;
3525 }
3526
3527 /* reset scheduling priority */
3528 my_err = setpriority( PRIO_PROCESS, 0, 0 );
3529 if ( my_err == -1 ) {
3530 printf( "setpriority - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3531 goto test_failed_exit;
3532 }
3533
3534 my_err = 0;
3535 goto test_passed_exit;
3536
3537 test_failed_exit:
3538 my_err = -1;
3539
3540 test_passed_exit:
3541 return( my_err );
3542 }
3543
3544 /* **************************************************************************************************************
3545 * Test futimes, gettimeofday, settimeofday, utimes system calls.
3546 * **************************************************************************************************************
3547 */
3548 int time_tests( void * the_argp )
3549 {
3550 int my_err;
3551 int my_fd = -1;
3552 char * my_pathp = NULL;
3553 struct timeval my_orig_time;
3554 struct timeval my_temp_time;
3555 struct timeval my_utimes[4];
3556 struct timezone my_tz;
3557 struct stat my_sb;
3558 kern_return_t my_kr;
3559
3560 if ( g_skip_setuid_tests != 0 ) {
3561 printf( "\t skipping this test \n" );
3562 my_err = 0;
3563 goto test_passed_exit;
3564 }
3565
3566 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3567 if(my_kr != KERN_SUCCESS){
3568 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3569 goto test_failed_exit;
3570 }
3571
3572 *my_pathp = 0x00;
3573 strcat( my_pathp, &g_target_path[0] );
3574 strcat( my_pathp, "/" );
3575
3576 /* create a test file */
3577 my_err = create_random_name( my_pathp, 1 );
3578 if ( my_err != 0 ) {
3579 goto test_failed_exit;
3580 }
3581
3582 my_err = gettimeofday( &my_orig_time, &my_tz );
3583 if ( my_err == -1 ) {
3584 printf( "gettimeofday - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3585 goto test_failed_exit;
3586 }
3587 //printf( "tv_sec %d tv_usec %ld \n", my_orig_time.tv_sec, my_orig_time.tv_usec );
3588
3589 my_temp_time = my_orig_time;
3590 my_temp_time.tv_sec -= 60;
3591 my_err = settimeofday( &my_temp_time, NULL );
3592 if ( my_err == -1 ) {
3593 printf( "settimeofday - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3594 goto test_failed_exit;
3595 }
3596
3597 my_err = gettimeofday( &my_temp_time, NULL );
3598 if ( my_err == -1 ) {
3599 printf( "gettimeofday - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3600 goto test_failed_exit;
3601 }
3602 //printf( "tv_sec %d tv_usec %ld \n", my_temp_time.tv_sec, my_temp_time.tv_usec );
3603 if ( my_orig_time.tv_sec <= my_temp_time.tv_sec ) {
3604 printf( "settimeofday did not set correct time \n" );
3605 goto test_failed_exit;
3606 }
3607
3608 /* set time back to original value plus 1 second */
3609 my_temp_time = my_orig_time;
3610 my_temp_time.tv_sec += 1;
3611 my_err = settimeofday( &my_temp_time, NULL );
3612 if ( my_err == -1 ) {
3613 printf( "settimeofday - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3614 goto test_failed_exit;
3615 }
3616
3617 /* test utimes and futimes - get current access and mod times then change them */
3618 my_err = stat( my_pathp, &my_sb );
3619 if ( my_err != 0 ) {
3620 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3621 goto test_failed_exit;
3622 }
3623 TIMESPEC_TO_TIMEVAL( &my_utimes[0], &my_sb.st_atimespec );
3624 TIMESPEC_TO_TIMEVAL( &my_utimes[1], &my_sb.st_mtimespec );
3625 my_utimes[0].tv_sec -= 120; /* make access time 2 minutes older */
3626 my_utimes[1].tv_sec -= 120; /* make mod time 2 minutes older */
3627
3628 my_err = utimes( my_pathp, &my_utimes[0] );
3629 if ( my_err == -1 ) {
3630 printf( "utimes - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3631 goto test_failed_exit;
3632 }
3633
3634 /* make sure the correct times are set */
3635 my_err = stat( my_pathp, &my_sb );
3636 if ( my_err != 0 ) {
3637 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3638 goto test_failed_exit;
3639 }
3640 TIMESPEC_TO_TIMEVAL( &my_utimes[2], &my_sb.st_atimespec );
3641 TIMESPEC_TO_TIMEVAL( &my_utimes[3], &my_sb.st_mtimespec );
3642 if ( my_utimes[0].tv_sec != my_utimes[2].tv_sec ||
3643 my_utimes[1].tv_sec != my_utimes[3].tv_sec ) {
3644 printf( "utimes failed to set access and mod times \n" );
3645 goto test_failed_exit;
3646 }
3647
3648 my_fd = open( my_pathp, O_RDWR, 0 );
3649 if ( my_fd == -1 ) {
3650 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3651 goto test_failed_exit;
3652 }
3653
3654 my_utimes[0].tv_sec -= 120; /* make access time 2 minutes older */
3655 my_utimes[1].tv_sec -= 120; /* make mod time 2 minutes older */
3656 my_err = futimes( my_fd, &my_utimes[0] );
3657 if ( my_err == -1 ) {
3658 printf( "futimes - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3659 goto test_failed_exit;
3660 }
3661
3662 /* make sure the correct times are set */
3663 my_err = stat( my_pathp, &my_sb );
3664 if ( my_err != 0 ) {
3665 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3666 goto test_failed_exit;
3667 }
3668 TIMESPEC_TO_TIMEVAL( &my_utimes[2], &my_sb.st_atimespec );
3669 TIMESPEC_TO_TIMEVAL( &my_utimes[3], &my_sb.st_mtimespec );
3670 if ( my_utimes[0].tv_sec != my_utimes[2].tv_sec ||
3671 my_utimes[1].tv_sec != my_utimes[3].tv_sec ) {
3672 printf( "futimes failed to set access and mod times \n" );
3673 goto test_failed_exit;
3674 }
3675
3676 my_err = 0;
3677 goto test_passed_exit;
3678
3679 test_failed_exit:
3680 my_err = -1;
3681
3682 test_passed_exit:
3683 if ( my_fd != -1 )
3684 close( my_fd );
3685 if ( my_pathp != NULL ) {
3686 remove( my_pathp );
3687 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
3688 }
3689 return( my_err );
3690 }
3691
3692 /* **************************************************************************************************************
3693 * Test rename, stat system calls.
3694 * **************************************************************************************************************
3695 */
3696 int rename_test( void * the_argp )
3697 {
3698 int my_err;
3699 char * my_pathp = NULL;
3700 char * my_new_pathp = NULL;
3701 ino_t my_file_id;
3702 struct stat my_sb;
3703 kern_return_t my_kr;
3704
3705 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3706 if(my_kr != KERN_SUCCESS){
3707 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3708 goto test_failed_exit;
3709 }
3710
3711 *my_pathp = 0x00;
3712 strcat( my_pathp, &g_target_path[0] );
3713 strcat( my_pathp, "/" );
3714
3715 /* create a test file */
3716 my_err = create_random_name( my_pathp, 1 );
3717 if ( my_err != 0 ) {
3718 goto test_failed_exit;
3719 }
3720
3721 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_new_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3722 if(my_kr != KERN_SUCCESS){
3723 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3724 goto test_failed_exit;
3725 }
3726
3727 *my_new_pathp = 0x00;
3728 strcat( my_new_pathp, &g_target_path[0] );
3729 strcat( my_new_pathp, "/" );
3730
3731 /* get a unique name for our rename test */
3732 my_err = create_random_name( my_new_pathp, 0 );
3733 if ( my_err != 0 ) {
3734 goto test_failed_exit;
3735 }
3736
3737 /* save file ID for later use */
3738 my_err = stat( my_pathp, &my_sb );
3739 if ( my_err != 0 ) {
3740 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3741 goto test_failed_exit;
3742 }
3743 my_file_id = my_sb.st_ino;
3744
3745 /* test rename */
3746 my_err = rename( my_pathp, my_new_pathp );
3747 if ( my_err == -1 ) {
3748 printf( "rename - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3749 goto test_failed_exit;
3750 }
3751
3752 /* make sure old name is no longer there */
3753 my_err = stat( my_pathp, &my_sb );
3754 if ( my_err == 0 ) {
3755 printf( "rename call failed - found old name \n" );
3756 goto test_failed_exit;
3757 }
3758
3759 /* make sure new name is there and is correct file id */
3760 my_err = stat( my_new_pathp, &my_sb );
3761 if ( my_err != 0 ) {
3762 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3763 goto test_failed_exit;
3764 }
3765 if ( my_file_id != my_sb.st_ino ) {
3766 printf( "rename failed - wrong file id \n" );
3767 goto test_failed_exit;
3768 }
3769
3770 my_err = 0;
3771 goto test_passed_exit;
3772
3773 test_failed_exit:
3774 my_err = -1;
3775
3776 test_passed_exit:
3777 if ( my_pathp != NULL ) {
3778 remove( my_pathp );
3779 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
3780 }
3781 if ( my_new_pathp != NULL ) {
3782 remove( my_new_pathp );
3783 vm_deallocate(mach_task_self(), (vm_address_t)my_new_pathp, PATH_MAX);
3784 }
3785 return( my_err );
3786 }
3787
3788 /* **************************************************************************************************************
3789 * Test locking system calls.
3790 * **************************************************************************************************************
3791 */
3792 int locking_test( void * the_argp )
3793 {
3794 int my_err, my_status;
3795 pid_t my_pid, my_wait_pid;
3796 int my_fd = -1;
3797 char * my_pathp = NULL;
3798 kern_return_t my_kr;
3799
3800 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3801 if(my_kr != KERN_SUCCESS){
3802 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3803 goto test_failed_exit;
3804 }
3805
3806 *my_pathp = 0x00;
3807 strcat( my_pathp, &g_target_path[0] );
3808 strcat( my_pathp, "/" );
3809
3810 /* create a test file */
3811 my_err = create_random_name( my_pathp, 1 );
3812 if ( my_err != 0 ) {
3813 goto test_failed_exit;
3814 }
3815
3816 /* test flock */
3817 my_fd = open( my_pathp, O_RDWR, 0 );
3818 if ( my_fd == -1 ) {
3819 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3820 goto test_failed_exit;
3821 }
3822
3823 my_err = flock( my_fd, LOCK_EX );
3824 if ( my_err == -1 ) {
3825 printf( "flock - LOCK_EX - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3826 goto test_failed_exit;
3827 }
3828
3829 /*
3830 * spin off a child process that we will use for testing.
3831 */
3832 my_pid = fork( );
3833 if ( my_pid == -1 ) {
3834 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
3835 goto test_failed_exit;
3836 }
3837 if ( my_pid == 0 ) {
3838 /*
3839 * child process.
3840 */
3841 int my_child_fd = -1;
3842 int my_child_err;
3843
3844 my_child_fd = open( my_pathp, O_RDWR, 0 );
3845 if ( my_child_fd == -1 ) {
3846 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3847 my_child_err = -1;
3848 goto child_exit;
3849 }
3850
3851 my_err = flock( my_child_fd, (LOCK_EX | LOCK_NB) );
3852 if ( my_err == -1 ) {
3853 if ( errno != EWOULDBLOCK ) {
3854 printf( "flock call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3855 my_child_err = -1;
3856 goto child_exit;
3857 }
3858 }
3859 else {
3860 printf( "flock call should have failed with EWOULDBLOCK err \n" );
3861 my_child_err = -1;
3862 goto child_exit;
3863 }
3864 my_child_err = 0;
3865 child_exit:
3866 if ( my_child_fd != -1 )
3867 close( my_child_fd );
3868 exit( my_child_err );
3869 }
3870
3871 /* parent process -
3872 * wait for child to exit
3873 */
3874 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
3875 if ( my_wait_pid == -1 ) {
3876 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
3877 goto test_failed_exit;
3878 }
3879
3880 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
3881 goto test_failed_exit;
3882 }
3883
3884 my_err = flock( my_fd, LOCK_UN );
3885 if ( my_err == -1 ) {
3886 printf( "flock - LOCK_UN - failed with error %d - \"%s\" \n", errno, strerror( errno) );
3887 goto test_failed_exit;
3888 }
3889
3890 my_err = 0;
3891 goto test_passed_exit;
3892
3893 test_failed_exit:
3894 my_err = -1;
3895
3896 test_passed_exit:
3897 if ( my_fd != -1 )
3898 close( my_fd );
3899 if ( my_pathp != NULL ) {
3900 remove( my_pathp );
3901 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
3902 }
3903 return( my_err );
3904 }
3905
3906 /* **************************************************************************************************************
3907 * Test mkfifo system calls.
3908 * **************************************************************************************************************
3909 */
3910 int mkfifo_test( void * the_argp )
3911 {
3912 int my_err, my_status;
3913 pid_t my_pid, my_wait_pid;
3914 int my_fd = -1;
3915 char * my_pathp = NULL;
3916 ssize_t my_result;
3917 off_t my_current_offset;
3918 kern_return_t my_kr;
3919
3920 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
3921 if(my_kr != KERN_SUCCESS){
3922 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
3923 goto test_failed_exit;
3924 }
3925
3926 *my_pathp = 0x00;
3927 strcat( my_pathp, &g_target_path[0] );
3928 strcat( my_pathp, "/" );
3929
3930 /* get unique name for our fifo */
3931 my_err = create_random_name( my_pathp, 0 );
3932 if ( my_err != 0 ) {
3933 goto test_failed_exit;
3934 }
3935
3936 my_err = mkfifo( my_pathp, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
3937 if ( my_err != 0 ) {
3938 printf( "mkfifo failed with errno %d - %s. \n", errno, strerror( errno ) );
3939 goto test_failed_exit;
3940 }
3941
3942 /*
3943 * spin off a child process that we will use for testing.
3944 */
3945 my_pid = fork( );
3946 if ( my_pid == -1 ) {
3947 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
3948 goto test_failed_exit;
3949 }
3950 if ( my_pid == 0 ) {
3951 /*
3952 * child process.
3953 */
3954 int my_child_fd = -1;
3955 int my_child_err;
3956 char my_buffer[64];
3957
3958 /* open read end of fifo */
3959 my_child_fd = open( my_pathp, O_RDWR, 0 );
3960 if ( my_child_fd == -1 ) {
3961 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3962 my_child_err = -1;
3963 goto child_exit;
3964 }
3965
3966 /* read message from parent */
3967 bzero( (void *)&my_buffer[0], sizeof(my_buffer) );
3968 my_result = read( my_child_fd, &my_buffer[0], sizeof(my_buffer) );
3969 if ( my_result == -1 ) {
3970 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3971 my_child_err = -1;
3972 goto child_exit;
3973 }
3974 if ( strcmp( "parent to child", &my_buffer[0] ) != 0 ) {
3975 printf( "read wrong message from parent \n" );
3976 my_child_err = -1;
3977 goto child_exit;
3978 }
3979
3980 my_child_err = 0;
3981 child_exit:
3982 if ( my_child_fd != -1 )
3983 close( my_child_fd );
3984 exit( my_child_err );
3985 }
3986
3987 /* parent process - open write end of fifo
3988 */
3989 my_fd = open( my_pathp, O_WRONLY, 0 );
3990 if ( my_fd == -1 ) {
3991 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
3992 goto test_failed_exit;
3993 }
3994
3995 /* make sure we can't seek on a fifo */
3996 my_current_offset = lseek( my_fd, 0, SEEK_CUR );
3997 if ( my_current_offset != -1 ) {
3998 printf( "lseek on fifo should fail but did not \n" );
3999 goto test_failed_exit;
4000 }
4001
4002 my_result = write( my_fd, "parent to child", 15 );
4003 if ( my_result == -1 ) {
4004 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4005 goto test_failed_exit;
4006 }
4007
4008 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
4009 if ( my_wait_pid == -1 ) {
4010 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
4011 goto test_failed_exit;
4012 }
4013
4014 if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
4015 goto test_failed_exit;
4016 }
4017
4018 my_err = 0;
4019 goto test_passed_exit;
4020
4021 test_failed_exit:
4022 my_err = -1;
4023
4024 test_passed_exit:
4025 if ( my_fd != -1 )
4026 close( my_fd );
4027 if ( my_pathp != NULL ) {
4028 remove( my_pathp );
4029 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
4030 }
4031 return( my_err );
4032 }
4033
4034 /* **************************************************************************************************************
4035 * Test quotactl system calls.
4036 * **************************************************************************************************************
4037 */
4038 int quotactl_test( void * the_argp )
4039 {
4040 int my_err;
4041 int is_quotas_on = 0;
4042 struct dqblk my_quota_blk;
4043
4044 if ( g_skip_setuid_tests != 0 ) {
4045 printf( "\t skipping this test \n" );
4046 my_err = 0;
4047 goto test_passed_exit;
4048 }
4049
4050 /* start off by checking the status of quotas on the boot volume */
4051 my_err = quotactl( "/System/Library/Kernels/kernel", QCMD(Q_QUOTASTAT, USRQUOTA), 0, (caddr_t)&is_quotas_on );
4052 if ( my_err == -1 ) {
4053 printf( "quotactl - Q_QUOTASTAT - failed with errno %d - %s \n", errno, strerror( errno ) );
4054 goto test_failed_exit;
4055 }
4056
4057 if ( is_quotas_on == 0 ) {
4058 /* quotas are off */
4059 my_err = 0;
4060 goto test_passed_exit;
4061 }
4062
4063 my_err = quotactl( "/System/Library/Kernels/kernel", QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t)&my_quota_blk );
4064 if ( my_err == -1 ) {
4065 printf( "quotactl - Q_GETQUOTA - failed with errno %d - %s \n", errno, strerror( errno ) );
4066 goto test_failed_exit;
4067 }
4068
4069 my_err = 0;
4070 goto test_passed_exit;
4071
4072 test_failed_exit:
4073 my_err = -1;
4074
4075 test_passed_exit:
4076 return( my_err );
4077 }
4078
4079 /* **************************************************************************************************************
4080 * Test getrlimit, setrlimit system calls.
4081 * **************************************************************************************************************
4082 */
4083 int limit_tests( void * the_argp )
4084 {
4085 int my_err;
4086 struct rlimit my_current_rlimit;
4087 struct rlimit my_rlimit;
4088
4089 my_err = getrlimit( RLIMIT_NOFILE, &my_current_rlimit );
4090 if ( my_err == -1 ) {
4091 printf( "getrlimit - failed with errno %d - %s \n", errno, strerror( errno ) );
4092 goto test_failed_exit;
4093 }
4094 if ( my_current_rlimit.rlim_cur != RLIM_INFINITY ) {
4095 if ( my_current_rlimit.rlim_cur != my_current_rlimit.rlim_max )
4096 my_current_rlimit.rlim_cur += 1;
4097 else
4098 my_current_rlimit.rlim_cur -= 1;
4099 my_rlimit.rlim_cur = my_current_rlimit.rlim_cur;
4100 my_rlimit.rlim_max = my_current_rlimit.rlim_max;
4101 my_err = setrlimit( RLIMIT_NOFILE, &my_rlimit );
4102 if ( my_err == -1 ) {
4103 printf( "setrlimit - failed with errno %d - %s \n", errno, strerror( errno ) );
4104 goto test_failed_exit;
4105 }
4106
4107 /* verify that we set a new limit */
4108 bzero( (void *) &my_rlimit, sizeof( my_rlimit ) );
4109 my_err = getrlimit( RLIMIT_NOFILE, &my_rlimit );
4110 if ( my_err == -1 ) {
4111 printf( "getrlimit - failed with errno %d - %s \n", errno, strerror( errno ) );
4112 goto test_failed_exit;
4113 }
4114 if ( my_rlimit.rlim_cur != my_current_rlimit.rlim_cur ) {
4115 printf( "failed to get/set new RLIMIT_NOFILE soft limit \n" );
4116 printf( "soft limits - current %lld should be %lld \n", my_rlimit.rlim_cur, my_current_rlimit.rlim_cur );
4117 goto test_failed_exit;
4118 }
4119
4120 #if CONFORMANCE_CHANGES_IN_XNU // can't do this check until conformance changes get into xnu
4121 printf( "hard limits - current %lld should be %lld \n", my_rlimit.rlim_max, my_current_rlimit.rlim_max );
4122 if ( my_rlimit.rlim_max != my_current_rlimit.rlim_max ) {
4123 printf( "failed to get/set new RLIMIT_NOFILE hard limit \n" );
4124 goto test_failed_exit;
4125 }
4126 #endif
4127
4128 /*
4129 * A test for a limit that won't fit in a signed 32 bits, a la 5414697
4130 * Note: my_rlimit should still have a valid rlim_max.
4131 */
4132 long long biglim = 2147483649ll; /* Just over 2^31 */
4133 my_rlimit.rlim_cur = biglim;
4134 my_err = setrlimit(RLIMIT_CPU, &my_rlimit);
4135 if (my_err == -1) {
4136 printf("failed to set large limit.\n");
4137 goto test_failed_exit;
4138 }
4139
4140 bzero(&my_rlimit, sizeof(struct rlimit));
4141 my_err = getrlimit(RLIMIT_CPU, &my_rlimit);
4142 if (my_err == -1) {
4143 printf("after setting large value, failed to getrlimit().\n");
4144 goto test_failed_exit;
4145 }
4146
4147 if (my_rlimit.rlim_cur != biglim) {
4148 printf("didn't retrieve large limit.\n");
4149 goto test_failed_exit;
4150 }
4151 }
4152
4153 my_err = 0;
4154 goto test_passed_exit;
4155
4156 test_failed_exit:
4157 my_err = -1;
4158
4159 test_passed_exit:
4160 return( my_err );
4161 }
4162
4163 /* **************************************************************************************************************
4164 * Test getattrlist, getdirentriesattr, setattrlist system calls.
4165 * **************************************************************************************************************
4166 */
4167 struct test_attr_buf {
4168 uint32_t length;
4169 fsobj_type_t obj_type;
4170 fsobj_id_t obj_id;
4171 struct timespec backup_time;
4172 };
4173
4174 typedef struct test_attr_buf test_attr_buf;
4175
4176 int directory_tests( void * the_argp )
4177 {
4178 int my_err, done, found_it, i;
4179 int my_fd = -1;
4180 int is_ufs = 0;
4181 char * my_pathp = NULL;
4182 char * my_bufp = NULL;
4183 char * my_file_namep;
4184 #ifdef __LP64__
4185 unsigned int my_base;
4186 unsigned int my_count;
4187 unsigned int my_new_state;
4188 #else
4189 unsigned long my_base;
4190 unsigned long my_count;
4191 unsigned long my_new_state;
4192 #endif
4193 fsobj_id_t my_obj_id;
4194 struct timespec my_new_backup_time;
4195 struct attrlist my_attrlist;
4196 test_attr_buf my_attr_buf[4];
4197 struct statfs my_statfs_buf;
4198 kern_return_t my_kr;
4199
4200 /* need to know type of file system */
4201 my_err = statfs( &g_target_path[0], &my_statfs_buf );
4202 if ( my_err == -1 ) {
4203 printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) );
4204 goto test_failed_exit;
4205 }
4206 if ( memcmp( &my_statfs_buf.f_fstypename[0], "ufs", 3 ) == 0 ) {
4207 is_ufs = 1;
4208 }
4209
4210 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufp, (1024 * 5), VM_FLAGS_ANYWHERE);
4211 if(my_kr != KERN_SUCCESS){
4212 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4213 goto test_failed_exit;
4214 }
4215
4216 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
4217 if(my_kr != KERN_SUCCESS){
4218 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4219 goto test_failed_exit;
4220 }
4221
4222 *my_pathp = 0x00;
4223 strcat( my_pathp, &g_target_path[0] );
4224 strcat( my_pathp, "/" );
4225
4226 /* create a test file */
4227 my_err = create_random_name( my_pathp, 1 );
4228 if ( my_err != 0 ) {
4229 goto test_failed_exit;
4230 }
4231
4232 /* get pointer to just the file name */
4233 my_file_namep = strrchr( my_pathp, '/' );
4234 my_file_namep++;
4235
4236 /* check out the test directory */
4237 my_fd = open( &g_target_path[0], (O_RDONLY), 0 );
4238 if ( my_fd == -1 ) {
4239 printf( "open failed with error %d - \"%s\" \n", errno, strerror( errno) );
4240 goto test_failed_exit;
4241 }
4242
4243 /* test get/setattrlist */
4244 memset( &my_attrlist, 0, sizeof(my_attrlist) );
4245 my_attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
4246 my_attrlist.commonattr = (ATTR_CMN_OBJTYPE | ATTR_CMN_OBJID | ATTR_CMN_BKUPTIME);
4247 my_err = getattrlist( my_pathp, &my_attrlist, &my_attr_buf[0], sizeof(my_attr_buf[0]), 0 );
4248
4249 if ( my_err != 0 ) {
4250 if ( errno == ENOTSUP && is_ufs ) {
4251 /* getattr calls not supported on ufs */
4252 my_err = 0;
4253 goto test_passed_exit;
4254 }
4255 printf( "getattrlist call failed. got errno %d - %s. \n", errno, strerror( errno ) );
4256 goto test_failed_exit;
4257 }
4258 /* validate returned data */
4259 if ( my_attr_buf[0].obj_type != VREG ) {
4260 printf( "getattrlist returned incorrect obj_type data. \n" );
4261 goto test_failed_exit;
4262 }
4263
4264 /* set new backup time */
4265 my_obj_id = my_attr_buf[0].obj_id;
4266 my_new_backup_time = my_attr_buf[0].backup_time;
4267 my_new_backup_time.tv_sec += 60;
4268 my_attr_buf[0].backup_time.tv_sec = my_new_backup_time.tv_sec;
4269 my_attrlist.commonattr = (ATTR_CMN_BKUPTIME);
4270 my_err = setattrlist( my_pathp, &my_attrlist, &my_attr_buf[0].backup_time, sizeof(my_attr_buf[0].backup_time), 0 );
4271 if ( my_err != 0 ) {
4272 printf( "setattrlist call failed. got errno %d - %s. \n", errno, strerror( errno ) );
4273 goto test_failed_exit;
4274 }
4275
4276 /* validate setattrlist using getdirentriesattr */
4277 close( my_fd );
4278 my_fd = open( &g_target_path[0], (O_RDONLY), 0 );
4279 if ( my_fd == -1 ) {
4280 printf( "open failed with error %d - \"%s\" \n", errno, strerror( errno) );
4281 goto test_failed_exit;
4282 }
4283 memset( &my_attrlist, 0, sizeof(my_attrlist) );
4284 memset( &my_attr_buf, 0, sizeof(my_attr_buf) );
4285 my_attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
4286 my_attrlist.commonattr = (ATTR_CMN_OBJTYPE | ATTR_CMN_OBJID | ATTR_CMN_BKUPTIME);
4287 my_count = 4;
4288 my_base = 0;
4289 my_err = getdirentriesattr( my_fd, &my_attrlist, &my_attr_buf[0], sizeof(my_attr_buf), &my_count,
4290 &my_base, &my_new_state, 0 );
4291 if ( my_err < 0 ) {
4292 printf( "getdirentriesattr call failed. got errno %d - %s. \n", errno, strerror( errno ) );
4293 goto test_failed_exit;
4294 }
4295
4296 found_it = 0;
4297 for ( i = 0; i < my_count; i++ ) {
4298 if ( my_attr_buf[i].obj_id.fid_objno == my_obj_id.fid_objno &&
4299 my_attr_buf[i].obj_id.fid_generation == my_obj_id.fid_generation ) {
4300 found_it = 1;
4301 if ( my_attr_buf[i].backup_time.tv_sec != my_new_backup_time.tv_sec ) {
4302 printf( "setattrlist failed to set backup time. \n" );
4303 goto test_failed_exit;
4304 }
4305 }
4306 }
4307 if ( found_it == 0 ) {
4308 printf( "getdirentriesattr failed to find test file. \n" );
4309 goto test_failed_exit;
4310 }
4311
4312 my_err = 0;
4313 goto test_passed_exit;
4314
4315 test_failed_exit:
4316 if(my_err != 0)
4317 my_err = -1;
4318
4319 test_passed_exit:
4320 if ( my_fd != -1 )
4321 close( my_fd );
4322 if ( my_pathp != NULL ) {
4323 remove( my_pathp );
4324 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
4325 }
4326 if ( my_bufp != NULL ) {
4327 vm_deallocate(mach_task_self(), (vm_address_t)my_bufp, (1024 * 5));
4328 }
4329 return( my_err );
4330 }
4331
4332 /* **************************************************************************************************************
4333 * Test exchangedata system calls.
4334 * **************************************************************************************************************
4335 */
4336 int exchangedata_test( void * the_argp )
4337 {
4338 int my_err;
4339 int my_fd1 = -1;
4340 int my_fd2 = -1;
4341 char * my_file1_pathp = NULL;
4342 char * my_file2_pathp = NULL;
4343 ssize_t my_result;
4344 char my_buffer[16];
4345 struct statfs my_statfs_buf;
4346 kern_return_t my_kr;
4347
4348 /* need to know type of file system */
4349 my_err = statfs( &g_target_path[0], &my_statfs_buf );
4350 if ( my_err == -1 ) {
4351 printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) );
4352 goto test_failed_exit;
4353 }
4354 if ( memcmp( &my_statfs_buf.f_fstypename[0], "ufs", 3 ) == 0 ) {
4355 /* ufs does not support exchangedata */
4356 my_err = 0;
4357 goto test_passed_exit;
4358 }
4359
4360 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_file1_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
4361 if(my_kr != KERN_SUCCESS){
4362 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4363 goto test_failed_exit;
4364 }
4365
4366 *my_file1_pathp = 0x00;
4367 strcat( my_file1_pathp, &g_target_path[0] );
4368 strcat( my_file1_pathp, "/" );
4369
4370 /* create a test file */
4371 my_err = create_random_name( my_file1_pathp, 1 );
4372 if ( my_err != 0 ) {
4373 printf( "create_random_name my_err: %d\n", my_err );
4374 goto test_failed_exit;
4375 }
4376 my_fd1 = open( my_file1_pathp, O_RDWR, 0 );
4377 if ( my_fd1 == -1 ) {
4378 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4379 goto test_failed_exit;
4380 }
4381 my_result = write( my_fd1, "11111111", 8 );
4382 if ( my_result == -1 ) {
4383 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4384 goto test_failed_exit;
4385 }
4386
4387 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_file2_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
4388 if(my_kr != KERN_SUCCESS){
4389 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4390 goto test_failed_exit;
4391 }
4392
4393 *my_file2_pathp = 0x00;
4394 strcat( my_file2_pathp, &g_target_path[0] );
4395 strcat( my_file2_pathp, "/" );
4396
4397 /* create a test file */
4398 my_err = create_random_name( my_file2_pathp, 1 );
4399 if ( my_err != 0 ) {
4400 printf( "create_random_name my_err: %d\n", my_err );
4401 goto test_failed_exit;
4402 }
4403 my_fd2 = open( my_file2_pathp, O_RDWR, 0 );
4404 if ( my_fd2 == -1 ) {
4405 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4406 goto test_failed_exit;
4407 }
4408 my_result = write( my_fd2, "22222222", 8 );
4409 if ( my_result == -1 ) {
4410 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4411 goto test_failed_exit;
4412 }
4413 close(my_fd1);
4414 my_fd1 = -1;
4415 close(my_fd2);
4416 my_fd2 = -1;
4417
4418 /* test exchangedata */
4419 my_err = exchangedata( my_file1_pathp, my_file2_pathp, 0 );
4420 if ( my_err == -1 ) {
4421 printf( "exchangedata failed with error %d - \"%s\" \n", errno, strerror( errno) );
4422 goto test_failed_exit;
4423 }
4424
4425 /* now validate exchange */
4426 my_fd1 = open( my_file1_pathp, O_RDONLY, 0 );
4427 if ( my_fd1 == -1 ) {
4428 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4429 goto test_failed_exit;
4430 }
4431 bzero( (void *)&my_buffer[0], sizeof(my_buffer) );
4432 my_result = read( my_fd1, &my_buffer[0], 8 );
4433 if ( my_result == -1 ) {
4434 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4435 goto test_failed_exit;
4436 }
4437
4438 if ( memcmp( &my_buffer[0], "22222222", 8 ) != 0 ) {
4439 printf( "exchangedata failed - incorrect data in file \n" );
4440 goto test_failed_exit;
4441 }
4442
4443 my_err = 0;
4444 goto test_passed_exit;
4445
4446 test_failed_exit:
4447 my_err = -1;
4448
4449 test_passed_exit:
4450 if ( my_fd1 != -1 )
4451 close( my_fd1 );
4452 if ( my_file1_pathp != NULL ) {
4453 remove( my_file1_pathp );
4454 vm_deallocate(mach_task_self(), (vm_address_t)my_file1_pathp, PATH_MAX);
4455 }
4456 if ( my_fd2 != -1 )
4457 close( my_fd2 );
4458 if ( my_file2_pathp != NULL ) {
4459 remove( my_file2_pathp );
4460 vm_deallocate(mach_task_self(), (vm_address_t)my_file2_pathp, PATH_MAX);
4461 }
4462 return( my_err );
4463 }
4464
4465
4466 /* **************************************************************************************************************
4467 * Test searchfs system calls.
4468 * **************************************************************************************************************
4469 */
4470
4471 struct packed_name_attr {
4472 u_int32_t size; /* Of the remaining fields */
4473 struct attrreference ref; /* Offset/length of name itself */
4474 char name[ PATH_MAX ];
4475 };
4476
4477 struct packed_attr_ref {
4478 u_int32_t size; /* Of the remaining fields */
4479 struct attrreference ref; /* Offset/length of attr itself */
4480 };
4481
4482 struct packed_result {
4483 u_int32_t size; /* Including size field itself */
4484 attrreference_t obj_name;
4485 struct fsobj_id obj_id;
4486 struct timespec obj_create_time;
4487 char room_for_name[ 64 ];
4488 };
4489 typedef struct packed_result packed_result;
4490 typedef struct packed_result * packed_result_p;
4491
4492 #define MAX_MATCHES 10
4493 #define MAX_EBUSY_RETRIES 20
4494
4495 int searchfs_test( void * the_argp )
4496 {
4497 int my_err, my_items_found = 0, my_ebusy_count;
4498 char * my_pathp = NULL;
4499 unsigned long my_matches;
4500 unsigned long my_search_options;
4501 struct fssearchblock my_search_blk;
4502 struct attrlist my_return_list;
4503 struct searchstate my_search_state;
4504 struct packed_name_attr my_info1;
4505 struct packed_attr_ref my_info2;
4506 packed_result my_result_buffer[ MAX_MATCHES ];
4507 struct statfs my_statfs_buf;
4508 kern_return_t my_kr;
4509
4510 /* need to know type of file system */
4511 my_err = statfs( &g_target_path[0], &my_statfs_buf );
4512 if ( my_err == -1 ) {
4513 printf( "statfs call failed. got errno %d - %s. \n", errno, strerror( errno ) );
4514 goto test_failed_exit;
4515 }
4516 if ( memcmp( &my_statfs_buf.f_fstypename[0], "ufs", 3 ) == 0 ) {
4517 /* ufs does not support exchangedata */
4518 my_err = 0;
4519 goto test_passed_exit;
4520 }
4521
4522 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
4523 if(my_kr != KERN_SUCCESS){
4524 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4525 goto test_failed_exit;
4526 }
4527
4528 *my_pathp = 0x00;
4529 strcat( my_pathp, &g_target_path[0] );
4530 strcat( my_pathp, "/" );
4531
4532 /* create test files */
4533 my_err = create_file_with_name( my_pathp, "foo", 0 );
4534 if ( my_err < 0 ) {
4535 printf( "failed to create a test file name in \"%s\" \n", my_pathp );
4536 goto test_failed_exit;
4537 }
4538
4539 my_err = create_file_with_name( my_pathp, "foobar", 0 );
4540 if ( my_err < 0 ) {
4541 printf( "failed to create a test file name in \"%s\" \n", my_pathp );
4542 goto test_failed_exit;
4543 }
4544
4545 my_err = create_file_with_name( my_pathp, "foofoo", 0 );
4546 if ( my_err < 0 ) {
4547 printf( "failed to create a test file name in \"%s\" \n", my_pathp );
4548 goto test_failed_exit;
4549 }
4550
4551 my_err = create_file_with_name( my_pathp, "xxxfoo", 0 );
4552 if ( my_err < 0 ) {
4553 printf( "failed to create a test file name in \"%s\" \n", my_pathp );
4554 goto test_failed_exit;
4555 }
4556
4557 /* EBUSY count updated below the catalogue_changed label */
4558 my_ebusy_count = 0;
4559
4560 catalogue_changed:
4561 /* search target volume for all file system objects with "foo" in the name */
4562 /* Set up the attributes we're searching on. */
4563 my_items_found = 0; /* Set this here in case we're completely restarting */
4564 my_search_blk.searchattrs.bitmapcount = ATTR_BIT_MAP_COUNT;
4565 my_search_blk.searchattrs.reserved = 0;
4566 my_search_blk.searchattrs.commonattr = ATTR_CMN_NAME;
4567 my_search_blk.searchattrs.volattr = 0;
4568 my_search_blk.searchattrs.dirattr = 0;
4569 my_search_blk.searchattrs.fileattr = 0;
4570 my_search_blk.searchattrs.forkattr = 0;
4571
4572 /* Set up the attributes we want for all returned matches. */
4573 /* Why is returnattrs a pointer instead of an embedded struct? */
4574 my_search_blk.returnattrs = &my_return_list;
4575 my_return_list.bitmapcount = ATTR_BIT_MAP_COUNT;
4576 my_return_list.reserved = 0;
4577 my_return_list.commonattr = ATTR_CMN_NAME | ATTR_CMN_OBJID | ATTR_CMN_CRTIME;
4578 my_return_list.volattr = 0;
4579 my_return_list.dirattr = 0;
4580 my_return_list.fileattr = 0;
4581 my_return_list.forkattr = 0;
4582
4583 /* Allocate a buffer for returned matches */
4584 my_search_blk.returnbuffer = my_result_buffer;
4585 my_search_blk.returnbuffersize = sizeof(my_result_buffer);
4586
4587 /* Pack the searchparams1 into a buffer */
4588 /* NOTE: A name appears only in searchparams1 */
4589 strcpy( my_info1.name, "foo" );
4590 my_info1.ref.attr_dataoffset = sizeof(struct attrreference);
4591 my_info1.ref.attr_length = strlen(my_info1.name) + 1;
4592 my_info1.size = sizeof(struct attrreference) + my_info1.ref.attr_length;
4593 my_search_blk.searchparams1 = &my_info1;
4594 my_search_blk.sizeofsearchparams1 = my_info1.size + sizeof(u_int32_t);
4595
4596 /* Pack the searchparams2 into a buffer */
4597 my_info2.size = sizeof(struct attrreference);
4598 my_info2.ref.attr_dataoffset = sizeof(struct attrreference);
4599 my_info2.ref.attr_length = 0;
4600 my_search_blk.searchparams2 = &my_info2;
4601 my_search_blk.sizeofsearchparams2 = sizeof(my_info2);
4602
4603 /* Maximum number of matches we want */
4604 my_search_blk.maxmatches = MAX_MATCHES;
4605
4606 /* Maximum time to search, per call */
4607 my_search_blk.timelimit.tv_sec = 1;
4608 my_search_blk.timelimit.tv_usec = 0;
4609
4610 my_search_options = (SRCHFS_START | SRCHFS_MATCHPARTIALNAMES |
4611 SRCHFS_MATCHFILES | SRCHFS_MATCHDIRS);
4612 do {
4613 char * my_end_ptr;
4614 char * my_ptr;
4615 int i;
4616
4617 my_err = searchfs( my_pathp, &my_search_blk, &my_matches, 0, my_search_options, &my_search_state );
4618 if ( my_err == -1 )
4619 my_err = errno;
4620 if ( (my_err == 0 || my_err == EAGAIN) && my_matches > 0 ) {
4621 /* Unpack the results */
4622 // printf("my_matches %d \n", my_matches);
4623 my_ptr = (char *) &my_result_buffer[0];
4624 my_end_ptr = (my_ptr + sizeof(my_result_buffer));
4625 for ( i = 0; i < my_matches; ++i ) {
4626 packed_result_p my_result_p = (packed_result_p) my_ptr;
4627 char * my_name_p;
4628
4629 /* see if we foound all our test files */
4630 my_name_p = (((char *)(&my_result_p->obj_name)) + my_result_p->obj_name.attr_dataoffset);
4631 if ( memcmp( my_name_p, "foo", 3 ) == 0 ||
4632 memcmp( my_name_p, "foobar", 6 ) == 0 ||
4633 memcmp( my_name_p, "foofoo", 6 ) == 0 ||
4634 memcmp( my_name_p, "xxxfoo", 6 ) == 0 ) {
4635 my_items_found++;
4636 }
4637 #if DEBUG
4638 printf("obj_name \"%.*s\" \n",
4639 (int) my_result_p->obj_name.attr_length,
4640 (((char *)(&my_result_p->obj_name)) +
4641 my_result_p->obj_name.attr_dataoffset));
4642 printf("size %d fid_objno %d fid_generation %d tv_sec 0x%02LX \n",
4643 my_result_p->size, my_result_p->obj_id.fid_objno,
4644 my_result_p->obj_id.fid_generation,
4645 my_result_p->obj_create_time.tv_sec);
4646 #endif
4647 my_ptr = (my_ptr + my_result_p->size);
4648 if (my_ptr > my_end_ptr)
4649 break;
4650 }
4651 }
4652
4653 /* EBUSY indicates catalogue change; retry a few times. */
4654 if ((my_err == EBUSY) && (my_ebusy_count++ < MAX_EBUSY_RETRIES)) {
4655 goto catalogue_changed;
4656 }
4657 if ( !(my_err == 0 || my_err == EAGAIN) ) {
4658 printf( "searchfs failed with error %d - \"%s\" \n", my_err, strerror( my_err) );
4659 }
4660 my_search_options &= ~SRCHFS_START;
4661 } while ( my_err == EAGAIN );
4662
4663 if ( my_items_found < 4 ) {
4664 printf( "searchfs failed to find all test files \n" );
4665 goto test_failed_exit;
4666 }
4667
4668 my_err = 0;
4669 goto test_passed_exit;
4670
4671 test_failed_exit:
4672 my_err = -1;
4673
4674 test_passed_exit:
4675 if ( my_pathp != NULL ) {
4676 char * my_ptr = (my_pathp + strlen( my_pathp ));
4677 strcat( my_pathp, "foo" );
4678 remove( my_pathp );
4679 *my_ptr = 0x00;
4680 strcat( my_pathp, "foobar" );
4681 remove( my_pathp );
4682 *my_ptr = 0x00;
4683 strcat( my_pathp, "foofoo" );
4684 remove( my_pathp );
4685 *my_ptr = 0x00;
4686 strcat( my_pathp, "xxxfoo" );
4687 remove( my_pathp );
4688 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
4689 }
4690 return( my_err );
4691 }
4692
4693
4694 #define AIO_TESTS_BUFFER_SIZE (1024 * 4000)
4695 #define AIO_TESTS_OUR_COUNT 5
4696 /* **************************************************************************************************************
4697 * Test aio_error, aio_read, aio_return, aio_suspend, aio_write, fcntl system calls.
4698 * **************************************************************************************************************
4699 */
4700 int aio_tests( void * the_argp )
4701 {
4702 int my_err, i;
4703 char * my_pathp;
4704 struct aiocb * my_aiocbp;
4705 ssize_t my_result;
4706 struct timespec my_timeout;
4707 int my_fd_list[ AIO_TESTS_OUR_COUNT ];
4708 char * my_buffers[ AIO_TESTS_OUR_COUNT ];
4709 struct aiocb * my_aiocb_list[ AIO_TESTS_OUR_COUNT ];
4710 struct aiocb my_aiocbs[ AIO_TESTS_OUR_COUNT ];
4711 char * my_file_paths[ AIO_TESTS_OUR_COUNT ];
4712 kern_return_t my_kr;
4713
4714 /* set up to have the ability to fire off up to AIO_TESTS_OUR_COUNT async IOs at once */
4715 memset( &my_fd_list[0], 0xFF, sizeof( my_fd_list ) );
4716 memset( &my_buffers[0], 0x00, sizeof( my_buffers ) );
4717 memset( &my_aiocb_list[0], 0x00, sizeof( my_aiocb_list ) );
4718 memset( &my_file_paths[0], 0x00, sizeof( my_file_paths ) );
4719 for ( i = 0; i < AIO_TESTS_OUR_COUNT; i++ ) {
4720 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_buffers[ i ], AIO_TESTS_BUFFER_SIZE, VM_FLAGS_ANYWHERE);
4721 if(my_kr != KERN_SUCCESS){
4722 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4723 goto test_failed_exit;
4724 }
4725
4726 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_file_paths[ i ], PATH_MAX, VM_FLAGS_ANYWHERE);
4727 if(my_kr != KERN_SUCCESS){
4728 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
4729 goto test_failed_exit;
4730 }
4731
4732 my_pathp = my_file_paths[ i ];
4733 *my_pathp = 0x00;
4734 strcat( my_pathp, &g_target_path[0] );
4735 strcat( my_pathp, "/" );
4736
4737 /* create a test file */
4738 my_err = create_random_name( my_pathp, 1 );
4739 if ( my_err != 0 ) {
4740 goto test_failed_exit;
4741 }
4742 my_fd_list[ i ] = open( my_pathp, O_RDWR, 0 );
4743 if ( my_fd_list[ i ] <= 0 ) {
4744 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4745 goto test_failed_exit;
4746 }
4747
4748 my_aiocbp = &my_aiocbs[ i ];
4749 my_aiocb_list[ i ] = my_aiocbp;
4750 memset( my_aiocbp, 0x00, sizeof( *my_aiocbp ) );
4751 my_aiocbp->aio_fildes = my_fd_list[ i ];
4752 my_aiocbp->aio_buf = (char *) my_buffers[ i ];
4753 my_aiocbp->aio_nbytes = 1024;
4754 my_aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE; // no signals at completion;
4755 my_aiocbp->aio_sigevent.sigev_signo = 0;
4756 }
4757
4758 /* test direct IO (F_NOCACHE) and aio_write */
4759 my_err = fcntl( my_fd_list[ 0 ], F_NOCACHE, 1 );
4760 if ( my_err != 0 ) {
4761 printf( "malloc failed with error %d - \"%s\" \n", errno, strerror( errno) );
4762 goto test_failed_exit;
4763 }
4764
4765 my_aiocbp = &my_aiocbs[ 0 ];
4766 my_aiocbp->aio_fildes = my_fd_list[ 0 ];
4767 my_aiocbp->aio_offset = 4096;
4768 my_aiocbp->aio_buf = my_buffers[ 0 ];
4769 my_aiocbp->aio_nbytes = AIO_TESTS_BUFFER_SIZE;
4770 my_aiocbp->aio_reqprio = 0;
4771 my_aiocbp->aio_sigevent.sigev_notify = 0;
4772 my_aiocbp->aio_sigevent.sigev_signo = 0;
4773 my_aiocbp->aio_sigevent.sigev_value.sival_int = 0;
4774 my_aiocbp->aio_sigevent.sigev_notify_function = NULL;
4775 my_aiocbp->aio_sigevent.sigev_notify_attributes = NULL;
4776 my_aiocbp->aio_lio_opcode = 0;
4777
4778 /* write some data */
4779 memset( my_buffers[ 0 ], 'j', AIO_TESTS_BUFFER_SIZE );
4780 my_err = aio_write( my_aiocbp );
4781 if ( my_err != 0 ) {
4782 printf( "aio_write failed with error %d - \"%s\" \n", my_err, strerror( my_err) );
4783 goto test_failed_exit;
4784 }
4785
4786 while ( 1 ) {
4787 my_err = aio_error( my_aiocbp );
4788 if ( my_err == EINPROGRESS ) {
4789 /* wait for IO to complete */
4790 sleep( 1 );
4791 continue;
4792 }
4793 else if ( my_err == 0 ) {
4794 ssize_t my_result;
4795 my_result = aio_return( my_aiocbp );
4796 break;
4797 }
4798 else {
4799 printf( "aio_error failed with error %d - \"%s\" \n", my_err, strerror( my_err ) );
4800 goto test_failed_exit;
4801 }
4802 } /* while loop */
4803
4804 /* read some data */
4805 memset( my_buffers[ 0 ], 'x', AIO_TESTS_BUFFER_SIZE );
4806 my_err = aio_read( my_aiocbp );
4807
4808 while ( 1 ) {
4809 my_err = aio_error( my_aiocbp );
4810 if ( my_err == EINPROGRESS ) {
4811 /* wait for IO to complete */
4812 sleep( 1 );
4813 continue;
4814 }
4815 else if ( my_err == 0 ) {
4816 ssize_t my_result;
4817 my_result = aio_return( my_aiocbp );
4818
4819 if ( *(my_buffers[ 0 ]) != 'j' || *(my_buffers[ 0 ] + AIO_TESTS_BUFFER_SIZE - 1) != 'j' ) {
4820 printf( "aio_read or aio_write failed - wrong data read \n" );
4821 goto test_failed_exit;
4822 }
4823 break;
4824 }
4825 else {
4826 printf( "aio_read failed with error %d - \"%s\" \n", my_err, strerror( my_err ) );
4827 goto test_failed_exit;
4828 }
4829 } /* while loop */
4830
4831 /* test aio_fsync */
4832 close( my_fd_list[ 0 ] );
4833 my_fd_list[ 0 ] = open( my_pathp, O_RDWR, 0 );
4834 if ( my_fd_list[ 0 ] == -1 ) {
4835 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4836 goto test_failed_exit;
4837 }
4838
4839 my_aiocbp = &my_aiocbs[ 0 ];
4840 my_aiocbp->aio_fildes = my_fd_list[ 0 ];
4841 my_aiocbp->aio_offset = 0;
4842 my_aiocbp->aio_buf = my_buffers[ 0 ];
4843 my_aiocbp->aio_nbytes = 1024;
4844 my_aiocbp->aio_reqprio = 0;
4845 my_aiocbp->aio_sigevent.sigev_notify = 0;
4846 my_aiocbp->aio_sigevent.sigev_signo = 0;
4847 my_aiocbp->aio_sigevent.sigev_value.sival_int = 0;
4848 my_aiocbp->aio_sigevent.sigev_notify_function = NULL;
4849 my_aiocbp->aio_sigevent.sigev_notify_attributes = NULL;
4850 my_aiocbp->aio_lio_opcode = 0;
4851
4852 /* write some data */
4853 memset( my_buffers[ 0 ], 'e', 1024 );
4854 my_err = aio_write( my_aiocbp );
4855 if ( my_err != 0 ) {
4856 printf( "aio_write failed with error %d - \"%s\" \n", my_err, strerror( my_err) );
4857 goto test_failed_exit;
4858 }
4859 while ( 1 ) {
4860 my_err = aio_error( my_aiocbp );
4861 if ( my_err == EINPROGRESS ) {
4862 /* wait for IO to complete */
4863 sleep( 1 );
4864 continue;
4865 }
4866 else if ( my_err == 0 ) {
4867 ssize_t my_result;
4868 my_result = aio_return( my_aiocbp );
4869 break;
4870 }
4871 else {
4872 printf( "aio_error failed with error %d - \"%s\" \n", my_err, strerror( my_err ) );
4873 goto test_failed_exit;
4874 }
4875 } /* while loop */
4876
4877 my_err = aio_fsync( O_SYNC, my_aiocbp );
4878 if ( my_err != 0 ) {
4879 printf( "aio_fsync failed with error %d - \"%s\" \n", my_err, strerror( my_err) );
4880 goto test_failed_exit;
4881 }
4882 while ( 1 ) {
4883 my_err = aio_error( my_aiocbp );
4884 if ( my_err == EINPROGRESS ) {
4885 /* wait for IO to complete */
4886 sleep( 1 );
4887 continue;
4888 }
4889 else if ( my_err == 0 ) {
4890 aio_return( my_aiocbp );
4891 break;
4892 }
4893 else {
4894 printf( "aio_error failed with error %d - \"%s\" \n", my_err, strerror( my_err ) );
4895 goto test_failed_exit;
4896 }
4897 } /* while loop */
4898
4899 /* validate write */
4900 memset( my_buffers[ 0 ], 0x20, 16 );
4901 lseek( my_fd_list[ 0 ], 0, SEEK_SET );
4902 my_result = read( my_fd_list[ 0 ], my_buffers[ 0 ], 16);
4903 if ( my_result == -1 ) {
4904 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4905 goto test_failed_exit;
4906 }
4907 if ( *(my_buffers[ 0 ]) != 'e' || *(my_buffers[ 0 ] + 16 - 1) != 'e' ) {
4908 printf( "aio_fsync or aio_write failed - wrong data read \n" );
4909 goto test_failed_exit;
4910 }
4911
4912 /* test aio_suspend and lio_listio */
4913 for ( i = 0; i < AIO_TESTS_OUR_COUNT; i++ ) {
4914 memset( my_buffers[ i ], 'a', AIO_TESTS_BUFFER_SIZE );
4915 my_aiocbp = &my_aiocbs[ i ];
4916 my_aiocbp->aio_nbytes = AIO_TESTS_BUFFER_SIZE;
4917 my_aiocbp->aio_lio_opcode = LIO_WRITE;
4918 }
4919 my_err = lio_listio( LIO_NOWAIT, my_aiocb_list, AIO_TESTS_OUR_COUNT, NULL );
4920 if ( my_err != 0 ) {
4921 printf( "lio_listio call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4922 goto test_failed_exit;
4923 }
4924
4925 my_timeout.tv_sec = 1;
4926 my_timeout.tv_nsec = 0;
4927 my_err = aio_suspend( (const struct aiocb *const*) my_aiocb_list, AIO_TESTS_OUR_COUNT, &my_timeout );
4928 if ( my_err != 0 ) {
4929 printf( "aio_suspend call failed with error %d - \"%s\" \n", errno, strerror( errno) );
4930 goto test_failed_exit;
4931 }
4932
4933 /* test aio_cancel */
4934 for ( i = 0; i < AIO_TESTS_OUR_COUNT; i++ ) {
4935 my_aiocbp = &my_aiocbs[ i ];
4936 my_err = aio_cancel( my_aiocbp->aio_fildes, my_aiocbp );
4937 if ( my_err != AIO_ALLDONE && my_err != AIO_CANCELED && my_err != AIO_NOTCANCELED ) {
4938 printf( "aio_cancel failed with error %d - \"%s\" \n", my_err, strerror( my_err) );
4939 goto test_failed_exit;
4940 }
4941 }
4942
4943 my_err = 0;
4944 goto test_passed_exit;
4945
4946 test_failed_exit:
4947 my_err = -1;
4948
4949 test_passed_exit:
4950 for ( i = 0; i < AIO_TESTS_OUR_COUNT; i++ ) {
4951 if ( my_fd_list[ i ] != -1 ) {
4952 close( my_fd_list[ i ] );
4953 my_fd_list[ i ] = -1;
4954 }
4955 if ( my_file_paths[ i ] != NULL ) {
4956 remove( my_file_paths[ i ] );
4957 vm_deallocate(mach_task_self(), (vm_address_t)my_file_paths[ i ], PATH_MAX);
4958 my_file_paths[ i ] = NULL;
4959 }
4960 if ( my_buffers[ i ] != NULL ) {
4961 vm_deallocate(mach_task_self(), (vm_address_t)my_buffers[ i ], AIO_TESTS_BUFFER_SIZE);
4962 my_buffers[ i ] = NULL;
4963 }
4964 }
4965 return( my_err );
4966 }
4967
4968
4969 /* **************************************************************************************************************
4970 * Test msgctl, msgget, msgrcv, msgsnd system calls.
4971 * **************************************************************************************************************
4972 */
4973 int message_queue_tests( void * the_argp )
4974 {
4975 int my_err;
4976 int my_msg_queue_id = -1;
4977 ssize_t my_result;
4978 struct msqid_ds my_msq_ds;
4979 struct testing_msq_message {
4980 long msq_type;
4981 char msq_buffer[ 32 ];
4982 } my_msg;
4983
4984 /* get a message queue established for our use */
4985 my_msg_queue_id = msgget( IPC_PRIVATE, (IPC_CREAT | IPC_EXCL | IPC_R | IPC_W) );
4986 if ( my_msg_queue_id == -1 ) {
4987 printf( "msgget failed with errno %d - %s \n", errno, strerror( errno ) );
4988 goto test_failed_exit;
4989 }
4990
4991 /* get some stats on our message queue */
4992 my_err = msgctl( my_msg_queue_id, IPC_STAT, &my_msq_ds );
4993 if ( my_err == -1 ) {
4994 printf( "msgctl failed with errno %d - %s \n", errno, strerror( errno ) );
4995 goto test_failed_exit;
4996 }
4997 if ( my_msq_ds.msg_perm.cuid != geteuid( ) ) {
4998 printf( "msgctl IPC_STAT failed to get correct creator uid \n" );
4999 goto test_failed_exit;
5000 }
5001 if ( (my_msq_ds.msg_perm.mode & (IPC_R | IPC_W)) == 0 ) {
5002 printf( "msgctl IPC_STAT failed to get correct mode \n" );
5003 goto test_failed_exit;
5004 }
5005
5006 /* put a message into our queue */
5007 my_msg.msq_type = 1;
5008 strcpy( &my_msg.msq_buffer[ 0 ], "testing 1, 2, 3" );
5009 my_err = msgsnd( my_msg_queue_id, &my_msg, sizeof( my_msg.msq_buffer ), 0 );
5010 if ( my_err == -1 ) {
5011 printf( "msgsnd failed with errno %d - %s \n", errno, strerror( errno ) );
5012 goto test_failed_exit;
5013 }
5014
5015 my_err = msgctl( my_msg_queue_id, IPC_STAT, &my_msq_ds );
5016 if ( my_err == -1 ) {
5017 printf( "msgctl failed with errno %d - %s \n", errno, strerror( errno ) );
5018 goto test_failed_exit;
5019 }
5020 if ( my_msq_ds.msg_qnum != 1 ) {
5021 printf( "msgctl IPC_STAT failed to get correct number of messages on the queue \n" );
5022 goto test_failed_exit;
5023 }
5024
5025 /* pull message off the queue */
5026 bzero( (void *)&my_msg, sizeof( my_msg ) );
5027 my_result = msgrcv( my_msg_queue_id, &my_msg, sizeof( my_msg.msq_buffer ), 0, 0 );
5028 if ( my_result == -1 ) {
5029 printf( "msgrcv failed with errno %d - %s \n", errno, strerror( errno ) );
5030 goto test_failed_exit;
5031 }
5032 if ( my_result != sizeof( my_msg.msq_buffer ) ) {
5033 printf( "msgrcv failed to return the correct number of bytes in our buffer \n" );
5034 goto test_failed_exit;
5035 }
5036 if ( strcmp( &my_msg.msq_buffer[ 0 ], "testing 1, 2, 3" ) != 0 ) {
5037 printf( "msgrcv failed to get the correct message \n" );
5038 goto test_failed_exit;
5039 }
5040
5041 my_err = msgctl( my_msg_queue_id, IPC_STAT, &my_msq_ds );
5042 if ( my_err == -1 ) {
5043 printf( "msgctl failed with errno %d - %s \n", errno, strerror( errno ) );
5044 goto test_failed_exit;
5045 }
5046 if ( my_msq_ds.msg_qnum != 0 ) {
5047 printf( "msgctl IPC_STAT failed to get correct number of messages on the queue \n" );
5048 goto test_failed_exit;
5049 }
5050
5051 /* tear down the message queue */
5052 my_err = msgctl( my_msg_queue_id, IPC_RMID, NULL );
5053 if ( my_err == -1 ) {
5054 printf( "msgctl IPC_RMID failed with errno %d - %s \n", errno, strerror( errno ) );
5055 goto test_failed_exit;
5056 }
5057 my_msg_queue_id = -1;
5058
5059 my_err = 0;
5060 goto test_passed_exit;
5061
5062 test_failed_exit:
5063 my_err = -1;
5064
5065 test_passed_exit:
5066 if ( my_msg_queue_id != -1 ) {
5067 msgctl( my_msg_queue_id, IPC_RMID, NULL );
5068 }
5069 return( my_err );
5070 }
5071
5072
5073
5074 /* **************************************************************************************************************
5075 * Test execution from data and stack areas.
5076 * **************************************************************************************************************
5077 */
5078 int data_exec_tests( void * the_argp )
5079 {
5080 int my_err = 0;
5081 int arch, bits;
5082 posix_spawnattr_t attrp;
5083 char *argv[] = { "helpers/data_exec32nonxspawn", NULL };
5084
5085 int my_pid, my_status, ret;
5086
5087 if ((arch = get_architecture()) == -1) {
5088 printf("data_exec_test: couldn't determine architecture\n");
5089 goto test_failed_exit;
5090 }
5091
5092 bits = get_bits();
5093
5094 /*
5095 * If the machine is 64-bit capable, run both the 32 and 64 bit versions of the test.
5096 * Otherwise, just run the 32-bit version.
5097 */
5098
5099 if (arch == INTEL) {
5100 if (bits == 64) {
5101 if (system("arch -arch x86_64 helpers/data_exec") != 0) {
5102 printf("data_exec-x86_64 failed\n");
5103 goto test_failed_exit;
5104 }
5105 }
5106
5107 if (system("arch -arch i386 helpers/data_exec") != 0) {
5108 printf("data_exec-i386 failed\n");
5109 goto test_failed_exit;
5110 }
5111
5112 posix_spawnattr_init(&attrp);
5113 posix_spawnattr_setflags(&attrp, _POSIX_SPAWN_ALLOW_DATA_EXEC );
5114 ret = posix_spawn(&my_pid, "helpers/data_exec32nonxspawn", NULL, &attrp, argv, NULL);
5115 if (ret) {
5116 printf("data_exec-i386 failed in posix_spawn %s\n", strerror(errno));
5117 goto test_failed_exit;
5118 }
5119 ret = wait4(my_pid, &my_status, 0, NULL);
5120 if (ret == -1) {
5121 printf("data_exec-i386 wait4 failed with errno %d - %s\n", errno, strerror(errno));
5122 goto test_failed_exit;
5123 }
5124 if (WEXITSTATUS(my_status) != 0) {
5125 printf("data_exec-i386 _POSIX_SPAWN_ALLOW_DATA_EXEC failed\n");
5126 goto test_failed_exit;
5127 }
5128 }
5129
5130 /* Add new architectures here similar to the above. */
5131
5132 goto test_passed_exit;
5133
5134 test_failed_exit:
5135 my_err = -1;
5136
5137 test_passed_exit:
5138 return my_err;
5139 }
5140
5141 /* **************************************************************************************************************
5142 * Test KASLR-related functionality
5143 * **************************************************************************************************************
5144 */
5145 int kaslr_test( void * the_argp )
5146 {
5147 int result = 0;
5148 uint64_t slide = 0;
5149 size_t size;
5150 int slide_enabled;
5151
5152 size = sizeof(slide_enabled);
5153 result = sysctlbyname("kern.slide", &slide_enabled, &size, NULL, 0);
5154 if (result != 0) {
5155 printf("sysctlbyname(\"kern.slide\") failed with errno %d\n", errno);
5156 goto test_failed_exit;
5157 }
5158
5159 /* Test positive case first */
5160 size = sizeof(slide);
5161 result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size);
5162 if (result == 0) {
5163 /* syscall supported, slide must be non-zero if running latest xnu and KASLR is enabled */
5164 if (slide_enabled && (slide == 0)) {
5165 printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size) reported slide of 0x%016llx\n", slide);
5166 goto test_failed_exit;
5167 }
5168 if (size != sizeof(slide)) {
5169 printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size) reported size of %lu\n", size);
5170 goto test_failed_exit;
5171 }
5172 } else {
5173 /* Only ENOTSUP is allowed. If so, assume all calls will be unsupported */
5174 if (errno == ENOTSUP) {
5175 return 0;
5176 } else {
5177 printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size) returned unexpected errno (errno %d)\n", errno);
5178 goto test_failed_exit;
5179 }
5180 }
5181
5182 /* Negative cases for expected failures */
5183 size = sizeof(slide);
5184 result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL /* EFAULT */, &size);
5185 if ((result == 0) || (errno != EFAULT)) {
5186 printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, &size) returned unexpected success or errno (result %d errno %d)\n", result, errno);
5187 goto test_failed_exit;
5188 }
5189
5190 size = sizeof(slide) + 1; /* EINVAL */
5191 result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, &size);
5192 if ((result == 0) || (errno != EINVAL)) {
5193 printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, &size+1) returned unexpected success or errno (result %d errno %d)\n", result, errno);
5194 goto test_failed_exit;
5195 }
5196
5197 result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL /* EFAULT */, NULL /* EFAULT */);
5198 if ((result == 0) || (errno != EFAULT)) {
5199 printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, NULL) returned unexpected success or errno (result %d errno %d)\n", result, errno);
5200 goto test_failed_exit;
5201 }
5202
5203 size = sizeof(slide);
5204 result = kas_info(KAS_INFO_MAX_SELECTOR /* EINVAL */, &slide, &size);
5205 if ((result == 0) || (errno != EINVAL)) {
5206 printf("kas_info(KAS_INFO_MAX_SELECTOR, &slide, &size) returned unexpected success or errno (result %d errno %d)\n", result, errno);
5207 goto test_failed_exit;
5208 }
5209
5210 return 0;
5211
5212 test_failed_exit:
5213 return -1;
5214 }
5215
5216 typedef struct attrs {
5217 uint32_t attrs_length;
5218 attribute_set_t attrs_returned;
5219 uint32_t attr_error;
5220 attrreference_t attr_name;
5221 fsobj_type_t attr_obj_type;
5222
5223 union {
5224 struct {
5225 uint32_t entry_count;
5226 } directory;
5227 struct {
5228 off_t size;
5229 } file;
5230 } attr_obj;
5231
5232 } attrs_t;
5233
5234 int getattrlistbulk_test( void * the_argp )
5235 {
5236
5237 int error;
5238 struct attrlist attr_list;
5239 attrs_t *attrsptr;
5240 char *entry_start;
5241 int retcount = 0, totalcount = 0;
5242 int index;
5243 char *nameptr;
5244 int attr_buf_size;
5245 char *attr_buf;
5246 int dirfd = -1;
5247 char* target = "/System/Library/CoreServices";
5248
5249 memset(&attr_list, 0, sizeof(attr_list));
5250 attr_list.bitmapcount = ATTR_BIT_MAP_COUNT;
5251 attr_list.commonattr = ATTR_CMN_RETURNED_ATTRS |
5252 ATTR_CMN_NAME |
5253 ATTR_CMN_OBJTYPE |
5254 ATTR_CMN_ERROR |
5255 ATTR_FILE_TOTALSIZE|
5256 ATTR_DIR_ENTRYCOUNT;
5257
5258 error = 0;
5259 /*allocate a buffer for 10 items*/
5260 attr_buf_size = 10 * (sizeof(attrs_t) + FILENAME_MAX );
5261 if (vm_allocate((vm_map_t) mach_task_self(),
5262 (vm_address_t*)&attr_buf,
5263 attr_buf_size, VM_FLAGS_ANYWHERE) != KERN_SUCCESS) {
5264 printf( "vm_allocate failed with error %d - \"%s\" \n",
5265 errno, strerror( errno) );
5266 attr_buf = NULL;
5267 error = -1;
5268 goto last_exit;
5269 }
5270
5271 dirfd = openat (AT_FDCWD, target, O_RDONLY, 0);
5272 if (dirfd == -1) {
5273 printf("openat \"%s\" failed with error %d - \"%s\" \n",
5274 target, errno, strerror( errno));
5275 error = -1;
5276 goto last_exit;
5277 }
5278
5279 do {
5280 retcount = getattrlistbulk(dirfd,
5281 &attr_list, &attr_buf[0],
5282 attr_buf_size, FSOPT_PACK_INVAL_ATTRS);
5283 if (retcount == -1) {
5284 printf("getattrlistbulk on %s returned %d items\n",
5285 target, totalcount);
5286 printf("getattrlistbulk failed with error %d - \"%s\" \n",
5287 errno, strerror( errno));
5288 error = -1;
5289 break;
5290 } else if (retcount == 0) {
5291 /* No more entries in directory */
5292 printf("getattrlistbulk succeded: found %d entries in %s\n", totalcount, target);
5293 error = 0;
5294 break;
5295 } else {
5296 totalcount += retcount;
5297 entry_start = &attr_buf[0];
5298 for (index = 0; index < retcount; index++) {
5299 /*set attrsptr to item record buffer*/
5300 attrsptr = (attrs_t *)entry_start;
5301
5302 /*
5303 *calculate starting point for next item in bulk
5304 *list
5305 */
5306 entry_start += attrsptr->attrs_length;
5307
5308 if ((attrsptr->attrs_returned.commonattr & ATTR_CMN_ERROR) &&
5309 attrsptr->attr_error) {
5310 nameptr = (char*)(&(attrsptr->attr_name)) + attrsptr->attr_name.attr_dataoffset;
5311 printf("getattrlistbulk item \"%s\" ATTR_CMN_ERROR %d \"%s\"\n",
5312 nameptr, attrsptr->attr_error,
5313 strerror(attrsptr->attr_error));
5314 }
5315 }
5316 }
5317 } while (1);
5318
5319 last_exit:
5320 if (dirfd != -1) {
5321 (void)close(dirfd);
5322 }
5323
5324 if (attr_buf != NULL) {
5325 vm_deallocate(
5326 mach_task_self(), (vm_address_t)attr_buf, attr_buf_size);
5327 }
5328
5329 return error;
5330 }
5331
5332 #define INVALID_FD -173
5333 static int create_random_name_at(int the_dirfd, char *the_dirpathp,
5334 char *the_namep, size_t the_namep_len,
5335 char *the_pathp, size_t the_pathp_len,
5336 int do_create );
5337 /*
5338 * create_random_name_at - creates a file with a random / unique name in the given directory.
5339 * when do_create is true we create a file else we generaate a name that does not exist in the
5340 * given directory (we do not create anything when do_open is 0).
5341 * A name is generated relative to the directory fd. If both a directory path and
5342 * and a buffer to hold the full pathname are provided, an abolute pathname is also returned.
5343 * An absolute pathname for the generated filename is returned in my_pathp.
5344 * WARNING - caller provides enough space in the_namep buffer for longest possible name (NAME_MAX).
5345 * WARNING - caller provides enough space in the_pathp buffer for longest possible path (PATH_MAX).
5346 * RAND_MAX is currently 2147483647 (ten characters plus one for a slash)
5347 */
5348 int create_random_name_at(int the_dirfd, char *the_dirpathp,
5349 char *the_namep, size_t the_namep_len,
5350 char *the_pathp, size_t the_pathp_len,
5351 int do_create )
5352 {
5353 int i, my_err;
5354 int my_fd = -1;
5355
5356 for ( i = 0; i < 1; i++ ) {
5357 int my_rand;
5358 char *myp;
5359 char my_name[32];
5360
5361 my_rand = rand( );
5362 sprintf( &my_name[0], "%d", my_rand );
5363 if ( (strlen( &my_name[0] ) + strlen( the_dirpathp ) + 2) > PATH_MAX ) {
5364 printf( "%s - path to test file greater than PATH_MAX \n", __FUNCTION__ );
5365 return( -1 );
5366 }
5367
5368 // generate name and absolute path
5369 myp = the_namep;
5370 *(myp) = (char)0x00;
5371 strlcat(the_namep, &my_name[0], the_namep_len);
5372
5373 /*
5374 *If the caller has passed in a path pointer and directory path
5375 *it means an absolute path is to be returned as well.
5376 */
5377 if (the_pathp && the_dirpathp) {
5378 *the_pathp = (char)0x00;
5379 strlcat(the_pathp, the_dirpathp, the_pathp_len);
5380 strlcat(the_pathp, "/", the_pathp_len);
5381 strlcat(the_pathp, the_namep, the_pathp_len);
5382 }
5383
5384 if (do_create) {
5385 /* create a file with this name */
5386 my_fd = openat( the_dirfd, the_namep, (O_RDWR | O_CREAT | O_EXCL),
5387 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
5388 if ( my_fd == -1 ) {
5389 if ( errno != EEXIST ) {
5390 printf( "%s - open failed with errno %d - %s \n",
5391 __FUNCTION__, errno, strerror( errno ) );
5392 return( -1 );
5393 }
5394 // name already exists, try another
5395 i--;
5396 continue;
5397 }
5398 }
5399
5400 else {
5401 /* make sure the name is unique */
5402 struct stat my_sb;
5403 my_err = fstatat( the_dirfd, the_namep, &my_sb, 0 );
5404 if ( my_err != 0 ) {
5405 if ( errno == ENOENT ) {
5406 break;
5407 }
5408 else {
5409 printf( "%s - open failed with errno %d - %s \n",
5410 __FUNCTION__, errno, strerror( errno ) );
5411 return( -1 );
5412 }
5413 }
5414 /* name already exists, try another */
5415 i--;
5416 continue;
5417 }
5418 }
5419
5420 if ( my_fd != -1 )
5421 close( my_fd );
5422
5423 return( 0 );
5424
5425 } /* create_random_name_at */
5426
5427 /* **************************************************************************************************************
5428 * Test close, fpathconf, fstat, open, pathconf system calls.
5429 * **************************************************************************************************************
5430 */
5431 int openat_close_test( void * the_argp )
5432 {
5433 int my_err;
5434 int my_dirfd = -1;
5435 int my_fd = -1;
5436 int error_fd = -1;
5437 char * my_dirpathp = NULL;
5438 char * my_namep = NULL;
5439 char * my_pathp = NULL;
5440 ssize_t my_result;
5441 long my_pconf_result;
5442 struct stat my_sb;
5443 char my_buffer[32];
5444 kern_return_t my_kr;
5445
5446
5447 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_dirpathp, PATH_MAX, VM_FLAGS_ANYWHERE);
5448 if(my_kr != KERN_SUCCESS){
5449 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5450 goto test_failed_exit;
5451 }
5452
5453 *my_dirpathp = 0x00;
5454 strlcat( my_dirpathp, &g_target_path[0], PATH_MAX );
5455
5456 my_dirfd = openat(AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
5457 if ( my_dirfd == -1 ) {
5458 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5459 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
5460 goto test_failed_exit;
5461 }
5462
5463 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
5464 if(my_kr != KERN_SUCCESS){
5465 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5466 goto test_failed_exit;
5467 }
5468
5469 *my_namep = 0x00;
5470 if (my_pathp) {
5471 *my_pathp = 0x00;
5472 }
5473
5474 /* If dirpath is absolute, we can ask for an absolute path name to file back from create_random_name_at */
5475 if (*my_dirpathp == '/') {
5476 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
5477 if(my_kr != KERN_SUCCESS){
5478 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5479 goto test_failed_exit;
5480 }
5481 }
5482
5483 /*
5484 * Some basic openat validation. If pathname is absolute, invalid fd should
5485 * not matter.
5486 */
5487
5488 if (*my_dirpathp == '/') {
5489 my_dirfd = openat( INVALID_FD, my_dirpathp, O_RDONLY, 0 );
5490 if ( my_dirfd == -1 ) {
5491 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5492 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
5493 printf( "\t Was Absolute pathname, invalid fd, %d, provided as input \n", INVALID_FD);
5494 goto test_failed_exit;
5495 }
5496 close(my_dirfd);
5497
5498 }
5499
5500 my_dirfd = openat( AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
5501 if ( my_dirfd == -1 ) {
5502 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5503 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
5504 goto test_failed_exit;
5505 }
5506
5507 /* create a test file */
5508 my_err = create_random_name_at( my_dirfd, my_dirpathp, my_namep, NAME_MAX, my_pathp, PATH_MAX, 1 );
5509 if ( my_err != 0 ) {
5510 goto test_failed_exit;
5511 }
5512
5513 /*
5514 * If pathname is not absolute, an openat relative to a invalid directory fd
5515 * should not work.
5516 */
5517 if (my_pathp) {
5518 /* test O_WRONLY case */
5519 my_fd = openat( INVALID_FD, my_namep, O_WRONLY, 0 );
5520 if ( my_fd != -1 ) {
5521 printf( "openat call relative to invalid dir fd worked\n");
5522 printf( "\t file we attempted to open -> \"%s\" relative to fd -173\n", my_pathp );
5523 goto test_failed_exit;
5524 }
5525 }
5526
5527 /* test O_WRONLY case */
5528 my_fd = openat( my_dirfd, my_namep, O_WRONLY, 0 );
5529 if ( my_fd == -1 ) {
5530 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5531 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
5532 goto test_failed_exit;
5533 }
5534
5535 /*
5536 * try to open relative to non-directory fd.
5537 * It should fail with ENOTDIR.
5538 */
5539 if ((error_fd = openat(my_fd, my_namep, O_WRONLY, 0)) != -1) {
5540 printf( "openat call succeded with fd being a non-directory fd\n");
5541 printf( "\t file we attempted to open (reltive to itself)-> \"%s\" \n", my_pathp );
5542 close(error_fd);
5543 goto test_failed_exit;
5544 } else if (errno != ENOTDIR) {
5545 printf( "openat call should have failed with errno 20 (ENOTDIR). actually failed with %d - \"%s\" \n", my_err, strerror( my_err) );
5546 }
5547
5548 my_pconf_result = fpathconf( my_fd, _PC_NAME_MAX );
5549 if ( my_pconf_result == -1 ) {
5550 printf( "fpathconf - _PC_PATH_MAX - failed with error %d - \"%s\" \n", errno, strerror( errno) );
5551 goto test_failed_exit;
5552 }
5553 // printf( "_PC_NAME_MAX %ld \n", my_pconf_result );
5554 /* results look OK? */
5555 if ( my_pconf_result < 6 ) {
5556 printf( "fpathconf - _PC_NAME_MAX - looks like wrong results \n" );
5557 goto test_failed_exit;
5558 }
5559
5560 /* write some data then try to read it */
5561 my_result = write( my_fd, "kat", 3 );
5562 my_err = errno;
5563 if ( my_result != 3 ) {
5564 if ( sizeof( ssize_t ) > sizeof( int ) ) {
5565 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
5566 }
5567 else {
5568 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
5569 }
5570 goto test_failed_exit;
5571 }
5572
5573 /* Try to read - this should fail since we opened file with O_WRONLY */
5574 my_result = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
5575 my_err = errno;
5576 if ( my_result != -1 ) {
5577 printf( "read call should have failed with errno 9 (EBADF) \n" );
5578 goto test_failed_exit;
5579 }
5580 else if ( my_err != EBADF ) {
5581 printf( "read call should have failed with errno 9 (EBADF). actually failed with %d - \"%s\" \n", my_err, strerror( my_err) );
5582 goto test_failed_exit;
5583 }
5584
5585 close( my_fd );
5586
5587 /* test O_TRUNC and O_APPEND case */
5588 my_fd = openat( my_dirfd, my_namep, (O_RDWR | O_TRUNC | O_APPEND), 0 );
5589 if ( my_fd == -1 ) {
5590 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5591 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
5592 goto test_failed_exit;
5593 }
5594
5595 my_result = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
5596 if ( my_result == -1 ) {
5597 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5598 goto test_failed_exit;
5599 }
5600 if ( my_result != 0 ) {
5601 printf( "read failed - should have read 0 bytes. \n" );
5602 goto test_failed_exit;
5603 }
5604
5605 my_result = write( my_fd, "kat", 3 );
5606 my_err = errno;
5607 if ( my_result != 3 ) {
5608 if ( sizeof( ssize_t ) > sizeof( int ) ) {
5609 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
5610 }
5611 else {
5612 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
5613 }
5614 goto test_failed_exit;
5615 }
5616
5617 /* add some more data to the test file - this should be appended */
5618 lseek( my_fd, 0, SEEK_SET );
5619 my_result = write( my_fd, "zzz", 3 );
5620 my_err = errno;
5621 if ( my_result != 3 ) {
5622 if ( sizeof( ssize_t ) > sizeof( int ) ) {
5623 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
5624 }
5625 else {
5626 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
5627 }
5628 goto test_failed_exit;
5629 }
5630
5631 /* now verify the writes */
5632 bzero( (void *)&my_buffer[0], sizeof(my_buffer) );
5633 lseek( my_fd, 0, SEEK_SET );
5634 my_result = read( my_fd, &my_buffer[0], sizeof(my_buffer) );
5635 if ( my_result == -1 ) {
5636 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5637 goto test_failed_exit;
5638 }
5639 if ( my_buffer[0] != 'k' || my_buffer[5] != 'z' ) {
5640 printf( "read failed to get correct data \n" );
5641 goto test_failed_exit;
5642 }
5643
5644 /*
5645 * try to stat relative to non-directory fd.
5646 * It should fail with ENOTDIR.
5647 */
5648 if ((fstatat( my_fd, my_namep, &my_sb, 0 )) != -1) {
5649 printf( "fstatat call succeded with fd being a non-directory fd\n");
5650 printf( "\t file we attempted to stat (relative to itself)-> \"%s\" \n", my_pathp );
5651 goto test_failed_exit;
5652 } else if (errno != ENOTDIR) {
5653 printf( "fstatat call should have failed with errno 20 (ENOTDIR). actually failed with %d - \"%s\" \n", my_err, strerror( my_err) );
5654 }
5655
5656 /* test fstatat */
5657 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
5658 if ( my_err == -1 ) {
5659 printf( "fstatat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5660 goto test_failed_exit;
5661 }
5662 if ( my_sb.st_size != 6 ) {
5663 printf( "fstatat call failed - st_size is wrong \n" );
5664 goto test_failed_exit;
5665 }
5666 if ( !S_ISREG( my_sb.st_mode ) ) {
5667 printf( "fstatat call failed - st_mode does not indicate regular file \n" );
5668 goto test_failed_exit;
5669 }
5670
5671 my_err = 0;
5672 goto test_passed_exit;
5673
5674 test_failed_exit:
5675 my_err = -1;
5676
5677 test_passed_exit:
5678 if ( my_fd != -1 )
5679 close( my_fd );
5680
5681 if ( my_pathp != NULL ) {
5682 remove(my_pathp);
5683 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
5684 }
5685
5686 if ( my_namep ) {
5687 unlinkat( my_dirfd, my_pathp, 0 );
5688 vm_deallocate(mach_task_self(), (vm_address_t)my_namep, NAME_MAX);
5689 }
5690
5691 if ( my_dirfd != -1)
5692 close(my_dirfd);
5693
5694 if ( my_dirpathp != NULL ) {
5695 vm_deallocate(mach_task_self(), (vm_address_t)my_dirpathp, PATH_MAX);
5696 }
5697
5698 return( my_err );
5699 }
5700
5701 /* **************************************************************************************************************
5702 * Test linkat, fstatat and unlinkat system calls.
5703 * **************************************************************************************************************
5704 */
5705 int linkat_fstatat_unlinkat_test( void * the_argp )
5706 {
5707 int my_err;
5708 int my_dirfd = -1;
5709 int my_fd = -1;
5710 char * my_dirpathp = NULL;
5711 char * my_namep = NULL;
5712 char * my_pathp = NULL;
5713 char * my_name2p = NULL;
5714 nlink_t my_link_count;
5715 ssize_t my_result;
5716 struct stat my_sb;
5717 kern_return_t my_kr;
5718
5719
5720 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_dirpathp, PATH_MAX, VM_FLAGS_ANYWHERE);
5721 if(my_kr != KERN_SUCCESS){
5722 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5723 goto test_failed_exit;
5724 }
5725
5726 *my_dirpathp = 0x00;
5727 strlcat( my_dirpathp, &g_target_path[0], PATH_MAX );
5728
5729 my_dirfd = openat(AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
5730 if ( my_dirfd == -1 ) {
5731 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5732 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
5733 goto test_failed_exit;
5734 }
5735
5736 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
5737 if(my_kr != KERN_SUCCESS){
5738 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5739 goto test_failed_exit;
5740 }
5741
5742 *my_namep = 0x00;
5743 if (my_pathp) {
5744 *my_pathp = 0x00;
5745 }
5746
5747 /* If dirpath is absolute, we can ask for an absolute path name to file back from create_random_name_at */
5748 if (*my_dirpathp == '/') {
5749 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
5750 if(my_kr != KERN_SUCCESS){
5751 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5752 goto test_failed_exit;
5753 }
5754 }
5755
5756 /* create a test file */
5757 my_err = create_random_name_at( my_dirfd, my_dirpathp, my_namep, NAME_MAX, my_pathp, PATH_MAX, 1 );
5758 if ( my_err != 0 ) {
5759 goto test_failed_exit;
5760 }
5761
5762 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_name2p, NAME_MAX, VM_FLAGS_ANYWHERE);
5763 if(my_kr != KERN_SUCCESS){
5764 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5765 goto test_failed_exit;
5766 }
5767
5768 *my_name2p = 0x00;
5769
5770 /* now create a name for the link file */
5771 strlcat( my_name2p, my_namep, NAME_MAX );
5772 strlcat( my_name2p, "link", NAME_MAX );
5773
5774 /* get the current link count */
5775 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
5776 if ( my_err != 0 ) {
5777 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5778 goto test_failed_exit;
5779 }
5780 my_link_count = my_sb.st_nlink;
5781
5782 /* Double check with absolute path name */
5783 if (my_pathp) {
5784 my_err = fstatat(INVALID_FD, my_pathp, &my_sb, 0 );
5785 if ( my_err != 0 ) {
5786 printf( "fstatat with INVALID_FD and absolute pathname failed. got errno %d - %s. \n", errno, strerror( errno ) );
5787 goto test_failed_exit;
5788 }
5789 if (my_link_count != my_sb.st_nlink) {
5790 printf( "fstatat call did not return correct number of links" );
5791 goto test_failed_exit;
5792 }
5793 }
5794
5795 /* check file size (should be 0) */
5796 if ( my_sb.st_size != 0 ) {
5797 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
5798 printf( "st_size is not 0 \n" );
5799 goto test_failed_exit;
5800 }
5801
5802 /* change file size */
5803 my_fd = openat(my_dirfd, my_namep, O_RDWR, 0 );
5804 if ( my_fd == -1 ) {
5805 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5806 printf( "\t file we attempted to open -> \"%s\" \n", my_pathp );
5807 goto test_failed_exit;
5808 }
5809
5810 my_result = write( my_fd, "kat", 3 );
5811 my_err = errno;
5812 if ( my_result != 3 ) {
5813 if ( sizeof( ssize_t ) > sizeof( int ) ) {
5814 printf( "write failed. should have written 3 bytes actually wrote - %ld \n", (long int) my_result );
5815 }
5816 else {
5817 printf( "write failed. should have written 3 bytes actually wrote - %d \n", (int) my_result );
5818 }
5819 goto test_failed_exit;
5820 }
5821 close( my_fd );
5822 my_fd = -1;
5823
5824 /* now link another file to our test file and recheck link count */
5825 /* N.B. - HFS only supports AT_SYMLINK_FOLLOW */
5826 my_err = linkat( my_dirfd, my_namep, my_dirfd, my_name2p, AT_SYMLINK_FOLLOW );
5827 if ( my_err != 0 ) {
5828 printf( "linkat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5829 goto test_failed_exit;
5830 }
5831 my_err = fstatat( my_dirfd, my_pathp, &my_sb, 0 );
5832 if ( my_err != 0 ) {
5833 printf( "fstatat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5834 goto test_failed_exit;
5835 }
5836 if ( (my_link_count + 1) != my_sb.st_nlink ) {
5837 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
5838 printf( "incorrect st_nlink \n" );
5839 goto test_failed_exit;
5840 }
5841
5842 /* check file size (should be 3) */
5843 if ( my_sb.st_size != 3 ) {
5844 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
5845 printf( "st_size is not 3 \n" );
5846 goto test_failed_exit;
5847 }
5848
5849 /* now make sure unlink works OK */
5850 my_err = unlinkat( my_dirfd, my_name2p, 0 );
5851 if ( my_err != 0 ) {
5852 printf( "unlinkat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5853 goto test_failed_exit;
5854 }
5855 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
5856 if ( my_err != 0 ) {
5857 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5858 goto test_failed_exit;
5859 }
5860 if ( my_link_count != my_sb.st_nlink ) {
5861 printf( "stat structure looks bogus for test file \"%s\" \n", my_pathp );
5862 printf( "incorrect st_nlink \n" );
5863 goto test_failed_exit;
5864 }
5865
5866 my_err = 0;
5867 goto test_passed_exit;
5868
5869 test_failed_exit:
5870 my_err = -1;
5871
5872 test_passed_exit:
5873 if ( my_fd != -1 )
5874 close( my_fd );
5875
5876 if ( my_name2p != NULL ) {
5877 (void)unlinkat( my_dirfd, my_name2p, 0 );
5878 vm_deallocate(mach_task_self(), (vm_address_t)my_name2p, NAME_MAX);
5879 }
5880
5881 if ( my_namep != NULL ) {
5882 (void)unlinkat( my_dirfd, my_name2p, 0 );
5883 vm_deallocate(mach_task_self(), (vm_address_t)my_name2p, NAME_MAX);
5884 }
5885
5886 if ( my_pathp != NULL ) {
5887 remove( my_pathp );
5888 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
5889 }
5890
5891 if ( my_dirpathp != NULL ) {
5892 vm_deallocate(mach_task_self(), (vm_address_t)my_dirpathp, PATH_MAX);
5893 }
5894
5895 if ( my_dirfd != -1 )
5896 close( my_dirfd );
5897
5898 return( my_err );
5899 }
5900
5901 /* **************************************************************************************************************
5902 * Test faccessat, fchmodat and fchmod system calls.
5903 * **************************************************************************************************************
5904 */
5905 int faccessat_fchmodat_fchmod_test( void * the_argp )
5906 {
5907 int error_occurred;
5908 int is_absolute_path = 0;
5909 int my_err;
5910 int my_dirfd = -1;
5911 int my_fd = -1;
5912
5913 char * my_dirpathp = NULL;
5914 char * my_namep = NULL;
5915 char * my_pathp = NULL;
5916
5917 uid_t ruid;
5918 struct stat my_sb;
5919
5920 FILE * file_handle;
5921
5922 kern_return_t my_kr;
5923
5924
5925 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_dirpathp, PATH_MAX, VM_FLAGS_ANYWHERE);
5926 if(my_kr != KERN_SUCCESS){
5927 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5928 goto test_failed_exit;
5929 }
5930
5931 *my_dirpathp = 0x00;
5932 strlcat( my_dirpathp, &g_target_path[0], PATH_MAX );
5933
5934 /*
5935 * Some basic openat validation. If pathname is absolute, an invalid fd should
5936 * not matter.
5937 */
5938
5939 if (*my_dirpathp == '/') {
5940 is_absolute_path = 1;
5941 my_dirfd = openat(INVALID_FD, my_dirpathp, O_RDONLY, 0 );
5942 if ( my_dirfd == -1 ) {
5943 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5944 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
5945 printf( "\t Was Absolute pathname, invalid fd, %d, provided as input \n", INVALID_FD);
5946 goto test_failed_exit;
5947 }
5948 close( my_dirfd );
5949 }
5950
5951 my_dirfd = openat(AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
5952 if ( my_dirfd == -1 ) {
5953 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
5954 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
5955 goto test_failed_exit;
5956 }
5957
5958 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
5959 if(my_kr != KERN_SUCCESS){
5960 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5961 goto test_failed_exit;
5962 }
5963
5964 *my_namep = 0x00;
5965
5966 if (is_absolute_path) {
5967 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
5968 if(my_kr != KERN_SUCCESS){
5969 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
5970 goto test_failed_exit;
5971 }
5972
5973 *my_pathp = 0x00;
5974 }
5975
5976 /* create a test file */
5977 my_err = create_random_name_at(my_dirfd, my_dirpathp, my_namep, NAME_MAX, my_pathp, PATH_MAX, 1);
5978 if ( my_err != 0 ) {
5979 goto test_failed_exit;
5980 }
5981
5982 /* test chmod */
5983 my_err = fchmodat(my_dirfd, my_namep, S_IRWXU, 0);
5984 if ( my_err == -1 ) {
5985 printf( "chmod call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5986 goto test_failed_exit;
5987 }
5988
5989 my_err = fchmodat( my_dirfd, my_namep, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP), 0 );
5990 if ( my_err == -1 ) {
5991 printf( "chmod call failed. got errno %d - %s. \n", errno, strerror( errno ) );
5992 goto test_failed_exit;
5993 }
5994
5995 /* test access - this should fail */
5996 my_err = faccessat( my_dirfd, my_namep, (X_OK), 0 );
5997 if ( my_err == 0 ) {
5998 printf( "access call should have failed, but did not. \n" );
5999 goto test_failed_exit;
6000 }
6001 else if ( my_err == -1 ) {
6002 int tmp = 0;
6003 tmp = getuid( );
6004
6005 /* special case when running as root - we get back EPERM when running as root */
6006 my_err = errno;
6007 if ( ( tmp == 0 && my_err != EPERM) || (tmp != 0 && my_err != EACCES) ) {
6008 printf( "access failed with errno %d - %s. \n", my_err, strerror( my_err ) );
6009 goto test_failed_exit;
6010 }
6011 }
6012
6013 /* verify correct modes are set */
6014 /* First check that Absolute path works even with an invalid FD */
6015 if (is_absolute_path) {
6016 my_err = fstatat( INVALID_FD, my_pathp, &my_sb, 0 );
6017 if ( my_err != 0 ) {
6018 printf( "fstatat call failed with an absolute pathname. got errno %d - %s. \n", errno, strerror( errno ) );
6019 goto test_failed_exit;
6020 }
6021 }
6022
6023 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
6024 if ( my_err != 0 ) {
6025 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6026 goto test_failed_exit;
6027 }
6028
6029 if ( (my_sb.st_mode & (S_IRWXO | S_IXGRP)) != 0 ||
6030 (my_sb.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == 0 ) {
6031 printf( "chmod call appears to have failed. stat shows incorrect values in st_mode! \n" );
6032 goto test_failed_exit;
6033 }
6034
6035
6036 /* another test for the access system call -- refer ro radar# 6725311 */
6037
6038
6039 /*
6040 * This test makes sure that the access system call does not give the current user extra
6041 * permissions on files the current user does not own. From radar #6725311, this could
6042 * happen when the current user calls access() on a file owned by the current user in
6043 * the same directory as the other files not owned by the current user.
6044 *
6045 * Note: This test expects that the effective uid (euid) is set to root.
6046 *
6047 */
6048
6049 /* Create a file that root owns */
6050 file_handle = fopen(FILE_NOTME, "w");
6051 fclose(file_handle);
6052
6053 /* Currently running as root (through settid manipulation), switch to running as the current user. */
6054 ruid = getuid();
6055 my_err = syscall(SYS_settid, ruid, KAUTH_GID_NONE);
6056 if (my_err != 0) {
6057 printf("Failed to settid to non-root with error %d:%s\n", errno, strerror(errno));
6058 goto test_failed_exit;
6059 }
6060
6061 /* Create a file that the current user owns */
6062 file_handle = fopen(FILE_ME, "w");
6063 fclose(file_handle);
6064
6065 error_occurred = 0;
6066
6067 /* Try to remove the file owned by root (this should fail). */
6068 my_err = unlinkat( AT_FDCWD, FILE_NOTME, 0 );
6069
6070 if (my_err < 0) {
6071 my_err = errno;
6072 }
6073
6074 if (my_err == 0) {
6075 printf("Unresolved: First attempt deleted '" FILE_NOTME "'! \n");
6076 error_occurred = 1;
6077 } else {
6078 printf("Passed: First attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
6079
6080 /* Set _DELETE_OK on a file that the current user owns */
6081 faccessat(AT_FDCWD, FILE_ME, _DELETE_OK, 0 );
6082
6083 /* Try to remove the file owned by root again (should give us: EPERM [13]) */
6084 my_err = unlinkat(AT_FDCWD, FILE_NOTME, 0);
6085
6086 if (my_err < 0) {
6087 my_err = errno;
6088 }
6089
6090 if (my_err == 0) {
6091 printf("Failed: Second attempt deleted '" FILE_NOTME "'!\n");
6092 error_occurred = 1;
6093 } else if (my_err == 13) {
6094 printf("Passed: Second attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
6095 } else {
6096 printf("Failed: Second attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
6097 error_occurred = 1;
6098 }
6099 }
6100
6101 /* Reset to running as root */
6102 my_err = syscall(SYS_settid, KAUTH_UID_NONE, KAUTH_GID_NONE);
6103 if (my_err != 0) {
6104 printf("Failed to settid revert to root with error %d:%s\n", errno, strerror(errno));
6105 goto test_failed_exit;
6106 }
6107
6108 if(error_occurred == 1) {
6109 goto test_failed_exit;
6110 }
6111
6112
6113 /* end of test*/
6114
6115
6116 /* test fchmod */
6117 my_fd = openat( my_dirfd, my_namep, O_RDONLY, 0);
6118 if ( my_fd == -1 ) {
6119 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6120 printf( "\t we attempted to open -> \"%s\" \n", &g_target_path[0] );
6121 goto test_failed_exit;
6122 }
6123
6124 my_err = fchmod( my_fd, S_IRWXU );
6125 if ( my_err == -1 ) {
6126 printf( "fchmod call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6127 goto test_failed_exit;
6128 }
6129
6130 my_err = fstatat( INVALID_FD, my_pathp, &my_sb, 0 );
6131 if ( my_err != 0 ) {
6132 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6133 goto test_failed_exit;
6134 }
6135
6136 /* verify correct modes are set */
6137 if ( (my_sb.st_mode & (S_IRWXG | S_IRWXO)) != 0 ||
6138 (my_sb.st_mode & (S_IRWXU)) == 0 ) {
6139 printf( "fchmod call appears to have failed. stat shows incorrect values in st_mode! \n" );
6140 goto test_failed_exit;
6141 }
6142
6143 my_err = 0;
6144 goto test_passed_exit;
6145
6146 test_failed_exit:
6147 my_err = -1;
6148
6149 test_passed_exit:
6150 if ( my_fd != -1 )
6151 close( my_fd );
6152 if ( my_pathp != NULL ) {
6153 remove( my_pathp );
6154 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
6155 }
6156 if ( my_namep != NULL ) {
6157 unlinkat(my_dirfd, my_namep, 0);
6158 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, NAME_MAX);
6159
6160 }
6161
6162 if ( my_dirfd != -1)
6163 close( my_dirfd);
6164
6165 if ( my_dirpathp != NULL ) {
6166 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
6167 }
6168
6169 return( my_err );
6170 }
6171
6172 /* **************************************************************************************************************
6173 * Test fchownat, fchown, readlinkat, symlinkat system calls.
6174 * **************************************************************************************************************
6175 */
6176 int fchownat_fchown_symlinkat_test( void * the_argp )
6177 {
6178 int my_err, my_group_count, i;
6179 int my_fd = -1;
6180 int my_dirfd = -1;
6181 char * my_dirpathp = NULL;
6182 char * my_namep = NULL;
6183 char * my_link_namep = NULL;
6184 char * my_pathp = NULL;
6185 char * my_link_pathp = NULL;
6186 int is_absolute_path = 0;
6187 uid_t my_orig_uid;
6188 gid_t my_orig_gid, my_new_gid1 = 0, my_new_gid2 = 0;
6189 ssize_t my_result;
6190 struct stat my_sb;
6191 gid_t my_groups[ NGROUPS_MAX ];
6192 char my_buffer[ 64 ];
6193 kern_return_t my_kr;
6194
6195
6196 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_dirpathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6197 if(my_kr != KERN_SUCCESS){
6198 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6199 goto test_failed_exit;
6200 }
6201
6202 *my_dirpathp = 0x00;
6203 strlcat( my_dirpathp, &g_target_path[0], PATH_MAX );
6204
6205 /*
6206 * Some basic openat validation. If pathname is absolute, an invalid fd should
6207 * not matter.
6208 */
6209 if (*my_dirpathp == '/') {
6210 is_absolute_path = 1;
6211 my_dirfd = openat(INVALID_FD, my_dirpathp, O_RDONLY, 0 );
6212 if ( my_dirfd == -1 ) {
6213 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6214 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
6215 printf( "\t Was Absolute pathname, invalid fd, %d, provided as input \n", INVALID_FD);
6216 goto test_failed_exit;
6217 }
6218 close( my_dirfd );
6219 }
6220
6221 my_dirfd = openat(AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
6222 if ( my_dirfd == -1 ) {
6223 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6224 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
6225 goto test_failed_exit;
6226 }
6227
6228 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
6229 if(my_kr != KERN_SUCCESS){
6230 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6231 goto test_failed_exit;
6232 }
6233
6234 *my_namep = 0x00;
6235
6236 if (is_absolute_path) {
6237 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6238 if(my_kr != KERN_SUCCESS){
6239 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6240 goto test_failed_exit;
6241 }
6242
6243 *my_pathp = 0x00;
6244 }
6245
6246 /* create a test file */
6247 my_err = create_random_name_at(my_dirfd, my_dirpathp, my_namep, NAME_MAX, my_pathp, PATH_MAX, 1);
6248 if ( my_err != 0 ) {
6249 goto test_failed_exit;
6250 }
6251
6252 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_link_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
6253 if(my_kr != KERN_SUCCESS){
6254 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6255 goto test_failed_exit;
6256 }
6257
6258 *my_link_namep = 0x00;
6259
6260 if (is_absolute_path) {
6261 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_link_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6262 if(my_kr != KERN_SUCCESS){
6263 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6264 goto test_failed_exit;
6265 }
6266
6267 *my_link_pathp = 0x00;
6268 }
6269
6270 /* get a name for the link (to create the symlink later) */
6271 my_err = create_random_name_at(my_dirfd, my_dirpathp, my_link_namep, NAME_MAX, my_link_pathp, PATH_MAX, 0 );
6272 if ( my_err != 0 ) {
6273 goto test_failed_exit;
6274 }
6275
6276 if ( !_prime_groups() ) {
6277 goto test_failed_exit;
6278 }
6279
6280 /* set up by getting a list of groups */
6281 my_group_count = getgroups( NGROUPS_MAX, &my_groups[0] );
6282
6283 if ( my_group_count == -1 || my_group_count < 1 ) {
6284 printf( "getgroups call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6285 goto test_failed_exit;
6286 }
6287
6288 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
6289 if ( my_err != 0 ) {
6290 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6291 goto test_failed_exit;
6292 }
6293
6294 /* now change group owner to something other than current value */
6295 my_orig_gid = my_sb.st_gid;
6296 my_orig_uid = my_sb.st_uid;
6297
6298 for ( i = 0; i < my_group_count; i++ ) {
6299 if ( my_orig_gid != my_groups[ i ] ) {
6300 if ( my_new_gid1 == 0 ) {
6301 my_new_gid1 = my_groups[ i ];
6302 }
6303 else if( my_new_gid1 != my_groups[ i ] ) {
6304 my_new_gid2 = my_groups[ i ];
6305 break;
6306 }
6307 }
6308 }
6309 if ( i >= my_group_count ) {
6310 printf( "not enough groups to choose from. st_gid is the same as current groups! \n" );
6311 goto test_failed_exit;
6312 }
6313
6314 my_err = fchownat( my_dirfd, my_namep, my_orig_uid, my_new_gid1, 0 );
6315 if ( my_err != 0 ) {
6316 printf( "chown call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6317 goto test_failed_exit;
6318 }
6319
6320 /* make sure the group owner was changed */
6321 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
6322 if ( my_err != 0 ) {
6323 printf( "stat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6324 goto test_failed_exit;
6325 }
6326 if ( my_sb.st_gid == my_orig_gid ) {
6327 printf( "chown call failed. st_gid is not correct! \n" );
6328 goto test_failed_exit;
6329 }
6330
6331 /* change group owner back using fchown */
6332 if (is_absolute_path) {
6333 my_fd = openat( INVALID_FD, my_pathp, O_RDWR, 0 );
6334 } else {
6335 my_fd = openat( my_dirfd, my_namep, O_RDWR, 0 );
6336 }
6337
6338 if ( my_fd == -1 ) {
6339 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6340 printf( "\t we attempted to open -> \"%s\" \n", &g_target_path[0] );
6341 goto test_failed_exit;
6342 }
6343
6344 my_err = fchown( my_fd, my_orig_uid, my_new_gid2 );
6345 if ( my_err != 0 ) {
6346 printf( "fchown call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6347 goto test_failed_exit;
6348 }
6349
6350 /* make sure the group owner was changed back to the original value */
6351 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
6352 if ( my_err != 0 ) {
6353 printf( "fstatat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6354 goto test_failed_exit;
6355 }
6356 if ( my_sb.st_gid == my_new_gid1 ) {
6357 printf( "fchown call failed. st_gid is not correct! \n" );
6358 goto test_failed_exit;
6359 }
6360
6361 /* create a link file and test fstatat(..., AT_SYMLINK_NOFOLLOW) */
6362 my_err = symlinkat( my_namep, my_dirfd, my_link_namep );
6363 if ( my_err != 0 ) {
6364 printf( "symlinkat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6365 goto test_failed_exit;
6366 }
6367
6368 my_err = fstatat( my_dirfd, my_link_namep, &my_sb, AT_SYMLINK_NOFOLLOW );
6369 if ( my_err != 0 ) {
6370 printf( "fstatat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6371 goto test_failed_exit;
6372 }
6373
6374 /* now change group owner to something other than current value */
6375 my_orig_gid = my_sb.st_gid;
6376 my_orig_uid = my_sb.st_uid;
6377 my_err = fchownat( my_dirfd, my_link_namep, my_orig_uid, my_new_gid1, AT_SYMLINK_NOFOLLOW );
6378 if ( my_err != 0 ) {
6379 printf( "fchownat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6380 goto test_failed_exit;
6381 }
6382
6383 /* make sure the group owner was changed to new value */
6384 my_err = fstatat( my_dirfd, my_link_namep, &my_sb, AT_SYMLINK_NOFOLLOW );
6385 if ( my_err != 0 ) {
6386 printf( "fstatat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6387 goto test_failed_exit;
6388 }
6389 if ( my_sb.st_gid == my_new_gid2 ) {
6390 printf( "fchownat call failed. st_gid is not correct! \n" );
6391 goto test_failed_exit;
6392 }
6393
6394 /* make sure we can read the symlink file */
6395 my_result = readlinkat( my_dirfd, my_link_namep, &my_buffer[0], sizeof(my_buffer) );
6396 if ( my_result == -1 ) {
6397 printf( "readlinkat call failed. got errno %d - %s. \n", errno, strerror( errno ) );
6398 goto test_failed_exit;
6399 }
6400 /* make sure we read some data */
6401 if ( my_result < 1 ) {
6402 printf( "readlinkat failed to read any data. \n" );
6403 goto test_failed_exit;
6404 }
6405
6406 my_err = 0;
6407 goto test_passed_exit;
6408
6409 test_failed_exit:
6410 my_err = -1;
6411
6412 test_passed_exit:
6413 if ( my_fd != -1 )
6414 close( my_fd );
6415 if ( my_namep ) {
6416 unlinkat( my_dirfd, my_namep, 0);
6417 vm_deallocate(mach_task_self(), (vm_address_t)my_namep, NAME_MAX);
6418 }
6419 if ( my_pathp != NULL ) {
6420 remove( my_pathp );
6421 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
6422 }
6423 if ( my_link_namep ) {
6424 unlinkat( my_dirfd, my_link_namep, 0);
6425 vm_deallocate(mach_task_self(), (vm_address_t)my_link_namep, NAME_MAX);
6426 }
6427 if ( my_link_pathp != NULL ) {
6428 unlink( my_link_pathp );
6429 vm_deallocate(mach_task_self(), (vm_address_t)my_link_pathp, PATH_MAX);
6430 }
6431 if ( my_dirfd != -1 )
6432 close(my_dirfd);
6433
6434 if ( my_dirpathp != NULL ) {
6435 vm_deallocate(mach_task_self(), (vm_address_t)my_dirpathp, PATH_MAX);
6436 }
6437
6438
6439 return( my_err );
6440 }
6441
6442 /* **************************************************************************************************************
6443 * Test mkdirat, unlinkat, umask system calls.
6444 * **************************************************************************************************************
6445 */
6446 int mkdirat_unlinkat_umask_test( void * the_argp )
6447 {
6448 int my_err;
6449 int my_dirfd = -1;
6450 int my_fd = -1;
6451 int did_umask = 0;
6452 char * my_dirpathp = NULL;
6453 char * my_namep = NULL;
6454 char * my_pathp = NULL;
6455 mode_t my_orig_mask;
6456 struct stat my_sb;
6457 kern_return_t my_kr;
6458
6459 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_dirpathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6460 if(my_kr != KERN_SUCCESS){
6461 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6462 goto test_failed_exit;
6463 }
6464
6465 *my_dirpathp = 0x00;
6466 strlcat( my_dirpathp, &g_target_path[0], PATH_MAX );
6467
6468 my_dirfd = openat(AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
6469 if ( my_dirfd == -1 ) {
6470 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6471 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
6472 goto test_failed_exit;
6473 }
6474
6475 /* If dirpath is absolute, we can ask for an absolute path name to file back from create_random_name_at */
6476 if (*my_dirpathp == '/') {
6477 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6478 if(my_kr != KERN_SUCCESS){
6479 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6480 goto test_failed_exit;
6481 }
6482 }
6483
6484 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
6485 if(my_kr != KERN_SUCCESS){
6486 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6487 goto test_failed_exit;
6488 }
6489
6490 *my_namep = 0x00;
6491 if (my_pathp) {
6492 *my_pathp = 0x00;
6493 }
6494
6495 /* get a random name to use with mkdirat (don't create) */
6496 my_err = create_random_name_at( my_dirfd, my_dirpathp, my_namep, NAME_MAX, my_pathp, PATH_MAX, 0 );
6497 if ( my_err != 0 ) {
6498 goto test_failed_exit;
6499 }
6500
6501 /* set umask to clear WX for other and group and clear X for user */
6502 my_orig_mask = umask( (S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH) );
6503 did_umask = 1;
6504
6505 /* create a directory with RWX for user, group, other (which should be limited by umask) */
6506 my_err = mkdirat( my_dirfd, my_namep, (S_IRWXU | S_IRWXG | S_IRWXO) );
6507 if ( my_err == -1 ) {
6508 printf( "mkdirat failed with error %d - \"%s\" \n", errno, strerror( errno) );
6509 goto test_failed_exit;
6510 }
6511
6512 /* verify results - (S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH) should be clear*/
6513 my_err = fstatat( my_dirfd, my_pathp, &my_sb, 0 );
6514 if ( my_err != 0 ) {
6515 printf( "fstat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6516 goto test_failed_exit;
6517 }
6518 if ( (my_sb.st_mode & (S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH)) != 0 ) {
6519 printf( "umask did not limit modes as it should have \n" );
6520 goto test_failed_exit;
6521 }
6522
6523 /* get rid of our test directory */
6524 my_err = unlinkat( my_dirfd, my_namep, AT_REMOVEDIR );
6525 if ( my_err == -1 ) {
6526 printf( "unlinkat(..., AT_REMOVEDIR) failed with error %d - \"%s\" \n", errno, strerror( errno) );
6527 goto test_failed_exit;
6528 }
6529 my_err = 0;
6530 goto test_passed_exit;
6531
6532 test_failed_exit:
6533 my_err = -1;
6534
6535 test_passed_exit:
6536 if ( my_fd != -1 )
6537 close( my_fd );
6538
6539 if ( my_namep ) {
6540 unlinkat( my_dirfd, my_namep, AT_REMOVEDIR );
6541 vm_deallocate(mach_task_self(), (vm_address_t)my_namep, NAME_MAX);
6542 }
6543
6544 if ( my_pathp != NULL ) {
6545 rmdir( my_pathp );
6546 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
6547 }
6548
6549 if ( my_dirfd != -1 )
6550 close(my_dirfd);
6551
6552 if ( my_dirpathp != NULL ) {
6553 vm_deallocate(mach_task_self(), (vm_address_t)my_dirpathp, PATH_MAX);
6554 }
6555
6556 if ( did_umask != 0 ) {
6557 umask( my_orig_mask );
6558 }
6559
6560 return( my_err );
6561 }
6562
6563 /* **************************************************************************************************************
6564 * Test renameat, fstatat system calls.
6565 * **************************************************************************************************************
6566 */
6567 int renameat_test( void * the_argp )
6568 {
6569 int my_err;
6570 int my_dirfd = -1;
6571 char * my_dirpathp = NULL;
6572 char * my_namep = NULL;
6573 char * my_pathp = NULL;
6574 char * my_new_namep = NULL;
6575 char * my_new_pathp = NULL;
6576 ino_t my_file_id;
6577 struct stat my_sb;
6578 kern_return_t my_kr;
6579
6580 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_dirpathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6581 if(my_kr != KERN_SUCCESS){
6582 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6583 goto test_failed_exit;
6584 }
6585
6586 *my_dirpathp = 0x00;
6587 strlcat( my_dirpathp, &g_target_path[0], PATH_MAX );
6588
6589 my_dirfd = openat(AT_FDCWD, my_dirpathp, O_RDONLY, 0 );
6590 if ( my_dirfd == -1 ) {
6591 printf( "openat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
6592 printf( "\t Directory we attempted to open -> \"%s\" \n", my_dirpathp );
6593 goto test_failed_exit;
6594 }
6595
6596 /* If dirpath is absolute, we can ask for an absolute path name to file back from create_random_name_at */
6597 if (*my_dirpathp == '/') {
6598 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6599 if(my_kr != KERN_SUCCESS){
6600 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6601 goto test_failed_exit;
6602 }
6603 }
6604
6605 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
6606 if(my_kr != KERN_SUCCESS){
6607 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6608 goto test_failed_exit;
6609 }
6610
6611 *my_namep = 0x00;
6612 if (my_pathp) {
6613 *my_pathp = 0x00;
6614 }
6615
6616 /* create random file */
6617 my_err = create_random_name_at( my_dirfd, my_dirpathp, my_namep, NAME_MAX, my_pathp, PATH_MAX, 1 );
6618 if ( my_err != 0 ) {
6619 goto test_failed_exit;
6620 }
6621
6622
6623 /* If dirpath is absolute, we can ask for an absolute path name to file back from create_random_name_at */
6624 if (*my_dirpathp == '/') {
6625 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_new_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6626 if(my_kr != KERN_SUCCESS){
6627 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6628 goto test_failed_exit;
6629 }
6630 }
6631
6632 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_new_namep, NAME_MAX, VM_FLAGS_ANYWHERE);
6633 if(my_kr != KERN_SUCCESS){
6634 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6635 goto test_failed_exit;
6636 }
6637
6638 *my_new_namep = 0x00;
6639 if (my_new_pathp) {
6640 *my_new_pathp = 0x00;
6641 }
6642
6643 /* create random file */
6644 my_err = create_random_name_at( my_dirfd, my_dirpathp, my_new_namep, NAME_MAX, my_new_pathp, PATH_MAX, 0 );
6645 if ( my_err != 0 ) {
6646 goto test_failed_exit;
6647 }
6648
6649 /* save file ID for later use */
6650 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
6651 if ( my_err != 0 ) {
6652 printf( "fstatat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
6653 goto test_failed_exit;
6654 }
6655 my_file_id = my_sb.st_ino;
6656
6657 /* test rename */
6658 my_err = renameat( my_dirfd, my_namep, my_dirfd, my_new_namep );
6659 if ( my_err == -1 ) {
6660 printf( "rename - failed with error %d - \"%s\" \n", errno, strerror( errno) );
6661 goto test_failed_exit;
6662 }
6663
6664 /* make sure old name is no longer there */
6665 my_err = fstatat( my_dirfd, my_namep, &my_sb, 0 );
6666 if ( my_err == 0 ) {
6667 printf( "renameat call failed - found old name \n" );
6668 goto test_failed_exit;
6669 }
6670
6671 /* make sure new name is there and is correct file id */
6672 my_err = fstatat( my_dirfd, my_new_namep, &my_sb, 0 );
6673 if ( my_err != 0 ) {
6674 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
6675 goto test_failed_exit;
6676 }
6677 if ( my_file_id != my_sb.st_ino ) {
6678 printf( "rename failed - wrong file id \n" );
6679 goto test_failed_exit;
6680 }
6681
6682 /* cross check with absolute path and invalid fd */
6683 if (my_new_pathp) {
6684 my_err = fstatat( INVALID_FD, my_new_pathp, &my_sb, 0 );
6685 if ( my_err != 0 ) {
6686 printf( "stat - failed with error %d - \"%s\" \n", errno, strerror( errno) );
6687 goto test_failed_exit;
6688 }
6689 if ( my_file_id != my_sb.st_ino ) {
6690 printf( "rename failed - wrong file id \n" );
6691 goto test_failed_exit;
6692 }
6693 }
6694
6695 my_err = 0;
6696 goto test_passed_exit;
6697
6698 test_failed_exit:
6699 my_err = -1;
6700
6701 test_passed_exit:
6702 if ( my_pathp != NULL ) {
6703 remove( my_pathp );
6704 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
6705 }
6706 if ( my_new_pathp != NULL ) {
6707 remove( my_new_pathp );
6708 vm_deallocate(mach_task_self(), (vm_address_t)my_new_pathp, PATH_MAX);
6709 }
6710 return( my_err );
6711 }
6712
6713 /* **************************************************************************************************************
6714 * Test task_set_exception_ports, host_set_exception_ports
6715 * **************************************************************************************************************
6716 */
6717 static int __get_except_port(int which, mach_port_t *portp,
6718 exception_behavior_t *behaviorp,
6719 thread_state_flavor_t *flavorp)
6720 {
6721 exception_mask_t masks[EXC_TYPES_COUNT];
6722 mach_msg_type_number_t nmasks = 0;
6723 exception_port_t ports[EXC_TYPES_COUNT];
6724 exception_behavior_t behaviors[EXC_TYPES_COUNT];
6725 thread_state_flavor_t flavors[EXC_TYPES_COUNT];
6726
6727 *portp = MACH_PORT_NULL;
6728 *behaviorp = 0;
6729 *flavorp = 0;
6730
6731 kern_return_t kr = KERN_FAILURE;
6732 if (which == 0) { /* host port */
6733 kr = host_get_exception_ports(mach_host_self(), EXC_MASK_BAD_ACCESS,
6734 masks, &nmasks, ports, behaviors, flavors);
6735 } else if (which == 1) { /* task port */
6736 kr = task_get_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS,
6737 masks, &nmasks, ports, behaviors, flavors);
6738 } else if (which == 2) { /* thread_port */
6739 kr = thread_get_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS,
6740 masks, &nmasks, ports, behaviors, flavors);
6741 } else {
6742 printf("ERROR: invalid 'which' in %s\n", __func__);
6743 return -1;
6744 }
6745 if (kr != KERN_SUCCESS) {
6746 printf("ERROR getting %s exception port!\n", which == 0 ? "task" : "host");
6747 return -1;
6748 }
6749 *portp = ports[0];
6750 *behaviorp = behaviors[0];
6751 *flavorp = flavors[0];
6752
6753 return 0;
6754 }
6755
6756 int set_exception_ports_test( void * the_argp )
6757 {
6758 int testFlavor = -900000;
6759 kern_return_t ret;
6760 mach_port_t exception_port;
6761
6762 mach_port_t old_except_port;
6763 exception_behavior_t old_behavior;
6764 thread_state_flavor_t old_flavor;
6765
6766
6767 ret = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exception_port );
6768 if (ret != KERN_SUCCESS) {
6769 printf("ERROR allocating new exception port?!\n");
6770 return -1;
6771 }
6772 ret = mach_port_insert_right( mach_task_self(), exception_port, exception_port, MACH_MSG_TYPE_MAKE_SEND );
6773 if (ret != KERN_SUCCESS) {
6774 printf("ERROR inserting send right into new exception port?!\n");
6775 goto test_failed_exit;
6776 }
6777
6778 if (__get_except_port(2, &old_except_port, &old_behavior, &old_flavor) < 0)
6779 goto test_failed_exit;
6780
6781 ret = thread_set_exception_ports( mach_thread_self(),
6782 EXC_MASK_BAD_ACCESS,
6783 exception_port,
6784 EXCEPTION_STATE_IDENTITY,
6785 testFlavor );
6786 /*
6787 * this test _fails_ if we successfully set the exception port
6788 * with an invalid thread flavor
6789 */
6790 if (ret == KERN_SUCCESS) {
6791 thread_set_exception_ports( mach_thread_self(),
6792 EXC_MASK_BAD_ACCESS,
6793 old_except_port, old_behavior, old_flavor );
6794 printf("thread_set_exception_ports failed: expected !KERN_SUCCESS for flavor %d\n", testFlavor);
6795 goto test_failed_exit;
6796 }
6797
6798 /*
6799 * so far, so good: the thread_set_exception_ports call failed,
6800 * so we don't need to reset anything, but we do need to
6801 * drop our reference to the old exception port we grabbed.
6802 */
6803 mach_port_deallocate( mach_task_self(), old_except_port );
6804
6805 if (__get_except_port(1, &old_except_port, &old_behavior, &old_flavor) < 0)
6806 goto test_failed_exit;
6807
6808 ret = task_set_exception_ports( mach_task_self(),
6809 EXC_MASK_BAD_ACCESS,
6810 exception_port,
6811 EXCEPTION_STATE_IDENTITY,
6812 testFlavor );
6813 /*
6814 * this test _fails_ if we successfully set the exception port
6815 * with an invalid thread flavor
6816 */
6817 if (ret == KERN_SUCCESS) {
6818 task_set_exception_ports( mach_task_self(),
6819 EXC_MASK_BAD_ACCESS,
6820 old_except_port, old_behavior, old_flavor );
6821 printf("task_set_exception_ports failed: expected !KERN_SUCCESS for flavor %d\n", testFlavor);
6822 goto test_failed_exit;
6823 }
6824
6825 /*
6826 * so far, so good: the task_set_exception_ports call failed,
6827 * so we don't need to reset anything, but we do need to
6828 * drop our reference to the old exception port we grabbed.
6829 */
6830 mach_port_deallocate( mach_task_self(), old_except_port );
6831
6832 /*
6833 * Now try the host exception port
6834 */
6835 if (__get_except_port(0, &old_except_port, &old_behavior, &old_flavor) < 0)
6836 goto test_failed_exit;
6837
6838 ret = host_set_exception_ports( mach_host_self(),
6839 EXC_MASK_BAD_ACCESS,
6840 exception_port,
6841 EXCEPTION_STATE_IDENTITY,
6842 testFlavor );
6843 /*
6844 * this test _fails_ if we successfully set the exception port
6845 * with an invalid thread flavor
6846 */
6847 if (ret == KERN_SUCCESS) {
6848 host_set_exception_ports( mach_host_self(),
6849 EXC_MASK_BAD_ACCESS,
6850 old_except_port, old_behavior, old_flavor );
6851 printf("host_set_exception_ports failed: expected !KERN_SUCCESS for flavor %d\n", testFlavor);
6852 goto test_failed_exit;
6853 }
6854
6855 mach_port_deallocate( mach_task_self(), exception_port );
6856 mach_port_deallocate( mach_task_self(), old_except_port );
6857 return 0;
6858
6859 test_failed_exit:
6860 mach_port_deallocate( mach_task_self(), exception_port );
6861 if (old_except_port != MACH_PORT_NULL)
6862 mach_port_deallocate( mach_task_self(), old_except_port );
6863 return -1;
6864 }
6865
6866
6867 #if TEST_SYSTEM_CALLS
6868
6869 /* **************************************************************************************************************
6870 * Test xxxxxxxxx system calls.
6871 * **************************************************************************************************************
6872 */
6873 int sample_test( void * the_argp )
6874 {
6875 int my_err;
6876 int my_fd = -1;
6877 char * my_pathp = NULL;
6878 kern_return_t my_kr;
6879
6880 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
6881 if(my_kr != KERN_SUCCESS){
6882 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
6883 goto test_failed_exit;
6884 }
6885
6886 *my_pathp = 0x00;
6887 strcat( my_pathp, &g_target_path[0] );
6888 strcat( my_pathp, "/" );
6889
6890 /* create a test file */
6891 my_err = create_random_name( my_pathp, 1 );
6892 if ( my_err != 0 ) {
6893 goto test_failed_exit;
6894 }
6895
6896 /* add your test code here... */
6897
6898
6899 my_err = 0;
6900 goto test_passed_exit;
6901
6902 test_failed_exit:
6903 my_err = -1;
6904
6905 test_passed_exit:
6906 if ( my_fd != -1 )
6907 close( my_fd );
6908 if ( my_pathp != NULL ) {
6909 remove( my_pathp );
6910 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
6911 }
6912 return( my_err );
6913 }
6914
6915 #endif