[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#227386: libc6-dev: ENOTSUP==EOPNOTSUPP, which violates SUSv3



On Mon, 2006-02-20 at 07:51 +0100, Aurelien Jarno wrote:
> Brian M. Carlson a écrit :
> > # bcc'd to control
> > forwarded 227386 http://sources.redhat.com/bugzilla/show_bug.cgi?id=2363
> > thanks, control, and have a nice day
> > 
> > On Sun, 2006-02-19 at 17:36 +0100, Aurelien Jarno wrote:
> 
> The problem is not that there is currently not possibility to fix the 
> bug without broking everything, at least nobody found one. Please 
> provide us a patch instead of complaning.

Attached.

> We can't change the SONAME for the glibc because it is plainly 
> impossible to rebuild all packages. Have you look how difficult was the 
> latest c++ transition? It could qualified as very very simple comparing 
> to a glibc transition.

It's been done at least once before.  However, if there were a libc7,
then all packages need not be rebuilt right away, because conceivably
libc7 would provide /lib/ld.so and libc6 could use that.  However, I am
not necessarily advocating that, just pointing out that it is not
impossible.  The only thing is that packages could not use both libc6
and libc7, directly or indirectly.

> > This in
> > itself is a bug, but I really don't care since I don't have to deal with
> > it.  If the glibc maintainers want to make it hard on themselves by
> > having to support breakage for eternity, that's fine, as long as they
> > support non-breakage too.
> 
> Again if you are not happy with the current situation, stop complaining 
> and provide us a patch.

As I said above, attached.

> > glibc cannot claim compatibility with POSIX 1003.1-2004 by defining
> > _POSIX_VERSION to 200112L unless it fixes this or the standard changes.
> > It would be a lie to claim that glibc supports a standard which it does
> > not in fact support.
> 
> Which is the case for almost every systems. AFAIK, every  have a small 
> part which is not POSIX compliant. You've just found one for GNU/Linux!

That does not mean we should not fix it.  You are claiming that
"everyone does it".  If everyone jumps off a bridge, should Debian do
that, too?

> > Anyway, it would significantly reduce the number of packages to be
> > recompiled if the new error number were only used if _POSIX_SOURCE is
> > defined to 200112L.
> 
> That only ensure code compatibility, but will still break binary 
> compatibility because the new glibc will use the new numbers, while 
> binaries that have not been rebuilt will use the old one.

I would argue that such programs expect non-standard behavior while
asking only for standard-conformant behavior.  They are buggy.

> > IIRC, we already did with OpenSSL.  The social contract states that our
> > priorities are *our* users and free software.  It makes no mention of
> > Redhat's or Slackware's or anyone else's users.  Personally, if one does
> > not recompile when moving from distribution to distribution, there is no
> > guarantee of even the most basic functionality anyway.
> 
> Loosing binary compatibility means that users won't be able to use third 
> party software, or packages from non-free that are provided in binary 
> form. But as you said "priorities are *our* users and free software", so 
> we could not do that. Also note that software provided in binary form is 
> usually compiled in static but the glibc, so the OpenSSL do not break 
> third party software.

I wasn't aware that we gave any support whatsoever for third party
software, hence the term "third party".  Packages from non-free that are
provided only in binary form would have to be removed (or recompiled by
upstream) if there were a security problem.

> Looks like the upstream have the same opinion...

And I have done what Ulrich asked: filed a bug on the Linux kernel.
However, please do not reassign this bug to linux-2.6 because the Debian
kernel maintainers will close it, apparently not realizing that Linux,
as well as glibc, has a certain responsibility for standards compliance.

What my patch does is use the value of _STRICT_POSIX to modify the value
of ENOTSUP.  As more ABI incompatible changes occur that cannot be fixed
any other way, this value is bumped, keeping the old code still there.
So the valid values of _STRICT_POSIX are as follows:

0, or undefined: same old and broken behavior that has always occured.
1: change ENOTSUP to a valid value
99999: use the largest supported value for _STRICT_POSIX
any other positive integral value: set _STRICT_POSIX to 1 and warn

Personally, I would recommend making getconf return
-D_STRICT_POSIX=99999 where applicable, but I understand that some
people might use getconf and not depend on strictly-conforming POSIX
behavior, even though such a use is incorrect.

It is my belief that this meets the binary compatibility criteria: the
code only breaks compatibility if someone explicitly requests it, so if
someone unintentionally breaks their code, they did it themselves.
Additionally, if glibc is built with the new error code, strerror and
friends will support it, but they will also support the old code, since
it is the same as EOPNOTSUPP.  I have not, however, tried to compile
with the patch; it is untested.

Due to binary compatibility reasons, it is not possible to make the
functions that return ENOTSUP on Linux return the new error code unless
new versions of those functions are implemented.  For the same reason, I
have modified Linux-specific code to use EOPNOTSUPP and code that is
used on, but not specific to, Linux check for __linux__ and ENOTSUP !=
EOPNOTSUPP and return EOPNOTSUPP instead.

Please note that this patch only works for Linux, but does not change
the behavior (or errno values) of non-Linux platforms.
--- ./include/features.h.orig	2006-02-21 03:59:28.000000000 +0000
+++ ./include/features.h	2006-02-21 04:45:48.000000000 +0000
@@ -41,6 +41,8 @@
    _GNU_SOURCE		All of the above, plus GNU extensions.
    _REENTRANT		Select additionally reentrant object.
    _THREAD_SAFE		Same as _REENTRANT, often used by other systems.
+   _STRICT_POSIX	If set to numeric value > 0 uses stricter POSIX
+		    conformance, according to level.
    _FORTIFY_SOURCE	If set to numeric value > 0 additional security
 			measures are defined, according to level.
 
@@ -51,6 +53,9 @@
    For example __STRICT_ANSI__, _POSIX_SOURCE and _POSIX_C_SOURCE
    together give you ISO C, 1003.1, and 1003.2, but nothing else.
 
+   Note that differing levels of _STRICT_POSIX can result in ABI
+   incompatibilities.
+
    These are defined by this file and are used by the
    header files to decide what to declare or define:
 
@@ -72,6 +77,7 @@
    __USE_GNU		Define GNU extensions.
    __USE_REENTRANT	Define reentrant/thread-safe *_r functions.
    __USE_FORTIFY_LEVEL	Additional security measures used, according to level.
+   __USE_POSIX_LEVEL	Additional POSIX compliance, according to level.
    __FAVOR_BSD		Favor 4.3BSD things in cases of conflict.
 
    The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are
@@ -105,6 +111,7 @@
 #undef	__USE_GNU
 #undef	__USE_REENTRANT
 #undef	__USE_FORTIFY_LEVEL
+#undef	__USE_POSIX_LEVEL
 #undef	__FAVOR_BSD
 #undef	__KERNEL_STRICT_NAMES
 
@@ -270,6 +277,16 @@
 # endif
 #endif
 
+#if defined __USE_XOPEN2K && (_STRICT_POSIX - 0) > 0
+# if _STRICT_POSIX == 1
+#  define __USE_POSIX_LEVEL 1
+# elif _STRICT_POSIX == 99999
+#  define __USE_POSIX_LEVEL 1
+# else
+#  define __USE_POSIX_LEVEL 1
+#  warn "The maximum value for _STRICT_POSIX is 1."
+# endif
+
 /* We do support the IEC 559 math functionality, real and complex.  */
 #define __STDC_IEC_559__		1
 #define __STDC_IEC_559_COMPLEX__	1
--- ./posix/tst-waitid.c.orig	2006-02-21 05:46:05.000000000 +0000
+++ ./posix/tst-waitid.c	2006-02-21 05:48:19.000000000 +0000
@@ -159,7 +159,11 @@
       RETURN (EXIT_FAILURE);
     case -1:
       printf ("waitid WNOHANG on stopped: %m\n");
+#if defined(__linux__)
+      RETURN (errno == EOPNOTSUPP ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
+#endif
     case 0:
       if (info.si_signo == 0)
 	break;
@@ -182,7 +186,11 @@
       RETURN (EXIT_FAILURE);
     case -1:
       printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n");
+#if defined(__linux__)
+      RETURN (errno == EOPNOTSUPP ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
+#endif
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
@@ -241,7 +249,11 @@
       RETURN (EXIT_FAILURE);
     case -1:
       printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n");
+#if defined(__linux__)
+      RETURN (errno == EOPNOTSUPP ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
+#endif
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
@@ -281,7 +293,11 @@
       RETURN (EXIT_FAILURE);
     case -1:
       printf ("waitid WCONTINUED on continued: %m\n");
+#if defined(__linux__)
+      RETURN (errno == EOPNOTSUPP ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
+#endif
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
@@ -317,7 +333,11 @@
       RETURN (EXIT_FAILURE);
     case -1:
       printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n");
+#if defined(__linux__)
+      RETURN (errno == EOPNOTSUPP ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
+#endif
     case 0:
       if (info.si_signo == 0)
 	break;
@@ -422,7 +442,11 @@
       RETURN (EXIT_FAILURE);
     case -1:
       printf ("waitid WNOWAIT on killed: %m\n");
+#if defined(__linux__)
+      RETURN (errno == EOPNOTSUPP ? EXIT_SUCCESS : EXIT_FAILURE);
+#else
       RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
+#endif
     case 0:
       if (info.si_signo != SIGCHLD)
 	{
--- ./sysdeps/unix/sysv/linux/alpha/bits/errno.h.orig	2006-02-21 03:50:41.000000000 +0000
+++ ./sysdeps/unix/sysv/linux/alpha/bits/errno.h	2006-02-21 04:01:08.000000000 +0000
@@ -25,7 +25,13 @@
 # include <linux/errno.h>
 
 /* Linux has no ENOTSUP error code.  */
+# if __USE_POSIX_LEVEL-0 == 1
+/* 11371 is the port number for HKP over HTTP; it is used here as a magic
+   number. */
+# define ENOTSUP 11371
+# else
 # define ENOTSUP EOPNOTSUPP
+# endif
 
 # ifndef ECANCELED
 #  define ECANCELED	131
--- ./sysdeps/unix/sysv/linux/mips/bits/errno.h.orig	2006-02-21 03:50:28.000000000 +0000
+++ ./sysdeps/unix/sysv/linux/mips/bits/errno.h	2006-02-21 04:01:12.000000000 +0000
@@ -25,7 +25,13 @@
 # include <linux/errno.h>
 
 /* Linux has no ENOTSUP error code.  */
+# if __USE_POSIX_LEVEL-0 == 1
+/* 11371 is the port number for HKP over HTTP; it is used here as a magic
+   number. */
+# define ENOTSUP 11371
+# else
 # define ENOTSUP EOPNOTSUPP
+# endif
 
 # ifndef __ASSEMBLER__
 /* Function to get address of global `errno' variable.  */
--- ./sysdeps/unix/sysv/linux/bits/errno.h.orig	2006-02-21 03:40:02.000000000 +0000
+++ ./sysdeps/unix/sysv/linux/bits/errno.h	2006-02-21 04:00:59.000000000 +0000
@@ -25,7 +25,13 @@
 # include <linux/errno.h>
 
 /* Linux has no ENOTSUP error code.  */
+# if __USE_POSIX_LEVEL-0 == 1
+/* 11371 is the port number for HKP over HTTP; it is used here as a magic
+   number. */
+# define ENOTSUP 11371
+# else
 # define ENOTSUP EOPNOTSUPP
+# endif
 
 /* Linux also had no ECANCELED error code.  Since it is not used here
    we define it to an invalid value.  */
--- ./sysdeps/unix/sysv/linux/sparc/bits/errno.h.orig	2006-02-21 03:50:17.000000000 +0000
+++ ./sysdeps/unix/sysv/linux/sparc/bits/errno.h	2006-02-21 04:01:21.000000000 +0000
@@ -25,7 +25,13 @@
 # include <linux/errno.h>
 
 /* Linux has no ENOTSUP error code.  */
+# if __USE_POSIX_LEVEL-0 == 1
+/* 11371 is the port number for HKP over HTTP; it is used here as a magic
+   number. */
+# define ENOTSUP 11371
+# else
 # define ENOTSUP EOPNOTSUPP
+# endif
 
 # ifndef ECANCELED
 #  define ECANCELED	127
--- ./nptl/sysdeps/pthread/timer_create.c.orig	2006-02-21 05:37:44.000000000 +0000
+++ ./nptl/sysdeps/pthread/timer_create.c	2006-02-21 05:38:10.000000000 +0000
@@ -48,7 +48,7 @@
     {
       /* We don't allow timers for CPU clocks.  At least not in the
 	 moment.  */
-      __set_errno (ENOTSUP);
+      __set_errno (EOPNOTSUPP);
       return -1;
     }
 
--- ./nptl/pthread_attr_setscope.c.orig	2006-02-21 05:35:18.000000000 +0000
+++ ./nptl/pthread_attr_setscope.c	2006-02-21 05:36:27.000000000 +0000
@@ -40,7 +40,7 @@
       break;
 
     case PTHREAD_SCOPE_PROCESS:
-      return ENOTSUP;
+      return EOPNOTSUPP;
 
     default:
       return EINVAL;
--- ./nptl/tst-attr2.c.orig	2006-02-21 05:59:01.000000000 +0000
+++ ./nptl/tst-attr2.c	2006-02-21 05:59:36.000000000 +0000
@@ -257,7 +257,7 @@
     }
 
   e = pthread_attr_setscope (&a, PTHREAD_SCOPE_PROCESS);
-  if (e != ENOTSUP)
+  if (e != EOPNOTSUPP)
     {
       if (e != 0)
 	{
--- ./linuxthreads/sysdeps/pthread/timer_create.c.orig	2006-02-21 06:05:37.000000000 +0000
+++ ./linuxthreads/sysdeps/pthread/timer_create.c	2006-02-21 06:07:22.000000000 +0000
@@ -48,7 +48,11 @@
     {
       /* We don't allow timers for CPU clocks.  At least not in the
 	 moment.  */
+#if defined __linux__ && EOPNOTSUPP != ENOTSUP
+      __set_errno (EOPNOTSUPP);
+#else
       __set_errno (ENOTSUP);
+#endif
       return -1;
     }
 
--- ./linuxthreads/attr.c.orig	2006-02-21 06:02:27.000000000 +0000
+++ ./linuxthreads/attr.c	2006-02-21 06:04:00.000000000 +0000
@@ -149,7 +149,11 @@
     attr->__scope = scope;
     return 0;
   case PTHREAD_SCOPE_PROCESS:
+#if defined __linux__ && ENOTSUP != EOPNOTSUPP
+	return EOPNOTSUPP;
+#else
     return ENOTSUP;
+#endif
   default:
     return EINVAL;
   }

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: