Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934339Ab3IDGPd (ORCPT ); Wed, 4 Sep 2013 02:15:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:8663 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1762048Ab3IDGPa (ORCPT ); Wed, 4 Sep 2013 02:15:30 -0400 From: Jan Kaluza To: davem@davemloft.net Cc: LKML , netdev@vger.kernel.org, eparis@redhat.com, rgb@redhat.com, tj@kernel.org, lizefan@huawei.com, containers@lists.linux-foundation.org, cgroups@vger.kernel.org, viro@zeniv.linux.org.uk, Jan Kaluza Subject: [PATCH v3 1/3] Send loginuid and sessionid in SCM_AUDIT Date: Wed, 4 Sep 2013 08:14:19 +0200 Message-Id: <1378275261-4553-2-git-send-email-jkaluza@redhat.com> In-Reply-To: <1378275261-4553-1-git-send-email-jkaluza@redhat.com> References: <1377614400-27122-1-git-send-email-jkaluza@redhat.com> <1378275261-4553-1-git-send-email-jkaluza@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6345 Lines: 184 Server-like processes in many cases need credentials and other metadata of the peer, to decide if the calling process is allowed to request a specific action, or the server just wants to log away this type of information for auditing tasks. The current practice to retrieve such process metadata is to look that information up in procfs with the $PID received over SCM_CREDENTIALS. This is sufficient for long-running tasks, but introduces a race which cannot be worked around for short-living processes; the calling process and all the information in /proc/$PID/ is gone before the receiver of the socket message can look it up. This introduces a new SCM type called SCM_AUDIT to allow the direct attaching of "loginuid" and "sessionid" to SCM, which is significantly more efficient and will reliably avoid the race with the round-trip over procfs. Signed-off-by: Jan Kaluza --- include/linux/socket.h | 6 ++++++ include/net/af_unix.h | 2 ++ include/net/scm.h | 28 ++++++++++++++++++++++++++-- net/unix/af_unix.c | 7 +++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/include/linux/socket.h b/include/linux/socket.h index 445ef75..505047a 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -130,6 +130,7 @@ static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr #define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ #define SCM_CREDENTIALS 0x02 /* rw: struct ucred */ #define SCM_SECURITY 0x03 /* rw: security label */ +#define SCM_AUDIT 0x04 /* rw: struct uaudit */ struct ucred { __u32 pid; @@ -137,6 +138,11 @@ struct ucred { __u32 gid; }; +struct uaudit { + __u32 loginuid; + __u32 sessionid; +}; + /* Supported address families. */ #define AF_UNSPEC 0 #define AF_UNIX 1 /* Unix domain sockets */ diff --git a/include/net/af_unix.h b/include/net/af_unix.h index a175ba4..3b9d22a 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -36,6 +36,8 @@ struct unix_skb_parms { u32 secid; /* Security ID */ #endif u32 consumed; + kuid_t loginuid; + unsigned int sessionid; }; #define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb)) diff --git a/include/net/scm.h b/include/net/scm.h index 8de2d37..e349a25 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -6,6 +6,7 @@ #include #include #include +#include /* Well, we should have at least one descriptor open * to accept passed FDs 8) @@ -18,6 +19,11 @@ struct scm_creds { kgid_t gid; }; +struct scm_audit { + kuid_t loginuid; + unsigned int sessionid; +}; + struct scm_fp_list { short count; short max; @@ -28,6 +34,7 @@ struct scm_cookie { struct pid *pid; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ struct scm_creds creds; /* Skb credentials */ + struct scm_audit audit; /* Skb audit */ #ifdef CONFIG_SECURITY_NETWORK u32 secid; /* Passed security ID */ #endif @@ -58,6 +65,13 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, scm->creds.gid = gid; } +static inline void scm_set_audit(struct scm_cookie *scm, + kuid_t loginuid, unsigned int sessionid) +{ + scm->audit.loginuid = loginuid; + scm->audit.sessionid = sessionid; +} + static __inline__ void scm_destroy_cred(struct scm_cookie *scm) { put_pid(scm->pid); @@ -77,8 +91,12 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, memset(scm, 0, sizeof(*scm)); scm->creds.uid = INVALID_UID; scm->creds.gid = INVALID_GID; - if (forcecreds) - scm_set_cred(scm, task_tgid(current), current_uid(), current_gid()); + if (forcecreds) { + scm_set_cred(scm, task_tgid(current), current_uid(), + current_gid()); + scm_set_audit(scm, audit_get_loginuid(current), + audit_get_sessionid(current)); + } unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) return 0; @@ -123,7 +141,13 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, .uid = from_kuid_munged(current_ns, scm->creds.uid), .gid = from_kgid_munged(current_ns, scm->creds.gid), }; + struct uaudit uaudits = { + .loginuid = from_kuid_munged(current_ns, + scm->audit.loginuid), + .sessionid = scm->audit.sessionid, + }; put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds); + put_cmsg(msg, SOL_SOCKET, SCM_AUDIT, sizeof(uaudits), &uaudits); } scm_destroy_cred(scm); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 86de99a..c410f76 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1393,6 +1393,8 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen UNIXCB(skb).pid = get_pid(scm->pid); UNIXCB(skb).uid = scm->creds.uid; UNIXCB(skb).gid = scm->creds.gid; + UNIXCB(skb).loginuid = scm->audit.loginuid; + UNIXCB(skb).sessionid = scm->audit.sessionid; UNIXCB(skb).fp = NULL; if (scm->fp && send_fds) err = unix_attach_fds(scm, skb); @@ -1416,6 +1418,8 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock, test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) { UNIXCB(skb).pid = get_pid(task_tgid(current)); current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); + UNIXCB(skb).loginuid = audit_get_loginuid(current); + UNIXCB(skb).sessionid = audit_get_sessionid(current); } } @@ -1812,6 +1816,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, memset(&tmp_scm, 0, sizeof(tmp_scm)); } scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); + scm_set_audit(siocb->scm, UNIXCB(skb).loginuid, UNIXCB(skb).sessionid); unix_set_secdata(siocb->scm, skb); if (!(flags & MSG_PEEK)) { @@ -1993,6 +1998,8 @@ again: } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { /* Copy credentials */ scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); + scm_set_audit(siocb->scm, UNIXCB(skb).loginuid, + UNIXCB(skb).sessionid); check_creds = 1; } -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/