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

RFC: [PATCH] SCM_CREDS support 1(2)



Hi,

Patch 1(2) on SCM_CREDS support for GNU/Hurd.

Time to publish the SCM_CREDS proposal to the list. From the patch there
are some FIXMEs that need to be resolved for a final patch to be
created. I've been running two kvm-images with eglibc built with this
patch for a few weeks now, and haven't seen any problems so far. On the
list of things running properly with SCM_CREDS support are:
- All 11 gamin tests OK
- All 15+2 dbus tests OK (with upstream patches)
- 171+ of 182 glib2.0 tests OK (with upstream patches)
- Many more window managers, web browsers and X applications work.
- emacs works in X (when built with patched eglibc)
- gdm3 builds (to be tested)
- ...

This patch implements the first cases in the test code sent to the list
in September 2013, options <no flag> and <-z> see
http://lists.debian.org/debian-hurd/2013/09/msg00034.html 


Options:
no flag: 
-z: send a zero credentials byte as data (used by dbus)

1) Sent credentials and PID are correct:
./scm_cred_recv &
./scm_cred_send
Linux: OK, only sent IDs
kFreeBSD: OK, sent IDs + groups (irrespective of sent IDs)
Hurd: OK, sent IDs + groups

./scm_cred_recv -z&
./scm_cred_send -z
Linux: OK, same as above
kFreeBSD: OK, same as above
Hurd: OK, sent IDs + groups (irrespective of sent IDs)

2) When wrong credentials are sent the behaviour is different:
Linux:
no flag: ERROR [EPERM Operation not permitted] sendmsg
-z: ERROR [EPERM Operation not permitted] sendmsg

kFreeBSD: 
no flag: sent credentials are not honoured, received ones are created
-z: sent credentials are not honoured, received ones are created

Hurd:
no flag: ERROR [EPERM Operation not permitted] sendmsg
-z: sent credentials are not honoured, received ones are created
--- a/sysdeps/mach/hurd/sendmsg.c
+++ b/sysdeps/mach/hurd/sendmsg.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001,2002,2004,2010 Free Software Foundation, Inc.
+/* Copyright (C) 2001,2002,2004,2010,2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -17,6 +17,7 @@
 
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
@@ -38,6 +39,8 @@
   int *fds, nfds;
   struct sockaddr_un *addr = message->msg_name;
   socklen_t addr_len = message->msg_namelen;
+  void *control = message->msg_control;
+  socklen_t controllen = message->msg_controllen;
   addr_port_t aport = MACH_PORT_NULL;
   union
   {
@@ -106,6 +109,90 @@
 	}
     }
 
+  error_t check_auth (pid_t pids, uid_t euids, size_t euidslen,
+		      uid_t auids, size_t auidslen,
+		      gid_t egids, size_t egidslen,
+		      gid_t agids, size_t agidslen,
+		      struct cmsgcred *ucredp)
+{
+  auth_t newauth;
+  error_t err;
+  pid_t pid, ppid;
+  int orphaned;
+
+  /* FIXME: Is locking needed? */
+  err = __USEPORT (AUTH,__auth_makeauth
+		   (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+		    &euids, euidslen,
+		    &auids, auidslen,
+		    &egids, egidslen,
+		    &agids, agidslen,
+		    &newauth));
+
+  /* FIXME: More cleanup needed? */
+  mach_port_deallocate (mach_task_self (), newauth);
+
+  if (! err)
+    {
+      err = __USEPORT (PROC, __proc_getpids (port, &pid, &ppid, &orphaned));
+      if (pids != pid )
+	return EPERM;
+      ucredp->cmcred_pid = pids;
+      ucredp->cmcred_uid = auids;
+      ucredp->cmcred_euid = euids;
+      ucredp->cmcred_gid = agids;
+      /* FIXME: groups not in input data */
+      ucredp->cmcred_ngroups =
+	__getgroups (sizeof (ucredp->cmcred_groups) / sizeof (gid_t),
+		     ucredp->cmcred_groups);
+      return 0;
+    }
+  return err;
+}
+
+  struct cmsgcred *ucredp = NULL;
+  pid_t pids;
+  uid_t euids, auids;
+  gid_t egids, agids;
+  size_t euidslen, auidslen, egidslen, agidslen;
+
+  /* SCM_CREDS support: Fill in the ancillary data  */
+  cmsg = CMSG_FIRSTHDR (message);
+
+  /* Normal case */
+  if (cmsg != NULL && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+    {
+      for (; cmsg; cmsg = CMSG_NXTHDR (message, cmsg))
+	{
+	  ucredp = (struct cmsgcred *) CMSG_DATA(cmsg);
+	  pids = ucredp->cmcred_pid;
+	  auids = ucredp->cmcred_uid;
+	  euids = ucredp->cmcred_euid;
+	  agids = ucredp->cmcred_gid;
+	  egids = agids; /* Not in struct cmsgcred */
+	  /* FIXME: check received cmcred_ngroups and cmcred_groups[] too */
+	}
+
+      /* Zero credentials byte sent: check and send credentials */
+      if (strncmp(data.ptr, "\0", 1) == 0)
+	{
+	  pids = __getpid();
+	  euids = __geteuid();
+	  auids = __getuid();
+	  egids = __getegid();
+	  agids = __getgid();
+	  euidslen = auidslen = egidslen = agidslen = 1;
+	}
+      nports = 0;
+
+      err = check_auth (pids, euids, euidslen, auids, auidslen,
+			egids, egidslen, agids, agidslen,
+			ucredp);
+      if (err)
+	return __hurd_fail (err);
+      goto label;
+    }
+
   /* SCM_RIGHTS support: get the number of fds to send.  */
   cmsg = CMSG_FIRSTHDR (message);
   for (; cmsg; cmsg = CMSG_NXTHDR (message, cmsg))
@@ -147,6 +234,7 @@
 	}
     }
 
+ label:
   if (addr)
     {
       if (addr->sun_family == AF_LOCAL)
@@ -188,8 +276,8 @@
 						   ports,
 						   MACH_MSG_TYPE_COPY_SEND,
 						   nports,
-						   message->msg_control,
-						   message->msg_controllen,
+						   control,
+						   controllen,
 						   &amount);
 			      __mach_port_deallocate (__mach_task_self (),
 						      aport);

Reply to: