git: 82fa7c3b83d8 - stable/13 - linux(4): Add compat.linux32.emulate_i386 knob.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Fri, 17 Jun 2022 19:38:53 UTC
The branch stable/13 has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=82fa7c3b83d841fb3e9071c41d39e92b8adb021c

commit 82fa7c3b83d841fb3e9071c41d39e92b8adb021c
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-03-31 18:01:09 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:33:47 +0000

    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
    
    (cherry picked from commit d5dc757e84d8dc1db987f3a17052e32621d6ea87)
---
 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 ee2629092100..ecf633f39648 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 f1f877181e47..1273ff485dd9 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 e84b61580b42..227cefa92847 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -884,6 +884,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 fa7d364681dc..b1f465ef5a9e 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);