summaryrefslogtreecommitdiff
path: root/src/arch-x86.c
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2020-01-23 17:01:39 +0100
committerPaul Moore <paul@paul-moore.com>2020-03-23 11:14:35 -0400
commit9b129c41ac1f43d373742697aa2faf6040b9dfab (patch)
tree25c69d113e954473adb7b5209c76b67773a383e9 /src/arch-x86.c
parentf5b3166d6126f4a45b59d6af6780b5e00a0e9867 (diff)
downloadlibseccomp-9b129c41ac1f43d373742697aa2faf6040b9dfab.tar.gz
arch: use gperf to generate a perfact hash to lookup syscall names
This patch significantly improves the performance of seccomp_syscall_resolve_name since it replaces the expensive strcmp for each syscall in the database, with a lookup table. The complexity for syscall_resolve_num is not changed and it uses the linear search, that is anyway less expensive than seccomp_syscall_resolve_name as it uses an index for comparison instead of doing a string comparison. On my machine, calling 1000 seccomp_syscall_resolve_name_arch and seccomp_syscall_resolve_num_arch over the entire syscalls DB passed from ~0.45 sec to ~0.06s. PM: After talking with Giuseppe I made a number of additional changes, some substantial, the highlights include: * various style tweaks * .gitignore fixes * fixed subject line, tweaked the description * dropped the arch-syscall-validate changes as they were masking other problems * extracted the syscalls.csv and file deletions to other patches to keep this one more focused * fixed the x86, x32, arm, all the MIPS ABIs, s390, and s390x ABIs as the syscall offsets were not properly incorporated into this change * cleaned up the ABI specific headers * cleaned up generate_syscalls_perf.sh and renamed to arch-gperf-generate * fixed problems with automake's file packaging Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> Reviewed-by: Tom Hromatka <tom.hromatka@oracle.com> [PM: see notes in the "PM" section above] Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'src/arch-x86.c')
-rw-r--r--src/arch-x86.c182
1 files changed, 172 insertions, 10 deletions
diff --git a/src/arch-x86.c b/src/arch-x86.c
index fc0deaa..2a4c074 100644
--- a/src/arch-x86.c
+++ b/src/arch-x86.c
@@ -24,6 +24,8 @@
#include <string.h>
#include <linux/audit.h>
+#include "db.h"
+#include "syscalls.h"
#include "arch.h"
#include "arch-x86.h"
@@ -31,16 +33,165 @@
#define __x86_NR_socketcall 102
#define __x86_NR_ipc 117
-const struct arch_def arch_def_x86 = {
- .token = SCMP_ARCH_X86,
- .token_bpf = AUDIT_ARCH_I386,
- .size = ARCH_SIZE_32,
- .endian = ARCH_ENDIAN_LITTLE,
- .syscall_resolve_name = x86_syscall_resolve_name,
- .syscall_resolve_num = x86_syscall_resolve_num,
- .syscall_rewrite = x86_syscall_rewrite,
- .rule_add = x86_rule_add,
-};
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number using the syscall table.
+ * Returns the syscall number on success, including negative pseudo syscall
+ * numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int x86_syscall_resolve_name_munge(const char *name)
+{
+ if (strcmp(name, "accept") == 0)
+ return __PNR_accept;
+ else if (strcmp(name, "accept4") == 0)
+ return __PNR_accept4;
+ else if (strcmp(name, "bind") == 0)
+ return __PNR_bind;
+ else if (strcmp(name, "connect") == 0)
+ return __PNR_connect;
+ else if (strcmp(name, "getpeername") == 0)
+ return __PNR_getpeername;
+ else if (strcmp(name, "getsockname") == 0)
+ return __PNR_getsockname;
+ else if (strcmp(name, "getsockopt") == 0)
+ return __PNR_getsockopt;
+ else if (strcmp(name, "listen") == 0)
+ return __PNR_listen;
+ else if (strcmp(name, "recv") == 0)
+ return __PNR_recv;
+ else if (strcmp(name, "recvfrom") == 0)
+ return __PNR_recvfrom;
+ else if (strcmp(name, "recvmsg") == 0)
+ return __PNR_recvmsg;
+ else if (strcmp(name, "recvmmsg") == 0)
+ return __PNR_recvmmsg;
+ else if (strcmp(name, "send") == 0)
+ return __PNR_send;
+ else if (strcmp(name, "sendmsg") == 0)
+ return __PNR_sendmsg;
+ else if (strcmp(name, "sendmmsg") == 0)
+ return __PNR_sendmmsg;
+ else if (strcmp(name, "sendto") == 0)
+ return __PNR_sendto;
+ else if (strcmp(name, "setsockopt") == 0)
+ return __PNR_setsockopt;
+ else if (strcmp(name, "shutdown") == 0)
+ return __PNR_shutdown;
+ else if (strcmp(name, "socket") == 0)
+ return __PNR_socket;
+ else if (strcmp(name, "socketpair") == 0)
+ return __PNR_socketpair;
+
+ if (strcmp(name, "semop") == 0)
+ return __PNR_semop;
+ else if (strcmp(name, "semget") == 0)
+ return __PNR_semget;
+ else if (strcmp(name, "semctl") == 0)
+ return __PNR_semctl;
+ else if (strcmp(name, "semtimedop") == 0)
+ return __PNR_semtimedop;
+ else if (strcmp(name, "msgsnd") == 0)
+ return __PNR_msgsnd;
+ else if (strcmp(name, "msgrcv") == 0)
+ return __PNR_msgrcv;
+ else if (strcmp(name, "msgget") == 0)
+ return __PNR_msgget;
+ else if (strcmp(name, "msgctl") == 0)
+ return __PNR_msgctl;
+ else if (strcmp(name, "shmat") == 0)
+ return __PNR_shmat;
+ else if (strcmp(name, "shmdt") == 0)
+ return __PNR_shmdt;
+ else if (strcmp(name, "shmget") == 0)
+ return __PNR_shmget;
+ else if (strcmp(name, "shmctl") == 0)
+ return __PNR_shmctl;
+
+ return x86_syscall_resolve_name(name);
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name using the syscall table.
+ * Returns a pointer to the syscall name string on success, including pseudo
+ * syscall names; returns NULL on failure.
+ *
+ */
+const char *x86_syscall_resolve_num_munge(int num)
+{
+ if (num == __PNR_accept)
+ return "accept";
+ else if (num == __PNR_accept4)
+ return "accept4";
+ else if (num == __PNR_bind)
+ return "bind";
+ else if (num == __PNR_connect)
+ return "connect";
+ else if (num == __PNR_getpeername)
+ return "getpeername";
+ else if (num == __PNR_getsockname)
+ return "getsockname";
+ else if (num == __PNR_getsockopt)
+ return "getsockopt";
+ else if (num == __PNR_listen)
+ return "listen";
+ else if (num == __PNR_recv)
+ return "recv";
+ else if (num == __PNR_recvfrom)
+ return "recvfrom";
+ else if (num == __PNR_recvmsg)
+ return "recvmsg";
+ else if (num == __PNR_recvmmsg)
+ return "recvmmsg";
+ else if (num == __PNR_send)
+ return "send";
+ else if (num == __PNR_sendmsg)
+ return "sendmsg";
+ else if (num == __PNR_sendmmsg)
+ return "sendmmsg";
+ else if (num == __PNR_sendto)
+ return "sendto";
+ else if (num == __PNR_setsockopt)
+ return "setsockopt";
+ else if (num == __PNR_shutdown)
+ return "shutdown";
+ else if (num == __PNR_socket)
+ return "socket";
+ else if (num == __PNR_socketpair)
+ return "socketpair";
+
+ if (num == __PNR_semop)
+ return "semop";
+ else if (num == __PNR_semget)
+ return "semget";
+ else if (num == __PNR_semctl)
+ return "semctl";
+ else if (num == __PNR_semtimedop)
+ return "semtimedop";
+ else if (num == __PNR_msgsnd)
+ return "msgsnd";
+ else if (num == __PNR_msgrcv)
+ return "msgrcv";
+ else if (num == __PNR_msgget)
+ return "msgget";
+ else if (num == __PNR_msgctl)
+ return "msgctl";
+ else if (num == __PNR_shmat)
+ return "shmat";
+ else if (num == __PNR_shmdt)
+ return "shmdt";
+ else if (num == __PNR_shmget)
+ return "shmget";
+ else if (num == __PNR_shmctl)
+ return "shmctl";
+
+ return x86_syscall_resolve_num(num);
+}
/**
* Convert a multiplexed pseudo syscall into a direct syscall
@@ -461,3 +612,14 @@ add_return:
free(rule_dup);
return rc;
}
+
+const struct arch_def arch_def_x86 = {
+ .token = SCMP_ARCH_X86,
+ .token_bpf = AUDIT_ARCH_I386,
+ .size = ARCH_SIZE_32,
+ .endian = ARCH_ENDIAN_LITTLE,
+ .syscall_resolve_name = x86_syscall_resolve_name_munge,
+ .syscall_resolve_num = x86_syscall_resolve_num_munge,
+ .syscall_rewrite = x86_syscall_rewrite,
+ .rule_add = x86_rule_add,
+};