public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug nptl/18726] New: Futexes are broken on MIPS/n32
@ 2015-07-27 13:30 oss at malat dot biz
2015-07-27 13:31 ` [Bug nptl/18726] " oss at malat dot biz
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: oss at malat dot biz @ 2015-07-27 13:30 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
Bug ID: 18726
Summary: Futexes are broken on MIPS/n32
Product: glibc
Version: unspecified
Status: NEW
Severity: normal
Priority: P2
Component: nptl
Assignee: unassigned at sourceware dot org
Reporter: oss at malat dot biz
CC: drepper.fsp at gmail dot com
Target Milestone: ---
Created attachment 8454
--> https://sourceware.org/bugzilla/attachment.cgi?id=8454&action=edit
Sample program illustrating the issue
Hi,
there is a problem in generic syscall implementation, which breaks futexes,
which break pthread_* functions using them.
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,
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
argument passed this way and a loaded value are compared. Even if they are the
same, comparison fails because one of them is sign extended and the second one
isn't.
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 (e.g.
llseek splits its arguments into two 32bit ones). Why this macro was
introduced?
See the attached code, which illustrates the problem.
The issue doesn't arise if futex is called trough syscall().
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
@ 2015-07-27 13:31 ` oss at malat dot biz
2015-07-27 15:33 ` joseph at codesourcery dot com
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: oss at malat dot biz @ 2015-07-27 13:31 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
Petr Malat <oss at malat dot biz> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |oss at malat dot biz
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
2015-07-27 13:31 ` [Bug nptl/18726] " oss at malat dot biz
@ 2015-07-27 15:33 ` joseph at codesourcery dot com
2015-07-27 16:18 ` oss at malat dot biz
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: joseph at codesourcery dot com @ 2015-07-27 15:33 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #1 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
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?
> 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>.
> 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 (e.g.
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.
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
2015-07-27 13:31 ` [Bug nptl/18726] " oss at malat dot biz
2015-07-27 15:33 ` joseph at codesourcery dot com
@ 2015-07-27 16:18 ` oss at malat dot biz
2015-07-27 16:51 ` joseph at codesourcery dot com
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: oss at malat dot biz @ 2015-07-27 16:18 UTC (permalink / raw)
To: glibc-bugs
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.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
` (2 preceding siblings ...)
2015-07-27 16:18 ` oss at malat dot biz
@ 2015-07-27 16:51 ` joseph at codesourcery dot com
2015-07-27 17:09 ` oss at malat dot biz
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: joseph at codesourcery dot com @ 2015-07-27 16:51 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #3 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
On Mon, 27 Jul 2015, oss at malat dot biz wrote:
> 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)
But the code in the kernel that handles syscall arguments should have
sign-extended the register value before it ever reached the C
implementation of futex in the kernel with a 32-bit argument type, so it
shouldn't matter what the high word of the register passed to the kernel
was. If the syscall wrapper code in the kernel doesn't do so, then
hostile userspace code can cause security issues by passing values to the
kernel that result in C code having register values for arguments that
don't conform to the ABI and so undefined behavior in that C code. And
because of the privilege boundary involved, the kernel can never rely on
userspace code sign-extending arguments correctly.
So why isn't the kernel ensuring that the "int" value conforms to the ABI
for int values (by sign-extending) before it gets to a C function in the
kernel with an int argument?
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
` (3 preceding siblings ...)
2015-07-27 16:51 ` joseph at codesourcery dot com
@ 2015-07-27 17:09 ` oss at malat dot biz
2015-07-27 17:24 ` joseph at codesourcery dot com
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: oss at malat dot biz @ 2015-07-27 17:09 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #4 from Petr Malat <oss at malat dot biz> ---
(In reply to joseph@codesourcery.com from comment #3)
> On Mon, 27 Jul 2015, oss at malat dot biz wrote:
>
> > 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)
>
> But the code in the kernel that handles syscall arguments should have
> sign-extended the register value before it ever reached the C
> implementation of futex in the kernel with a 32-bit argument type, so it
> shouldn't matter what the high word of the register passed to the kernel
> was. If the syscall wrapper code in the kernel doesn't do so, then
> hostile userspace code can cause security issues by passing values to the
> kernel that result in C code having register values for arguments that
> don't conform to the ABI and so undefined behavior in that C code. And
> because of the privilege boundary involved, the kernel can never rely on
> userspace code sign-extending arguments correctly.
>
> So why isn't the kernel ensuring that the "int" value conforms to the ABI
> for int values (by sign-extending) before it gets to a C function in the
> kernel with an int argument?
In this case it can't cause any security issues as the value is used only to
decide if the caller shall sleep on the futex. As the value is not stored
according to the ABI, it's not equal to any valid value and the process is
not put to sleep.
I agree returning EINVAL would be better in such a case, but the bug would
have to be fixed in glibc anyway.
After checking implementation of these new syscalls, which were not present
in my old version, I think the proper fix would be to change futex value to
signed int type.
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
` (4 preceding siblings ...)
2015-07-27 17:09 ` oss at malat dot biz
@ 2015-07-27 17:24 ` joseph at codesourcery dot com
2015-07-28 10:27 ` oss at malat dot biz
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: joseph at codesourcery dot com @ 2015-07-27 17:24 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #5 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
On Mon, 27 Jul 2015, oss at malat dot biz wrote:
> > So why isn't the kernel ensuring that the "int" value conforms to the ABI
> > for int values (by sign-extending) before it gets to a C function in the
> > kernel with an int argument?
> In this case it can't cause any security issues as the value is used only to
The MIPS architecture specification says there is UNPREDICTABLE behavior
if a non-sign-extended value is used with a 32-bit instruction. The
compiler may generate such instructions to work with the int value.
While such architecturally UNPREDICTABLE behavior can't itself cross
privilege boundaries, that only means it doesn't cause a security issue if
such an instruction is executed in userspace - and the problem code is
executing in the kernel. So you're relying on particular combinations of
(compiler code generation, behavior of particular processors on such
inputs) to avoid security issues, which does not seem a good idea.
> After checking implementation of these new syscalls, which were not present
> in my old version, I think the proper fix would be to change futex value to
> signed int type.
Are you saying that in fact the bug was fixed in the kernel, but later
than 2.6.32? Because the conclusion in the kernel community was that the
kernel was the right place to fix this (by always sign-extending affected
syscall arguments on kernel entry). And I think the conclusion from more
recent discussions in the glibc context of a generic API for internal
futex uses in glibc is that unsigned int is the preferred type for futexes
within glibc.
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
` (5 preceding siblings ...)
2015-07-27 17:24 ` joseph at codesourcery dot com
@ 2015-07-28 10:27 ` oss at malat dot biz
2015-07-28 16:07 ` oss at malat dot biz
2015-07-28 16:21 ` joseph at codesourcery dot com
8 siblings, 0 replies; 10+ messages in thread
From: oss at malat dot biz @ 2015-07-28 10:27 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #6 from Petr Malat <oss at malat dot biz> ---
(In reply to joseph@codesourcery.com from comment #5)
> On Mon, 27 Jul 2015, oss at malat dot biz wrote:
> > After checking implementation of these new syscalls, which were not present
> > in my old version, I think the proper fix would be to change futex value to
> > signed int type.
>
> Are you saying that in fact the bug was fixed in the kernel, but later
> than 2.6.32?
No, I meant my original proposal of changing ARGIFY is not good, because it
will not work with ftruncate64, lockf64 etc., which are not present in my old
version.
> Because the conclusion in the kernel community was that the
> kernel was the right place to fix this (by always sign-extending affected
> syscall arguments on kernel entry).
OK, I will try with a never kernel. Nevertheless I still think this is also
a bug on glibc side as it violates the ABI.
> And I think the conclusion from more recent discussions in the glibc context
> of a generic API for internal futex uses in glibc is that unsigned int is
> the preferred type for futexes within glibc.
I've got this idea from the prototype specified in futex(2), which says val
argument is of the type int, but on the other hand using unsigned is aligned
with the kernel, as the value is unsigned there too.
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
` (6 preceding siblings ...)
2015-07-28 10:27 ` oss at malat dot biz
@ 2015-07-28 16:07 ` oss at malat dot biz
2015-07-28 16:21 ` joseph at codesourcery dot com
8 siblings, 0 replies; 10+ messages in thread
From: oss at malat dot biz @ 2015-07-28 16:07 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #7 from Petr Malat <oss at malat dot biz> ---
I've tracked down a change, which prevents the problem in the kernel:
https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/kernel/futex_compat.c?id=90caf58dad77a4021e9dade5d051756cea2a2cd7
When COMPAT_SYSCALL_DEFINE is used a wrapper is created, which casts the
futex value to unsigned long and then to unsigned int, which forces gcc to
emit sll instruction, which, according to the specification, can be used even
when a register is not properly sign extended.
I will report this to the kernel mailing list, as from current long term
releases
2.6.32.67, 3.2.69 and 3.4.108 are affected. From my POV glibc shall be fixed
too,
as it violates the ABI.
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug nptl/18726] Futexes are broken on MIPS/n32
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
` (7 preceding siblings ...)
2015-07-28 16:07 ` oss at malat dot biz
@ 2015-07-28 16:21 ` joseph at codesourcery dot com
8 siblings, 0 replies; 10+ messages in thread
From: joseph at codesourcery dot com @ 2015-07-28 16:21 UTC (permalink / raw)
To: glibc-bugs
https://sourceware.org/bugzilla/show_bug.cgi?id=18726
--- Comment #8 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
On Tue, 28 Jul 2015, oss at malat dot biz wrote:
> I will report this to the kernel mailing list, as from current long term
> releases 2.6.32.67, 3.2.69 and 3.4.108 are affected.
Thanks. As a potential security issue ("incomplete fix for
CVE-2009-0029", I suppose it would be described) this clearly ought to be
fixed in stable kernels.
> From my POV glibc shall be fixed too, as it violates the ABI.
Well, the kernel discussion in 2007 said the ABI should be for the kernel
to do the sign extension, and the approach taken with syscall wrappers in
the kernel in 2009 confirmed that as the intended ABI. That doesn't rule
out working around the kernel bug in glibc while some affected kernel
versions are still supported, but does make clear that it's the kernel
that's buggy.
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-07-28 16:21 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-27 13:30 [Bug nptl/18726] New: Futexes are broken on MIPS/n32 oss at malat dot biz
2015-07-27 13:31 ` [Bug nptl/18726] " oss at malat dot biz
2015-07-27 15:33 ` joseph at codesourcery dot com
2015-07-27 16:18 ` oss at malat dot biz
2015-07-27 16:51 ` joseph at codesourcery dot com
2015-07-27 17:09 ` oss at malat dot biz
2015-07-27 17:24 ` joseph at codesourcery dot com
2015-07-28 10:27 ` oss at malat dot biz
2015-07-28 16:07 ` oss at malat dot biz
2015-07-28 16:21 ` joseph at codesourcery dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).