Bug 9685 - __have_{sock_cloexec,pipe2} checks not valid with linux headers older than 2.6.27
Summary: __have_{sock_cloexec,pipe2} checks not valid with linux headers older than 2....
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
Depends on:
Reported: 2008-12-27 03:51 UTC by Mike Frysinger
Modified: 2014-07-02 07:46 UTC (History)
2 users (show)

See Also:
Last reconfirmed:
fweimer: security-


Note You need to log in before you can comment on or make changes to this bug.
Description Mike Frysinger 2008-12-27 03:51:50 UTC
if you build glibc-2.9 against kernel headers older than 2.6.27, then the
resulting libc code can easily break when running on a kernel 2.6.27 or newer. 
for example, this simple code will result in popen() failing with ENOSYS:

#include <grp.h>
#include <stdio.h>
    if (!popen("ls", "r"))

this is because __have_pipe2 is defined to __have_sock_cloexec in
include/unistd.h.  sock_cloexec is tested at runtime using defines that are
completely contained within glibc and so works properly regardless of the
version of kernel headers built against and the kernel version run on.  pipe2
however requires __NR_pipe2 to be defined in the kernel headers otherwise glibc
creates an ENOSYS stub for it.

so in the previous example, if we run on linux-2.6.27 or newer, getgrnam()
recurses into socket() with SOCK_CLOEXEC and detects that it works, and so it
sets __have_sock_cloexec to 1.  but when we call popen(), it sees that
__have_pipe2 is set to 1 (since it is defined to __have_sock_cloexec), and so
only calls pipe2() (which is an ENOSYS stub) and things fail.

if we give __have_pipe2 dedicated storage, then things work properly --
SOCK_CLOEXEC is detected independent of pipe2().

i wrote a patch here, but i imagine drepper will simply say it's "wrong" and do
whatever else, so no point in writing a ChangeLog/etc...
Comment 1 Mike Frysinger 2008-12-27 19:52:25 UTC
further, assuming sock_cloexec and pipe2 support were added at the same time is
invalid for all arches, so they'll need separate storage anyways.  the assumption
is only valid for a subset of architectures.
Comment 2 Ulrich Drepper 2008-12-28 06:04:51 UTC
The only architectures of interest are those in the main tree.  Anything else
must be handled elsewhere.  So, which architecture do you think doesn't work?
Comment 3 Mike Frysinger 2008-12-29 09:06:31 UTC
sysdeps/unix/sysv/linux/kernel-features.h omits __sh__ from the list as it does
have pipe2 in linux-2.6.27, but that's a different issue

the point of the way glibc is laid out is for arches to control features like
this.  by binding sock_cloexec and pipe2 together without any sort of recourse,
you're basically saying that all other arches will be broken and there's nothing
they can do about it (regardless of whether they're in the "main" set of ports). 
if you want to add another define like __ASSUME_SOCK_CLOEXEC_AND_PIPE2 and key
the __have_pipe2->__have_sock_cloexec define off of that vs dedicated storage,
then that would work as the other arches would be able to disable it.
Comment 4 Ulrich Drepper 2009-02-07 05:20:17 UTC
You're wrong.  Architectures simply have to define the __ASSUME_* macros when
all the features they represent are available.
Comment 5 Mike Frysinger 2009-02-07 06:28:42 UTC
umm, there's two parts here: first, the original report where glibc is broken on
*all* arches, even when you want to put on your "supported" goggles.  second:
you're turning the __ASSUME_XXX code into "only works on supported arches".  yes,
other arches can disable the __ASSUME_XXX stuff completely, but that sort of
defeats the entire purpose of it.

even if you choose to wrongly ignore the second part (which i imagine you will),
there's still the matter of the first
Comment 6 Mike Frysinger 2009-02-15 21:44:37 UTC
when i think about it some more, your latest statements are irrelevant.  the
problem here is that if the __ASSUME_xxx defines are not defined, then glibc
falls back to the runtime test.  as i illustrated in the original summary, this
will create a broken glibc if the linux-headers do not contain the pipe2 syscall
number.  the arch in question is irrelevant.  that means that the linux-headers
have to be very recent (and in some cases, not even available today let alone at
the time of the glibc-2.9 release).
Comment 7 Mike Frysinger 2012-08-18 04:37:00 UTC
committed @ http://sourceware.org/ml/libc-alpha/2012-08/msg00424.html