On Mon, Aug 19, 2019 at 3:34 PM Aleksandar Markovic < aleksandar.m.m...@gmail.com> wrote:
> Hi, David. > > I can't repro the problem either, but I do have a patch authored by an > engineer that left the company a while ago that seems to be at least > related to your scenario. May I ask you to test it (just apply it to QEMU > ToT and rerun the scenario to see if it changes the outcome) (feel free to > experiment and modify the changes)? I never managed to understand the > purpose of that patch (I lost the contact with the former engineer, and the > patch is without any comment), so I never dared to send it to the list, but > I hope your scenario may actually explain the purpose and the origin of the > patch. > > I am attaching the patch both as a file and inline. > > In the patch I had sent in my previous mail, TARGET_ENONET should be replaced by TARGET_ENOENT. I made a mistake while doing speedy rebasing. Though, both ENONET and ENOENT compile, and perhaps the error code value is not crucial. I am attaching the updated/corrected patch. Aleksandar > Yours, > Aleksandar > > > From 377f99e807f4aa42ece9f0cd437f50af11611b4c Mon Sep 17 00:00:00 2001 > From: Aleksandar Markovic <amarko...@wavecomp.com> > Date: Mon, 19 Aug 2019 15:20:29 +0200 > Subject: [PATCH] linux-user: Special case /etc/ld.cache.so and pretend it > does > not exist > > Prevent target executables from opening host ld.so.cache. > --- > linux-user/syscall.c | 28 ++++++++++++++++++++++++++++ > 1 file changed, 28 insertions(+) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 8367cb1..f5bae6e 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -8820,6 +8820,10 @@ static abi_long do_syscall1(void *cpu_env, int num, > abi_long arg1, > if (!(p = lock_user_string(arg1))) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > ret = get_errno(statfs(path(p), &stfs)); > unlock_user(p, arg1, 0); > convert_statfs: > @@ -8859,6 +8863,10 @@ static abi_long do_syscall1(void *cpu_env, int num, > abi_long arg1, > if (!(p = lock_user_string(arg1))) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > ret = get_errno(statfs(path(p), &stfs)); > unlock_user(p, arg1, 0); > convert_statfs64: > @@ -9059,6 +9067,10 @@ static abi_long do_syscall1(void *cpu_env, int num, > abi_long arg1, > if (!(p = lock_user_string(arg1))) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > ret = get_errno(stat(path(p), &st)); > unlock_user(p, arg1, 0); > goto do_stat; > @@ -9068,6 +9080,10 @@ static abi_long do_syscall1(void *cpu_env, int num, > abi_long arg1, > if (!(p = lock_user_string(arg1))) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > ret = get_errno(lstat(path(p), &st)); > unlock_user(p, arg1, 0); > goto do_stat; > @@ -10268,6 +10284,10 @@ static abi_long do_syscall1(void *cpu_env, int > num, abi_long arg1, > if (!(p = lock_user_string(arg1))) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > ret = get_errno(stat(path(p), &st)); > unlock_user(p, arg1, 0); > if (!is_error(ret)) > @@ -10279,6 +10299,10 @@ static abi_long do_syscall1(void *cpu_env, int > num, abi_long arg1, > if (!(p = lock_user_string(arg1))) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > ret = get_errno(lstat(path(p), &st)); > unlock_user(p, arg1, 0); > if (!is_error(ret)) > @@ -10319,6 +10343,10 @@ static abi_long do_syscall1(void *cpu_env, int > num, abi_long arg1, > if (p == NULL) { > return -TARGET_EFAULT; > } > + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { > + unlock_user(p, arg1, 0); > + return -TARGET_ENONET; > + } > #if defined(__NR_statx) > { > /* > -- > 2.7.4 > > > On Mon, Aug 19, 2019 at 3:08 PM David Hildenbrand <da...@redhat.com> > wrote: > >> On 19.08.19 14:11, Peter Maydell wrote: >> > On Sat, 17 Aug 2019 at 17:14, David Hildenbrand <da...@redhat.com> >> wrote: >> >> >> >> On 17.08.19 17:59, David Hildenbrand wrote: >> >>> Hi everybody, >> >>> >> >>> I was just trying to run qemu-s390x (linux-user) with a very simple >> >>> binary (gzip + lib/ld64.so.1, compiled under Fedora 27). This used to >> >>> work just fine a while ago (especially when I was working on vector >> >>> instructions using QEMU v3.1). However, now I can't get past a >> SEGFAULT >> >>> in the dynamic library loader (I assume it is trying to locate >> glibc). I >> >>> tried a couple of other binaries that definitely used to work (from >> >>> Fedora 30). >> >>> >> >>> I checked QEMU v4.1, v4.0 and v3.1. All are broken for me. Which is >> >>> weird - because it used to work :/ >> >>> >> >>> I remember that I was running Fedora 29 the last time I had it >> running, >> >>> so my gut feeling is that this is related to some other system library >> >>> (but which?). I am running on an up-to-date Fedora 30 x86-64 now. >> >>> >> >>> Any ideas? Has this been reported already? (not sure if this is a >> Fedora >> >>> 30 issue) >> > >> > I'm pretty sure the problem you've run into is a long standing >> > bug in the glibc dynamic loader. It cannot cope with the ld.so.cache >> > being for the wrong endianness. (Correct endianness but incorrect >> > architecture it correctly detects and ignores). The result is that >> > running a linux-user QEMU dynamic binary for big-endian on little-endian >> > like this will crash in the dynamic loader unless you arrange that it >> can't >> > find the host's ld.so.cache somehow, eg: >> > (a) run inside a chroot >> > (b) create an empty /etc/ld.so.cache file inside the -L directory >> > >> > The ideal fix would be if somebody cared enough to track down >> > and fix the ld.so bug. >> > >> > Compare: >> > https://bugs.launchpad.net/qemu/+bug/1701798 >> > https://bugs.launchpad.net/qemu/+bug/1835693 >> > >> > thanks >> > -- PMM >> > >> >> Thanks, running >> >> "ldconfig -c etc/ld.so.cache -r ." >> >> Seems to fix the issue for me. So you are sure the bug resides in glic >> and not in the qemu-user pieces of the library loader? >> >> -- >> >> Thanks, >> >> David / dhildenb >> >>
From 6146453ecbbeca26e64a6ed6aa86b359032d32be Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic <amarko...@wavecomp.com> Date: Mon, 19 Aug 2019 15:20:29 +0200 Subject: [PATCH] linux-user: Special case /etc/ld.cache.so and pretend it does not exist Prevent target executables from opening host ld.so.cache. --- linux-user/syscall.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8367cb1..983c6e7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8820,6 +8820,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!(p = lock_user_string(arg1))) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } ret = get_errno(statfs(path(p), &stfs)); unlock_user(p, arg1, 0); convert_statfs: @@ -8859,6 +8863,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!(p = lock_user_string(arg1))) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } ret = get_errno(statfs(path(p), &stfs)); unlock_user(p, arg1, 0); convert_statfs64: @@ -9059,6 +9067,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!(p = lock_user_string(arg1))) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } ret = get_errno(stat(path(p), &st)); unlock_user(p, arg1, 0); goto do_stat; @@ -9068,6 +9080,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!(p = lock_user_string(arg1))) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } ret = get_errno(lstat(path(p), &st)); unlock_user(p, arg1, 0); goto do_stat; @@ -10268,6 +10284,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!(p = lock_user_string(arg1))) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } ret = get_errno(stat(path(p), &st)); unlock_user(p, arg1, 0); if (!is_error(ret)) @@ -10279,6 +10299,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!(p = lock_user_string(arg1))) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } ret = get_errno(lstat(path(p), &st)); unlock_user(p, arg1, 0); if (!is_error(ret)) @@ -10319,6 +10343,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (p == NULL) { return -TARGET_EFAULT; } + if (strcmp("/etc/ld.so.cache", path(p)) == 0) { + unlock_user(p, arg1, 0); + return -TARGET_ENOENT; + } #if defined(__NR_statx) { /* -- 2.7.4