Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | #include "mach_vm_tests.h" #include "unistd.h" #define TEST_TXT_FILE "/tmp/xnu.vm.sharing.test.txt" static const char * lorem_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate\ velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; static int fd = 0; static struct stat sb; mach_port_t persistentReplyPort; int mach_server_data_setup(void **buffer) { if (0 != access(TEST_TXT_FILE, F_OK)) { /* create a test file */ const size_t lorem_text_length = strlen(lorem_text); int w_fd = open(TEST_TXT_FILE, O_WRONLY | O_CREAT | O_TRUNC, (mode_t)0666); size_t required_length = 450783; assert(w_fd >= 0); size_t bytes_written = 0; while (bytes_written < required_length) { bytes_written += (size_t)write(w_fd, &lorem_text[0], (size_t)(lorem_text_length - 1)); if ((bytes_written + lorem_text_length) > required_length) { bytes_written += (size_t)write(w_fd, &lorem_text[0], (size_t)(required_length - bytes_written)); break; } } close(w_fd); } /* Sample data set needs to be mapped in our space */ fd = open(TEST_TXT_FILE, O_RDONLY | O_EXCL, 0666); if (fd < 0) { printf("mach_server_data_setup: cannot open file %s - %d (%s).\n", TEST_TXT_FILE, errno, strerror(errno)); return errno; } if (fstat(fd, &sb) < 0) { printf("mach_server_data_setup: cannot stat file %s - %d (%s).\n", TEST_TXT_FILE, errno, strerror(errno)); return errno; } #if MMAP_PATH *buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); if (*buffer == MAP_FAILED) { printf("mach_server_remap: mmap failed - %d (%s).\n", errno, strerror(errno)); *buffer = NULL; } #else kern_return_t kr = KERN_SUCCESS; kr = mach_vm_allocate(mach_task_self(), (mach_vm_address_t *)buffer, (mach_vm_size_t)sb.st_size, VM_FLAGS_ANYWHERE); assert(kr == KERN_SUCCESS); #endif return 0; } void mach_server_data_cleanup(void *buffer, mach_vm_address_t src, mach_vm_size_t size) { #if MMAP_PATH if (buffer) { munmap(buffer, sb.st_size); } #else mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)buffer, (mach_vm_size_t)sb.st_size); #endif if (src) { mach_vm_deallocate(mach_task_self(), src, size); } if (fd > 2) { close(fd); } } void mach_server_construct_header(ipc_message_t *message, mach_port_t replyPort) { bzero(message, sizeof(*message)); message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) | MACH_MSGH_BITS_COMPLEX; message->header.msgh_remote_port = persistentReplyPort;//serverPort; message->header.msgh_local_port = replyPort; message->header.msgh_size = sizeof(*message); message->header.msgh_id = 1; } void mach_server_contruct_payload(ipc_message_t *message, mach_vm_address_t src, mach_port_t port, mach_vm_size_t size, mach_vm_offset_t misoffset, boolean_t copy, int vm_op) { if (port == MACH_PORT_NULL) { message->address = src;//LD TODO: (src + 8193); } else { message->body.msgh_descriptor_count = 1; message->port_descriptor.name = port; message->port_descriptor.disposition = MACH_MSG_TYPE_COPY_SEND; message->port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR; } message->pid = (uint64_t)getpid(); message->size = size; message->vm_op = vm_op; message->copy = copy; message->misoffset = misoffset; } void mach_server_create_allocation(mach_vm_address_t *src, mach_vm_size_t size, void *buffer) { kern_return_t kr = KERN_SUCCESS; mach_vm_size_t chunk_size = 0; unsigned int chunk_count = 0; mach_vm_address_t localsrc = 0; kr = mach_vm_allocate(mach_task_self(), &localsrc, size, VM_FLAGS_ANYWHERE); assert(KERN_SUCCESS == kr); chunk_size = MIN(size, (mach_vm_size_t)sb.st_size); if (chunk_size == 0) { printf("mach_server_remap: Input size is 0\n"); exit(0); } chunk_count = (unsigned int)(size / (mach_vm_size_t)sb.st_size); if (debug && 0) { printf("Chunks of size: 0x%llx and count: %d\n", chunk_size, chunk_count); } for (unsigned int i = 0; i < chunk_count; i++) { memcpy((void*)(localsrc + (i * chunk_size)), buffer, chunk_size); } *src = localsrc; } void server_error_out(mach_port_t port) { /* All done here...*/ kern_return_t ret; mach_msg_size_t messageSize = sizeof(ipc_message_t) + sizeof(mach_msg_trailer_t) + 64; ipc_message_t *message = (ipc_message_t *)calloc(1, messageSize); message->header.msgh_bits = MACH_MSGH_BITS_ZERO; message->header.msgh_size = messageSize; message->header.msgh_remote_port = MACH_PORT_NULL; message->header.msgh_local_port = port; mach_server_construct_header(message, port); message->vm_op = VM_OP_EXIT_ERROR; ret = mach_msg(&message->header, MACH_SEND_MSG, message->header.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (ret != KERN_SUCCESS) { T_LOG("ERROR: Failed to send message to client: (%d) %s\n", ret, mach_error_string(ret)); exit(1); } T_LOG("server_error_out. abort()\n"); abort(); } |