This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug nptl/18726] Futexes are broken on MIPS/n32


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]