static ssize_t ExampleDescRecvMsg(void *handle, struct NaClImcTypedMsgHdr *msg, int flags) { ssize_t result = 0; uint32_t index; CHECK(handle == g_handle); CHECK(msg->flags == 0); CHECK(flags == 0); /* * ndesc_length tells us how large the buffer is. *Currently*, the * syscall allocates the same size buffer regardless of the buffer * size that untrusted code provided. Furthermore, the buffer is * filled with NULLs to guard against RecvMsg() forgetting to set * ndesc_length. However, a RecvMsg() implementation should not * rely on either of these things. */ CHECK(msg->ndesc_length == NACL_ABI_IMC_DESC_MAX); for (index = 0; index < msg->ndesc_length; index++) { CHECK(msg->ndescv[index] == NULL); } if (g_desc_state == REPLY_WITH_DATA_ONLY) { result = WriteReplyData(msg, "test_receiving_data_only"); /* * TODO(mseaborn): RecvMsg() currently has to set ndesc_length to * indicate how many descriptors are in the message. Since * ndesc_length is used as an input and output parameter, there is * no way for a caller of RecvMsg() to have an assertion to check * whether RecvMsg() has forgotten to set ndesc_length. We might * want to change this so that there are separate input and output * parameters. */ msg->ndesc_length = 0; /* * TODO(mseaborn): RecvMsg() currently receives a pointer into * untrusted address space. We might want to change things so * that RecvMsg() does not write directly into untrusted address * space. */ CHECK(msg->iov_length == 1); CHECK(NaClIsUserAddr(g_nap, (uintptr_t) msg->iov[0].base)); } else if (g_desc_state == REPLY_WITH_DESCS) { result = WriteReplyData(msg, "test_receiving_descs"); /* * A non-test implementation would truncate the descriptor array * if the buffer were too small, rather than producing a fatal * error. */ CHECK(msg->ndesc_length >= 2); msg->ndescv[0] = MakeExampleDesc(); msg->ndescv[1] = MakeExampleDesc(); msg->ndesc_length = 2; } else { NaClLog(LOG_FATAL, "RecvMsg called while in an expected state\n"); } g_desc_state = REPLY_UNEXPECTED; return result; }
int NaClMachThreadStateIsInUntrusted(x86_thread_state_t *state, size_t nacl_thread_index) { #if NACL_BUILD_SUBARCH == 32 uint16_t global_cs; UNREFERENCED_PARAMETER(nacl_thread_index); CHECK(state->tsh.flavor == x86_THREAD_STATE32); global_cs = NaClGetGlobalCs(); /* * If global_cs is 0 (which is not a usable segment selector), the * sandbox has not been initialised yet, so there can be no untrusted * code running. */ if (global_cs == 0) { return 0; } return state->uts.ts32.__cs != global_cs; #elif NACL_BUILD_SUBARCH == 64 struct NaClAppThread *natp; CHECK(state->tsh.flavor == x86_THREAD_STATE64); natp = NaClAppThreadGetFromIndex(nacl_thread_index); return NaClIsUserAddr(natp->nap, state->uts.ts64.__rip); #endif /* NACL_BUILD_SUBARCH */ }
static ssize_t ExampleDescSendMsg(void *handle, const struct NaClImcTypedMsgHdr *msg, int flags) { int result_code = 100; CHECK(handle == g_handle); CHECK(msg->flags == 0); CHECK(flags == 0); if (MessageDataMatches(msg, "test_sending_data_only")) { CHECK(msg->ndesc_length == 0); /* * TODO(mseaborn): SendMsg() currently receives a pointer into * untrusted address space. We might want to change things so * that SendMsg() receives a copy of the message data. */ CHECK(msg->iov_length == 1); CHECK(NaClIsUserAddr(g_nap, (uintptr_t) msg->iov[0].base)); result_code = 101; } else if (MessageDataMatches(msg, "test_sending_descs")) { uint32_t index; for (index = 0; index < msg->ndesc_length; index++) { CHECK(msg->ndescv[index] == g_expected_desc); } CHECK(msg->ndesc_length == 2); result_code = 102; } else if (MessageDataMatches(msg, "request_receiving_data_only")) { CHECK(msg->ndesc_length == 0); g_desc_state = REPLY_WITH_DATA_ONLY; result_code = 200; } else if (MessageDataMatches(msg, "request_receiving_descs")) { CHECK(msg->ndesc_length == 0); g_desc_state = REPLY_WITH_DESCS; result_code = 200; } else { NaClLog(LOG_FATAL, "Unexpected message\n"); } /* * imc_sendmsg() is normally expected to return the number of bytes * that were sent, but the custom descriptor can assign whatever * meaning it wants to the return value. Here, for testing, we use * the return value to indicate which message was matched. */ return result_code; }