/* ### * get the fully qualified ip address from swift daemon * populate given NaClAppThread object with channel info * return 0 when success, otherwise - nacl error code */ int32_t ZMQSysOpen(struct NaClAppThread *natp, char *name, int flags, int mode) { int32_t retval = 0; struct NaClHostDesc *hd; NaClLog(3, "Entered ZMQSysOpen(natp, %s, %X, %X)\n", name, flags, mode); /* ### dummy * just open the local file w/o "http://" prefix to test this function * example of file name: "http://dummy_zmq.dat" (will open "dummy_zmq.dat") */ hd = malloc(sizeof *hd); if (NULL == hd) { return -NACL_ABI_ENOMEM; } /* add extra info to hd */ // strcpy(hd->channel, name); // ### NaClLog(1, "NaClHostDescOpen(0x%08"NACL_PRIxPTR", %s, 0%o, 0%o) returned %d\n", (uintptr_t) hd, name + URL_MARK_SIZE - 1, flags, mode, retval); /* add a new record to the file descriptors table */ if (0 == retval) { retval = NaClSetAvail(natp->nap, ((struct NaClDesc *) NaClDescIoDescMake(hd))); NaClLog(1, "Entered url into open file table at %d\n", retval); } /* ### log to remove. i only use it to debug this class */ // NaClLog(1, "int32_t ZMQSysOpen(struct NaClAppThread *natp, char " // "*pathname, int flags, int mode): channel == %s, desc == %d\n", hd->channel, hd->d); return retval; }
/* * Look up by string name, resulting in a handle (if name is in the * preimage), a object proxy handle, and an error code. */ static void NaClReverseServiceManifestLookupRpc( struct NaClSrpcRpc *rpc, struct NaClSrpcArg **in_args, struct NaClSrpcArg **out_args, struct NaClSrpcClosure *done_cls) { struct NaClReverseService *nrsp = (struct NaClReverseService *) rpc->channel->server_instance_data; char *url_key = in_args[0]->arrays.str; int flags = in_args[0]->u.ival; struct NaClFileInfo info; struct NaClHostDesc *host_desc; struct NaClDescIoDesc *io_desc = NULL; struct NaClDesc *nacl_desc = NULL; memset(&info, 0, sizeof(info)); NaClLog(4, "Entered ManifestLookupRpc: 0x%08"NACL_PRIxPTR", %s, %d\n", (uintptr_t) nrsp, url_key, flags); NaClLog(4, "ManifestLookupRpc: invoking OpenManifestEntry\n"); if (!(*NACL_VTBL(NaClReverseInterface, nrsp->iface)-> OpenManifestEntry)(nrsp->iface, url_key, &info) || -1 == info.desc) { NaClLog(1, "ManifestLookupRpc: OpenManifestEntry failed.\n"); out_args[0]->u.ival = NACL_ABI_ENOENT; /* failed */ out_args[1]->u.hval = (struct NaClDesc *) NaClDescInvalidMake(); out_args[2]->u.lval = 0; out_args[3]->u.lval = 0; out_args[4]->u.count = 0; goto done; } NaClLog(4, "ManifestLookupRpc: OpenManifestEntry returned desc %d.\n", info.desc); host_desc = (struct NaClHostDesc *) malloc(sizeof *host_desc); CHECK(host_desc != NULL); CHECK(NaClHostDescPosixTake(host_desc, info.desc, NACL_ABI_O_RDONLY) == 0); io_desc = NaClDescIoDescMake(host_desc); CHECK(io_desc != NULL); nacl_desc = (struct NaClDesc *) io_desc; out_args[0]->u.ival = 0; /* OK */ out_args[1]->u.hval = nacl_desc; out_args[2]->u.lval = (int64_t) info.file_token.lo; out_args[3]->u.lval = (int64_t) info.file_token.hi; out_args[4]->u.count = 10; strncpy(out_args[4]->arrays.carr, "123456789", 10); /* * TODO(phosek): the array should be an object reference (issue 3035). */ done: rpc->result = NACL_SRPC_RESULT_OK; (*done_cls->Run)(done_cls); NaClDescSafeUnref((struct NaClDesc *) io_desc); }
struct NaClDescIoDesc *NaClDescIoDescOpen(char *path, int mode, int perms) { struct NaClHostDesc *nhdp; nhdp = malloc(sizeof *nhdp); if (NULL == nhdp) { NaClLog(LOG_FATAL, "NaClDescIoDescOpen: no memory for %s\n", path); } if (0 != NaClHostDescOpen(nhdp, path, mode, perms)) { NaClLog(LOG_FATAL, "NaClDescIoDescOpen: NaClHostDescOpen failed for %s\n", path); } return NaClDescIoDescMake(nhdp); }
struct NaClDesc *NaClDescIoDescFromDescAllocCtor(int desc, int flags) { struct NaClHostDesc *nhdp; nhdp = NaClHostDescPosixMake(desc, flags); if (NULL == nhdp) { /* * BUG: In Windows, we leak posix_d representation in the POSIX * layer, since caller will continue to own |handle| on a failure * return, but we cannot close |posix_d| without implicitly * invoking CloseHandle on |handle|. */ return NULL; } return (struct NaClDesc *) NaClDescIoDescMake(nhdp); }
struct NaClDesc *NaClDescIoDescMakeFromHandle(NaClHandle handle) { int posix_d; struct NaClHostDesc *nhdp; struct NaClDescIoDesc *desc; #if NACL_WINDOWS posix_d = _open_osfhandle((intptr_t) handle, _O_RDWR | _O_BINARY); if (-1 == posix_d) return NULL; #else posix_d = handle; #endif nhdp = NaClHostDescPosixMake(posix_d, NACL_ABI_O_RDWR); if (NULL == nhdp) return NULL; desc = NaClDescIoDescMake(nhdp); return &desc->base; }
/* * premap given file (channel). return 0 if success, otherwise negative errcode * note: malloc() */ int PremapChannel(struct NaClApp *nap, struct PreOpenedFileDesc* channel) { int desc; struct NaClHostDesc *hd = malloc(sizeof(*hd)); /* debug checks */ COND_ABORT(!hd, "cannot allocate memory to hold channel descriptor\n"); COND_ABORT(!channel, "channel is not constructed\n"); COND_ABORT(channel->mounted != MAPPED, "channel is not supposed to be mapped\n"); COND_ABORT(!channel->name, "cannot resolve channel name\n"); /* open file */ channel->handle = open((char*)channel->name, GetChannelOpenFlags(channel), S_IRWXU); COND_ABORT(channel->handle < 0, "channel open error\n"); /* check if given file in bounds of manifest limits */ channel->fsize = GetFileSize((char*)channel->name); PreallocateChannel(channel); COND_ABORT(channel->max_size < channel->fsize, "channel legnth exceeded policy limit\n"); /* construct nacl descriptor */ hd->d = channel->handle; desc = NaClSetAvail(nap, ((struct NaClDesc *) NaClDescIoDescMake(hd))); /* map whole file into the memory. address cannot be higher than stack */ channel->buffer = NaClCommonSysMmapIntern(nap, NULL, channel->fsize, GetChannelMapProt(channel), GetChannelMapFlags(channel), desc, 0); COND_ABORT((uint32_t)channel->buffer > 0xFF000000, "channel map error\n"); /* mounting finalization */ close(channel->handle); channel->bsize = channel->fsize; /* yes. mapped file always put to memory whole */ channel->handle = -1; /* there is no opened file for mapped channel */ return 0; }
int32_t NaClSysOpen(struct NaClAppThread *natp, uint32_t pathname, int flags, int mode) { struct NaClApp *nap = natp->nap; uint32_t retval = -NACL_ABI_EINVAL; char path[NACL_CONFIG_PATH_MAX]; nacl_host_stat_t stbuf; int allowed_flags; NaClLog(3, "NaClSysOpen(0x%08"NACL_PRIxPTR", " "0x%08"NACL_PRIx32", 0x%x, 0x%x)\n", (uintptr_t) natp, pathname, flags, mode); if (!NaClAclBypassChecks) { return -NACL_ABI_EACCES; } retval = CopyPathFromUser(nap, path, sizeof path, (uintptr_t) pathname); if (0 != retval) goto cleanup; allowed_flags = (NACL_ABI_O_ACCMODE | NACL_ABI_O_CREAT | NACL_ABI_O_EXCL | NACL_ABI_O_TRUNC | NACL_ABI_O_APPEND | NACL_ABI_O_DIRECTORY); if (0 != (flags & ~allowed_flags)) { NaClLog(LOG_WARNING, "Invalid open flags 0%o, ignoring extraneous bits\n", flags); flags &= allowed_flags; } if (0 != (mode & ~0600)) { NaClLog(1, "IGNORING Invalid access mode bits 0%o\n", mode); mode &= 0600; } /* * Perform a stat to determine whether the file is a directory. * * NB: it is okay for the stat to fail, since the request may be to * create a new file. * * There is a race conditions here: between the stat and the * open-as-a-file and open-as-a-dir, the type of the object that the * path refers to can change. */ retval = NaClHostDescStat(path, &stbuf); /* Windows does not have S_ISDIR(m) macro */ if (0 == retval && S_IFDIR == (S_IFDIR & stbuf.st_mode)) { struct NaClHostDir *hd; /* * Directories cannot be opened with O_EXCL. Technically, due to the above * race condition we might no longer be dealing with a directory, but * until the race is fixed this is best we can do. */ if (flags & NACL_ABI_O_EXCL) { retval = -NACL_ABI_EEXIST; goto cleanup; } hd = malloc(sizeof *hd); if (NULL == hd) { retval = -NACL_ABI_ENOMEM; goto cleanup; } retval = NaClHostDirOpen(hd, path); NaClLog(1, "NaClHostDirOpen(0x%08"NACL_PRIxPTR", %s) returned %d\n", (uintptr_t) hd, path, retval); if (0 == retval) { retval = NaClAppSetDescAvail( nap, (struct NaClDesc *) NaClDescDirDescMake(hd)); NaClLog(1, "Entered directory into open file table at %d\n", retval); } } else { struct NaClHostDesc *hd; if (flags & NACL_ABI_O_DIRECTORY) { retval = -NACL_ABI_ENOTDIR; goto cleanup; } hd = malloc(sizeof *hd); if (NULL == hd) { retval = -NACL_ABI_ENOMEM; goto cleanup; } retval = NaClHostDescOpen(hd, path, flags, mode); NaClLog(1, "NaClHostDescOpen(0x%08"NACL_PRIxPTR", %s, 0%o, 0%o) returned %d\n", (uintptr_t) hd, path, flags, mode, retval); if (0 == retval) { struct NaClDesc *desc = (struct NaClDesc *) NaClDescIoDescMake(hd); if ((flags & NACL_ABI_O_ACCMODE) == NACL_ABI_O_RDONLY) { /* * Let any read-only open be used for PROT_EXEC mmap * calls. Under -a, the user informally warrants that * files' code segments won't be changed after open. */ NaClDescSetFlags(desc, NaClDescGetFlags(desc) | NACL_DESC_FLAGS_MMAP_EXEC_OK); } retval = NaClAppSetDescAvail(nap, desc); NaClLog(1, "Entered into open file table at %d\n", retval); } } cleanup: return retval; }
int main(int ac, char **av) { int opt; char const *message = NULL; char *conn_addr = NULL; ssize_t rv; struct NaClDesc *channel; struct NaClNrdXferEffector eff; struct NaClDescEffector *effp; struct NaClDesc *pair[2]; struct NaClSocketAddress nsa; struct NaClDescConnCap ndcc; struct NaClImcTypedMsgHdr msg_hdr; struct NaClImcMsgIoVec iov[1]; struct NaClDesc *desc_buffer[NACL_ABI_IMC_USER_DESC_MAX]; char data_buffer[4096]; size_t i; char *transfer_file = NULL; printf("Hello world\n"); NaClNrdAllModulesInit(); printf("Learning to walk... (parsing command line)\n"); while (EOF != (opt = getopt(ac, av, "c:m:st:v"))) { switch (opt) { case 'c': conn_addr = optarg; break; case 'm': message = optarg; break; case 's': server = 1; break; case 't': transfer_file = optarg; break; case 'v': NaClLogIncrVerbosity(); break; default: fprintf(stderr, "Usage: nrd_xfer_test [-sv] [-c connect-addr] [-m message]\n" " [-t transfer_file_name]\n" "\n"); fprintf(stderr, " -s run in server mode (prints NaCl sock addr)\n" " -v increases verbosity in the NRD xfer library\n" " -c run in client mode, with server NaCl sock addr as\n" " parameter\n" " -m message to be sent to peer (client sends message\n" " as payload data in IMC datagram; and if -t was\n" " specifed in the client to transfer a file\n" " descriptor to the server, the server will write its\n" " message into the file via the transferred\n" " descriptor\n"); return 1; } } printf("Learning to talk... (setting up channels)\n"); if (NULL == message) { if (server) { message = "\"Hello world!\", from server\n"; } else { message = "\"Goodbye cruel world!\", from client\n"; } } if (0 != (rv = NaClCommonDescMakeBoundSock(pair))) { fprintf(stderr, "make bound sock returned %"NACL_PRIdS"\n", rv); return 2; } if (!NaClNrdXferEffectorCtor(&eff, pair[0])) { fprintf(stderr, "EffectorCtor failed\n"); return 3; } effp = (struct NaClDescEffector *) &eff; memset(desc_buffer, 0, sizeof desc_buffer); memset(data_buffer, 0, sizeof data_buffer); if (server) { /* * print out our sockaddr, accept a connection, then receive a message, * and print it out */ /* not opaque type */ printf("Server socket address:\n%.*s\n", NACL_PATH_MAX, ((struct NaClDescConnCap *) pair[1])->cap.path); fflush(stdout); if (0 != (rv = (*pair[0]->vtbl->AcceptConn)(pair[0], effp))) { fprintf(stderr, "AcceptConn returned %"NACL_PRIdS"\n", rv); return 4; } channel = NaClNrdXferEffectorTakeDesc(&eff); if (NULL == channel) { fprintf(stderr, "Could not take descriptor from accept\n"); return 5; } iov[0].base = data_buffer; iov[0].length = sizeof data_buffer; msg_hdr.iov = iov; msg_hdr.iov_length = NACL_ARRAY_SIZE(iov); msg_hdr.ndescv = desc_buffer; msg_hdr.ndesc_length = NACL_ARRAY_SIZE(desc_buffer); rv = NaClImcRecvTypedMessage(channel, effp, &msg_hdr, 0); printf("Receive returned %"NACL_PRIdS"\n", rv); if (!NaClIsNegErrno(rv)) { /* Sanity check: make sure the return value is within range. * This is a panic check because NaClImcRecvTypedMessage should * never return more than the amount of data we asked for, and * that should never be more than INT_MAX. */ if(((size_t)rv > sizeof data_buffer) || (rv > INT_MAX)) { NaClLog(LOG_FATAL, "Buffer overflow in NaClImcRecvTypedMessage. " "Requested %"NACL_PRIdS" bytes, received %"NACL_PRIdS".", sizeof data_buffer, rv); } /* Casting rv to int here because otherwise the pedantic Mac compiler * will complain. Cast is safe due to the range check above. */ printf("Data bytes: %.*s\n", (int)rv, data_buffer); printf("Got %"NACL_PRIdNACL_SIZE" NaCl descriptors\n", msg_hdr.ndesc_length); for (i = 0; i < msg_hdr.ndesc_length; ++i) { struct NaClDesc *ndp; size_t msglen = strlen(message); ssize_t write_result; /* * TODO(bsy): a bit gross; we should expose type tags and RTTI * in a better way, e.g, downcast functions. (Though exposing * type tags allows users to use a switch statement on the * type tag, rather than linearly trying to downcast to all * subclasses.) */ ndp = msg_hdr.ndescv[i]; printf(" type %d\n", ndp->vtbl->typeTag); write_result = (*ndp->vtbl->Write)(ndp, effp, (void *) message, msglen); if (-1 == write_result || msglen != (size_t) write_result) { printf("Write failed: got %"NACL_PRIdS", expected %"NACL_PRIuS"\n", write_result, msglen); } NaClDescUnref(ndp); } } NaClDescUnref(channel); NaClDescUnref(pair[0]); NaClDescUnref(pair[1]); } else { if (NULL == conn_addr) { fprintf(stderr, "Client needs server socket address to which to connect\n"); return 100; } memset(&nsa, 0, sizeof nsa); strncpy(nsa.path, conn_addr, sizeof nsa.path); /* not nec'y NUL term'd */ if (!NaClDescConnCapCtor(&ndcc, &nsa)) { fprintf(stderr, "Client conn cap initialization failed\n"); return 101; } rv = (*ndcc.base.vtbl->ConnectAddr)((struct NaClDesc *) &ndcc, effp); printf("Connect returned %"NACL_PRIdS"\n", rv); if (0 != rv) { fprintf(stderr, "Client could not connect\n"); return 102; } channel = NaClNrdXferEffectorTakeDesc(&eff); if (NULL == channel) { fprintf(stderr, "Could not take descriptor from connect\n"); return 103; } strncpy(data_buffer, message, sizeof data_buffer); iov[0].base = data_buffer; iov[0].length = strlen(data_buffer); msg_hdr.iov = iov; msg_hdr.iov_length = NACL_ARRAY_SIZE(iov); msg_hdr.ndesc_length = 0; msg_hdr.ndescv = desc_buffer; if (NULL != transfer_file) { int xfer_fd; struct NaClHostDesc *nhdp = malloc(sizeof *nhdp); xfer_fd = OPEN(transfer_file, O_CREAT| O_WRONLY | O_TRUNC, 0777); if (-1 == xfer_fd) { fprintf(stderr, "Could not open file \"%s\" to transfer descriptor.\n", transfer_file); return 104; } NaClHostDescPosixTake(nhdp, xfer_fd, O_RDWR); desc_buffer[0] = (struct NaClDesc *) NaClDescIoDescMake(nhdp); msg_hdr.ndesc_length = 1; } rv = NaClImcSendTypedMessage(channel, effp, &msg_hdr, 0); if (NULL != desc_buffer[0]) { NaClDescUnref(desc_buffer[0]); desc_buffer[0] = NULL; } printf("Send returned %"NACL_PRIdS"\n", rv); } (*effp->vtbl->Dtor)(effp); NaClNrdAllModulesFini(); return 0; }