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

Re: glib2.0 test gio/tests/socket fails, BUG in libc0.3?



On Fri, 2013-09-13 at 00:01 +0200, Svante Signell wrote:
> Hello,
> 
> Running the test suite for glib2.0 one test: gio/tests/socket,
> sub-test: /socket/unix-connection-ancillary-data fails for unknown
> reasons The ancillary data sent is using SCM_RIGHTS (not SCM_CREDS). The
> latest libc-2.17-92, hurd-20130727 and glib2.0-2.36.4-1, are installed.
> 
> The test errors out with err = EKERN_INVALID_ADDRESS after calling
> sendmsg.c:
> Is there any reason for this error message to fail that test? (setting
> err to zero and rebuilding libc.so makes this, and other, test pass)
> 
> ./lt-socket
> /socket/unix-connection-ancillary-data: **

I've now built patched versions of dbus and glib2.0, see attachments:
the first for dbus and the other two for glib2.0.
(The  write_credentials_byte() and _dbus_read_credentials_socket() code
are fixes to disable dbus to error out. The domain is not available in
these functions. Comments welcomed). 

With them the test above fails with stock libc-2.17-92.
Additionally, the test before fails:
/socket/ipv6_sync: **
GLib-GIO:ERROR:/home/srs/DEBs/glib2.0/glib2.0-2.36.4/./gio/tests/socket.c:92:create_server: assertion failed (error == NULL): Unable to create socket: Address family not supported by protocol (g-io-error-quark, 0)
Aborted

This is strange, since the arguments to socket are (26,1,0), i.e.
socket(AF_INET6, SOCK_STREAM, 0). The test works om my locally modified
libc0.3 though?

> I'm attaching the built test program, not stripped, it's only 25k.

I had some problems running that program if copied to another computer,
since it was linked to the currently built glib2.0 libraries.
chrpath -r /usr/lib/i386-gnu ./lt-socket; ldd ./lt-socket
fixed that.
--- a/dbus/dbus-sysdeps-unix.c	2013-09-08 12:01:26.000000000 +0200
+++ b/dbus/dbus-sysdeps-unix.c	2013-09-12 14:04:27.000000000 +0200
@@ -139,7 +139,7 @@ _dbus_open_socket (int              *fd_
   cloexec_done = *fd_p >= 0;
 
   /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
-  if (*fd_p < 0 && errno == EINVAL)
+  if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
 #endif
     {
       *fd_p = socket (domain, type, protocol);
@@ -887,16 +887,21 @@ _dbus_connect_exec (const char     *path
 {
   int fds[2];
   pid_t pid;
+  int retval;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
   _dbus_verbose ("connecting to process %s\n", path);
 
-  if (socketpair (AF_UNIX, SOCK_STREAM
 #ifdef SOCK_CLOEXEC
-                  |SOCK_CLOEXEC
+  retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
 #endif
-                  , 0, fds) < 0)
+  if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
+    {
+      retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+    }
+
+  if (retval < 0)
     {
       dbus_set_error (error,
                       _dbus_error_from_errno (errno),
@@ -1617,6 +1622,12 @@ write_credentials_byte (int
   if (bytes_written < 0 && errno == EINTR)
     goto again;
 
+  /* sendmsg() only accepts domain == PF_UNIX*/
+#if defined(HAVE_CMSGCRED)
+  if (bytes_written < 0 && errno == EINVAL)
+    bytes_written = send (server_fd, buf, 1, 0);
+#endif
+
   if (bytes_written < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
@@ -1753,8 +1764,12 @@ _dbus_read_credentials_socket  (int
     }
 
 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
-  if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
-		  || cmsg.hdr.cmsg_type != SCM_CREDS)
+  /* Special case for a zero credentials byte written */
+  if (bytes_read == 1 && buf == '\0')
+    {
+    }
+  else if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
+      || cmsg.hdr.cmsg_type != SCM_CREDS)
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Message from recvmsg() was not SCM_CREDS");
@@ -3055,7 +3070,7 @@ _dbus_full_duplex_pipe (int        *fd1,
   retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
   cloexec_done = retval >= 0;
 
-  if (retval < 0 && errno == EINVAL)
+  if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
 #endif
     {
       retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
--- a/gio/gcredentials.c
+++ b/gio/gcredentials.c
@@ -79,7 +79,7 @@
 
 #ifdef __linux__
   struct ucred native;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   struct cmsgcred native;
 #elif defined(__OpenBSD__)
   struct sockpeercred native;
@@ -131,7 +131,7 @@
   credentials->native.pid = getpid ();
   credentials->native.uid = geteuid ();
   credentials->native.gid = getegid ();
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   memset (&credentials->native, 0, sizeof (struct cmsgcred));
   credentials->native.cmcred_pid  = getpid ();
   credentials->native.cmcred_euid = geteuid ();
@@ -193,7 +193,7 @@
     g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid);
   if (ret->str[ret->len - 1] == ',')
     ret->str[ret->len - 1] = '\0';
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   g_string_append (ret, "freebsd-cmsgcred:");
   if (credentials->native.cmcred_pid != -1)
     g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid);
@@ -251,7 +251,7 @@
 #ifdef __linux__
   if (credentials->native.uid == other_credentials->native.uid)
     ret = TRUE;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
     ret = TRUE;
 #elif defined(__OpenBSD__)
@@ -307,7 +307,7 @@
     {
       ret = &credentials->native;
     }
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   if (native_type != G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED)
     {
       g_warning ("g_credentials_get_native: Trying to get credentials of type %d but only "
@@ -368,7 +368,7 @@
     {
       memcpy (&credentials->native, native, sizeof (struct ucred));
     }
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   if (native_type != G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED)
     {
       g_warning ("g_credentials_set_native: Trying to set credentials of type %d "
@@ -426,7 +426,7 @@
 
 #ifdef __linux__
   ret = credentials->native.uid;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   ret = credentials->native.cmcred_euid;
 #elif defined(__OpenBSD__)
   ret = credentials->native.uid;
@@ -468,7 +468,7 @@
 
 #ifdef __linux__
   ret = credentials->native.pid;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   ret = credentials->native.cmcred_pid;
 #elif defined(__OpenBSD__)
   ret = credentials->native.pid;
@@ -515,7 +515,7 @@
 #ifdef __linux__
   credentials->native.uid = uid;
   ret = TRUE;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   credentials->native.cmcred_euid = uid;
   ret = TRUE;
 #elif defined(__OpenBSD__)
--- a/gio/gunixcredentialsmessage.c
+++ b/gio/gunixcredentialsmessage.c
@@ -38,7 +38,7 @@
 /* ---------------------------------------------------------------------------------------------------- */
 #ifdef __linux__
 #define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
 #define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
 #else
 /* TODO: please add support for your UNIX flavor */
@@ -75,7 +75,7 @@
 {
 #ifdef __linux__
   return sizeof (struct ucred);
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   return sizeof (struct cmsgcred);
 #else
   return 0;
@@ -87,7 +87,7 @@
 {
 #ifdef __linux__
   return SOL_SOCKET;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   return SOL_SOCKET;
 #else
   return 0;
@@ -99,7 +99,7 @@
 {
 #ifdef __linux__
   return SCM_CREDENTIALS;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   return SCM_CREDS;
 #else
   return 0;
@@ -149,7 +149,7 @@
  out:
     ;
   }
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   {
     GCredentials *credentials;
     struct cmsgcred *cred;
@@ -191,7 +191,7 @@
           g_credentials_get_native (message->priv->credentials,
                                     G_CREDENTIALS_TYPE_LINUX_UCRED),
           sizeof (struct ucred));
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
   memcpy (data,
           g_credentials_get_native (message->priv->credentials,
                                     G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED),
--- a/gio/tests/credentials.c
+++ b/gio/tests/credentials.c
@@ -30,6 +30,7 @@
 # if (defined(__linux__) || \
   defined(__FreeBSD__) || \
   defined(__FreeBSD_kernel__) || \
+  defined(__GNU__) || \
   defined(__OpenBSD__))
 #   define SHOULD_HAVE_CREDENTIALS
 # endif
@@ -91,7 +92,7 @@
           g_assert_cmpuint (native->uid, ==, geteuid ());
           g_assert_cmpuint (native->pid, ==, getpid ());
         }
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)|| defined(__GNU__)
         {
           struct cmsgcred *native = g_credentials_get_native (creds,
               G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED);
--- a/gio/tests/gdbus-peer.c
+++ b/gio/tests/gdbus-peer.c
@@ -47,6 +47,7 @@
 #if (defined(__linux__) || \
   defined(__FreeBSD__) || \
   defined(__FreeBSD_kernel__) || \
+  defined(__GNU__) || \
   defined(__OpenBSD__))
 #define SHOULD_HAVE_CREDENTIALS_PASSING
 #endif
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -499,7 +499,7 @@
     return fd;
 
   /* It's possible that libc has SOCK_CLOEXEC but the kernel does not */
-  if (fd < 0 && errno == EINVAL)
+  if (fd < 0 && (errno == EINVAL || errno == EPROTOTYPE))
 #endif
     fd = socket (domain, type, protocol);
 

Reply to: