Bool StrUtil_StrToSizet(size_t *out, // OUT: The output value const char *str) // IN : String to parse { char *ptr; ASSERT(out); ASSERT(str); errno = 0; #if defined VM_X86_64 ASSERT_ON_COMPILE(sizeof *out == sizeof(uint64)); # if defined(_WIN32) *out = _strtoui64(str, &ptr, 0); # elif defined(__FreeBSD__) *out = strtouq(str, &ptr, 0); # else *out = strtoull(str, &ptr, 0); # endif #else ASSERT_ON_COMPILE(sizeof *out == sizeof(uint32)); *out = strtoul(str, &ptr, 0); #endif return *ptr == '\0' && errno != ERANGE; }
int Posix_Open(const char *pathName, // IN: int flags, // IN: ...) // IN: { char *path; mode_t mode = 0; int fd; if (!PosixConvertToCurrent(pathName, &path)) { return -1; } if ((flags & O_CREAT) != 0) { va_list a; /* * The FreeBSD tools compiler * (toolchain/lin32/gcc-4.1.2-5/bin/i686-freebsd5.0-gcc) * wants us to use va_arg(a, int) instead of va_arg(a, mode_t), * so oblige. -- edward */ va_start(a, flags); ASSERT_ON_COMPILE(sizeof (int) >= sizeof(mode_t)); mode = va_arg(a, int); va_end(a); }
void PhysTrack_Add(PhysTracker *tracker, MPN mpn) { unsigned int p1; unsigned int p2; unsigned int p3; unsigned int pos; unsigned int bit; PhysTrackerL2 *dir2; PhysTrackerL3 *dir3; ASSERT(tracker); PHYSTRACK_MPN2IDX(mpn, p1, p2, p3); ASSERT(p1 < PHYSTRACK_L1_ENTRIES); dir2 = tracker->dir[p1]; if (!dir2) { // more efficient with page alloc ASSERT_ON_COMPILE(sizeof *dir2 == PAGE_SIZE); dir2 = HostIF_AllocPage(); if (!dir2) { PANIC(); } memset(dir2, 0, sizeof *dir2); tracker->dir[p1] = dir2; } dir3 = PHYSTRACK_ALLOCL3(dir2, p2); PHYSTRACK_GETL3POS(p3, pos, bit); if (dir3->bits[pos] & bit) { PANIC(); } dir3->bits[pos] |= bit; }
/** * @brief New timer request from monitor * @param monTimer Monitor timer * @param when64 Timer target value */ void MonitorTimer_Request(struct MonTimer *monTimer, uint64 when64) { if (when64) { ktime_t kt; /* * Simple conversion, assuming RATE64 is 1e+9 */ kt = ns_to_ktime(when64); ASSERT_ON_COMPILE(MVP_TIMER_RATE64 == 1000000000); /* * Start the timer. If it was already active, it will remove * the previous expiration time. Linux handles correctly timer * with deadline in the past, and forces a safety minimal delta * for closer timer deadlines. */ hrtimer_start(&monTimer->timer, kt, HRTIMER_MODE_ABS); } else { /* * Cancel a pending request. If there is none, this will do * nothing. If it's too late, monitor tolerance will forgive * us. */ hrtimer_cancel(&monTimer->timer); } }
static INLINE void * VThreadBaseGetNative(void) { /* All thread types must fit into a uintptr_t so we can set them atomically. */ #ifdef _WIN32 /* * On Windows, use a ThreadId instead of the thread handle, to avoid * holding a reference that is hard to clean up. */ ASSERT_ON_COMPILE(sizeof (DWORD) <= sizeof (void*)); return (void *)(uintptr_t)GetCurrentThreadId(); #else ASSERT_ON_COMPILE(sizeof (pthread_t) <= sizeof (void*)); return (void *)(uintptr_t)pthread_self(); #endif }
static int MXUserTimedDown(NativeSemaphore *sema, // IN: uint32 msecWait, // IN: Bool *downOccurred) // OUT: { uint64 nsecWait; VmTimeType before; kern_return_t err; ASSERT_ON_COMPILE(KERN_SUCCESS == 0); /* * Work in nanoseconds. Time the semaphore_timedwait operation in case * it is interrupted (KERN_ABORT). If it is, determine how much time is * necessary to fulfill the specified wait time and retry with a new * and appropriate timeout. */ nsecWait = 1000000ULL * (uint64) msecWait; before = Hostinfo_SystemTimerNS(); do { VmTimeType after; mach_timespec_t ts; ts.tv_sec = nsecWait / MXUSER_A_BILLION; ts.tv_nsec = nsecWait % MXUSER_A_BILLION; err = semaphore_timedwait(*sema, ts); after = Hostinfo_SystemTimerNS(); if (err == KERN_SUCCESS) { *downOccurred = TRUE; } else { *downOccurred = FALSE; if (err == KERN_OPERATION_TIMED_OUT) { /* Really timed out; no down occurred, no error */ err = KERN_SUCCESS; } else { if (err == KERN_ABORTED) { VmTimeType duration = after - before; if (duration < nsecWait) { nsecWait -= duration; before = after; } else { err = KERN_SUCCESS; // "timed out" anyway... no error } } } } } while (nsecWait && (err == KERN_ABORTED)); return err; }
static AuthorizationRef IdAuthCreate(void) { /* * Bug 195868: If thread credentials are in use, we need to fork. * Otherwise, avoid forking, as it breaks Apple's detection of * whether the calling process is a GUI process. * * This is needed because AuthorizationRefs created by GUI * processes can be passed to non-GUI processes to allow them to * prompt for authentication with a dialog that automatically * steals focus from the current GUI app. (This is how the Mac UI * and VMX work today.) * * TODO: How should we handle single-threaded apps where uid != * euid or gid != egid? Some callers may expect us to check * against euid, others may expect us to check against uid. */ uid_t thread_uid; gid_t thread_gid; int ret; ret = syscall(SYS_gettid, &thread_uid, &thread_gid); if (ret != -1) { /* * We have per-thread UIDs in use, so Apple's authorization * APIs don't work. Fork so we can use them. */ return IdAuthCreateWithFork(); } else { if (errno != ESRCH) { Warning("%s: gettid failed, error %d.\n", __func__, errno); return NULL; } else { // Per-thread identities are not in use in this thread. AuthorizationRef auth; OSStatus ret; ret = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth); if (ret == errAuthorizationSuccess) { return auth; } else { ASSERT_ON_COMPILE(sizeof ret == sizeof (int32)); Warning("%s: AuthorizationCreate failed, error %d.\n", __func__, (int32)ret); return NULL; } } } }
static bool_t DynXdrPutLong(XDR *xdrs, // IN/OUT DYNXDR_CONST DYNXDR_LONG *lp) // IN { int32 out; DynXdrData *priv = (DynXdrData *) xdrs->x_private; #ifdef __APPLE__ ASSERT_ON_COMPILE(sizeof *lp <= sizeof (int32)); #endif out = htonl((int32)*lp); return DynBuf_Append(&priv->data, &out, sizeof out); }
void MonitorTimer_Request(MonTimer *monTimer, uint64 when64) { if (when64) { ktime_t kt; kt = ns_to_ktime(when64); ASSERT_ON_COMPILE(MVP_TIMER_RATE64 == 1000000000); hrtimer_start(&monTimer->timer, kt, HRTIMER_MODE_ABS); } else { hrtimer_cancel(&monTimer->timer); } }
/** * Sends a command to the Sandbox daemon's MMC driver. * * @param mmc Pointer to device * @param cmd Pointer to device command * @param data Pointer to device data * Result == 0 -> success * Result != 0 -> failure */ static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct doorbell_t *db = sandbox_get_doorbell(); struct doorbell_command_t *dbc = sandbox_get_doorbell_command(); const unsigned is_sandbox_mem = (data != NULL && sandbox_in_shared_memory(data->dest)); const unsigned device = get_device(mmc); db->mmc[device].mmc_capacity = mmc->capacity; ASSERT_ON_COMPILE(ARRAY_SIZE(db->mmc) == 2); dbc->device_id = device == 0 ? SB_MMC0 : SB_MMC1; dbc->command_data[0] = cmd->cmdidx; dbc->command_data[1] = cmd->resp_type; dbc->command_data[2] = cmd->cmdarg; dbc->command_data[3] = cmd->flags; dbc->command_data[4] = 0; dbc->command_data[5] = 0; dbc->command_data[6] = 0; dbc->command_data[7] = 0; if (data != NULL) { /* * If the data buffer is not in shared memory, then * it's likely a stack variable in the MMC driver. * The sandbox-daemon does not have access to that * memory, so use a local buffer for the transfer. */ dbc->command_data[4] = (__u32)(uintptr_t)data->dest; dbc->command_data[5] = data->flags; dbc->command_data[6] = data->blocks; dbc->command_data[7] = data->blocksize; if (!is_sandbox_mem) dbc->command_data[4] = (__u32)(uintptr_t)dbc->dbc_buf; } sandbox_ring_doorbell(); if (data != NULL && !is_sandbox_mem) memcpy(data->dest, dbc->dbc_buf, data->blocks * data->blocksize); cmd->response[0] = dbc->command_data[8]; cmd->response[1] = dbc->command_data[9]; cmd->response[2] = dbc->command_data[10]; cmd->response[3] = dbc->command_data[11]; return dbc->result; }
char * print_time_local_short(uint32 time) { char str[128]; struct tm *ts; time_t t = time; ASSERT_ON_COMPILE(sizeof t == sizeof(time_t)); memset(str, 0, sizeof str); ts = localtime(&t); if (ts) { strftime(str, sizeof str, "%d %b %T", ts); } return safe_strdup(str); }
void blockstore_write_headers(struct blockstore *bs) { btc_block_header *buf; struct blockentry *e; size_t numWritten; uint32 count; uint32 numhdr; int res; e = bs->best_chain; count = 0; while (e && e->written == 0) { e = e->prev; count++; } ASSERT(count < 2048); numhdr = count; if (count == 0) { return; } buf = safe_malloc(count * sizeof *buf); e = bs->best_chain; while (e && e->written == 0) { count--; memcpy(buf + count, &e->header, sizeof e->header); e->written = 1; e = e->prev; } ASSERT(count == 0); ASSERT(bs->blockSet); ASSERT_ON_COMPILE(sizeof *buf == 80); res = file_pwrite(bs->blockSet->desc, bs->blockSet->filesize, buf, numhdr * sizeof *buf, &numWritten); free(buf); if (res != 0 || numWritten != numhdr * sizeof *buf) { Warning(LGPFX" failed to write %u block entries.\n", numhdr); return; } bs->blockSet->filesize += numWritten; }
char * print_time_local(uint32 time, const char *fmt) { char str[128]; struct tm *ts; time_t t = time; ASSERT_ON_COMPILE(sizeof t == sizeof(time_t)); memset(str, 0, sizeof str); ts = localtime(&t); if (ts) { strftime(str, sizeof str, fmt, ts); } return safe_strdup(str); }
void ToolsCore_DumpState(ToolsServiceState *state) { guint i; const char *providerStates[] = { "idle", "active", "error" }; ASSERT_ON_COMPILE(ARRAYSIZE(providerStates) == TOOLS_PROVIDER_MAX); if (!g_main_loop_is_running(state->ctx.mainLoop)) { ToolsCore_LogState(TOOLS_STATE_LOG_ROOT, "VM Tools Service '%s': not running.\n", state->name); return; } ToolsCore_LogState(TOOLS_STATE_LOG_ROOT, "VM Tools Service '%s':\n", state->name); ToolsCore_LogState(TOOLS_STATE_LOG_CONTAINER, "Plugin path: %s\n", state->pluginPath); for (i = 0; i < state->providers->len; i++) { ToolsAppProviderReg *prov = &g_array_index(state->providers, ToolsAppProviderReg, i); ToolsCore_LogState(TOOLS_STATE_LOG_CONTAINER, "App provider: %s (%s)\n", prov->prov->name, providerStates[prov->state]); if (prov->prov->dumpState != NULL) { prov->prov->dumpState(&state->ctx, prov->prov, NULL); } } ToolsCore_DumpPluginInfo(state); g_signal_emit_by_name(state->ctx.serviceObj, TOOLS_CORE_SIG_DUMP_STATE, &state->ctx); }
static INLINE_SINGLE_CALLER PhysTrackerL3 * PhysTrackAllocL3(PhysTrackerL2 *dir2, unsigned int p2) { PhysTrackerL3 *dir3; dir3 = dir2->dir[p2]; if (!dir3) { ASSERT_ON_COMPILE(sizeof *dir3 == PAGE_SIZE); dir3 = HostIF_AllocPage(); if (!dir3) { PANIC(); } memset(dir3, 0, sizeof *dir3); dir2->dir[p2] = dir3; } return dir3; }
Bool VSockAddr_SocketContextStream(uint32 cid) // IN { uint32 i; VMCIId nonSocketContexts[] = { VMCI_HYPERVISOR_CONTEXT_ID, VMCI_WELL_KNOWN_CONTEXT_ID, }; ASSERT_ON_COMPILE(sizeof cid == sizeof *nonSocketContexts); for (i = 0; i < ARRAYSIZE(nonSocketContexts); i++) { if (cid == nonSocketContexts[i]) { return FALSE; } } return TRUE; }
int sandbox_mmc_init(int verbose) { struct doorbell_t *db = sandbox_get_doorbell(); unsigned i; ASSERT_ON_COMPILE(ARRAY_SIZE(db->mmc) == ARRAY_SIZE(mmc_dev)); if (!db->mmc[0].mmc_enabled) /* No MMC devices. */ return -ENODEV; for (i = 0; i < ARRAY_SIZE(db->mmc); ++i) { if (db->mmc[i].mmc_enabled) { /* Only device 0 is a removable device */ register_mmc_device(&mmc_dev[i]); mmc_dev[1].block_dev.removable = i == 0; } } return 0; }
int HgfsConvertFromNtTimeNsec(struct timespec *unixTime, // OUT: Time in UNIX format uint64 ntTime) // IN: Time in Windows NT format { #if !defined(VM_X86_64) && !defined(__arm__) uint32 sec; uint32 nsec; ASSERT(unixTime); /* We assume that time_t is 32bit */ ASSERT_ON_COMPILE(sizeof (unixTime->tv_sec) == 4); /* Cap NT time values that are outside of Unix time's range */ if (ntTime >= UNIX_S32_MAX) { unixTime->tv_sec = 0x7FFFFFFF; unixTime->tv_nsec = 0; return 1; } #else ASSERT(unixTime); #endif if (ntTime < UNIX_EPOCH) { unixTime->tv_sec = 0; unixTime->tv_nsec = 0; return -1; } #if !defined(VM_X86_64) && !defined(__arm__) Div643232(ntTime - UNIX_EPOCH, 10000000, &sec, &nsec); unixTime->tv_sec = sec; unixTime->tv_nsec = nsec * 100; #else unixTime->tv_sec = (ntTime - UNIX_EPOCH) / 10000000; unixTime->tv_nsec = ((ntTime - UNIX_EPOCH) % 10000000) * 100; #endif return 0; }
int VMCIDatagram_Dispatch(VMCIId contextID, VMCIDatagram *dg, Bool fromGuest) { int retval; VMCIRoute route; ASSERT(dg); ASSERT_ON_COMPILE(sizeof(VMCIDatagram) == 24); if (VMCI_DG_SIZE(dg) > VMCI_MAX_DG_SIZE) { VMCI_DEBUG_LOG(4, (LGPFX"Payload (size=%"FMT64"u bytes) too big to " "send.\n", dg->payloadSize)); return VMCI_ERROR_INVALID_ARGS; } retval = VMCI_Route(&dg->src, &dg->dst, fromGuest, &route); if (retval < VMCI_SUCCESS) { VMCI_DEBUG_LOG(4, (LGPFX"Failed to route datagram (src=0x%x, dst=0x%x, " "err=%d)\n.", dg->src.context, dg->dst.context, retval)); return retval; } if (VMCI_ROUTE_AS_HOST == route) { if (VMCI_INVALID_ID == contextID) { contextID = VMCI_HOST_CONTEXT_ID; } return VMCIDatagramDispatchAsHost(contextID, dg); } if (VMCI_ROUTE_AS_GUEST == route) { return VMCIDatagramDispatchAsGuest(dg); } VMCI_WARNING((LGPFX"Unknown route (%d) for datagram.\n", route)); return VMCI_ERROR_DST_UNREACHABLE; }
/** * Returns the device number of 'dev'. * * @param dev Pointer into array 'mmc_dev' * Result == 0 -> &mmc_dev[0] * Result == 1 -> &mmc_dev[1] */ static unsigned get_device(const struct mmc *dev) { ASSERT_ON_COMPILE(ARRAY_SIZE(mmc_dev) == 2); return dev == &mmc_dev[1]; }
gboolean ToolsDaemonHgfsImpersonated(RpcInData *data) // IN { VixError err; size_t hgfsPacketSize = 0; size_t hgfsReplySize = 0; const char *origArgs = data->args; Bool impersonatingVMWareUser = FALSE; char *credentialTypeStr = NULL; char *obfuscatedNamePassword = NULL; void *userToken = NULL; int actualUsed; #define STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING 20 #define OTHER_TEXT_SIZE 4 /* strlen(space zero space quote) */ static char resultPacket[STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE + HGFS_LARGE_PACKET_MAX]; char *hgfsReplyPacket = resultPacket + STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE; Debug(">ToolsDaemonHgfsImpersonated\n"); err = VIX_OK; /* * We assume VixError is 64 bits. If it changes, we need * to adjust STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING. * * There isn't much point trying to return gracefully * if sizeof(VixError) is larger than we expected: we didn't * allocate enough space to actually represent the error! * So we're stuck. Panic at this point. */ ASSERT_ON_COMPILE(sizeof (uint64) == sizeof err); /* * Get the authentication information. */ credentialTypeStr = ToolsDaemonTcloGetQuotedString(data->args, &data->args); obfuscatedNamePassword = ToolsDaemonTcloGetQuotedString(data->args, &data->args); /* * Make sure we are passed the correct arguments. */ if ((NULL == credentialTypeStr) || (NULL == obfuscatedNamePassword)) { err = VIX_E_INVALID_ARG; goto abort; } /* * Skip over our token that is right before the HGFS packet. * This makes ToolsDaemonTcloGetQuotedString parsing predictable, * since it will try to eat trailing spaces after a quoted string, * and the HGFS packet might begin with a space. */ if (((data->args - origArgs) >= data->argsSize) || ('#' != *(data->args))) { /* * Buffer too small or we got an unexpected token. */ err = VIX_E_FAIL; goto abort; } data->args++; /* * At this point args points to the HGFS packet. * If we're pointing beyond the end of the buffer, we'll * get a negative HGFS packet length and abort. */ hgfsPacketSize = data->argsSize - (data->args - origArgs); if (hgfsPacketSize <= 0) { err = VIX_E_FAIL; goto abort; } if (thisProcessRunsAsRoot) { impersonatingVMWareUser = VixToolsImpersonateUserImpl(credentialTypeStr, VIX_USER_CREDENTIAL_NONE, obfuscatedNamePassword, &userToken); if (!impersonatingVMWareUser) { err = VIX_E_GUEST_USER_PERMISSIONS; goto abort; } } /* * Impersonation was okay, so let's give our packet to * the HGFS server and forward the reply packet back. */ hgfsReplySize = sizeof resultPacket - (hgfsReplyPacket - resultPacket); HgfsServerManager_ProcessPacket(&gFoundryHgfsBkdrConn, // hgfs server connection data->args, // packet in buf hgfsPacketSize, // packet in size hgfsReplyPacket, // packet out buf &hgfsReplySize); // reply buf/data size abort: if (impersonatingVMWareUser) { VixToolsUnimpersonateUser(userToken); } VixToolsLogoutUser(userToken); /* * These were allocated by ToolsDaemonTcloGetQuotedString. */ free(credentialTypeStr); free(obfuscatedNamePassword); data->result = resultPacket; data->resultLen = STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE + hgfsReplySize; /* * Render the foundry error codes into the buffer. */ actualUsed = Str_Snprintf(resultPacket, STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE, "%"FMT64"d 0 ", err); if (actualUsed < 0) { /* * We computed our string length wrong! This should never happen. * But if it does, let's try to recover gracefully. The "1" in * the string below is VIX_E_FAIL. We don't try to use %d since * we couldn't even do that right the first time around. * That hash is needed for the parser on the other * end to stop before the HGFS packet, since the HGFS packet * can contain a space (and the parser can eat trailing spaces). */ ASSERT(0); actualUsed = Str_Snprintf(resultPacket, STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING, "1 0 #"); data->resultLen = actualUsed; } else { /* * We computed the string length correctly. Great! * * We allocated enough space to cover a large 64 bit number * for VixError. Chances are we didn't use all that space. * Instead, pad it with whitespace so the text parser can skip * over it. */ memset(resultPacket + actualUsed, ' ', STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE - actualUsed); /* * Put a hash right before the HGFS packet. * So the buffer will look something like this: * "0 0 #" followed by the HGFS packet. */ resultPacket[STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE - 1] = '#'; } Debug("<<<ToolsDaemonHgfsImpersonated\n"); return TRUE; } // ToolsDaemonHgfsImpersonated