18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * System call table mapper
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "syscalltbl.h"
98c2ecf20Sopenharmony_ci#include <stdlib.h>
108c2ecf20Sopenharmony_ci#include <linux/compiler.h>
118c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#ifdef HAVE_SYSCALL_TABLE_SUPPORT
148c2ecf20Sopenharmony_ci#include <string.h>
158c2ecf20Sopenharmony_ci#include "string2.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#if defined(__x86_64__)
188c2ecf20Sopenharmony_ci#include <asm/syscalls_64.c>
198c2ecf20Sopenharmony_ciconst int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID;
208c2ecf20Sopenharmony_cistatic const char **syscalltbl_native = syscalltbl_x86_64;
218c2ecf20Sopenharmony_ci#elif defined(__s390x__)
228c2ecf20Sopenharmony_ci#include <asm/syscalls_64.c>
238c2ecf20Sopenharmony_ciconst int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID;
248c2ecf20Sopenharmony_cistatic const char **syscalltbl_native = syscalltbl_s390_64;
258c2ecf20Sopenharmony_ci#elif defined(__powerpc64__)
268c2ecf20Sopenharmony_ci#include <asm/syscalls_64.c>
278c2ecf20Sopenharmony_ciconst int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_64_MAX_ID;
288c2ecf20Sopenharmony_cistatic const char **syscalltbl_native = syscalltbl_powerpc_64;
298c2ecf20Sopenharmony_ci#elif defined(__powerpc__)
308c2ecf20Sopenharmony_ci#include <asm/syscalls_32.c>
318c2ecf20Sopenharmony_ciconst int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_32_MAX_ID;
328c2ecf20Sopenharmony_cistatic const char **syscalltbl_native = syscalltbl_powerpc_32;
338c2ecf20Sopenharmony_ci#elif defined(__aarch64__)
348c2ecf20Sopenharmony_ci#include <asm/syscalls.c>
358c2ecf20Sopenharmony_ciconst int syscalltbl_native_max_id = SYSCALLTBL_ARM64_MAX_ID;
368c2ecf20Sopenharmony_cistatic const char **syscalltbl_native = syscalltbl_arm64;
378c2ecf20Sopenharmony_ci#elif defined(__loongarch__)
388c2ecf20Sopenharmony_ci#include <asm/syscalls.c>
398c2ecf20Sopenharmony_ciconst int syscalltbl_native_max_id = SYSCALLTBL_LOONGARCH_MAX_ID;
408c2ecf20Sopenharmony_cistatic const char **syscalltbl_native = syscalltbl_loongarch;
418c2ecf20Sopenharmony_ci#endif
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistruct syscall {
448c2ecf20Sopenharmony_ci	int id;
458c2ecf20Sopenharmony_ci	const char *name;
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic int syscallcmpname(const void *vkey, const void *ventry)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	const char *key = vkey;
518c2ecf20Sopenharmony_ci	const struct syscall *entry = ventry;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	return strcmp(key, entry->name);
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic int syscallcmp(const void *va, const void *vb)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	const struct syscall *a = va, *b = vb;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	return strcmp(a->name, b->name);
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic int syscalltbl__init_native(struct syscalltbl *tbl)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	int nr_entries = 0, i, j;
668c2ecf20Sopenharmony_ci	struct syscall *entries;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	for (i = 0; i <= syscalltbl_native_max_id; ++i)
698c2ecf20Sopenharmony_ci		if (syscalltbl_native[i])
708c2ecf20Sopenharmony_ci			++nr_entries;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
738c2ecf20Sopenharmony_ci	if (tbl->syscalls.entries == NULL)
748c2ecf20Sopenharmony_ci		return -1;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
778c2ecf20Sopenharmony_ci		if (syscalltbl_native[i]) {
788c2ecf20Sopenharmony_ci			entries[j].name = syscalltbl_native[i];
798c2ecf20Sopenharmony_ci			entries[j].id = i;
808c2ecf20Sopenharmony_ci			++j;
818c2ecf20Sopenharmony_ci		}
828c2ecf20Sopenharmony_ci	}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
858c2ecf20Sopenharmony_ci	tbl->syscalls.nr_entries = nr_entries;
868c2ecf20Sopenharmony_ci	tbl->syscalls.max_id	 = syscalltbl_native_max_id;
878c2ecf20Sopenharmony_ci	return 0;
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistruct syscalltbl *syscalltbl__new(void)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	struct syscalltbl *tbl = malloc(sizeof(*tbl));
938c2ecf20Sopenharmony_ci	if (tbl) {
948c2ecf20Sopenharmony_ci		if (syscalltbl__init_native(tbl)) {
958c2ecf20Sopenharmony_ci			free(tbl);
968c2ecf20Sopenharmony_ci			return NULL;
978c2ecf20Sopenharmony_ci		}
988c2ecf20Sopenharmony_ci	}
998c2ecf20Sopenharmony_ci	return tbl;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_civoid syscalltbl__delete(struct syscalltbl *tbl)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	zfree(&tbl->syscalls.entries);
1058c2ecf20Sopenharmony_ci	free(tbl);
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ciconst char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ciint syscalltbl__id(struct syscalltbl *tbl, const char *name)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	struct syscall *sc = bsearch(name, tbl->syscalls.entries,
1168c2ecf20Sopenharmony_ci				     tbl->syscalls.nr_entries, sizeof(*sc),
1178c2ecf20Sopenharmony_ci				     syscallcmpname);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	return sc ? sc->id : -1;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ciint syscalltbl__strglobmatch_next(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	int i;
1258c2ecf20Sopenharmony_ci	struct syscall *syscalls = tbl->syscalls.entries;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	for (i = *idx + 1; i < tbl->syscalls.nr_entries; ++i) {
1288c2ecf20Sopenharmony_ci		if (strglobmatch(syscalls[i].name, syscall_glob)) {
1298c2ecf20Sopenharmony_ci			*idx = i;
1308c2ecf20Sopenharmony_ci			return syscalls[i].id;
1318c2ecf20Sopenharmony_ci		}
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	return -1;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ciint syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	*idx = -1;
1408c2ecf20Sopenharmony_ci	return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#else /* HAVE_SYSCALL_TABLE_SUPPORT */
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci#include <libaudit.h>
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistruct syscalltbl *syscalltbl__new(void)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct syscalltbl *tbl = zalloc(sizeof(*tbl));
1508c2ecf20Sopenharmony_ci	if (tbl)
1518c2ecf20Sopenharmony_ci		tbl->audit_machine = audit_detect_machine();
1528c2ecf20Sopenharmony_ci	return tbl;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_civoid syscalltbl__delete(struct syscalltbl *tbl)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	free(tbl);
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ciconst char *syscalltbl__name(const struct syscalltbl *tbl, int id)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	return audit_syscall_to_name(id, tbl->audit_machine);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciint syscalltbl__id(struct syscalltbl *tbl, const char *name)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	return audit_name_to_syscall(name, tbl->audit_machine);
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ciint syscalltbl__strglobmatch_next(struct syscalltbl *tbl __maybe_unused,
1718c2ecf20Sopenharmony_ci				  const char *syscall_glob __maybe_unused, int *idx __maybe_unused)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	return -1;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciint syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_glob, int *idx)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx);
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci#endif /* HAVE_SYSCALL_TABLE_SUPPORT */
181