From fab8f9b1046e8c36ae865903903025dce73e8767 Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Wed, 28 Oct 2020 11:31:11 -0400 Subject: [PATCH] Cygwin: AF_UNIX: create_cmsg_data: check credentials If the user is not an administrator, check that the specified credentials match the user's credentials. --- winsup/cygwin/fhandler_socket_unix.cc | 34 +++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 973e4ac0f..258c03bc2 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -2537,10 +2537,7 @@ fhandler_socket_unix::readv (const struct iovec *const iov, int iovcnt, /* For now, just support an ancillary data block consisting of a single cmsghdr, containing SCM_CREDENTIALS. - FIXME: Check errnos below. - - FIXME: We're supposed to check the credentials. - https://man7.org/linux/man-pages/man7/unix.7.html */ + FIXME: Check errnos below. */ bool fhandler_socket_unix::create_cmsg_data (af_unix_pkt_hdr_t *packet, const struct msghdr *msg) @@ -2563,6 +2560,35 @@ fhandler_socket_unix::create_cmsg_data (af_unix_pkt_hdr_t *packet, set_errno (EOPNOTSUPP); return false; } + /* Check credentials. */ + struct ucred *cred = (struct ucred *) CMSG_DATA (cmsg); + /* FIXME: check_token_membership returns false even when running in + a privileged shell. Why? */ + bool perms = check_token_membership (&well_known_admins_sid); + if (!perms) + { + tmp_pathbuf tp; + gid_t *gids = (gid_t *) tp.w_get (); + int num = getgroups (65536 / sizeof (*gids), gids); + + for (int idx = 0; idx < num; ++idx) + if (gids[idx] == 544) + { + perms = true; + break; + } + } + if (perms) + /* FIXME: We don't have to check uid and gid, but we should still + check that the specified pid is the pid of an existing + process. */ + ; + else if (cred->pid != myself->pid || cred->uid != myself->uid + || cred->gid != myself->gid) + { + set_errno (EPERM); + return false; + } memcpy (AF_UNIX_PKT_CMSG (packet), msg->msg_control, msg->msg_controllen); packet->pckt_len += msg->msg_controllen; packet->cmsg_len = msg->msg_controllen;