From d5dc757e84d8dc1db987f3a17052e32621d6ea87 Mon Sep 17 00:00:00 2001 From: Dmitry Chagin Date: Thu, 31 Mar 2022 21:01:09 +0300 Subject: [PATCH] linux(4): Add compat.linux32.emulate_i386 knob. Historically 32-bit Linuxulator under amd64 emulated the real i386 behavior. Since 3d8dd983 the old i386 Linux world can't be used under amd64 Linuxulator as it don't know anything about amd64 machine (which is returned now by newuname() syscall). So, add a knob to allow to swith the behavior and use i386 Linux binaries on amd64. Set knob to the new behavior as I think this is common to the modern Linux distros. Reviewed by: Pau Amma (doc), emaste Differential revision: https://reviews.freebsd.org/D34708 MFC after: 2 weeks --- share/man/man4/linux.4 | 6 ++++++ sys/amd64/linux32/linux.h | 2 ++ sys/amd64/linux32/linux32_sysvec.c | 3 +++ sys/compat/linux/linux_misc.c | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/share/man/man4/linux.4 b/share/man/man4/linux.4 index ee262909210..ecf633f3964 100644 --- a/share/man/man4/linux.4 +++ b/share/man/man4/linux.4 @@ -145,6 +145,12 @@ This might be reasonable or even required, because does not emulate the Linux environment completely, and missed features may result in security vulnerabilities. Defaults to 1. +.It Va compat.linux32.emulate_i386 +In the x86_64 (amd64) world enable the real i386 Linuxulator behavior. +For example, when set to 0, Linux uname -m will return "x86_64" even if +uname itself is a i386 Linux executable. When set to 1, Linux i386 +uname -m will return "i686". +Defaults to 0. .El .Sh FILES .Bl -tag -width /compat/linux/dev/shm -compact diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index f1f877181e4..1273ff485dd 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -637,4 +637,6 @@ struct reg32; void bsd_to_linux_regset32(const struct reg32 *b_reg, struct linux_pt_regset32 *l_regset); +extern bool linux32_emulate_i386; + #endif /* !_AMD64_LINUX_H_ */ diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index ff9ceda795c..782ab224606 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -885,6 +885,9 @@ SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxssiz, CTLFLAG_RW, static u_long linux32_maxvmem = LINUX32_MAXVMEM; SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxvmem, CTLFLAG_RW, &linux32_maxvmem, 0, ""); +bool linux32_emulate_i386 = false; +SYSCTL_BOOL(_compat_linux32, OID_AUTO, emulate_i386, CTLFLAG_RWTUN, + &linux32_emulate_i386, 0, "Emulate the real i386"); static void linux32_fixlimit(struct rlimit *rl, int which) diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index f4ea9294172..0579ac1a03c 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -720,6 +720,11 @@ linux_newuname(struct thread *td, struct linux_newuname_args *args) * the string returned by getauxval(AT_PLATFORM) needs * to remain "i686", though. */ +#if defined(COMPAT_LINUX32) + if (linux32_emulate_i386) + strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME); + else +#endif strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME); #elif defined(__aarch64__) strlcpy(utsname.machine, "aarch64", LINUX_MAX_UTSNAME);