static nacl_off64_t NaClDescIoDescSeek(struct NaClDesc *vself, nacl_off64_t offset, int whence) { struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself; return NaClHostDescSeek(self->hd, offset, whence); }
int SeekPastEndAndWriteTest(struct NaClHostDesc *test_file, struct NaClHostDesc *ro_view, void const *test_params) { nacl_host_stat_t stbuf; nacl_off64_t new_size; ssize_t io_err; int err; nacl_off64_t seek_result; UNREFERENCED_PARAMETER(test_params); err = NaClHostDescFstat(test_file, &stbuf); if (0 != err) { fprintf(stderr, "SeekPastEndAndWriteTest: fstat failed\n"); return 0; } new_size = stbuf.st_size + (2 << 16); seek_result = NaClHostDescSeek(test_file, new_size, 0); if (seek_result != new_size) { fprintf(stderr, "SeekPastEndAndWriteTest: seek failed\n"); return 0; } io_err = NaClHostDescWrite(test_file, "1", 1); if (1 != io_err) { fprintf(stderr, "SeekPastEndAndWriteTest: write failed: %"NACL_PRIdS"\n", io_err); } err = NaClHostDescFstat(test_file, &stbuf); if (0 != err) { fprintf(stderr, "SeekPastEndAndWriteTest: post-write fstat failed\n"); return 0; } ASSERT_EQ(stbuf.st_size, new_size + 1); err = NaClHostDescFstat(ro_view, &stbuf); if (0 != err) { fprintf(stderr, "SeekPastEndAndWriteTest: post-write ro_view fstat failed\n"); return 0; } ASSERT_EQ(stbuf.st_size, new_size + 1); return 1; }
void CreateTestFile(struct NaClHostDesc *d_out, char const *pathname, struct TestParams *param) { struct NaClHostDesc hd; int err; nacl_off64_t off; size_t desired_write; ssize_t bytes_written; printf("pathname = %s, perms 0%o\n", pathname, param->file_perms); if (0 != (err = NaClHostDescOpen(&hd, pathname, NACL_ABI_O_WRONLY | NACL_ABI_O_CREAT | NACL_ABI_O_TRUNC, param->file_perms))) { fprintf(stderr, "Could not open test scratch file: NaCl errno %d\n", -err); exit(1); } if (0 != (err = CreateTestData(&hd))) { fprintf(stderr, "Could not write test data into test scratch file: NaCl errno %d\n", -err); exit(1); } if (NULL != param->test_data_start) { off = NaClHostDescSeek(&hd, 0, 0); if (off < 0) { fprintf(stderr, "Could not seek to create test data: NaCl errno %d\n", (int) -off); exit(1); } desired_write = param->test_data_size; bytes_written = NaClHostDescWrite(&hd, param->test_data_start, desired_write); if (bytes_written < 0) { fprintf(stderr, "Could not write specialized test data: NaCl errno %d\n", (int) -bytes_written); exit(1); } if ((size_t) bytes_written != desired_write) { fprintf(stderr, "Error while writing specialized test data:" " tried to write %d, actual %d\n", (int) desired_write, (int) bytes_written); exit(1); } } if (0 != (err = NaClHostDescClose(&hd))) { fprintf(stderr, "Error while closing test data file, errno %d\n", -err); exit(1); } if (0 != (err = NaClHostDescOpen(d_out, pathname, param->open_flags, param->file_perms))) { fprintf(stderr, "Could not open test scratch file: NaCl errno %d\n", -err); exit(1); } }
/* * mmap MAP_PRIVATE test * * Make sure that a MAP_PRIVATE view initially sees the changes made * in a MAP_SHARED view, but after touching the private view further * changes become invisible. */ int map_private_test(struct NaClHostDesc *d, void *test_specifics) { struct MapPrivateSpecifics *params = (struct MapPrivateSpecifics *) test_specifics; struct NaClDescEffector *null_eff = NaClDescEffectorTrustedMem(); uintptr_t view1; uintptr_t view2; nacl_off64_t off; ssize_t bytes_written; char *v1ptr; char *v2ptr; if ((uintptr_t) -4095 < (view1 = NaClHostDescMap(d, null_eff, NULL, kNumFileBytes, NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, NACL_ABI_MAP_SHARED, /* offset */ 0))) { fprintf(stderr, "map_private_test: view1 map failed, errno %d\n", -(int) view1); return 1; } NaClLog(2, "map_private_test: view1 = 0x%"NACL_PRIxPTR"\n", view1); if ((uintptr_t) -4095 < (view2 = NaClHostDescMap(d, null_eff, NULL, kNumFileBytes, NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, NACL_ABI_MAP_PRIVATE, /* offset */ 0))) { fprintf(stderr, "map_private_test: view2 map failed, errno %d\n", -(int) view2); return 1; } NaClLog(2, "map_private_test: view2 = 0x%"NACL_PRIxPTR"\n", view2); v1ptr = (char *) view1; v2ptr = (char *) view2; CHECK(v1ptr[0] == '\0'); CHECK(v2ptr[0] == '\0'); if (params->shm_not_write) { NaClLog(2, "map_private_test: changing via shm view\n"); v1ptr[0] = 'x'; /* write through shared view */ } else { NaClLog(2, "map_private_test: changing via write interface\n"); off = NaClHostDescSeek(d, 0, 0); if (off < 0) { fprintf(stderr, "Could not seek: NaCl errno %d\n", (int) -off); return 1; } bytes_written = NaClHostDescWrite(d, "x", 1); if (1 != bytes_written) { fprintf(stderr, "Could not write: NaCl errno %d\n", (int) -bytes_written); return 1; } } #if NACL_LINUX || NACL_WINDOWS /* * Most OSes have this behavior: a PRIVATE mapping is copy-on-write, * but the COW occurs when the fault occurs on that mapping, not * other mappings; otherwise, the page tables just point the system * to the buffer cache (or, if evicted, a stub entry that permits * faulting in the page). So, a write through a writable file * descriptor or a SHARED mapping would modify the buffer cache, and * the PRIVATE mapping would see such changes until a fault occurs. */ CHECK(v2ptr[0] == 'x'); /* visible! */ #elif NACL_OSX /* * On OSX, however, the underlying Mach primitives provide * bidirectional COW. */ CHECK(v2ptr[0] == '\0'); /* NOT visible! */ #else # error "Unsupported OS" #endif v2ptr[0] = 'z'; /* COW fault */ v1ptr[0] = 'y'; CHECK(v2ptr[0] == 'z'); /* private! */ CHECK(v1ptr[0x400] == '\0'); v2ptr[0x400] = 'y'; CHECK(v1ptr[0x400] == '\0'); CHECK(0 == NaClHostDescUnmapUnsafe((void *) view1, kNumFileBytes)); CHECK(0 == NaClHostDescUnmapUnsafe((void *) view2, kNumFileBytes)); return 0; }
int PWriteUsesOffsetReadPtrVerification(struct NaClHostDesc *test_file, struct NaClHostDesc *ro_view, void const *test_params) { nacl_off64_t seek_err; char buffer[512]; ssize_t io_rv; const size_t pwrite_position = 4096; UNREFERENCED_PARAMETER(test_params); seek_err = NaClHostDescSeek(test_file, 0, 0); if (seek_err < 0) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: seek failed, errno %d\n", -(int) seek_err); return 0; } io_rv = NaClHostDescRead(test_file, buffer, sizeof buffer); if (sizeof buffer != io_rv) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: read failed, got %d," " expected %d", (int) io_rv, (int) sizeof buffer); return 0; } if (0 != memcmp(buffer, quote, sizeof buffer)) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: initial bytes mangled?!?\n"); return 0; } io_rv = NaClHostDescPWrite(test_file, another_quote, sizeof another_quote - 1, pwrite_position); if (io_rv != sizeof another_quote - 1) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: pwrite failed\n"); return 0; } io_rv = NaClHostDescRead(test_file, buffer, sizeof buffer); if (sizeof buffer != io_rv) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification:" " 2nd implicit file ptr read failed, got %d," " expected %d\n", (int) io_rv, (int) sizeof buffer); return 0; } if (0 != memcmp(buffer, quote + sizeof buffer, sizeof buffer)) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: 2nd read contents mangled\n" "Expected:\n" "%.*s\n" "Got:\n" "%.*s\n", (int) sizeof buffer, quote + sizeof buffer, (int) sizeof buffer, buffer); return 0; } io_rv = NaClHostDescPRead(ro_view, buffer, sizeof buffer, pwrite_position); if (io_rv != sizeof buffer) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: verification pread failed," " got %d, expected %d", (int) io_rv, (int) sizeof buffer); return 0; } if (0 != memcmp(buffer, another_quote, sizeof buffer)) { fprintf(stderr, "PWriteUsesOffsetReadPtrVerification: verification content bad\n" "Got:\n" "%.*s\n" "Expected:\n" "%.*s\n", (int) sizeof buffer, buffer, (int) sizeof buffer, another_quote); return 0; } return 1; }
int PWriteUsesOffsetSeekReadVerification(struct NaClHostDesc *test_file, struct NaClHostDesc *ro_view, void const *test_params) { size_t len = strlen(another_quote); char buffer[4096]; ssize_t io_rv; nacl_off64_t seek_err; UNREFERENCED_PARAMETER(ro_view); UNREFERENCED_PARAMETER(test_params); CHECK(len <= sizeof buffer); io_rv = NaClHostDescPWrite(test_file, another_quote, len, GG_LONGLONG(0)); if (io_rv < 0) { fprintf(stderr, "PWriteUsesOffsetSeekReadVerification:" " pwrite (ostensibly to beginning) failed," " errno %d\n", -(int) io_rv); return 0; } if ((size_t) io_rv != len) { fprintf(stderr, "PWriteUsesOffsetSeekReadVerification:" " pwrite short write, expected %"NACL_PRIuS ", got %"NACL_PRIuS"\n", len, (size_t) io_rv); return 0; } seek_err = NaClHostDescSeek(test_file, 0, 0); if (seek_err < 0) { fprintf(stderr, "PWriteUsesOffsetSeekReadVerification:" " seek failed, errno %d\n", -(int) seek_err); return 0; } ASSERT_EQ(seek_err, (nacl_off64_t) 0); CHECK(len <= sizeof buffer); io_rv = NaClHostDescRead(test_file, buffer, len); if (io_rv < 0) { fprintf(stderr, "PWriteUsesOffsetSeekReadVerification:" " NaClHostDescRead failed, errno %d\n", -(int) io_rv); return 0; } if ((size_t) io_rv != len) { fprintf(stderr, "PWriteUsesOffsetSeekReadVerification:" " short read, expected %"NACL_PRIuS ", got %"NACL_PRIuS"\n", len, (size_t) io_rv); return 0; } if (0 != memcmp(buffer, another_quote, len)) { fprintf(stderr, "PWriteUsesOffsetSeekReadVerification:" " data at beginning differs\n" " Expected: %.*s\n" " Got: %.*s\n", (int) len, another_quote, (int) len, buffer); return 0; } return 1; }
int BasicPermChecks(struct NaClHostDesc *test_file, struct NaClHostDesc *ro_view, void const *test_params) { struct BasicPermChecksParams const *params = (struct BasicPermChecksParams const *) test_params; char buffer[1<<16]; ssize_t result; nacl_off64_t seek_result; size_t len; CHECK(params->seq_read_bytes1 <= sizeof buffer); CHECK(params->seq_read_bytes2 <= sizeof buffer); seek_result = NaClHostDescSeek(test_file, 0, 0); ASSERT_EQ(0, seek_result); /* * Some tests skip the initial read. */ if (0 != params->seq_read_bytes1) { memset(buffer, 0, sizeof buffer); CHECK(params->seq_read_bytes1 <= sizeof buffer); result = NaClHostDescRead(test_file, buffer, params->seq_read_bytes1); if (result != (ssize_t) params->seq_read_bytes1) { fprintf(stderr, "BasicPermChecks: first sequential read, got %"NACL_PRIdS ", expected %"NACL_PRIuS" bytes\n", result, params->seq_read_bytes1); return 0; } if (0 != memcmp(quote, buffer, params->seq_read_bytes1)) { fprintf(stderr, "BasicPermChecks: first sequential read result differs\n"); fprintf(stderr, "got: %.*s\n", (int) params->seq_read_bytes1, buffer); return 0; } } len = strlen(params->expected_pread_data); memset(buffer, 0, sizeof buffer); CHECK(len <= sizeof buffer); result = NaClHostDescPRead(test_file, buffer, len, params->pread_offset); if (result != (ssize_t) params->expected_pread_result) { fprintf(stderr, "BasicPermChecks: pread failed, got %"NACL_PRIdS", expected %" NACL_PRIuS" bytes\n", result, params->expected_pread_result); return 0; } if (params->expected_pread_result > 0 && 0 != memcmp(params->expected_pread_data, buffer, len)) { fprintf(stderr, "BasicPermChecks: pread result: %.*s\n" " expected output: %.*s\n", (int) len, buffer, (int) len, quote + params->pread_offset); return 0; } if (0 != params->seq_read_bytes2) { /* * Make sure that the read pointer did not change. */ memset(buffer, 0, sizeof buffer); CHECK(params->seq_read_bytes2 <= sizeof buffer); result = NaClHostDescRead(test_file, buffer, params->seq_read_bytes2); if (result != (ssize_t) params->seq_read_bytes2) { fprintf(stderr, "BasicPermChecks: second sequential read, got %"NACL_PRIdS ", expected %"NACL_PRIuS" bytes\n", result, params->seq_read_bytes2); return 0; } if (0 != memcmp(quote + params->seq_read_bytes1, buffer, params->seq_read_bytes2)) { fprintf(stderr, "BasicPermChecks: second sequential read result differs\n"); fprintf(stderr, "got: %.*s\n", (int) params->seq_read_bytes1, buffer); return 0; } } /* * Now try to write. */ if (NULL != params->pwrite_data) { len = strlen(params->pwrite_data); result = NaClHostDescPWrite(test_file, params->pwrite_data, len, params->pwrite_offset); if (result != params->expected_pwrite_result) { fprintf(stderr, "BasicPermChecks: pwrite failed, got %"NACL_PRIdS ", expected %"NACL_PRIdS"\n", result, params->expected_pwrite_result); return 0; } if (result == (ssize_t) len) { /* re-read by seek/sequential read and check data, using ro_view */ seek_result = NaClHostDescSeek(ro_view, params->pwrite_offset, 0); ASSERT_EQ(params->pwrite_offset, seek_result); memset(buffer, 0, sizeof buffer); CHECK(len <= sizeof buffer); result = NaClHostDescRead(ro_view, buffer, len); if (result != (ssize_t) len) { fprintf(stderr, "BasicPermChecks: pwrite verification read failed\n"); fprintf(stderr, " got %"NACL_PRIdS", expected %"NACL_PRIuS"\n", result, len); return 0; } if (0 != memcmp(buffer, params->pwrite_data, len)) { fprintf(stderr, "BasicPermChecks: pwrite verification data mismatch\n"); fprintf(stderr, " got %.*s\n" "expected %.*s\n", (int) len, buffer, (int) len, params->pwrite_data); return 0; } } } return 1; }