Overview
Comment: | removed sneaky segfault in x86-64 syscall fn where %r8 (the register that contains the pointer to the syscall arguments from the C syscall wrapper, which need to be copied into the correct registers before the kernel is invoked) gets overwritten if the syscall valency > 5, because of overlapping ccall and syscall ABI argument registers - r8 is clobbered by argument 5 and any further attempts to use it as a ptr segfault at best. also modified the report function so that it immediate cancels compilation if a sub-process reports failure. changed allocator function signatures so they can return a condition code if the kernel reports an error; updated example code so it compiles and runs without fault. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e50a476efef720ed926f519a291311b5 |
User & Date: | lexi on 2019-08-22 02:52:20 |
Other Links: | manifest | tags |
Context
2019-08-22
| ||
04:31 | finish moving heap allocation/free functions to the posix syscall apparatus and deprecate the direct assembly implementations of platform_mmap; update the kmem docs to match new function signatures (and remove typos) check-in: 709ffb094d user: lexi tags: trunk | |
02:52 | removed sneaky segfault in x86-64 syscall fn where %r8 (the register that contains the pointer to the syscall arguments from the C syscall wrapper, which need to be copied into the correct registers before the kernel is invoked) gets overwritten if the syscall valency > 5, because of overlapping ccall and syscall ABI argument registers - r8 is clobbered by argument 5 and any further attempts to use it as a ptr segfault at best. also modified the report function so that it immediate cancels compilation if a sub-process reports failure. changed allocator function signatures so they can return a condition code if the kernel reports an error; updated example code so it compiles and runs without fault. check-in: e50a476efe user: lexi tags: trunk | |
01:37 | add first iteration of knum header check-in: 5560c2725b user: lexi tags: trunk | |
Changes
Modified arch/posix/errnos from [cc3bf9e501] to [1054d9a4df].
5 5 ENOSPC 6 6 EDQUOT 7 7 EIO 8 8 EAGAIN 9 9 EFBIG 10 10 EINTR 11 11 EDESTADDRREQ 12 +EACCES 13 +EMFILE 14 +ENODEV 15 +ENOMEM 16 +ENXIO 17 +EOVERFLOW
Modified build.sh from [d7b4907031] to [b5a70ac75f].
146 146 if test ! "$output" -ot "$src"; then 147 147 return 148 148 fi 149 149 fi 150 150 if test "$debug" = yes; then 151 151 local dflag="-g dwarf2" 152 152 fi 153 - report $asm $flags $dflag "-f$bin_fmt" -i "$gen" "$src" -o "$output"; 153 + report $asm $flags $dflag "-f$bin_fmt" -i "$gen" -i "$PWD" "$src" -o "$output"; 154 154 } 155 155 comp_co() { comp_c $1 $2 "-c -fPIC"; } 156 156 comp_c(){ 157 157 local src=$1 158 158 local output=$2 159 159 local flags=$3 160 160 if test -e "$output"; then
Modified global/common.sh from [e60df5a627] to [582c735deb].
57 57 fi 58 58 59 59 # the following function is called to report a command invocation 60 60 # the person compiling the library. the first argument should be 61 61 # an ansi format string; this is used to color-code the tool being 62 62 # launched and thus should be different for each one. 63 63 64 -report() { announce $@; $@; } 64 +report() { 65 + announce $@; $@; 66 + status=$? 67 + if test $status -ne 0; then 68 + args=($@) 69 + say "process ${args[0]} failed with status code $status" 70 + exit $status 71 + fi 72 +}
Modified mod/kcore/syscall.fn.x86.lin.64.s from [472ad3a7d3] to [9bf0ba9bf3].
7 7 ; altogether and access the error value of a 8 8 ; syscall directly. invoke as: 9 9 ; 10 10 ; void k_platform_syscall_raw(s64* result, u64* errno, 11 11 ; syscall, u8 valency, s64[] args) 12 12 13 13 bits 64 14 -%include "../arch/posix/x86.lin.64.s" 15 -%include "../arch/x86.cdecl.64.s" 14 +%include "arch/posix/x86.lin.64.s" 15 +%include "arch/x86.cdecl.64.s" 16 16 ; vim: ft=nasm 17 17 18 18 %macro handle_arg 1 19 19 %assign v %1+1 20 - mov sys.reg. %+ v, [ccall.reg.4 + 8 * %1] 20 + mov sys.reg. %+ v, [r15 + 8 * %1] 21 21 dec ccall.reg.3 22 22 jz .perform_call 23 23 %endmacro 24 24 25 25 global k_platform_syscall_raw:function 26 26 k_platform_syscall_raw: 27 27 ; locals: rbx = s64* result ................................................................................ 38 38 ; and popping back from the stack 39 39 mov rbx, ccall.reg.0 40 40 mov r12, ccall.reg.1 41 41 42 42 ; this needs to go before the loop 43 43 ; or it'll get clobbered 44 44 mov sys.reg.0, ccall.reg.2 45 + 46 + ; the fourth argument is in %r8, which 47 + ; is also a syscall register, so we 48 + ; need to move it to a safe register 49 + ; to keep it from getting clobbered 50 + ; before we begin the "loop" 51 + mov r15, ccall.reg.4 45 52 46 53 ; automatically generate the code 47 54 ; needed to move the arguments into 48 55 ; their correct registers. see above 49 56 %assign i 0 50 57 %rep 6 51 58 handle_arg i
Modified mod/kcore/testbin.exe.c from [c4d82c1a4a] to [ae0ed8cd11].
18 18 19 19 if (kiosend(e.std, ptr, null) == kiocond_ok) { 20 20 /* great, continue */ 21 21 } else { 22 22 return kbad_io; 23 23 } 24 24 25 - void* region = kmheapa(2048); 26 - if (region == null) return kbad_mem; 25 + void* region; 26 + kmcond alloc = kmheapa(®ion, 2048); 27 + if (alloc != kmcond_ok) return kbad_mem; 27 28 28 29 kmzero(region,2048); 29 30 30 31 if (kmheapf(region) >= kmcond_fail) return kbad_mem; 31 32 32 33 return kbad_ok; 33 34 }
Modified mod/kmem/heapa.fn.c from [641176b71f] to [e093792a2c].
8 8 * see also: kmheapf() "heap free" 9 9 */ 10 10 11 11 /* arch specific headers */ 12 12 #ifdef KFenv_posix 13 13 # include <posix/posix.h> 14 14 #endif 15 + 16 +#include <error_table.h> 15 17 16 18 /* we define all our platform functions here, whether or not 17 19 * they're for the correct platform - only the ones that are 18 20 * called by the preprocessed form of the code will actually 19 21 * be linked, linker errors are our friend here! */ 20 22 extern void* kmem_platform_mmap(void* addr, 21 23 unsigned long sz, unsigned long prot, unsigned long flags, 22 24 unsigned long fd, unsigned long off); 23 25 24 -void* kmheapa(sz len) { 26 +kmcond kmheapa(void** where, sz len) { 25 27 /* allocate an object on the heap and return 26 28 * a pointer, or NULL if the allocation failed. */ 27 29 union { 28 30 void* raw; 29 31 ubyte* byte; 30 32 kmbox* header; 31 33 } region; ................................................................................ 49 51 /* because munmap needs to be informed of the size of 50 52 * the region we are going to unmap, we need to store 51 53 * that information in the region that we are mapping. 52 54 * the user will receive an adjusted pointer that can 53 55 * be adjusted to point a field of type size_t that 54 56 * contains the size of the allocated space.*/ 55 57 56 - region.byte = kmem_platform_mmap(null, region_size, 57 - posix_prot_read | posix_prot_write, 58 - posix_flag_anonymous | posix_map_shared, -1, 0); 58 + k_platform_syscall_arg args[] = { 59 + null, region_size, 60 + posix_prot_read | posix_prot_write, 61 + posix_flag_anonymous | posix_map_shared, 62 + -1, 0 63 + }; 64 + 65 + struct k_platform_syscall_answer r = k_platform_syscall 66 + (k_platform_syscall_mmap, Kmsz(args), args); 67 + 68 + if (r.error == 0) region.byte = (ubyte*)r.ret; else { 69 + switch (r.error) { 70 + case k_platform_error_EAGAIN: return kmcond_bad_lock; 71 + case k_platform_error_EINVAL: return kmcond_bad_size; 72 + case k_platform_error_EMFILE: return kmcond_too_many; 73 + case k_platform_error_ENOMEM: return kmcond_no_room; 74 + default: return kmcond_fail_assert; 75 + } 76 + } 77 + 78 + /* region.byte = kmem_platform_mmap(null, region_size, */ 79 + /* posix_prot_read | posix_prot_write, */ 80 + /* posix_flag_anonymous | posix_map_shared, -1, 0); */ 81 + 59 82 /* impl note: while per manpage fd is "ignored" 60 83 * for MAP_ANONYMOUS, "some implementations" require 61 84 * a value of -1 */ 62 85 63 - if (region.raw == (void*) -1) return null; 64 - /* worth retrieving errno? discuss */ 65 - 66 86 # else 67 87 Knoimpl(kmheapa,KVos); 68 88 # error missing implementation 69 89 # endif 70 90 71 91 void* const object = (region.byte + sizeof (kmbox)); 72 92 73 93 region.header -> kind = kmkind_heap; 74 94 region.header -> size = len; 75 95 76 - return object; 96 + *where = object; 97 + return kmcond_ok; 77 98 }
Modified mod/kmem/heapao.fn.c from [930b5d7379] to [e98ef79662].
3 3 /* heapao.fn.c - kmheapao() "allocate heap object" 4 4 * ~ lexi hale <lexi@hale.su> 5 5 * kmheapao() allocates a region in heap memory 6 6 * and returns a kmptr struct referencing that 7 7 * newly allocated region. 8 8 */ 9 9 10 -kmptr kmheapao(sz size) { 11 - void* ptr = kmheapa(size); 10 +kmcond kmheapao(kmptr* where, sz size) { 11 + void* ptr; 12 + kmcond e = kmheapa(&ptr, size); 13 + if (e != kmcond_ok) return e; 12 14 kmptr p = { 13 15 .kind = (ptr != null ? kmkind_heap : kmkind_fail), 14 16 .ref = ptr, 15 17 .shred = false, 16 - }; return p; 18 + }; 19 + *where = p; 20 + return kmcond_ok; 17 21 }
Modified mod/kmem/mem.h from [bec7e80543] to [d8d36f64f5].
1 1 #ifndef KImem 2 2 #define KImem 3 3 #include <k/type.h> 4 +#include <k/internal.egroup.h> 4 5 5 6 #ifndef KFclean 6 7 # define Kmsz(e) ( sizeof (e) / sizeof (e) [0] ) 7 8 #endif 8 9 9 10 #ifdef __cplusplus 10 11 extern "C" { 11 12 #endif 12 13 13 14 typedef enum kmcond { 14 - kmcond_ok, 15 + kmcond_ok = kmcond_id, 15 16 kmcond_unnecessary, 16 17 17 18 kmcond_fail, 18 19 kmcond_unhandled, 19 20 kmcond_mismatch, 20 21 kmcond_bad_address, 22 + kmcond_bad_lock, 23 + kmcond_bad_size, 24 + kmcond_no_room, 25 + kmcond_too_many, 26 + 27 + /* when something truly should 28 + * never happen: */ 29 + kmcond_fail_assert, 21 30 } kmcond; 22 31 23 32 typedef enum kmkind { 24 33 kmkind_none, 25 34 kmkind_fail, 26 35 kmkind_linear, 27 36 kmkind_heap, ................................................................................ 59 68 kmkind kind; 60 69 kmshred shred; 61 70 void* ref; 62 71 } kmptr; 63 72 64 73 /* heap functions */ 65 74 66 -void* kmheapa(sz); 67 -kmptr kmheapao(sz); 68 -kmcond kmheapf(void*); 75 +kmcond kmheapa (void**, sz); 76 +kmcond kmheapao(kmptr*, sz); 77 +kmcond kmheapf (void*); 69 78 70 79 /* generic functions */ 71 80 72 81 kmcond kmfree(kmptr); 73 82 kmkind kmtell(void*); 74 83 void kmzero(void*,sz); 75 84 void kmozero(kmptr);