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