Jaunty i386 popen() misbehaves on x86_64 kernel 2.6.26
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Fedora |
Fix Released
|
Medium
|
|||
glibc (Ubuntu) |
Invalid
|
Undecided
|
Unassigned | ||
Intrepid |
Invalid
|
Undecided
|
Unassigned | ||
Jaunty |
Invalid
|
Undecided
|
Unassigned | ||
linux (Ubuntu) |
Fix Released
|
Medium
|
Andy Whitcroft | ||
Intrepid |
Fix Released
|
Medium
|
Stefan Bader | ||
Jaunty |
Fix Released
|
Medium
|
Andy Whitcroft | ||
linux-2.6 (Debian) |
Fix Released
|
Unknown
|
Bug Description
SRU justification:
Impact: A bug in the syscall implementation can cause incorrect behavior when trying to use syscalls that are not implemented.
Fix: Cherry pick from upstream to correctly return an error code in that situation.
Testcase: see test below.
---
There is something very wrong with the popen() implementation in Jaunty on i386. It works fine when run on the Jaunty kernel, but when run on the Lenny 2.6.26-1-amd64 kernel, it misbehaves as follows. The output of the subcommand, instead of being fed to the pipe, is fed directly to stdout; the pipe either returns errors or hangs forever.
This causes weird errors in many programs running in a Jaunty i386 chroot on our Lenny build server.
Attached is a small 5-line test program. Run
gcc -static popen-test.c -o popen-test
and then copy popen-test to a Lenny machine to see the problem.
Correct output:
$ uname -r
2.6.28-8-generic
$ ./popen-test
popen returned 0x1ec6400
ferror returned 0
fread returned 19
ferror returned 0
pclose returned 0
Incorrect output:
$ uname -r
2.6.26-1-amd64
$ ./popen-test
popen returned 0x935f688
ferror returned 0
SHOULD NOT DISPLAY
This has been reproduced independently by two of us with two different Jaunty i386 installs and two different Lenny installs.
Related branches
Changed in linux: | |
importance: | Undecided → Medium |
status: | New → Triaged |
Changed in linux-2.6: | |
status: | Unknown → New |
Changed in openvz-kernel: | |
status: | Unknown → Confirmed |
Changed in glibc (Ubuntu Intrepid): | |
status: | New → Invalid |
description: | updated |
Changed in linux: | |
status: | In Progress → Fix Committed |
Changed in linux: | |
importance: | Undecided → Medium |
Changed in openvz-kernel: | |
status: | Confirmed → Fix Released |
Changed in linux-2.6 (Debian): | |
status: | New → Fix Released |
Changed in fedora: | |
importance: | Unknown → Medium |
+++ This bug was initially created as a clone of Bug #481682 +++
Created an attachment (id=330051)
proposed fix
in kernel- 2.6.18- 128.el5 and prior versions, arch/x86_ 64/ia32/ ia32entry. S hunk of the linux-2. 6-misc- utrace- update. patch contains incorrect optimization.
As result, out-of-table 32-bit syscalls on the x86_64 kernel do not return ENOSYS (unless the caller is being ptraced).
For example, glibc-2.9+ popen() goes mad when pipe2 syscall returns its number 331 instead of fail with ENOSYS.
As result, FC10+ 32-bit processes on RHEL5 x86_64 kernel break once popen(3) is called.
--- Additional comment from <email address hidden> on 2009-01-27 04:29:59 EDT ---
The issue was found while running Fedora 10 containers on an RHEL5+OpenVZ kernel.
Relative OpenVZ bug: http:// bugzilla. openvz. org/show_ bug.cgi? id=1150
--- Additional comment from <email address hidden> on 2009-02-06 20:59:52 EDT ---
Created an attachment (id=331182)
test case source
Simple test case, compile with -m32 and run on x86-64 kernel.
The RHEL5 code is the same (broken) as upstream. I'll fix it upstream and then RHEL5 should backport the change so it continues to match upstream.
--- Additional comment from <email address hidden> on 2009-02-06 21:02:48 EDT ---
Created an attachment (id=331183)
test case source
Test case fixed to exit 0 for correct and nonzero for bug.
Also, I forgot to note that to reproduce you have to have auditd disabled:
/sbin/chkconfig auditd off; reboot
--- Additional comment from <email address hidden> on 2009-02-06 21:34:13 EDT ---
Created an attachment (id=331187)
fix posted upstream
Wait to see if upstream takes this as is, but almost certain they will.
With s,/x86/,/x86_64/,g this same patch applies to RHEL5 fine.
--- Additional comment from <email address hidden> on 2009-02-07 04:57:47 EDT ---
> The RHEL5 code is the same (broken) as upstream.
RHEL5 is not broken, I wasn't able to reproduce it. As I understood, this is due to this check:
testl $(_TIF_ SYSCALL_ TRACE|_ TIF_SYSCALL_ AUDIT|_ TIF_SECCOMP) ,threadinfo_ flags(% r10)
jnz ia32_tracesys
And we have TIF_SYSCALL_AUDIT set.
Also, it's possible to make the patch shorter:
--- a/arch/ x86/ia32/ ia32entry. S x86/ia32/ ia32entry. S
GET_THREAD_ INFO(%r10) TI_status( %r10) SYSCALL_ ENTRY,TI_ flags(% r10) RAX-ARGOFFSET( %rsp) NR_syscalls- 1),%eax
+++ b/arch/
@@ -417,6 +417,7 @@ ENTRY(ia32_syscall)
orl $TS_COMPAT,
testl $_TIF_WORK_
+ movq $-ENOSYS,
jnz ia32_tracesys
ia32_do_syscall:
cmpl $(IA32_
I've tested it yesterday, but didn't post upstream yet.
--- Additional comment from <email address hidden> on 2009-02-07 17:21:41 EDT ---
It is broken. See comment#3 on how to reproduce it.
Shorter patch does not mean shorter code path, which is what matters.
Anyway, I've already posted upstream.
--- Additional comment from <email address hidden> on 2009-02-07 17:25:55 EDT ---
Upstream fix was merged: http:// git.kernel. org/?p= linux/kernel/ git/torvalds/ linux-2. 6.git;a= commit; h=c09249f8d1b84 344eca882547afd bffee8c09d14