aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-11-16 18:16:46 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-11-16 18:16:46 +0000
commitabb1565d3d863cf210f18f70c4a42b0f39b8ccdb (patch)
tree7198bb5e6ae6a5dde3c665aa6612771a6140c28b /linux-user
parent43f2def68476697deb0d119cbae51b20019c6c86 (diff)
parent8377e3fb854d126ba10e61cb6b60885af8443ad4 (diff)
downloadqemu-abb1565d3d863cf210f18f70c4a42b0f39b8ccdb.zip
qemu-abb1565d3d863cf210f18f70c4a42b0f39b8ccdb.tar.gz
qemu-abb1565d3d863cf210f18f70c4a42b0f39b8ccdb.tar.bz2
Merge tag 'pull-tcg-20241116' of https://gitlab.com/rth7680/qemu into staging
cpu: ensure we don't call start_exclusive from cpu_exec tcg: Allow top bit of SIMD_DATA_BITS to be set in simd_desc() accel/tcg: Fix user-only probe_access_internal plugin check linux-user: Fix setreuid and setregid to use direct syscalls linux-user: Tolerate CONFIG_LSM_MMAP_MIN_ADDR linux-user: Honor elf alignment when placing images linux-user/*: Reduce vdso alignment to 4k linux-user/arm: Select vdso for be8 and be32 modes # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmc4z/8dHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/vWgf5Af8105enuWEdJ9c+ # KiyTsOWQEOKXTUSlSUxPs9FEeEr2l/mccvqUhiD7ptZq7P5/40+3tB18KXc5YuiE # 45CZGRAr/tjALGT5LidSYzm6RgljWXYlvWVShqKlQpOD2L0GP5k8a7KEKsT3SLtS # 9l+SVvjNOE+Jv23FWSOVYq0K0e5dPKzS1gtviCg+obA56dsiSKiEwwg+a5ca6oRe # 9SUKoRnudpUv3fiYo8yZaHPW0ADhsITAB20ncN+cI9t4li9q5AWUbPZ+ADP113+2 # pWlco1VqR4pONK2UgbSmxDtjQf1GBi7E2MBFBjBMxTaiw/jXAZcZGIK4geZYKdHT # NJj/0Q== # =oKCm # -----END PGP SIGNATURE----- # gpg: Signature made Sat 16 Nov 2024 17:01:51 GMT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-tcg-20241116' of https://gitlab.com/rth7680/qemu: tcg: Allow top bit of SIMD_DATA_BITS to be set in simd_desc() linux-user/arm: Select vdso for be8 and be32 modes linux-user/ppc: Reduce vdso alignment to 4k linux-user/loongarch64: Reduce vdso alignment to 4k linux-user/arm: Reduce vdso alignment to 4k linux-user/aarch64: Reduce vdso alignment to 4k linux-user: Drop image_info.alignment linux-user: Honor elf alignment when placing images cpu: ensure we don't call start_exclusive from cpu_exec target/i386: fix hang when using slow path for ptw_setl tests/tcg: Test that sigreturn() does not corrupt the signal mask linux-user: Tolerate CONFIG_LSM_MMAP_MIN_ADDR accel/tcg: Fix user-only probe_access_internal plugin check target/arm: Drop user-only special case in sve_stN_r linux-user: Fix setreuid and setregid to use direct syscalls Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/aarch64/Makefile.vdso5
-rwxr-xr-xlinux-user/aarch64/vdso-be.sobin3224 -> 3224 bytes
-rwxr-xr-xlinux-user/aarch64/vdso-le.sobin3224 -> 3224 bytes
-rw-r--r--linux-user/arm/Makefile.vdso11
-rw-r--r--linux-user/arm/meson.build13
-rwxr-xr-xlinux-user/arm/vdso-be32.sobin0 -> 2648 bytes
-rwxr-xr-xlinux-user/arm/vdso-be8.so (renamed from linux-user/arm/vdso-be.so)bin2648 -> 2648 bytes
-rwxr-xr-xlinux-user/arm/vdso-le.sobin2648 -> 2648 bytes
-rw-r--r--linux-user/elfload.c71
-rw-r--r--linux-user/loongarch64/Makefile.vdso3
-rwxr-xr-xlinux-user/loongarch64/vdso.sobin3560 -> 3560 bytes
-rw-r--r--linux-user/ppc/Makefile.vdso6
-rwxr-xr-xlinux-user/ppc/vdso-32.sobin3020 -> 3020 bytes
-rwxr-xr-xlinux-user/ppc/vdso-64.sobin3896 -> 3896 bytes
-rwxr-xr-xlinux-user/ppc/vdso-64le.sobin3896 -> 3896 bytes
-rw-r--r--linux-user/qemu.h1
-rw-r--r--linux-user/syscall.c20
17 files changed, 97 insertions, 33 deletions
diff --git a/linux-user/aarch64/Makefile.vdso b/linux-user/aarch64/Makefile.vdso
index 5999581..c33a679 100644
--- a/linux-user/aarch64/Makefile.vdso
+++ b/linux-user/aarch64/Makefile.vdso
@@ -5,8 +5,9 @@ VPATH += $(SUBDIR)
all: $(SUBDIR)/vdso-be.so $(SUBDIR)/vdso-le.so
-LDFLAGS = -nostdlib -shared -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
- -Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld
+LDFLAGS = -nostdlib -shared -Wl,-h,linux-vdso.so.1 \
+ -Wl,--build-id=sha1 -Wl,--hash-style=both \
+ -Wl,-z,max-page-size=4096 -Wl,-T,$(SUBDIR)/vdso.ld
$(SUBDIR)/vdso-be.so: vdso.S vdso.ld
$(CC) -o $@ $(LDFLAGS) -mbig-endian $<
diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so
index 808206a..d43c3b1 100755
--- a/linux-user/aarch64/vdso-be.so
+++ b/linux-user/aarch64/vdso-be.so
Binary files differ
diff --git a/linux-user/aarch64/vdso-le.so b/linux-user/aarch64/vdso-le.so
index 941aaf2..aaedc9d 100755
--- a/linux-user/aarch64/vdso-le.so
+++ b/linux-user/aarch64/vdso-le.so
Binary files differ
diff --git a/linux-user/arm/Makefile.vdso b/linux-user/arm/Makefile.vdso
index 2d098a5..ede489e 100644
--- a/linux-user/arm/Makefile.vdso
+++ b/linux-user/arm/Makefile.vdso
@@ -3,15 +3,18 @@ include $(BUILD_DIR)/tests/tcg/arm-linux-user/config-target.mak
SUBDIR = $(SRC_PATH)/linux-user/arm
VPATH += $(SUBDIR)
-all: $(SUBDIR)/vdso-be.so $(SUBDIR)/vdso-le.so
+all: $(SUBDIR)/vdso-be8.so $(SUBDIR)/vdso-be32.so $(SUBDIR)/vdso-le.so
# Adding -use-blx disables unneeded interworking without actually using blx.
-LDFLAGS = -nostdlib -shared -Wl,-use-blx \
+LDFLAGS = -nostdlib -shared -Wl,-use-blx -Wl,-z,max-page-size=4096 \
-Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
-Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld
-$(SUBDIR)/vdso-be.so: vdso.S vdso.ld vdso-asmoffset.h
- $(CC) -o $@ $(LDFLAGS) -mbig-endian $<
+$(SUBDIR)/vdso-be8.so: vdso.S vdso.ld vdso-asmoffset.h
+ $(CC) -o $@ $(LDFLAGS) -mbig-endian -mbe8 $<
+
+$(SUBDIR)/vdso-be32.so: vdso.S vdso.ld vdso-asmoffset.h
+ $(CC) -o $@ $(LDFLAGS) -mbig-endian -mbe32 $<
$(SUBDIR)/vdso-le.so: vdso.S vdso.ld vdso-asmoffset.h
$(CC) -o $@ $(LDFLAGS) -mlittle-endian $<
diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
index c4bb9af..348ffb8 100644
--- a/linux-user/arm/meson.build
+++ b/linux-user/arm/meson.build
@@ -10,10 +10,17 @@ syscall_nr_generators += {
# is always true as far as source_set.apply() is concerned. Always build
# both header files and include the right one via #if.
-vdso_be_inc = gen_vdso.process('vdso-be.so',
- extra_args: ['-s', 'sigreturn_codes'])
+vdso_be8_inc = gen_vdso.process('vdso-be8.so',
+ extra_args: ['-s', 'sigreturn_codes',
+ '-p', 'vdso_be8'])
+
+vdso_be32_inc = gen_vdso.process('vdso-be32.so',
+ extra_args: ['-s', 'sigreturn_codes',
+ '-p', 'vdso_be32'])
vdso_le_inc = gen_vdso.process('vdso-le.so',
extra_args: ['-s', 'sigreturn_codes'])
-linux_user_ss.add(when: 'TARGET_ARM', if_true: [vdso_be_inc, vdso_le_inc])
+linux_user_ss.add(when: 'TARGET_ARM', if_true: [
+ vdso_be8_inc, vdso_be32_inc, vdso_le_inc
+])
diff --git a/linux-user/arm/vdso-be32.so b/linux-user/arm/vdso-be32.so
new file mode 100755
index 0000000..b896d3d
--- /dev/null
+++ b/linux-user/arm/vdso-be32.so
Binary files differ
diff --git a/linux-user/arm/vdso-be.so b/linux-user/arm/vdso-be8.so
index 69cafbb..784b7bd 100755
--- a/linux-user/arm/vdso-be.so
+++ b/linux-user/arm/vdso-be8.so
Binary files differ
diff --git a/linux-user/arm/vdso-le.so b/linux-user/arm/vdso-le.so
index ad05a12..38d3d51 100755
--- a/linux-user/arm/vdso-le.so
+++ b/linux-user/arm/vdso-le.so
Binary files differ
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 6cef8db..471a384 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -659,6 +659,23 @@ static const char *get_elf_platform(void)
#undef END
}
+#if TARGET_BIG_ENDIAN
+#include "elf.h"
+#include "vdso-be8.c.inc"
+#include "vdso-be32.c.inc"
+
+static const VdsoImageInfo *vdso_image_info(uint32_t elf_flags)
+{
+ return (EF_ARM_EABI_VERSION(elf_flags) >= EF_ARM_EABI_VER4
+ && (elf_flags & EF_ARM_BE8)
+ ? &vdso_be8_image_info
+ : &vdso_be32_image_info);
+}
+#define vdso_image_info vdso_image_info
+#else
+# define VDSO_HEADER "vdso-le.c.inc"
+#endif
+
#else
/* 64 bit ARM definitions */
@@ -958,14 +975,14 @@ const char *elf_hwcap2_str(uint32_t bit)
#undef GET_FEATURE_ID
-#endif /* not TARGET_AARCH64 */
-
#if TARGET_BIG_ENDIAN
# define VDSO_HEADER "vdso-be.c.inc"
#else
# define VDSO_HEADER "vdso-le.c.inc"
#endif
+#endif /* not TARGET_AARCH64 */
+
#endif /* TARGET_ARM */
#ifdef TARGET_SPARC
@@ -2898,7 +2915,7 @@ static uintptr_t pgb_try_itree(const PGBAddrs *ga, uintptr_t base,
static uintptr_t pgb_find_itree(const PGBAddrs *ga, IntervalTreeRoot *root,
uintptr_t align, uintptr_t brk)
{
- uintptr_t last = mmap_min_addr;
+ uintptr_t last = sizeof(uintptr_t) == 4 ? MiB : GiB;
uintptr_t base, skip;
while (true) {
@@ -3179,7 +3196,8 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
char **pinterp_name)
{
g_autofree struct elf_phdr *phdr = NULL;
- abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+ abi_ulong load_addr, load_bias, loaddr, hiaddr, error, align;
+ size_t reserve_size, align_size;
int i, prot_exec;
Error *err = NULL;
@@ -3219,7 +3237,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
* amount of memory to handle that. Locate the interpreter, if any.
*/
loaddr = -1, hiaddr = 0;
- info->alignment = 0;
+ align = 0;
info->exec_stack = EXSTACK_DEFAULT;
for (i = 0; i < ehdr->e_phnum; ++i) {
struct elf_phdr *eppnt = phdr + i;
@@ -3233,7 +3251,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
hiaddr = a;
}
++info->nsegs;
- info->alignment |= eppnt->p_align;
+ align |= eppnt->p_align;
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
g_autofree char *interp_name = NULL;
@@ -3263,6 +3281,8 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
load_addr = loaddr;
+ align = pow2ceil(align);
+
if (pinterp_name != NULL) {
if (ehdr->e_type == ET_EXEC) {
/*
@@ -3271,8 +3291,6 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
*/
probe_guest_base(image_name, loaddr, hiaddr);
} else {
- abi_ulong align;
-
/*
* The binary is dynamic, but we still need to
* select guest_base. In this case we pass a size.
@@ -3290,10 +3308,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
* Since we do not have complete control over the guest
* address space, we prefer the kernel to choose some address
* rather than force the use of LOAD_ADDR via MAP_FIXED.
- * But without MAP_FIXED we cannot guarantee alignment,
- * only suggest it.
*/
- align = pow2ceil(info->alignment);
if (align) {
load_addr &= -align;
}
@@ -3317,13 +3332,35 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
* In both cases, we will overwrite pages in this range with mappings
* from the executable.
*/
- load_addr = target_mmap(load_addr, (size_t)hiaddr - loaddr + 1, PROT_NONE,
+ reserve_size = (size_t)hiaddr - loaddr + 1;
+ align_size = reserve_size;
+
+ if (ehdr->e_type != ET_EXEC && align > qemu_real_host_page_size()) {
+ align_size += align - 1;
+ }
+
+ load_addr = target_mmap(load_addr, align_size, PROT_NONE,
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
(ehdr->e_type == ET_EXEC ? MAP_FIXED_NOREPLACE : 0),
-1, 0);
if (load_addr == -1) {
goto exit_mmap;
}
+
+ if (align_size != reserve_size) {
+ abi_ulong align_addr = ROUND_UP(load_addr, align);
+ abi_ulong align_end = align_addr + reserve_size;
+ abi_ulong load_end = load_addr + align_size;
+
+ if (align_addr != load_addr) {
+ target_munmap(load_addr, align_addr - load_addr);
+ }
+ if (align_end != load_end) {
+ target_munmap(align_end, load_end - align_end);
+ }
+ load_addr = align_addr;
+ }
+
load_bias = load_addr - loaddr;
if (elf_is_fdpic(ehdr)) {
@@ -3504,12 +3541,14 @@ static void load_elf_interp(const char *filename, struct image_info *info,
load_elf_image(filename, &src, info, &ehdr, NULL);
}
+#ifndef vdso_image_info
#ifdef VDSO_HEADER
#include VDSO_HEADER
-#define vdso_image_info() &vdso_image_info
+#define vdso_image_info(flags) &vdso_image_info
#else
-#define vdso_image_info() NULL
-#endif
+#define vdso_image_info(flags) NULL
+#endif /* VDSO_HEADER */
+#endif /* vdso_image_info */
static void load_elf_vdso(struct image_info *info, const VdsoImageInfo *vdso)
{
@@ -3840,7 +3879,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
* Load a vdso if available, which will amongst other things contain the
* signal trampolines. Otherwise, allocate a separate page for them.
*/
- const VdsoImageInfo *vdso = vdso_image_info();
+ const VdsoImageInfo *vdso = vdso_image_info(info->elf_flags);
if (vdso) {
load_elf_vdso(&vdso_info, vdso);
info->vdso = vdso_info.load_bias;
diff --git a/linux-user/loongarch64/Makefile.vdso b/linux-user/loongarch64/Makefile.vdso
index 369de13..1d760b1 100644
--- a/linux-user/loongarch64/Makefile.vdso
+++ b/linux-user/loongarch64/Makefile.vdso
@@ -8,4 +8,5 @@ all: $(SUBDIR)/vdso.so
$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
$(CC) -o $@ -nostdlib -shared -fpic -Wl,-h,linux-vdso.so.1 \
-Wl,--build-id=sha1 -Wl,--hash-style=both \
- -Wl,--no-warn-rwx-segments -Wl,-T,$(SUBDIR)/vdso.ld $<
+ -Wl,--no-warn-rwx-segments -Wl,-z,max-page-size=4096 \
+ -Wl,-T,$(SUBDIR)/vdso.ld $<
diff --git a/linux-user/loongarch64/vdso.so b/linux-user/loongarch64/vdso.so
index bfaa26f..7c2de6c 100755
--- a/linux-user/loongarch64/vdso.so
+++ b/linux-user/loongarch64/vdso.so
Binary files differ
diff --git a/linux-user/ppc/Makefile.vdso b/linux-user/ppc/Makefile.vdso
index 3ca3c6b..e2b8fac 100644
--- a/linux-user/ppc/Makefile.vdso
+++ b/linux-user/ppc/Makefile.vdso
@@ -6,9 +6,11 @@ VPATH += $(SUBDIR)
all: $(SUBDIR)/vdso-32.so $(SUBDIR)/vdso-64.so $(SUBDIR)/vdso-64le.so
LDFLAGS32 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-32.ld \
- -Wl,-h,linux-vdso32.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
+ -Wl,-h,linux-vdso32.so.1 -Wl,--hash-style=both \
+ -Wl,--build-id=sha1 -Wl,-z,max-page-size=4096
LDFLAGS64 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-64.ld \
- -Wl,-h,linux-vdso64.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
+ -Wl,-h,linux-vdso64.so.1 -Wl,--hash-style=both \
+ -Wl,--build-id=sha1 -Wl,-z,max-page-size=4096
$(SUBDIR)/vdso-32.so: vdso.S vdso-32.ld vdso-asmoffset.h
$(CC) -o $@ $(LDFLAGS32) -m32 $<
diff --git a/linux-user/ppc/vdso-32.so b/linux-user/ppc/vdso-32.so
index b19baaf..0dc55e0 100755
--- a/linux-user/ppc/vdso-32.so
+++ b/linux-user/ppc/vdso-32.so
Binary files differ
diff --git a/linux-user/ppc/vdso-64.so b/linux-user/ppc/vdso-64.so
index 913c831..ac1ab25 100755
--- a/linux-user/ppc/vdso-64.so
+++ b/linux-user/ppc/vdso-64.so
Binary files differ
diff --git a/linux-user/ppc/vdso-64le.so b/linux-user/ppc/vdso-64le.so
index 258a03b..424abb4 100755
--- a/linux-user/ppc/vdso-64le.so
+++ b/linux-user/ppc/vdso-64le.so
Binary files differ
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 895bdd7..67bc81b 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -44,7 +44,6 @@ struct image_info {
abi_ulong file_string;
uint32_t elf_flags;
int personality;
- abi_ulong alignment;
bool exec_stack;
/* Generic semihosting knows about these pointers. */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 59b2080..0279f23 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7233,12 +7233,24 @@ static inline int tswapid(int id)
#else
#define __NR_sys_setgroups __NR_setgroups
#endif
+#ifdef __NR_sys_setreuid32
+#define __NR_sys_setreuid __NR_setreuid32
+#else
+#define __NR_sys_setreuid __NR_setreuid
+#endif
+#ifdef __NR_sys_setregid32
+#define __NR_sys_setregid __NR_setregid32
+#else
+#define __NR_sys_setregid __NR_setregid
+#endif
_syscall1(int, sys_setuid, uid_t, uid)
_syscall1(int, sys_setgid, gid_t, gid)
_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
_syscall2(int, sys_setgroups, int, size, gid_t *, grouplist)
+_syscall2(int, sys_setreuid, uid_t, ruid, uid_t, euid);
+_syscall2(int, sys_setregid, gid_t, rgid, gid_t, egid);
void syscall_init(void)
{
@@ -11932,9 +11944,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return get_errno(high2lowgid(getegid()));
#endif
case TARGET_NR_setreuid:
- return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
+ return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2)));
case TARGET_NR_setregid:
- return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
+ return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2)));
case TARGET_NR_getgroups:
{ /* the same code as for TARGET_NR_getgroups32 */
int gidsetsize = arg1;
@@ -12264,11 +12276,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_setreuid32
case TARGET_NR_setreuid32:
- return get_errno(setreuid(arg1, arg2));
+ return get_errno(sys_setreuid(arg1, arg2));
#endif
#ifdef TARGET_NR_setregid32
case TARGET_NR_setregid32:
- return get_errno(setregid(arg1, arg2));
+ return get_errno(sys_setregid(arg1, arg2));
#endif
#ifdef TARGET_NR_getgroups32
case TARGET_NR_getgroups32: