1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 Benjamin Berg <benjamin@sipsolutions.net> 4 */ 5 6 #include <sysdep/stub.h> 7 8 static __always_inline int syscall_handler(struct stub_data *d) 9 { 10 int i; 11 unsigned long res; 12 13 for (i = 0; i < d->syscall_data_len; i++) { 14 struct stub_syscall *sc = &d->syscall_data[i]; 15 16 switch (sc->syscall) { 17 case STUB_SYSCALL_MMAP: 18 res = stub_syscall6(STUB_MMAP_NR, 19 sc->mem.addr, sc->mem.length, 20 sc->mem.prot, 21 MAP_SHARED | MAP_FIXED, 22 sc->mem.fd, sc->mem.offset); 23 if (res != sc->mem.addr) { 24 d->err = res; 25 d->syscall_data_len = i; 26 return -1; 27 } 28 break; 29 case STUB_SYSCALL_MUNMAP: 30 res = stub_syscall2(__NR_munmap, 31 sc->mem.addr, sc->mem.length); 32 if (res) { 33 d->err = res; 34 d->syscall_data_len = i; 35 return -1; 36 } 37 break; 38 case STUB_SYSCALL_MPROTECT: 39 res = stub_syscall3(__NR_mprotect, 40 sc->mem.addr, sc->mem.length, 41 sc->mem.prot); 42 if (res) { 43 d->err = res; 44 d->syscall_data_len = i; 45 return -1; 46 } 47 break; 48 case STUB_SYSCALL_LDT: 49 res = stub_syscall3(__NR_modify_ldt, sc->ldt.func, 50 (unsigned long) &sc->ldt.desc, 51 sizeof(sc->ldt.desc)); 52 /* We only write, so the expected result is zero */ 53 if (res) { 54 d->err = res; 55 d->syscall_data_len = i; 56 return -1; 57 } 58 break; 59 default: 60 d->err = -95; /* EOPNOTSUPP */ 61 d->syscall_data_len = i; 62 return -1; 63 } 64 } 65 66 d->err = 0; 67 d->syscall_data_len = 0; 68 69 return 0; 70 } 71 72 void __section(".__syscall_stub") 73 stub_syscall_handler(void) 74 { 75 struct stub_data *d = get_stub_data(); 76 77 syscall_handler(d); 78 79 trap_myself(); 80 } 81