int recv_imc_msg(int channel, char *recvbuf, int bufsize, int *descp) { struct NaClAbiNaClImcMsgHdr msg_hdr; struct NaClAbiNaClImcMsgIoVec iov; int rv; msg_hdr.iov = &iov; msg_hdr.iov_length = 1; msg_hdr.descv = descp; msg_hdr.desc_length = NULL != descp; msg_hdr.flags = 0; iov.base = recvbuf; iov.length = bufsize; if (-1 == (rv = imc_recvmsg(channel, &msg_hdr, 0))) { fprintf(stderr, "imc_recvmsg returned %d\n", rv); fprintf(stderr, "errno %d\n", errno); exit(1); } if (0 != (msg_hdr.flags & (NACL_ABI_RECVMSG_DATA_TRUNCATED | NACL_ABI_RECVMSG_DESC_TRUNCATED))) { fprintf(stderr, "imc_recvmsg truncated: %d\n", msg_hdr.flags); exit(1); } if (msg_hdr.desc_length != (NULL != descp)) { fprintf(stderr, "icm_recvmsg: got wrong descriptor count\n"); exit(1); } return rv; }
/* * __NaClSrpcImcFillBuf fills buffer from an IMC channel. It returns 1 if * successful, and 0 otherwise. */ NaClSrpcImcBuffer* __NaClSrpcImcFillbuf(NaClSrpcChannel* channel) { NaClSrpcImcBuffer* buffer; ssize_t retval; buffer = &channel->receive_buf; buffer->iovec[0].base = buffer->bytes; buffer->iovec[0].length = sizeof(buffer->bytes); NACL_SRPC_IMC_HEADER_DESC_LENGTH(*buffer) = SRPC_DESC_MAX; #ifdef __native_client__ retval = imc_recvmsg(channel->imc_handle, &buffer->header, 0); #else retval = NaClImcRecvTypedMessage(channel->imc_handle, &buffer->header, 0); #endif buffer->next_desc = 0; if (!NaClSSizeIsNegErrno(&retval)) { channel->receive_buf.next_byte = 0; channel->receive_buf.last_byte = nacl_abi_size_t_saturate(retval); } else { dprintf((SIDE "SRPC: READ: read failed.\n")); return NULL; } return buffer; }
int main(void) { /* * There are two possible kinds of fault in trusted code: * 1) Faults legitimately triggered by untrusted code. These are * safe and do not indicate a bug. * 2) Faults caused by bugs in trusted code. * * Currently the signal handler does not distinguish between the * two. Ultimately, we do want to distinguish between them in order * to avoid misleading bug reports. * See http://code.google.com/p/nativeclient/issues/detail?id=579 * * Below, we trigger a memory access fault in trusted code, inside a * syscall handler. The imc_recvmsg() implementation does a * memcpy() from the address we give it. This is an instance of * (1). If we later extend the system to distinguish (1) and (2), * we will want to add a separate test case for (2). * * We use 0x1000 because we know that is unmapped. (If this changes * and the call fails to fault, the test runner will catch that.) * We don't use NULL because the syscall checks for NULL. */ fprintf(stderr, "About to crash\n"); fflush(stderr); int rc = imc_recvmsg(0, (struct NaClImcMsgHdr *) 0x1000, 0); if (rc < 0) { perror("imc_recvmsg"); } printf("We do not expect to reach here.\n"); return 1; }
static ssize_t ImcRecvmsg(NaClSrpcMessageDesc desc, NaClSrpcMessageHeader* header, int flags) { nacl_abi_ssize_t retval = imc_recvmsg(desc, header, flags); if (-1 == retval) { return -errno; } return retval; }
void domain2(void) { char buffer[100]; struct NaClImcMsgIoVec iov = { buffer, sizeof(buffer) - 1 }; struct NaClImcMsgHdr msg = { &iov, 1, NULL, 0, 0 }; int got = imc_recvmsg(RECEIVE_DESC, &msg, 0); assert(got >= 0); buffer[got] = 0; printf("In domain 2: Received message, \"%s\"\n", buffer); }
int receive_message(int sock_fd, char *data, size_t data_size, int *fds, int fds_size, int *fds_got) { struct NaClAbiNaClImcMsgIoVec iov; struct NaClAbiNaClImcMsgHdr msg; int received; iov.base = data; iov.length = data_size; msg.iov = &iov; msg.iov_length = 1; msg.descv = fds; msg.desc_length = fds_size; received = imc_recvmsg(sock_fd, &msg, 0); if (fds_got != NULL) *fds_got = msg.desc_length; return received; }
/* * Receive a message from the browser. */ static void ReceiveRequest(int d) { char recvbuf[kBufferSize]; struct NaClImcMsgHdr header; struct NaClImcMsgIoVec iovec[1]; int retval; /* Construct the IO vector to have one data payload. */ iovec[0].base = recvbuf; iovec[0].length = sizeof(recvbuf); /* Set the header to have the IO vector and no descriptors. */ header.iov = iovec; header.iov_length = sizeof(iovec) / sizeof(iovec[0]); header.descv = 0; header.desc_length = 0; /* Receive the message. */ retval = imc_recvmsg(d, &header, 0); if (0 >= retval) { fprintf(stderr, "Message not received: %d, errno %d.\n", retval, errno); exit(1); } }