diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2020-01-23 17:01:39 +0100 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2020-03-23 11:14:35 -0400 |
commit | 9b129c41ac1f43d373742697aa2faf6040b9dfab (patch) | |
tree | 25c69d113e954473adb7b5209c76b67773a383e9 /src/arch-x86.c | |
parent | f5b3166d6126f4a45b59d6af6780b5e00a0e9867 (diff) | |
download | libseccomp-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.c | 182 |
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, +}; |