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: