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 21extern char g_target_path[ PATH_MAX ]; 22extern int g_skip_setuid_tests; 23extern int g_is_single_user; 24 25 26void 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 */ 70int 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 106test_failed_exit: 107 my_err = -1; 108 109test_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 */ 123int 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 */ 184int 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 430test_failed_exit: 431 my_err = -1; 432 433test_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 */ 449int 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 611test_failed_exit: 612 my_err = -1; 613 614test_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 */ 628int 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 746test_failed_exit: 747 my_err = -1; 748 749test_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 */ 767int 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 876test_failed_exit: 877 my_err = -1; 878 879test_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 */ 895int 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 1076test_failed_exit: 1077 my_err = -1; 1078 1079test_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 1089static 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 */ 1111int 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 1285test_failed_exit: 1286 my_err = -1; 1287 1288test_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) 1308struct vol_attr_buf { 1309 u_int32_t length; 1310 off_t volume_size; 1311 u_int32_t io_blksize; 1312}; 1313#pragma pack() 1314typedef struct vol_attr_buf vol_attr_buf; 1315 1316#define STATFS_TEST_PATH "/tmp" 1317 1318int 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 1497test_failed_exit: 1498 my_err = -1; 1499 1500test_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 */ 1517int 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 1607test_failed_exit: 1608 my_err = -1; 1609 1610test_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 */ 1623int 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 1831test_failed_exit: 1832 my_err = -1; 1833 1834test_passed_exit: 1835 return( my_err ); 1836} 1837 1838/* ************************************************************************************************************** 1839 * Test mknod, sync system calls. 1840 * ************************************************************************************************************** 1841 */ 1842int 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 1881test_failed_exit: 1882 my_err = -1; 1883 1884test_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 */ 1896int 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 1976test_failed_exit: 1977 my_err = -1; 1978 1979test_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 2014int 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 2143test_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 */ 2154int 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 2284test_failed_exit: 2285 my_err = -1; 2286 2287test_passed_exit: 2288 return( my_err ); 2289} 2290 2291 2292/* ************************************************************************************************************** 2293 * Test dup, dup2, getdtablesize system calls. 2294 * ************************************************************************************************************** 2295 */ 2296int 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 2342redo: 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 2405test_failed_exit: 2406 my_err = -1; 2407 2408test_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 */ 2425int 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 2449test_failed_exit: 2450 my_err = -1; 2451 2452test_passed_exit: 2453 return( my_err ); 2454} 2455 2456/* ************************************************************************************************************** 2457 * Test getitimer, setitimer, sigaction, sigpending, sigprocmask, sigsuspend, sigwait system calls. 2458 * ************************************************************************************************************** 2459 */ 2460 2461int alarm_global = 0; 2462void test_alarm_handler( int the_arg ); 2463void 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 2472void test_signal_handler( int the_arg ); 2473void 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 2481int 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 2717test_failed_exit: 2718 my_err = -1; 2719 2720test_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 */ 2734int 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; 2819exit_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 2841test_failed_exit: 2842 my_err = -1; 2843 2844test_passed_exit: 2845 return( my_err ); 2846} 2847 2848/* ************************************************************************************************************** 2849 * Test acct system call. 2850 * ************************************************************************************************************** 2851 */ 2852int 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 2984test_failed_exit: 2985 my_err = -1; 2986 2987test_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 2997void 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 */ 3023int 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 3079test_failed_exit: 3080 my_err = -1; 3081 3082test_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 */ 3092int 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 3150test_failed_exit: 3151 my_err = -1; 3152 3153test_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 */ 3171int 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 3258test_failed_exit: 3259 my_err = -1; 3260 3261test_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 */ 3276int 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 3339test_failed_exit: 3340 my_err = -1; 3341 3342test_passed_exit: 3343 return( my_err ); 3344} 3345 3346/* ************************************************************************************************************** 3347 * Test fcntl system calls. 3348 * ************************************************************************************************************** 3349 */ 3350int 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 3467test_failed_exit: 3468 my_err = -1; 3469 3470test_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 */ 3486int 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 3531test_failed_exit: 3532 my_err = -1; 3533 3534test_passed_exit: 3535 return( my_err ); 3536} 3537 3538/* ************************************************************************************************************** 3539 * Test futimes, gettimeofday, settimeofday, utimes system calls. 3540 * ************************************************************************************************************** 3541 */ 3542int 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 3673test_failed_exit: 3674 my_err = -1; 3675 3676test_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 */ 3690int 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 3767test_failed_exit: 3768 my_err = -1; 3769 3770test_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 */ 3786int 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; 3859child_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 3887test_failed_exit: 3888 my_err = -1; 3889 3890test_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 */ 3904int 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; 3975child_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 4015test_failed_exit: 4016 my_err = -1; 4017 4018test_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 */ 4032int 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 4066test_failed_exit: 4067 my_err = -1; 4068 4069test_passed_exit: 4070 return( my_err ); 4071} 4072 4073/* ************************************************************************************************************** 4074 * Test getrlimit, setrlimit system calls. 4075 * ************************************************************************************************************** 4076 */ 4077int 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 4150test_failed_exit: 4151 my_err = -1; 4152 4153test_passed_exit: 4154 return( my_err ); 4155} 4156 4157/* ************************************************************************************************************** 4158 * Test getattrlist, getdirentriesattr, setattrlist system calls. 4159 * ************************************************************************************************************** 4160 */ 4161struct 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 4168typedef struct test_attr_buf test_attr_buf; 4169 4170int 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 4309test_failed_exit: 4310 if(my_err != 0) 4311 my_err = -1; 4312 4313test_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 */ 4330int 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 4440test_failed_exit: 4441 my_err = -1; 4442 4443test_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 4465struct 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 4471struct packed_attr_ref { 4472 u_int32_t size; /* Of the remaining fields */ 4473 struct attrreference ref; /* Offset/length of attr itself */ 4474}; 4475 4476struct 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}; 4483typedef struct packed_result packed_result; 4484typedef struct packed_result * packed_result_p; 4485 4486#define MAX_MATCHES 10 4487#define MAX_EBUSY_RETRIES 20 4488 4489int 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 4554catalogue_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 4665test_failed_exit: 4666 my_err = -1; 4667 4668test_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 */ 4694int 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 4940test_failed_exit: 4941 my_err = -1; 4942 4943test_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 */ 4967int 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 5056test_failed_exit: 5057 my_err = -1; 5058 5059test_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 */ 5072int 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 5128test_failed_exit: 5129 my_err = -1; 5130 5131test_passed_exit: 5132 return my_err; 5133} 5134 5135/* ************************************************************************************************************** 5136 * Test KASLR-related functionality 5137 * ************************************************************************************************************** 5138 */ 5139int 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 5206test_failed_exit: 5207 return -1; 5208} 5209 5210typedef 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 5228int 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 5313last_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 5327static 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 */ 5342int 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 */ 5425int 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 5668test_failed_exit: 5669 my_err = -1; 5670 5671test_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 */ 5699int 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 5863test_failed_exit: 5864 my_err = -1; 5865 5866test_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 */ 5899int 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 6133test_failed_exit: 6134 my_err = -1; 6135 6136test_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 */ 6163int 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 6396test_failed_exit: 6397 my_err = -1; 6398 6399test_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 */ 6433int 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 6519test_failed_exit: 6520 my_err = -1; 6521 6522test_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 */ 6554int 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 6685test_failed_exit: 6686 my_err = -1; 6687 6688test_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 */ 6704static 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 6743int 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 6846test_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 */ 6860int 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 6889test_failed_exit: 6890 my_err = -1; 6891 6892test_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 6903