From b496f4beef1456a2457031d268b45870457aab8a Mon Sep 17 00:00:00 2001 From: rawrmonster17 Date: Thu, 18 Jun 2026 22:57:03 -0500 Subject: [PATCH] api: add seccomp_arch_name() to resolve an arch token to its name Add seccomp_arch_name() as the inverse of seccomp_arch_resolve_name(): given a SCMP_ARCH_* token it returns the canonical architecture name string. This allows callers to obtain a human-readable name for a token without maintaining their own token-to-string table. - SCMP_ARCH_NATIVE resolves to the native architecture name, matching the behaviour of seccomp_arch_exist()/seccomp_arch_add() for the zero token value. - Returns a pointer to a static string constant; the caller must not free the returned pointer. - Returns NULL for an unrecognized token. Implementation: add arch_def_name() to src/arch.c holding the single authoritative token-to-name table, declared in src/arch.h. The existing static _pfc_arch() in src/gen_pfc.c is reduced to a thin wrapper calling arch_def_name(), removing the duplicate switch and the linux/audit.h include that was required solely for that switch. The new public API function seccomp_arch_name() in src/api.c calls arch_def_name() directly. Documentation: add the new function to the seccomp_arch_add(3) man page (NAME, SYNOPSIS, DESCRIPTION, RETURN VALUE) and add a .so redirect seccomp_arch_name(3) following the same pattern as all other arch function stubs. Tests: add test 65-basic-arch_name which round-trips every known SCMP_ARCH_* token through seccomp_arch_resolve_name() and back through seccomp_arch_name(), verifies that SCMP_ARCH_NATIVE resolves to the native architecture name, and confirms that an unrecognized token returns NULL. Fixes: Github Issue #295 Signed-off-by: rawrmonster17 --- doc/Makefile.am | 1 + doc/man/man3/seccomp_arch_add.3 | 27 ++++++++- doc/man/man3/seccomp_arch_name.3 | 1 + include/seccomp.h.in | 13 +++++ src/api.c | 6 ++ src/arch.c | 70 ++++++++++++++++++++++ src/arch.h | 1 + src/gen_pfc.c | 55 +----------------- tests/.gitignore | 1 + tests/65-basic-arch_name.c | 99 ++++++++++++++++++++++++++++++++ tests/65-basic-arch_name.tests | 10 ++++ tests/Makefile.am | 6 +- 12 files changed, 234 insertions(+), 56 deletions(-) create mode 100644 doc/man/man3/seccomp_arch_name.3 create mode 100644 tests/65-basic-arch_name.c create mode 100644 tests/65-basic-arch_name.tests diff --git a/doc/Makefile.am b/doc/Makefile.am index 5f0b8567..744394ca 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -22,6 +22,7 @@ dist_man1_MANS = \ dist_man3_MANS = \ man/man3/seccomp_arch_add.3 \ man/man3/seccomp_arch_exist.3 \ + man/man3/seccomp_arch_name.3 \ man/man3/seccomp_arch_native.3 \ man/man3/seccomp_arch_remove.3 \ man/man3/seccomp_arch_resolve_name.3 \ diff --git a/doc/man/man3/seccomp_arch_add.3 b/doc/man/man3/seccomp_arch_add.3 index ede5d92f..4efbb071 100644 --- a/doc/man/man3/seccomp_arch_add.3 +++ b/doc/man/man3/seccomp_arch_add.3 @@ -2,7 +2,7 @@ .\" ////////////////////////////////////////////////////////////////////////// .SH NAME .\" ////////////////////////////////////////////////////////////////////////// -seccomp_arch_add, seccomp_arch_remove, seccomp_arch_exist, seccomp_arch_native \- Manage seccomp filter architectures +seccomp_arch_add, seccomp_arch_remove, seccomp_arch_exist, seccomp_arch_native, seccomp_arch_resolve_name, seccomp_arch_name \- Manage seccomp filter architectures .\" ////////////////////////////////////////////////////////////////////////// .SH SYNOPSIS .\" ////////////////////////////////////////////////////////////////////////// @@ -37,6 +37,7 @@ seccomp_arch_add, seccomp_arch_remove, seccomp_arch_exist, seccomp_arch_native \ .B #define SCMP_ARCH_RISCV64 .sp .BI "uint32_t seccomp_arch_resolve_name(const char *" arch_name ");" +.BI "const char *seccomp_arch_name(uint32_t " arch_token ");" .BI "uint32_t seccomp_arch_native();" .BI "int seccomp_arch_exist(const scmp_filter_ctx " ctx ", uint32_t " arch_token ");" .BI "int seccomp_arch_add(scmp_filter_ctx " ctx ", uint32_t " arch_token ");" @@ -75,6 +76,17 @@ function also returns a constant, the returned token matches the name of the architecture passed as an argument to the function. .P +The +.BR seccomp_arch_name () +function is the inverse of +.BR seccomp_arch_resolve_name (): +it takes an architecture token and returns the canonical architecture name +string. If the token is +.BR SCMP_ARCH_NATIVE +the name of the native architecture is returned. The returned string is a +static constant; the caller must not free it. Returns NULL if the token is +not recognized. +.P When a seccomp filter is initialized with the call to .BR seccomp_init (3) the native architecture is automatically added to the filter. @@ -89,6 +101,7 @@ new architecture will be added to all of the architectures in the filter. .\" ////////////////////////////////////////////////////////////////////////// .SH RETURN VALUE .\" ////////////////////////////////////////////////////////////////////////// +.P The .BR seccomp_arch_add (), .BR seccomp_arch_remove (), @@ -112,6 +125,18 @@ Invalid input, either the context or architecture token is invalid. .TP .B -ENOMEM The library was unable to allocate enough memory. +.P +The +.BR seccomp_arch_resolve_name () +and +.BR seccomp_arch_native () +functions return an architecture token value greater than zero on success and +zero on failure. +.P +The +.BR seccomp_arch_name () +function returns a pointer to a static architecture name string on success and +NULL if the architecture token is not recognized. .\" ////////////////////////////////////////////////////////////////////////// .SH EXAMPLES .\" ////////////////////////////////////////////////////////////////////////// diff --git a/doc/man/man3/seccomp_arch_name.3 b/doc/man/man3/seccomp_arch_name.3 new file mode 100644 index 00000000..f72602be --- /dev/null +++ b/doc/man/man3/seccomp_arch_name.3 @@ -0,0 +1 @@ +.so man3/seccomp_arch_add.3 diff --git a/include/seccomp.h.in b/include/seccomp.h.in index f685480e..66c47476 100644 --- a/include/seccomp.h.in +++ b/include/seccomp.h.in @@ -541,6 +541,19 @@ int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src); */ uint32_t seccomp_arch_resolve_name(const char *arch_name); +/** + * Resolve the architecture token to a architecture name + * @param arch_token the architecture token, e.g. SCMP_ARCH_* + * + * This function resolves the given architecture token to the canonical + * architecture name string. If the token is SCMP_ARCH_NATIVE the name of + * the native architecture is returned. Returns a pointer to a static string + * on success; the caller must not free the returned string. Returns NULL if + * the architecture token is not recognized. + * + */ +const char *seccomp_arch_name(uint32_t arch_token); + /** * Return the native architecture token * diff --git a/src/api.c b/src/api.c index 413cc81a..913fb594 100644 --- a/src/api.c +++ b/src/api.c @@ -387,6 +387,12 @@ API uint32_t seccomp_arch_resolve_name(const char *arch_name) return arch->token; } +/* NOTE - function header comment in include/seccomp.h */ +API const char *seccomp_arch_name(uint32_t arch_token) +{ + return arch_def_name(arch_token); +} + /* NOTE - function header comment in include/seccomp.h */ API uint32_t seccomp_arch_native(void) { diff --git a/src/arch.c b/src/arch.c index a3ff7ca6..d6d1237b 100644 --- a/src/arch.c +++ b/src/arch.c @@ -188,6 +188,76 @@ const struct arch_def *arch_def_lookup(uint32_t token) return NULL; } +/** + * Return the name of the architecture + * @param token the architecture token, e.g. SCMP_ARCH_* + * + * Return the name of the architecture associated with the given token, or + * NULL if the token is not valid. If the token is SCMP_ARCH_NATIVE then the + * name of the native architecture is returned. The caller must not free the + * returned string. + * + */ +const char *arch_def_name(uint32_t token) +{ + const struct arch_def *arch; + + if (token == SCMP_ARCH_NATIVE) + token = arch_def_native->token; + arch = arch_def_lookup(token); + if (arch == NULL) + return NULL; + switch (arch->token) { + case SCMP_ARCH_X86: + return "x86"; + case SCMP_ARCH_X86_64: + return "x86_64"; + case SCMP_ARCH_X32: + return "x32"; + case SCMP_ARCH_ARM: + return "arm"; + case SCMP_ARCH_AARCH64: + return "aarch64"; + case SCMP_ARCH_LOONGARCH64: + return "loongarch64"; + case SCMP_ARCH_M68K: + return "m68k"; + case SCMP_ARCH_MIPS: + return "mips"; + case SCMP_ARCH_MIPSEL: + return "mipsel"; + case SCMP_ARCH_MIPS64: + return "mips64"; + case SCMP_ARCH_MIPSEL64: + return "mipsel64"; + case SCMP_ARCH_MIPS64N32: + return "mips64n32"; + case SCMP_ARCH_MIPSEL64N32: + return "mipsel64n32"; + case SCMP_ARCH_PARISC: + return "parisc"; + case SCMP_ARCH_PARISC64: + return "parisc64"; + case SCMP_ARCH_PPC: + return "ppc"; + case SCMP_ARCH_PPC64: + return "ppc64"; + case SCMP_ARCH_PPC64LE: + return "ppc64le"; + case SCMP_ARCH_S390: + return "s390"; + case SCMP_ARCH_S390X: + return "s390x"; + case SCMP_ARCH_RISCV64: + return "riscv64"; + case SCMP_ARCH_SHEB: + return "sheb"; + case SCMP_ARCH_SH: + return "sh"; + } + return NULL; +} + /** * Lookup the architecture definition by name * @param arch_name the architecture name diff --git a/src/arch.h b/src/arch.h index 419878e3..88196ebb 100644 --- a/src/arch.h +++ b/src/arch.h @@ -120,6 +120,7 @@ struct arch_syscall_def { int arch_valid(uint32_t arch); +const char *arch_def_name(uint32_t token); const struct arch_def *arch_def_lookup(uint32_t token); const struct arch_def *arch_def_lookup_name(const char *arch_name); diff --git a/src/gen_pfc.c b/src/gen_pfc.c index 91017166..a3eb4381 100644 --- a/src/gen_pfc.c +++ b/src/gen_pfc.c @@ -26,9 +26,6 @@ #include #include -/* NOTE: needed for the arch->token decoding in _pfc_arch() */ -#include - #include #include "arch.h" @@ -50,56 +47,8 @@ struct pfc_sys_list { */ static const char *_pfc_arch(const struct arch_def *arch) { - switch (arch->token) { - case SCMP_ARCH_X86: - return "x86"; - case SCMP_ARCH_X86_64: - return "x86_64"; - case SCMP_ARCH_X32: - return "x32"; - case SCMP_ARCH_ARM: - return "arm"; - case SCMP_ARCH_AARCH64: - return "aarch64"; - case SCMP_ARCH_LOONGARCH64: - return "loongarch64"; - case SCMP_ARCH_M68K: - return "m68k"; - case SCMP_ARCH_MIPS: - return "mips"; - case SCMP_ARCH_MIPSEL: - return "mipsel"; - case SCMP_ARCH_MIPS64: - return "mips64"; - case SCMP_ARCH_MIPSEL64: - return "mipsel64"; - case SCMP_ARCH_MIPS64N32: - return "mips64n32"; - case SCMP_ARCH_MIPSEL64N32: - return "mipsel64n32"; - case SCMP_ARCH_PARISC: - return "parisc"; - case SCMP_ARCH_PARISC64: - return "parisc64"; - case SCMP_ARCH_PPC64: - return "ppc64"; - case SCMP_ARCH_PPC64LE: - return "ppc64le"; - case SCMP_ARCH_PPC: - return "ppc"; - case SCMP_ARCH_S390X: - return "s390x"; - case SCMP_ARCH_S390: - return "s390"; - case SCMP_ARCH_RISCV64: - return "riscv64"; - case SCMP_ARCH_SHEB: - return "sheb"; - case SCMP_ARCH_SH: - return "sh"; - default: - return "UNKNOWN"; - } + const char *name = arch_def_name(arch->token); + return (name != NULL ? name : "UNKNOWN"); } /** diff --git a/tests/.gitignore b/tests/.gitignore index 55d1af1b..db6d04c2 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -72,3 +72,4 @@ util.pyc 62-sim-arch_transactions 63-live-notify_addfd 64-live-trapx +65-basic-arch_name diff --git a/tests/65-basic-arch_name.c b/tests/65-basic-arch_name.c new file mode 100644 index 00000000..7e6660b9 --- /dev/null +++ b/tests/65-basic-arch_name.c @@ -0,0 +1,99 @@ +/** + * Seccomp Library test program + * + * Copyright (c) 2025 Paul Moore + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +#include +#include + +#include + +#include "util.h" + +int main(int argc, char *argv[]) +{ + int rc = 0; + uint32_t token; + const char *name; + + /* + * Verify round-trip: seccomp_arch_resolve_name() then + * seccomp_arch_name() must return the original name for every + * known architecture. + */ +#define CHECK_ARCH(str, tok) \ + do { \ + token = seccomp_arch_resolve_name(str); \ + if (token != (tok)) { \ + rc = -1; \ + goto out; \ + } \ + name = seccomp_arch_name(token); \ + if (name == NULL || strcmp(name, (str)) != 0) { \ + rc = -1; \ + goto out; \ + } \ + } while (0) + + CHECK_ARCH("x86", SCMP_ARCH_X86); + CHECK_ARCH("x86_64", SCMP_ARCH_X86_64); + CHECK_ARCH("x32", SCMP_ARCH_X32); + CHECK_ARCH("arm", SCMP_ARCH_ARM); + CHECK_ARCH("aarch64", SCMP_ARCH_AARCH64); + CHECK_ARCH("loongarch64", SCMP_ARCH_LOONGARCH64); + CHECK_ARCH("m68k", SCMP_ARCH_M68K); + CHECK_ARCH("mips", SCMP_ARCH_MIPS); + CHECK_ARCH("mipsel", SCMP_ARCH_MIPSEL); + CHECK_ARCH("mips64", SCMP_ARCH_MIPS64); + CHECK_ARCH("mipsel64", SCMP_ARCH_MIPSEL64); + CHECK_ARCH("mips64n32", SCMP_ARCH_MIPS64N32); + CHECK_ARCH("mipsel64n32", SCMP_ARCH_MIPSEL64N32); + CHECK_ARCH("parisc", SCMP_ARCH_PARISC); + CHECK_ARCH("parisc64", SCMP_ARCH_PARISC64); + CHECK_ARCH("ppc", SCMP_ARCH_PPC); + CHECK_ARCH("ppc64", SCMP_ARCH_PPC64); + CHECK_ARCH("ppc64le", SCMP_ARCH_PPC64LE); + CHECK_ARCH("s390", SCMP_ARCH_S390); + CHECK_ARCH("s390x", SCMP_ARCH_S390X); + CHECK_ARCH("riscv64", SCMP_ARCH_RISCV64); + CHECK_ARCH("sheb", SCMP_ARCH_SHEB); + CHECK_ARCH("sh", SCMP_ARCH_SH); +#undef CHECK_ARCH + + /* SCMP_ARCH_NATIVE must resolve to the native arch's name */ + name = seccomp_arch_name(SCMP_ARCH_NATIVE); + if (name == NULL) { + rc = -1; + goto out; + } + token = seccomp_arch_resolve_name(name); + if (token != seccomp_arch_native()) { + rc = -1; + goto out; + } + + /* invalid token must return NULL */ + name = seccomp_arch_name(0xdeadbeef); + if (name != NULL) { + rc = -1; + goto out; + } + +out: + return (rc < 0 ? EOPNOTSUPP : 0); +} diff --git a/tests/65-basic-arch_name.tests b/tests/65-basic-arch_name.tests new file mode 100644 index 00000000..ce28b5ec --- /dev/null +++ b/tests/65-basic-arch_name.tests @@ -0,0 +1,10 @@ +# +# libseccomp regression test automation data +# +# Copyright (c) 2025 Paul Moore +# + +test type: basic + +# Test command +65-basic-arch_name diff --git a/tests/Makefile.am b/tests/Makefile.am index 280cfa83..eda0a112 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -99,7 +99,8 @@ check_PROGRAMS = \ 61-sim-transactions \ 62-sim-arch_transactions \ 63-live-notify_addfd \ - 64-live-trapx + 64-live-trapx \ + 65-basic-arch_name EXTRA_DIST_TESTPYTHON = \ util.py \ @@ -230,7 +231,8 @@ EXTRA_DIST_TESTCFGS = \ 61-sim-transactions.tests \ 62-sim-arch_transactions.tests \ 63-live-notify_addfd.tests \ - 64-live-trapx.tests + 64-live-trapx.tests \ + 65-basic-arch_name.tests EXTRA_DIST_TESTSCRIPTS = \ 38-basic-pfc_coverage.sh 38-basic-pfc_coverage.pfc \