/*
 * 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);
}
예제 #2
0
struct NaClHostDesc *NaClHostDescPosixMake(int  posix_d,
                                           int  flags) {
  struct NaClHostDesc *nhdp;
  int                 error;

  nhdp = malloc(sizeof *nhdp);
  if (NULL == nhdp) {
    NaClLog(LOG_FATAL, "NaClHostDescPosixMake(%d,0x%x): malloc failed\n",
            posix_d, flags);
  }
  if (0 != (error = NaClHostDescPosixTake(nhdp, posix_d, flags))) {
    NaClLog(LOG_FATAL,
            "NaClHostDescPosixMake(%d,0x%x): Take failed, error %da\n",
            posix_d, flags, error);
  }
  return nhdp;
}
/*
 * It is the responsibility of the invoking environment to delete the
 * file passed as command-line argument.  See the build.scons file.
 */
int main(int ac, char **av) {
  char const *test_dir_name = "/tmp/nacl_host_desc_mmap_win_test";
  struct NaClHostDesc hd;
  int test_passed;
  size_t error_count;
  size_t ix;
  int opt;
  int num_runs = 1;
  int test_run;
  HANDLE h;
  int d;

  while (EOF != (opt = getopt(ac, av, "c:t:"))) {
    switch (opt) {
      case 'c':
        num_runs = atoi(optarg);
        break;
      case 't':
        test_dir_name = optarg;
        break;
      default:
        fprintf(stderr,
                "Usage: nacl_host_desc_mmap_win_test [-c run_count]\n"
                "                                    [-t test_temp_dir]\n");
        exit(1);
    }
  }

  NaClPlatformInit();

  error_count = 0;
  for (test_run = 0; test_run < num_runs; ++test_run) {
    printf("Test run %d\n\n", test_run);
    for (ix = 0; ix < NACL_ARRAY_SIZE(tests); ++ix) {
      char test_file_name[PATH_MAX];
      _snprintf_s(test_file_name, sizeof test_file_name, _TRUNCATE,
                  "%s/f%d.%"NACL_PRIuS, test_dir_name, test_run, ix);
      printf("%s\n", tests[ix].test_info);
      printf("-- %s\n", tests[ix].file_type->file_type_description);

      h = CreateTestFile(test_file_name, tests[ix].file_type);
      if (ERROR_SUCCESS == tests[ix].expected_open_error) {
        if (INVALID_HANDLE_VALUE == h) {
          DWORD err = GetLastError();
          NaClLog(LOG_ERROR,
                  "CreateTestFile for %s failed, error %d\n",
                  test_file_name, err);
          printf("FAILED\n");
          ++error_count;
          continue;
        }

        d = _open_osfhandle((intptr_t) h, tests[ix].oflags);
        NaClHostDescPosixTake(&hd, d, tests[ix].posix_flags);
        test_passed = TryToMap(&hd, tests[ix].map_bytes, tests[ix].prot,
                               tests[ix].map_flags,
                               tests[ix].expected_mmap_errno);
        error_count += !test_passed;
        printf("%s\n", test_passed ? "PASSED" : "FAILED");

        CHECK(0 == NaClHostDescClose(&hd));
        AttemptToDeleteTestFile(test_file_name);
      } else {
        if (INVALID_HANDLE_VALUE == h) {
          DWORD err = GetLastError();
          if (err != tests[ix].expected_open_error) {
            NaClLog(LOG_ERROR,
                    "Expected CreateTestFile for %s to failed with"
                    " error %d, but got error %d\n",
                    test_file_name, err, tests[ix].expected_open_error);
            printf("FAILED\n");
            ++error_count;
          } else {
            printf("PASSED (open failed)\n");
          }
          continue;
        } else {
          NaClLog(LOG_ERROR,
                  "Expected CreateTestFile for %s to fail with error %d,"
                  " but succeeded instead!\n",
                  test_file_name,
                  tests[ix].expected_open_error);
          (void) CloseHandle(h);
          AttemptToDeleteTestFile(test_file_name);
          printf("FAILED\n");
          ++error_count;
          continue;
        }
      }
    }
  }

  printf("Total of %d error%s.\n", error_count, (error_count == 1) ? "" : "s");

  NaClPlatformFini();

  /* we ignore the 2^32 or 2^64 total errors case */
  return (error_count > 255) ? 255 : error_count;
}
예제 #4
0
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;
}
예제 #5
0
/* set *out_desc to struct NaClDescIo * output */
int NaClDescIoInternalize(struct NaClDesc               **out_desc,
                          struct NaClDescXferState      *xfer,
                          struct NaClDescQuotaInterface *quota_interface) {
  int                   rv;
  NaClHandle            h;
  int                   d;
  int                   flags;
  struct NaClHostDesc   *nhdp;
  struct NaClDescIoDesc *ndidp;

  UNREFERENCED_PARAMETER(quota_interface);
  rv = -NACL_ABI_EIO;  /* catch-all */
  h = NACL_INVALID_HANDLE;
  nhdp = NULL;
  ndidp = NULL;

  nhdp = malloc(sizeof *nhdp);
  if (NULL == nhdp) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  ndidp = malloc(sizeof *ndidp);
  if (!ndidp) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  if (!NaClDescInternalizeCtor((struct NaClDesc *) ndidp, xfer)) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  if (xfer->next_handle == xfer->handle_buffer_end ||
      xfer->next_byte + sizeof ndidp->hd->flags > xfer->byte_buffer_end) {
    rv = -NACL_ABI_EIO;
    goto cleanup_ndidp_dtor;
  }

  NACL_COMPILE_TIME_ASSERT(sizeof flags == sizeof(ndidp->hd->flags));
  memcpy(&flags, xfer->next_byte, sizeof flags);
  xfer->next_byte += sizeof flags;

  h = *xfer->next_handle;
  *xfer->next_handle++ = NACL_INVALID_HANDLE;
#if NACL_WINDOWS
  if (-1 == (d = _open_osfhandle((intptr_t) h, _O_RDWR | _O_BINARY))) {
    rv = -NACL_ABI_EIO;
    goto cleanup_ndidp_dtor;
  }
#else
  d = h;
#endif
  /*
   * We mark it as read/write, but don't really know for sure until we
   * try to make those syscalls (in which case we'd get EBADF).
   */
  if ((rv = NaClHostDescPosixTake(nhdp, d, flags)) < 0) {
    goto cleanup_ndidp_dtor;
  }
  h = NACL_INVALID_HANDLE;  /* nhdp took ownership of h */

  if (!NaClDescIoDescSubclassCtor(ndidp, nhdp)) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup_nhdp_dtor;
  }
  /*
   * ndidp took ownership of nhdp, now give ownership of ndidp to caller.
   */
  *out_desc = (struct NaClDesc *) ndidp;
  rv = 0;
 cleanup_nhdp_dtor:
  if (rv < 0) {
    if (0 != NaClHostDescClose(nhdp)) {
      NaClLog(LOG_FATAL, "NaClDescIoInternalize: NaClHostDescClose failed\n");
    }
  }
 cleanup_ndidp_dtor:
  if (rv < 0) {
    NaClDescSafeUnref((struct NaClDesc *) ndidp);
    ndidp = NULL;
  }
 cleanup:
  if (rv < 0) {
    free(nhdp);
    free(ndidp);
    if (NACL_INVALID_HANDLE != h) {
      (void) NaClClose(h);
    }
  }
  return rv;
}