[glib] GNetworkMonitorNetlink: Fix check for non-kernel messages



commit 7cba800a84730c9c5843acdd775e42b8c1438edf
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Jun 1 10:02:47 2015 +0200

    GNetworkMonitorNetlink: Fix check for non-kernel messages
    
    This code used to look at the SCM_CREDENTIALS and ignore every message
    not from uid 0. However, when user namespaces are in use this does not
    work, as if uid 0 is not mapped you get overflowuid instead. Right now
    this means we ignore all messages in such user namespaces and glib
    apps hang on startup.
    
    We can't look at pids either, as pid 0 is returned for processes
    outside your pid namespace.
    
    Instead the correct approach is to look at the sending sockaddr and
    if the port id (nl_pid) is zero, then its from the kernel.
    
    Source:
    http://lists.linuxfoundation.org/pipermail/containers/2015-May/036032.html
    
    https://bugzilla.gnome.org/show_bug.cgi?id=750203

 gio/gnetworkmonitornetlink.c |   30 +++++++++++++++---------------
 1 files changed, 15 insertions(+), 15 deletions(-)
---
diff --git a/gio/gnetworkmonitornetlink.c b/gio/gnetworkmonitornetlink.c
index 21a7ad5..b9ff011 100644
--- a/gio/gnetworkmonitornetlink.c
+++ b/gio/gnetworkmonitornetlink.c
@@ -293,14 +293,13 @@ read_netlink_messages (GSocket      *socket,
   GNetworkMonitorNetlink *nl = user_data;
   GInputVector iv;
   gssize len;
-  GSocketControlMessage **cmsgs = NULL;
-  gint num_cmsgs = 0, i, flags;
+  gint flags;
   GError *error = NULL;
-  GCredentials *creds;
-  uid_t sender;
+  GSocketAddress *addr;
   struct nlmsghdr *msg;
   struct rtmsg *rtmsg;
   struct rtattr *attr;
+  struct sockaddr_nl source_sockaddr;
   gsize attrlen;
   guint8 *dest, *gateway, *oif;
   gboolean retval = TRUE;
@@ -322,8 +321,8 @@ read_netlink_messages (GSocket      *socket,
 
   iv.buffer = g_malloc (len);
   iv.size = len;
-  len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
-                                  &cmsgs, &num_cmsgs, NULL, NULL, &error);
+  len = g_socket_receive_message (nl->priv->sock, &addr, &iv, 1,
+                                  NULL, NULL, NULL, NULL, &error);
   if (len < 0)
     {
       g_warning ("Error on netlink socket: %s", error->message);
@@ -333,12 +332,17 @@ read_netlink_messages (GSocket      *socket,
       return FALSE;
     }
 
-  if (num_cmsgs != 1 || !G_IS_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]))
-    goto done;
+  if (!g_socket_address_to_native (addr, &source_sockaddr, sizeof (source_sockaddr), &error))
+    {
+      g_warning ("Error on netlink socket: %s", error->message);
+      g_error_free (error);
+      if (nl->priv->dump_networks)
+        finish_dump (nl);
+      return FALSE;
+    }
 
-  creds = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (cmsgs[0]));
-  sender = g_credentials_get_unix_user (creds, NULL);
-  if (sender != 0)
+  /* If the sender port id is 0 (not fakeable) then the message is from the kernel */
+  if (source_sockaddr.nl_pid != 0)
     goto done;
 
   msg = (struct nlmsghdr *) iv.buffer;
@@ -420,10 +424,6 @@ read_netlink_messages (GSocket      *socket,
     }
 
  done:
-  for (i = 0; i < num_cmsgs; i++)
-    g_object_unref (cmsgs[i]);
-  g_free (cmsgs);
-
   g_free (iv.buffer);
 
   if (!retval && nl->priv->dump_networks)


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