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