From patchwork Wed Apr 5 21:54:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 9665803 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1125D602B5 for ; Wed, 5 Apr 2017 21:54:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 01E6828173 for ; Wed, 5 Apr 2017 21:54:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E91942856D; Wed, 5 Apr 2017 21:54:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1CFAE28173 for ; Wed, 5 Apr 2017 21:54:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932280AbdDEVyT (ORCPT ); Wed, 5 Apr 2017 17:54:19 -0400 Received: from nm21-vm6.bullet.mail.ne1.yahoo.com ([98.138.91.114]:54276 "EHLO nm21-vm6.bullet.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933475AbdDEVyS (ORCPT ); Wed, 5 Apr 2017 17:54:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1491429258; bh=ACSy/rqCsm2cfpUdq5nlcG+InR71DsGPqUuXBEXHjN8=; h=Subject:To:References:Cc:From:Date:In-Reply-To:From:Subject; b=O1kymVkIfxKbgfa34iqN02AlDijzrdtytS2EPTOd+Xa3GhjiNHFHpLvLgI79VHdz0/qCY+sZG267dZBy9patD+I8uG4OsjbMcV35j/u+C/oP9jRL9Z8zXHw1FHHpCI17u8BdQ1ykxo3MQVzMBgxaI/tFUaRtFgMvAMGWKYLaXpwCX71nwIes63vByfAr0lCUQfaSvU4YZMzxc/2qqcavDtzjt9vFsP8suv1B8nDT6haXA7jBdf6YR9+8IrhArfD2DxLVEawIwMLhB36yVlLkMA3JPZLtF8Xa7sg/nU9yGKJIivE1Yc6uyEyc14kE1tekR23Yuy/1YhKXVGv4Yacmzw== Received: from [98.138.100.111] by nm21.bullet.mail.ne1.yahoo.com with NNFMP; 05 Apr 2017 21:54:18 -0000 Received: from [98.138.84.45] by tm100.bullet.mail.ne1.yahoo.com with NNFMP; 05 Apr 2017 21:54:18 -0000 Received: from [127.0.0.1] by smtp113.mail.ne1.yahoo.com with NNFMP; 05 Apr 2017 21:54:18 -0000 X-Yahoo-Newman-Id: 79638.8113.bm@smtp113.mail.ne1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: 9yVsyiYVM1mvaJalwHKm7G2OMRnCVwtGC6wWYuLK0jLGdD9 sZHXb6kkeQ1ukGcevaFLY3JmUITETszSKaNqY05gJ5QsaDGQToHBnUlaNA7V PLyWQzA2PimpAmWk.ZWP7IDoNCaMtDS7o7hAqLlfsDdrsLOAoALKeldzcgWq XSe.oQJdjnEurmz3IrVYM.jSAv7y_N2FKDGOgySx4XhUNVZW6WYglXACZIHa TZvINDrF5M89k6obniior6ja2vI8UYr6UIWN8VSfNGznsha_xyrKb8Qvg7_r 1LNU.O0Oyjbf4Rj_WLLfc61M5DwGAclGkcY_s4NQmCoiEDjgp2BxKR96orr1 d.bxzZXQLYajoCkjZwdNAg0TLUXkSxx4L2Pfo.3imyamgbXnC9tbV7w4odoe t3xSAmiU12rSTkHwqXux3jxDNn0pS4vIgHcy10wEksCKaU3h_hNhY71Gina8 xcmHeoCJE_Tq9IAr6A1okKchkNaOKU_gTVgve64QHyTnGDgHJEg1fSHViUQs SqLBzSM9ndBrL4WStjzZP6oCS_JXgzwUFUx_BefJC.dwgf4zkepMp8i0xT9o kiLKg38w8Mw-- X-Yahoo-SMTP: OIJXglSswBDfgLtXluJ6wiAYv6_cnw-- Subject: [PATCH RFC 09/11] netlabel agreement checking To: LSM , James Morris References: <509e0281-9f8a-83c2-f9d6-5532903cda46@schaufler-ca.com> Cc: John Johansen , Tetsuo Handa , Paul Moore , Stephen Smalley , Kees Cook , Casey Schaufler From: Casey Schaufler Message-ID: <21a11f67-bd72-d4eb-81bf-bd0e2b61b3d7@schaufler-ca.com> Date: Wed, 5 Apr 2017 14:54:11 -0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: <509e0281-9f8a-83c2-f9d6-5532903cda46@schaufler-ca.com> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Subject: [PATCH RFC 09/11] netlabel agreement checking If multiple security modules are using netlabel to pass security attributes they must agree on the labeling for each packet. Because a module may decide on the labeling based on a number of factors the check needs to be done at send time. Signed-off-by: Casey Schaufler --- include/linux/lsm_hooks.h | 5 +++- include/net/netlabel.h | 8 +++++++ net/netlabel/netlabel_kapi.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ security/security.c | 23 ++++++++++++++++++- security/selinux/hooks.c | 7 +++++- security/smack/smack_lsm.c | 4 +++- security/tomoyo/tomoyo.c | 3 ++- 7 files changed, 99 insertions(+), 5 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 6b0ede2..d848a0a 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -28,6 +28,8 @@ #include #include +struct netlbl_lsm_secattr; + /** * Security hooks for program execution operations. * @@ -789,6 +791,7 @@ * @sock contains the socket structure. * @msg contains the message to be transmitted. * @size contains the size of message. + * @attrs points to the network attributes on return. * Return 0 if permission is granted. * @socket_recvmsg: * Check permission before receiving a message from a socket. @@ -1584,7 +1587,7 @@ union security_list_options { int (*socket_listen)(struct socket *sock, int backlog); int (*socket_accept)(struct socket *sock, struct socket *newsock); int (*socket_sendmsg)(struct socket *sock, struct msghdr *msg, - int size); + int size, struct netlbl_lsm_secattr **attrs); int (*socket_recvmsg)(struct socket *sock, struct msghdr *msg, int size, int flags); int (*socket_getsockname)(struct socket *sock); diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 8cdd2d6..3cda2f3 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -472,6 +472,8 @@ int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap, u32 offset, unsigned long bitmap, gfp_t flags); +bool netlbl_secattr_equal(const struct netlbl_lsm_secattr *secattr_a, + const struct netlbl_lsm_secattr *secattr_b); /* Bitmap functions */ @@ -623,6 +625,12 @@ static inline int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap, { return 0; } +static inline bool netlbl_secattr_equal( + const struct netlbl_lsm_secattr *secattr_a, + const struct netlbl_lsm_secattr *secattr_b) +{ + return true; +} static inline int netlbl_enabled(void) { return 0; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index cb8a2c7..5692d92 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -1461,6 +1461,60 @@ int netlbl_cache_add(const struct sk_buff *skb, u16 family, return -ENOMSG; } +/** + * netlbl_secattr_equal - Compare two lsm secattrs + * @secattr_a: one security attribute + * @secattr_b: the other security attribute + * + * Description: + * Compare two lsm security attribute structures. Returns true + * if they are the same, false otherwise. + * + */ +bool netlbl_secattr_equal(const struct netlbl_lsm_secattr *secattr_a, + const struct netlbl_lsm_secattr *secattr_b) +{ + struct netlbl_lsm_catmap *iter_a; + struct netlbl_lsm_catmap *iter_b; + + if (secattr_a == secattr_b) + return true; + if (!secattr_a || !secattr_b) + return false; + + if ((secattr_a->flags & NETLBL_SECATTR_SECID) && + (secattr_b->flags & NETLBL_SECATTR_SECID)) + return secattr_a->attr.secid.common == + secattr_b->attr.secid.common; + + if ((secattr_a->flags & NETLBL_SECATTR_MLS_LVL) != + (secattr_b->flags & NETLBL_SECATTR_MLS_LVL)) + return false; + + if ((secattr_a->flags & NETLBL_SECATTR_MLS_LVL) && + secattr_a->attr.mls.lvl != secattr_b->attr.mls.lvl) + return false; + + if ((secattr_a->flags & NETLBL_SECATTR_MLS_CAT) != + (secattr_b->flags & NETLBL_SECATTR_MLS_CAT)) + return false; + + iter_a = secattr_a->attr.mls.cat; + iter_b = secattr_b->attr.mls.cat; + + while (iter_a && iter_b) { + if (iter_a->startbit != iter_b->startbit) + return false; + if (memcmp(iter_a->bitmap, iter_b->bitmap, + sizeof(iter_a->bitmap))) + return false; + iter_a = iter_a->next; + iter_b = iter_b->next; + } + + return !iter_a && !iter_b; +} + /* * Protocol Engine Functions */ diff --git a/security/security.c b/security/security.c index 35ccc81..5cf3214 100644 --- a/security/security.c +++ b/security/security.c @@ -28,6 +28,7 @@ #include #include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -2134,7 +2135,27 @@ int security_socket_accept(struct socket *sock, struct socket *newsock) int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { - return call_int_hook(socket_sendmsg, 0, sock, msg, size); + struct security_hook_list *hp; + int rc; + struct netlbl_lsm_secattr *pattrs = NULL; + struct netlbl_lsm_secattr *attrs = NULL; + + list_for_each_entry(hp, &security_hook_heads.socket_sendmsg, list) { + rc = hp->hook.socket_sendmsg(sock, msg, size, &attrs); + if (rc) + return rc; + /* + * Only do the check if the current module reports + * an attribute, and there is something to compare it to. + */ + if (attrs) { + if (!pattrs) + pattrs = attrs; + else if (!netlbl_secattr_equal(pattrs, attrs)) + return -EACCES; + } + } + return 0; } int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d5c8868..6c493b8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4437,8 +4437,13 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) } static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, - int size) + int size, struct netlbl_lsm_secattr **attrs) { +#ifdef CONFIG_NETLABEL + struct sk_security_struct *sksec = selinux_sock(sock->sk); + + *attrs = sksec->nlbl_secattr; +#endif return sock_has_perm(sock->sk, SOCKET__WRITE); } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0034365..7c8ffe4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3635,7 +3635,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) * For IPv6 this is a check against the label of the port. */ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, - int size) + int size, struct netlbl_lsm_secattr **attrs) { struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; #if IS_ENABLED(CONFIG_IPV6) @@ -3647,6 +3647,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, #endif int rc = 0; + *attrs = NULL; /* * Perfectly reasonable for this to be NULL */ @@ -3656,6 +3657,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, switch (sock->sk->sk_family) { case AF_INET: rc = smack_netlabel_send(sock->sk, sip); + *attrs = &ssp->smk_out->smk_netlabel; break; case AF_INET6: #ifdef SMACK_IPV6_SECMARK_LABELING diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 27f1198..914eab3 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -499,11 +499,12 @@ static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, * @sock: Pointer to "struct socket". * @msg: Pointer to "struct msghdr". * @size: Size of message. + * @attrs: unused * * Returns 0 on success, negative value otherwise. */ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, - int size) + int size, struct netlbl_lsm_secattr **attrs) { return tomoyo_socket_sendmsg_permission(sock, msg, size); }