This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug nptl/18726] Futexes are broken on MIPS/n32
- From: "oss at malat dot biz" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Mon, 27 Jul 2015 16:18:33 +0000
- Subject: [Bug nptl/18726] Futexes are broken on MIPS/n32
- Auto-submitted: auto-generated
- References: <bug-18726-131 at http dot sourceware dot org/bugzilla/>
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #2 from Petr Malat <oss at malat dot biz> ---
(In reply to joseph@codesourcery.com from comment #1)
> On Mon, 27 Jul 2015, oss at malat dot biz wrote:
>
> > Hi,
> > there is a problem in generic syscall implementation, which breaks
> > futexes, which break pthread_* functions using them.
>
> What glibc and Linux kernel versions did you test with?
Linux 2.6.32 and glibc-2.9 (with glibc-ports-2.9), then with 2.16 and then
I've checked the code trough gitweb and it's the same.
> > The problem is in
> > sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
> > file in the macro
> > #define ARGIFY(X) ((long long) (__typeof__ ((X) - (X))) (X))
> > which is then used to load syscall arguments into registers. I assume its
> > purpose is to avoid sign extension of an argument if it's of unsigned
> > type,
>
> No, its purpose is to avoid warnings for converting 32-bit pointers to
> 64-bit integers - which means that 32-bit pointers have to be converted to
> 32-bit integers before being converted to 64-bit integers. See
> <https://sourceware.org/ml/libc-ports/2007-06/msg00003.html>.
That's what I was looking for. The old code seems wrong too, it prevents sign
extension.
> > which seems to be wrong. The CPU always does sign extensions while it's
> > loading 32bit integers and this is expected by Linux and GCC. The problem
> > arises, if an
>
> Linux (versions since SYSCALL_WRAPPERS, which I think includes all 2.6.29
> and later versions) should always do that sign extension on syscall entry
> to avoid a security issue (CVE-2009-0029, see bug 4459). The minimum
> kernel supported by current glibc is 2.6.32 (likely to move to 3.2 in the
> not too distant future when the 2.6.32 kernel series ceases to be
> maintained).
>
> > This can be fixed by replacing ARGIFY with a simple cast to long, however
> > it wouldn't work for a syscall, which takes 64bit argument, but I do not
> > know about a syscall, which would take such an argument on 32bit platform
> n32 syscalls take arguments in the same way as n32 userspace functions, in
> general (that is, 64-bit arguments go in single registers). Look at the
> various *.c files in sysdeps/unix/sysv/linux/mips/mips64/n32/ for code
> using the syscall macros in such a way that requires them to work with
> 64-bit integer arguments.
In that case the fix is not going to be so simple (I will check the code), but
I still think ARGIFY is wrong:
- Assume the futex value is 0x8000 0000.
- Because it's unsigned, ARGIFY expands to
((long long) (unsigned) (0x8000 0000))
so the content of the register is:
0x0000 0000 8000 0000
- Then the futex syscall is made and the kernel loads the value for
comparison from the provided memory address into an unsigned variable
(using load word instruction)
- The content of register is 0xFFFF FFFF 8000 0000 because sign extension has
been done
- Comparison fails (because whole registers are compared even when unsigned
integers are used) and the process doesn't go to sleep. If this happens in
e.g. pthread_cond_wail, the process ends up livelocked.
--
You are receiving this mail because:
You are on the CC list for the bug.