#include "env-util.h"
#include "errno-list.h"
#include "macro.h"
+#include "namespace-util.h"
#include "nsflags.h"
#include "nulstr-util.h"
#include "process-util.h"
SCMP_ARCH_AARCH64, /* native */
#elif defined(__arm__)
SCMP_ARCH_ARM,
+#elif defined(__loongarch_lp64)
+ SCMP_ARCH_LOONGARCH64,
#elif defined(__mips__) && __BYTE_ORDER == __BIG_ENDIAN && _MIPS_SIM == _MIPS_SIM_ABI32
SCMP_ARCH_MIPSEL,
SCMP_ARCH_MIPS, /* native */
return "arm";
case SCMP_ARCH_AARCH64:
return "arm64";
+#ifdef SCMP_ARCH_LOONGARCH64
+ case SCMP_ARCH_LOONGARCH64:
+ return "loongarch64";
+#endif
case SCMP_ARCH_MIPS:
return "mips";
case SCMP_ARCH_MIPS64:
*ret = SCMP_ARCH_ARM;
else if (streq(n, "arm64"))
*ret = SCMP_ARCH_AARCH64;
+#ifdef SCMP_ARCH_LOONGARCH64
+ else if (streq(n, "loongarch64"))
+ *ret = SCMP_ARCH_LOONGARCH64;
+#endif
else if (streq(n, "mips"))
*ret = SCMP_ARCH_MIPS;
else if (streq(n, "mips64"))
"exit_group\0"
"futex\0"
"futex_time64\0"
+ "futex_waitv\0"
"get_robust_list\0"
"get_thread_area\0"
"getegid\0"
"pause\0"
"prlimit64\0"
"restart_syscall\0"
+ "riscv_flush_icache\0"
+ "riscv_hwprobe\0"
"rseq\0"
"rt_sigreturn\0"
"sched_getaffinity\0"
"pidfd_getfd\0"
"ptrace\0"
"rtas\0"
-#if defined __s390__ || defined __s390x__
"s390_runtime_instr\0"
-#endif
"sys_debug_setcontext\0"
},
[SYSCALL_FILTER_SET_FILE_SYSTEM] = {
"open_by_handle_at\0"
"pivot_root\0"
"quotactl\0"
+ "quotactl_fd\0"
"setdomainname\0"
"setfsuid\0"
"setfsuid32\0"
"pciconfig_iobase\0"
"pciconfig_read\0"
"pciconfig_write\0"
-#if defined __s390__ || defined __s390x__
"s390_pci_mmio_read\0"
"s390_pci_mmio_write\0"
-#endif
},
[SYSCALL_FILTER_SET_REBOOT] = {
.name = "@reboot",
"sched_setparam\0"
"sched_setscheduler\0"
"set_mempolicy\0"
+ "set_mempolicy_home_node\0"
"setpriority\0"
"setrlimit\0"
},
+ [SYSCALL_FILTER_SET_SANDBOX] = {
+ .name = "@sandbox",
+ .help = "Sandbox functionality",
+ .value =
+ "landlock_add_rule\0"
+ "landlock_create_ruleset\0"
+ "landlock_restrict_self\0"
+ "seccomp\0"
+ },
[SYSCALL_FILTER_SET_SETUID] = {
.name = "@setuid",
.help = "Operations for changing user/group credentials",
"@signal\0"
"@sync\0"
"@timer\0"
+ "arm_fadvise64_64\0"
"capget\0"
"capset\0"
"copy_file_range\0"
bool log_missing,
char ***added) {
- const char *sys;
int r;
/* Any syscalls that are handled are added to the *added strv. It needs to be initialized. */
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
r = seccomp_init_for_arch(&seccomp, arch, default_action);
if (r < 0)
return log_debug_errno(r, "Failed to add filter set: %m");
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
void *syscall_id, *val;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
r = seccomp_init_for_arch(&seccomp, arch, default_action);
if (r < 0)
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
log_debug_errno(r, "Failed to install system call filter for architecture %s, skipping: %m",
if (name[0] == '@') {
const SyscallFilterSet *set;
- const char *i;
set = syscall_filter_set_find(name);
if (!set) {
}
NULSTR_FOREACH(i, set->value) {
- /* Call ourselves again, for the group to parse. Note that we downgrade logging here (i.e. take
- * away the SECCOMP_PARSE_LOG flag) since any issues in the group table are our own problem,
- * not a problem in user configuration data and we shouldn't pretend otherwise by complaining
- * about them. */
+ /* Call ourselves again, for the group to parse. Note that we downgrade logging here
+ * (i.e. take away the SECCOMP_PARSE_LOG flag) since any issues in the group table
+ * are our own problem, not a problem in user configuration data and we shouldn't
+ * pretend otherwise by complaining about them. */
r = seccomp_parse_syscall_filter(i, errno_num, filter, flags &~ SECCOMP_PARSE_LOG, unit, filename, line);
if (r < 0)
return r;
return 0;
}
- /* If we previously wanted to forbid a syscall and now we want to allow it, then remove
- * it from the list. The entries in allow-list with non-negative error value will be
- * handled with SCMP_ACT_ERRNO() instead of the default action. */
+ /* If we previously wanted to forbid a syscall and now we want to allow it, then remove it
+ * from the list. The entries in allow-list with non-negative error value will be handled
+ * with SCMP_ACT_ERRNO() instead of the default action. */
if (!FLAGS_SET(flags, SECCOMP_PARSE_INVERT) == FLAGS_SET(flags, SECCOMP_PARSE_ALLOW_LIST) ||
(FLAGS_SET(flags, SECCOMP_PARSE_INVERT | SECCOMP_PARSE_ALLOW_LIST) && errno_num >= 0)) {
r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num));
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
if (r < 0)
SCMP_SYS(clone3),
0);
if (r < 0)
- log_debug_errno(r, "Failed to add clone3() rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add clone3() rule for architecture %s, ignoring: %m",
+ seccomp_arch_to_string(arch));
if ((retain & NAMESPACE_FLAGS_ALL) == 0)
- /* If every single kind of namespace shall be prohibited, then let's block the whole setns() syscall
- * altogether. */
+ /* If every single kind of namespace shall be prohibited, then let's block the whole
+ * setns() syscall altogether. */
r = seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(setns),
0);
else
- /* Otherwise, block only the invocations with the appropriate flags in the loop below, but also the
- * special invocation with a zero flags argument, right here. */
+ /* Otherwise, block only the invocations with the appropriate flags in the loop
+ * below, but also the special invocation with a zero flags argument, right here. */
r = seccomp_rule_add_exact(
seccomp,
SCMP_ACT_ERRNO(EPERM),
1,
SCMP_A1(SCMP_CMP_EQ, 0));
if (r < 0) {
- log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
- for (unsigned i = 0; namespace_flag_map[i].name; i++) {
+ for (unsigned i = 0; namespace_info[i].proc_name; i++) {
unsigned long f;
- f = namespace_flag_map[i].flag;
+ f = namespace_info[i].clone_flag;
if (FLAGS_SET(retain, f)) {
- log_debug("Permitting %s.", namespace_flag_map[i].name);
+ log_debug("Permitting %s.", namespace_info[i].proc_name);
continue;
}
- log_debug("Blocking %s.", namespace_flag_map[i].name);
+ log_trace("Blocking %s.", namespace_info[i].proc_name);
r = seccomp_rule_add_exact(
seccomp,
1,
SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
if (r < 0) {
- log_debug_errno(r, "Failed to add unshare() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add unshare() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
break;
}
1,
SCMP_A1(SCMP_CMP_MASKED_EQ, f, f));
if (r < 0) {
- log_debug_errno(r, "Failed to add clone() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add clone() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
break;
}
1,
SCMP_A1(SCMP_CMP_MASKED_EQ, f, f));
if (r < 0) {
- log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
break;
}
}
continue;
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to install namespace restriction rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to install namespace restriction rules for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
if (IN_SET(arch,
SCMP_ARCH_AARCH64,
+#ifdef SCMP_ARCH_LOONGARCH64
+ SCMP_ARCH_LOONGARCH64,
+#endif
#ifdef SCMP_ARCH_RISCV64
SCMP_ARCH_RISCV64,
#endif
SCMP_SYS(_sysctl),
0);
if (r < 0) {
- log_debug_errno(r, "Failed to add _sysctl() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add _sysctl() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to install sysctl protection rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to install sysctl protection rules for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to install syslog protection rules for architecture %s, skipping %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to install syslog protection rules for architecture %s, skipping %m",
+ seccomp_arch_to_string(arch));
}
return 0;
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
bool supported;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
switch (arch) {
case SCMP_ARCH_X32:
case SCMP_ARCH_ARM:
case SCMP_ARCH_AARCH64:
+#ifdef SCMP_ARCH_LOONGARCH64
+ case SCMP_ARCH_LOONGARCH64:
+#endif
case SCMP_ARCH_MIPSEL64N32:
case SCMP_ARCH_MIPS64N32:
case SCMP_ARCH_MIPSEL64:
SCMP_SYS(socket),
0);
if (r < 0) {
- log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
1,
SCMP_A0(SCMP_CMP_LT, first));
if (r < 0) {
- log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
1,
SCMP_A0(SCMP_CMP_GT, last));
if (r < 0) {
- log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
break;
}
if (r < 0) {
- log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
}
break;
}
if (r < 0) {
- log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to install socket family rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to install socket family rules for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
int p;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
if (r < 0)
1,
SCMP_A1(SCMP_CMP_EQ, p));
if (r < 0) {
- log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
}
1,
SCMP_A1(SCMP_CMP_GT, max_policy));
if (r < 0) {
- log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to install realtime protection rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to install realtime protection rules for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
}
/* For known architectures, check that syscalls are indeed defined or not. */
-#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64) || (defined(__riscv) && __riscv_xlen == 64)
assert_cc(SCMP_SYS(shmget) > 0);
assert_cc(SCMP_SYS(shmat) > 0);
assert_cc(SCMP_SYS(shmdt) > 0);
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
int filter_syscall = 0, block_syscall = 0, shmat_syscall = 0, r;
- log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+ log_trace("Operating on architecture: %s", seccomp_arch_to_string(arch));
switch (arch) {
case SCMP_ARCH_X86_64:
case SCMP_ARCH_X32:
case SCMP_ARCH_AARCH64:
+#ifdef SCMP_ARCH_LOONGARCH64
+ case SCMP_ARCH_LOONGARCH64:
+#endif
#ifdef SCMP_ARCH_RISCV64
case SCMP_ARCH_RISCV64:
#endif
- filter_syscall = SCMP_SYS(mmap); /* amd64, x32, arm64 and riscv64 have only mmap */
+ filter_syscall = SCMP_SYS(mmap); /* amd64, x32, arm64, loongarch64 and riscv64 have only mmap */
shmat_syscall = SCMP_SYS(shmat);
break;
/* Please add more definitions here, if you port systemd to other architectures! */
-#if !defined(__i386__) && !defined(__x86_64__) && !defined(__hppa__) && !defined(__hppa64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390__) && !defined(__s390x__) && !(defined(__riscv) && __riscv_xlen == 64)
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__hppa__) && !defined(__hppa64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390__) && !defined(__s390x__) && !(defined(__riscv) && __riscv_xlen == 64) && !defined(__loongarch_lp64)
#warning "Consider adding the right mmap() syscall definitions here!"
#endif
}
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
log_debug_errno(r, "Failed to install MemoryDenyWriteExecute= rule for architecture %s, skipping: %m",
return r;
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
log_debug_errno(r, "Failed to restrict system call architectures, skipping: %m");
}
int seccomp_filter_set_add(Hashmap *filter, bool add, const SyscallFilterSet *set) {
- const char *i;
int r;
assert(set);
1,
SCMP_A0(SCMP_CMP_NE, personality));
if (r < 0) {
- log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to enable personality lock for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to enable personality lock for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
SCMP_SYS(sethostname),
0);
if (r < 0) {
- log_debug_errno(r, "Failed to add sethostname() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add sethostname() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
SCMP_SYS(setdomainname),
0);
if (r < 0) {
- log_debug_errno(r, "Failed to add setdomainname() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add setdomainname() rule for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
continue;
}
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to apply hostname restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to apply hostname restrictions for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
r = seccomp_restrict_sxid(seccomp, S_ISUID);
if (r < 0)
- log_debug_errno(r, "Failed to add suid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add suid rule for architecture %s, ignoring: %m",
+ seccomp_arch_to_string(arch));
k = seccomp_restrict_sxid(seccomp, S_ISGID);
if (k < 0)
- log_debug_errno(r, "Failed to add sgid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to add sgid rule for architecture %s, ignoring: %m",
+ seccomp_arch_to_string(arch));
if (r < 0 && k < 0)
continue;
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
- const char *c;
r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
if (r < 0)
#endif
r = seccomp_load(seccomp);
- if (ERRNO_IS_SECCOMP_FATAL(r))
+ if (ERRNO_IS_NEG_SECCOMP_FATAL(r))
return r;
if (r < 0)
- log_debug_errno(r, "Failed to apply sync() suppression for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+ log_debug_errno(r, "Failed to apply sync() suppression for architecture %s, skipping: %m",
+ seccomp_arch_to_string(arch));
}
return 0;