static int setgroups_if_single_user(void) { int i, retval = -1; struct group *grp; gid_t gids[NUM_GROUPS]; if (!_ds_running()) { printf("In single-user mode.\n"); g_is_single_user = 1; /* We skip 'nobody' and 'anyone' */ getgrent(); getgrent(); for (i = 0; i < NUM_GROUPS; i++) { grp = getgrent(); if (!grp) { break; } gids[i] = grp->gr_gid; } endgrent(); /* Only succeed if we find at least NUM_GROUPS */ if (i == NUM_GROUPS) { retval = setgroups(NUM_GROUPS, gids); if (retval == 0) { getgroups(NUM_GROUPS, gids); printf("After single-user hack, groups are: "); for (i = 0; i < NUM_GROUPS; i++) { printf("%d, ", gids[i]); } putchar('\n'); } else { printf("Setgroups failed.\n"); } } else { printf("Couldn't get sufficient number of groups.\n"); } } else { printf("Not in single user mode.\n"); retval = 0; } return retval; }
__private_extern__ kern_return_t get_procno( const char *procname, int32_t *procno ) { kern_return_t status; security_token_t token; bool lookAgain; do { lookAgain = false; if (_ds_running() == 0) return KERN_FAILURE; if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; status = libinfoDSmig_GetProcedureNumber( _ds_port, (char *) procname, procno, &token ); switch( status ) { case MACH_SEND_INVALID_DEST: case MIG_SERVER_DIED: mach_port_mod_refs( mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1 ); _ds_port = MACH_PORT_NULL; lookAgain = true; break; case KERN_SUCCESS: // is there a security call to parse this private token? if ( token.val[0] != 0 ) { (*procno) = -1; status = KERN_FAILURE; } break; default: break; } } while ( lookAgain == true ); return status; }
__private_extern__ kern_return_t ds_lookup( int32_t procno, kvbuf_t *request, kvarray_t **answer ) { kern_return_t status; security_token_t token; bool lookAgain; mach_msg_type_number_t oolen = 0; vm_address_t oobuf = 0; char ilbuf[MAX_MIG_INLINE_DATA]; mach_msg_type_number_t illen = 0; do { lookAgain = false; if ( _ds_running() == 0 ) return KERN_FAILURE; if ( _ds_port == MACH_PORT_NULL ) return KERN_FAILURE; if ( request == NULL ) return KERN_FAILURE; status = libinfoDSmig_Query( _ds_port, procno, request->databuf, request->datalen, ilbuf, &illen, &oobuf, &oolen, &token ); switch( status ) { case MACH_SEND_INVALID_DEST: case MIG_SERVER_DIED: mach_port_mod_refs( mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1 ); _ds_port = MACH_PORT_NULL; lookAgain = true; break; case KERN_SUCCESS: // is there a security call to parse this private token? if ( token.val[0] == 0 ) { if ( answer != NULL ) { kvbuf_t *tempBuf; if ( oolen != 0 ) { tempBuf = kvbuf_init( (char *)oobuf, (uint32_t) oolen ); } else { tempBuf = kvbuf_init( ilbuf, illen ); } (*answer) = kvbuf_decode( tempBuf ); if ( (*answer) == NULL ) { kvbuf_free( tempBuf ); } } } else { // response came from a process not running as root procno = -1; status = KERN_FAILURE; } break; default: break; } } while ( lookAgain == true ); if ( oolen != 0 ) { vm_deallocate( mach_task_self(), oobuf, oolen ); } return status; }