1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * System call table mapper 4 * 5 * (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com> 6 */ 7 8 #include "syscalltbl.h" 9 #include <stdlib.h> 10 #include <linux/compiler.h> 11 #include <linux/zalloc.h> 12 13 #ifdef HAVE_SYSCALL_TABLE_SUPPORT 14 #include <string.h> 15 #include "string2.h" 16 17 #if defined(__x86_64__) 18 #include <asm/syscalls_64.c> 19 const int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID; 20 static const char *const *syscalltbl_native = syscalltbl_x86_64; 21 #elif defined(__i386__) 22 #include <asm/syscalls_32.c> 23 const int syscalltbl_native_max_id = SYSCALLTBL_x86_MAX_ID; 24 static const char *const *syscalltbl_native = syscalltbl_x86; 25 #elif defined(__s390x__) 26 #include <asm/syscalls_64.c> 27 const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID; 28 static const char *const *syscalltbl_native = syscalltbl_s390_64; 29 #elif defined(__powerpc64__) 30 #include <asm/syscalls_64.c> 31 const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_64_MAX_ID; 32 static const char *const *syscalltbl_native = syscalltbl_powerpc_64; 33 #elif defined(__powerpc__) 34 #include <asm/syscalls_32.c> 35 const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_32_MAX_ID; 36 static const char *const *syscalltbl_native = syscalltbl_powerpc_32; 37 #elif defined(__aarch64__) 38 #include <asm/syscalls.c> 39 const int syscalltbl_native_max_id = SYSCALLTBL_ARM64_MAX_ID; 40 static const char *const *syscalltbl_native = syscalltbl_arm64; 41 #elif defined(__mips__) 42 #include <asm/syscalls_n64.c> 43 const int syscalltbl_native_max_id = SYSCALLTBL_MIPS_N64_MAX_ID; 44 static const char *const *syscalltbl_native = syscalltbl_mips_n64; 45 #elif defined(__loongarch__) 46 #include <asm/syscalls.c> 47 const int syscalltbl_native_max_id = SYSCALLTBL_LOONGARCH_MAX_ID; 48 static const char *const *syscalltbl_native = syscalltbl_loongarch; 49 #endif 50 51 struct syscall { 52 int id; 53 const char *name; 54 }; 55 56 static int syscallcmpname(const void *vkey, const void *ventry) 57 { 58 const char *key = vkey; 59 const struct syscall *entry = ventry; 60 61 return strcmp(key, entry->name); 62 } 63 64 static int syscallcmp(const void *va, const void *vb) 65 { 66 const struct syscall *a = va, *b = vb; 67 68 return strcmp(a->name, b->name); 69 } 70 71 static int syscalltbl__init_native(struct syscalltbl *tbl) 72 { 73 int nr_entries = 0, i, j; 74 struct syscall *entries; 75 76 for (i = 0; i <= syscalltbl_native_max_id; ++i) 77 if (syscalltbl_native[i]) 78 ++nr_entries; 79 80 entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries); 81 if (tbl->syscalls.entries == NULL) 82 return -1; 83 84 for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) { 85 if (syscalltbl_native[i]) { 86 entries[j].name = syscalltbl_native[i]; 87 entries[j].id = i; 88 ++j; 89 } 90 } 91 92 qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp); 93 tbl->syscalls.nr_entries = nr_entries; 94 tbl->syscalls.max_id = syscalltbl_native_max_id; 95 return 0; 96 } 97 98 struct syscalltbl *syscalltbl__new(void) 99 { 100 struct syscalltbl *tbl = malloc(sizeof(*tbl)); 101 if (tbl) { 102 if (syscalltbl__init_native(tbl)) { 103 free(tbl); 104 return NULL; 105 } 106 } 107 return tbl; 108 } 109 110 void syscalltbl__delete(struct syscalltbl *tbl) 111 { 112 zfree(&tbl->syscalls.entries); 113 free(tbl); 114 } 115 116 const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id) 117 { 118 return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL; 119 } 120 121 int syscalltbl__id(struct syscalltbl *tbl, const char *name) 122 { 123 struct syscall *sc = bsearch(name, tbl->syscalls.entries, 124 tbl->syscalls.nr_entries, sizeof(*sc), 125 syscallcmpname); 126 127 return sc ? sc->id : -1; 128 } 129 130 int syscalltbl__id_at_idx(struct syscalltbl *tbl, int idx) 131 { 132 struct syscall *syscalls = tbl->syscalls.entries; 133 134 return idx < tbl->syscalls.nr_entries ? syscalls[idx].id : -1; 135 } 136 137 int syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx) 138 { 139 int i; 140 struct syscall *syscalls = tbl->syscalls.entries; 141 142 for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) { 143 if (strglobmatch(syscalls[i].name, syscall_glob)) { 144 *idx = i; 145 return syscalls[i].id; 146 } 147 } 148 149 return -1; 150 } 151 152 int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx) 153 { 154 *idx = -1; 155 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); 156 } 157 158 #else /* HAVE_SYSCALL_TABLE_SUPPORT */ 159 160 #include <libaudit.h> 161 162 struct syscalltbl *syscalltbl__new(void) 163 { 164 struct syscalltbl *tbl = zalloc(sizeof(*tbl)); 165 if (tbl) 166 tbl->audit_machine = audit_detect_machine(); 167 return tbl; 168 } 169 170 void syscalltbl__delete(struct syscalltbl *tbl) 171 { 172 free(tbl); 173 } 174 175 const char *syscalltbl__name(const struct syscalltbl *tbl, int id) 176 { 177 return audit_syscall_to_name(id, tbl->audit_machine); 178 } 179 180 int syscalltbl__id(struct syscalltbl *tbl, const char *name) 181 { 182 return audit_name_to_syscall(name, tbl->audit_machine); 183 } 184 185 int syscalltbl__strglobmatch_next(struct syscalltbl *tbl __maybe_unused, 186 const char *syscall_glob __maybe_unused, int *idx __maybe_unused) 187 { 188 return -1; 189 } 190 191 int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx) 192 { 193 return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); 194 } 195 #endif /* HAVE_SYSCALL_TABLE_SUPPORT */ 196