--- 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 #include +#include #include #include @@ -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);