this repo has no description
at fixPythonPipStalling 215 lines 6.4 kB view raw
1/* 2 * This file is part of Darling. 3 * Copyright (C) 2021 Darling developers 4 * 5 * Originally part of the Darling Mach Linux Kernel Module 6 * Copyright (C) 2017 Lubos Dolezel 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2 11 * of the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 */ 22 23#include <stddef.h> 24#include <string.h> 25#include <unistd.h> 26#include <stdlib.h> 27#include <stdio.h> 28#include "loader.h" 29#include <darling-config.h> 30#include "elfcalls/elfcalls.h" 31 32#if defined(GEN_64BIT) 33#define FUNCTION_NAME setup_stack64 34#define user_long_t unsigned long 35#elif defined(GEN_32BIT) 36#define FUNCTION_NAME setup_stack32 37#define user_long_t unsigned int 38#else 39#error See above 40#endif 41 42#define __user 43 44#define EXECUTABLE_PATH "executable_path=" 45 46#define __put_user(value, pointer) ({ \ 47 __typeof__(value) _tmpval = (value); \ 48 memcpy((pointer), &_tmpval, sizeof(_tmpval)); \ 49 0; \ 50 }) 51 52void elfcalls_make(struct elf_calls* calls); 53 54static struct elf_calls _elfcalls; 55 56void FUNCTION_NAME(const char* filepath, struct load_results* lr) 57{ 58 int err = 0; 59 // unsigned char rand_bytes[16]; 60 char *executable_path; 61 static char executable_buf[4096]; 62 user_long_t __user* argv; 63 user_long_t __user* envp; 64 user_long_t __user* applep; 65 user_long_t __user* sp; 66 char __user* exepath_user; 67 size_t exepath_len; 68 char __user* kernfd_user; 69 char kernfd[12]; 70 char __user* elfcalls_user; 71 char elfcalls[27]; 72 char __user* applep_contents[4]; 73 74#define user_long_count(_val) (((_val) + (sizeof(user_long_t) - 1)) / sizeof(user_long_t)) 75 76 elfcalls_make(&_elfcalls); 77 78 // Produce executable_path=... for applep 79 executable_buf[sizeof(executable_buf) - 1] = '\0'; 80 strncpy(executable_buf, filepath, 4096); 81 if (executable_buf[sizeof(executable_buf) - 1] != '\0') 82 { 83 fprintf(stderr, "File path was too big\n"); 84 exit(1); 85 } 86 87 executable_path = executable_buf; 88 89 if (lr->root_path) 90 { 91 exepath_len = strlen(executable_path); 92 93 if (strncmp(executable_path, lr->root_path, lr->root_path_length) == 0) 94 { 95 memmove(executable_buf, executable_path + lr->root_path_length, exepath_len - lr->root_path_length + 1); 96 } 97 else 98 { 99 // FIXME: potential buffer overflow 100 memmove(executable_buf + sizeof(SYSTEM_ROOT) - 1, executable_path, exepath_len + 1); 101 memcpy(executable_buf, SYSTEM_ROOT, sizeof(SYSTEM_ROOT) - 1); 102 } 103 executable_path = executable_buf; 104 } 105 106 // printk(KERN_NOTICE "Stack top: %p\n", bprm->p); 107 exepath_len = strlen(executable_path); 108 sp = (user_long_t*) (lr->stack_top & ~(sizeof(user_long_t)-1)); 109 110 // 1 pointer for the mach header 111 // 1 user_long_t for the argument count 112 // `argc`-count pointers for arguments (+1 for NULL) 113 // `envc`-count pointers for env vars (+1 for NULL) 114 // `sizeof(applep_contents) / sizeof(*applep_contents)`-count pointers for applep arguments (already includes NULL) 115 // space for exepath, kernfd, and elfcalls 116 sp -= 1 + 1 + (lr->argc + 1) + (lr->envc + 1) + (sizeof(applep_contents) / sizeof(*applep_contents)) + user_long_count(exepath_len + sizeof(EXECUTABLE_PATH) + sizeof(kernfd) + sizeof(elfcalls)); 117 118 exepath_user = (char __user*) lr->stack_top - exepath_len - sizeof(EXECUTABLE_PATH); 119 memcpy(exepath_user, EXECUTABLE_PATH, sizeof(EXECUTABLE_PATH)-1); 120 memcpy(exepath_user + sizeof(EXECUTABLE_PATH)-1, executable_path, exepath_len + 1); 121 122 snprintf(kernfd, sizeof(kernfd), "kernfd=%d", lr->kernfd); 123 kernfd_user = exepath_user - sizeof(kernfd); 124 memcpy(kernfd_user, kernfd, sizeof(kernfd)); 125 126#if defined(GEN_64BIT) 127 #define POINTER_FORMAT "%lx" 128#elif defined(GEN_32BIT) 129 #define POINTER_FORMAT "%x" 130#endif 131 132 snprintf(elfcalls, sizeof(elfcalls), "elf_calls=" POINTER_FORMAT, (unsigned long)(uintptr_t)&_elfcalls); 133 elfcalls_user = kernfd_user - sizeof(elfcalls); 134 memcpy(elfcalls_user, elfcalls, sizeof(elfcalls)); 135 136 applep_contents[0] = exepath_user; 137 applep_contents[1] = kernfd_user; 138 applep_contents[2] = elfcalls_user; 139 applep_contents[3] = NULL; 140 141 lr->stack_top = (unsigned long) sp; 142 143 // XXX: skip this for static executables, but we don't support them anyway... 144 if (__put_user((user_long_t) lr->mh, sp++)) 145 { 146 fprintf(stderr, "Failed to copy mach header address to stack\n"); 147 exit(1); 148 } 149 if (__put_user((user_long_t) lr->argc, sp++)) 150 { 151 fprintf(stderr, "Failed to copy argument count to stack\n"); 152 exit(1); 153 } 154 155 // Fill in argv pointers 156 argv = sp; 157 for (int i = 0; i < lr->argc; ++i) 158 { 159 if (!lr->argv[i]) { 160 lr->argc = i; 161 break; 162 } 163 if (__put_user((user_long_t) lr->argv[i], argv++)) 164 { 165 fprintf(stderr, "Failed to copy an argument pointer to stack\n"); 166 exit(1); 167 } 168 } 169 if (__put_user((user_long_t) 0, argv++)) 170 { 171 fprintf(stderr, "Failed to null-terminate the argument pointer array\n"); 172 exit(1); 173 } 174 175 // Fill in envp pointers 176 envp = argv; 177 for (int i = 0; i < lr->envc; ++i) 178 { 179 if (!lr->envp[i]) { 180 lr->envc = i; 181 break; 182 } 183 184 if (__put_user((user_long_t) lr->envp[i], envp++)) 185 { 186 fprintf(stderr, "Failed to copy an environment variable pointer to stack\n"); 187 exit(1); 188 } 189 } 190 if (__put_user((user_long_t) 0, envp++)) 191 { 192 fprintf(stderr, "Failed to null-terminate the environment variable pointer array\n"); 193 exit(1); 194 } 195 196 applep = envp; // envp is now at the end of env pointers 197 198 for (int i = 0; i < sizeof(applep_contents)/sizeof(applep_contents[0]); i++) 199 { 200 if (__put_user((user_long_t)(unsigned long) applep_contents[i], applep++)) 201 { 202 fprintf(stderr, "Failed to copy an applep value to stack\n"); 203 exit(1); 204 } 205 } 206 207 // get_random_bytes(rand_bytes, sizeof(rand_bytes)); 208 209 // TODO: produce stack_guard, e.g. stack_guard=0xcdd5c48c061b00fd (must contain 00 somewhere!) 210 // TODO: produce malloc_entropy, e.g. malloc_entropy=0x9536cc569d9595cf,0x831942e402da316b 211 // TODO: produce main_stack? 212} 213 214#undef FUNCTION_NAME 215#undef user_long_t