From patchwork Thu Oct 24 21:44:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 1183583 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=schaufler-ca.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=yahoo.com header.i=@yahoo.com header.b="DlYWnnkz"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zgl93sqRz9sCJ for ; Fri, 25 Oct 2019 08:45:09 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729298AbfJXVpF (ORCPT ); Thu, 24 Oct 2019 17:45:05 -0400 Received: from sonic317-39.consmr.mail.ne1.yahoo.com ([66.163.184.50]:46108 "EHLO sonic317-39.consmr.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726965AbfJXVpE (ORCPT ); Thu, 24 Oct 2019 17:45:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1571953502; bh=LCpRAal86o/xAMqGwYkdQW9t87uiX/01PxsMjwVKvIc=; h=From:To:Subject:Date:From:Subject; b=DlYWnnkzNKXEXvHN6AaMgx+Rwy6cTHDNJm/PARnfHTA05BCYHJFfBNS+KWd3Rc4zZTSyrn0ZWnicrACxofDWh/sEem7PAXwadR6DKmqNFmywLMs/EB/F238wzrdwBp04zSj9EXMCZRPAzKd6FPtI+CRMIONw2tXRNqQ/lDUbWq4/qK6v4Fe7OeRehGIcrb99V1DP9xAGHj3CSdrpX86cNe9ugz3X0Cxei8Bsr5r7vKojL8+rfxIFG1FJskG5FBElN80M1+umvkysEzdQquJnmCTRjh0yCDGpqds4I/ht/WhKC2EIEsRme6OW87HvlwXmReM2ChJcexF6+3TXt6TE8Q== X-YMail-OSG: eH3uWjEVM1ktkaNK3loYc0xqSzWGMv4uopD2q19fsDMvhv8xr2k_tBip_Kf.IG8 kR_wvmmIhTBZMe2xsqHGWiRkh4Xq74XpeXbWDGQk_EvdVf2pghf5LoIyLyEgCntZcpyjhjLzm7vL f_.H5_0URZf2eMHsNmIIIfFrBwBHiCP9m1tzX_R1ddtMz2gJZFq1b7q7xVV1ivc1skyflr_Vzupd iRh.yMHB1Nld2HgGM2CrruaFmGVhb8dF8R6dLLCiYOnpFUOI0es58VQnDseuDMTr0wPwYl4QcSCa mCNySgPCqUOUB2ZZ823DVKfNUDt3nF68EVaGh7foppfY.5pVmO18oAcMgI7AMv8WUPZcoa8POqwn cfljV47akTgqXOIMSKN2OZvR9JzW1HzKRiEHKmBJEFqCdEX61fxPMfoye4npfC_4QQqaJHBjsbqH gG1nf0c344RwyuViDb.s1C3N6anLAbExVi6RIf4B3Hw4ZjIbWXk6cWZwddyqepjCC4SmnfFZSs3o mlecdIHQ4r8GIkrbJK5Ca9hnIc0z5iI4kbJV2dCWeN_bS7r8XkYA0xAkiUpfm9dlTvwjyiOe_T3H hgG_ZqFyWcbB.SeTPdZyducuXVnxftKxE0EqH6C_ndfq1bdjxUzdrrwFzYWdQ0gryTlIlbLWzAnz ONf_wi49d83fZEcFe.2W.wopysCqwdHZXdTzkpOj7c5EIHQuzJ6z9o5Tv919PHcPgpNcZKQTPBOi 8IJ.CLsEwrbId7TJa6qLw2sOPD5QJ3Bic5x3SmKcuxjADEdcu.0.zbc90Kbbt14Qdt1IzwxFQbjN wnY4wVo2MeEpO1go.qq7m0yYtWRUBdRKi28CMr.exTHxbf01wVSocIBLvL6YERcvDIr3Ggo9rIe7 I561tFwQ2vfqjHjBk60iitaKBUw3KlFu8HwO_gCm9pPK8HVFYWJuPYs6ABVIyxA73yaY0f8b8VDf NUQvTBLFfDrIvZA94otef3akWrHTqY4l3PA4QylCMkb41KLrC3uvZ2lX3OBCFKxDLkTnkau4nnG1 bLFSta989vjyjCRn25In.RPNhAe9Vsr8Y89Y8zhvK9Fd6NYN0.S.ai_3eWtmr_icDM0enQdaxfyJ obtUPAJBbZL9w6cI3d0qTLWzfhXUuZdFvBQQJqf862MEnUiT0fIChpHXMn6MtaomdeAF8Qzz5jyF CtCqAkEAzsmc2SakOrn7SWwyMpPmpLUW8r7N91QH3a5J0yMr5E5bL.HBX88gCLI8co96mr7K_HI7 Ky4ANSlhbVyTPaeB3TY6fvRCoati.FXKuX64U9h5SX2l8hBp3dJJs21n1ONbM_6pjXsuHC6h9X9o AwLq7AxhesxJyAfilQgtKh.gf5rKH_LFP18ju4qouXlXP983Ec5mqMdCx45R_l1RtIpBGz3x4DpE 68A-- Received: from sonic.gate.mail.ne1.yahoo.com by sonic317.consmr.mail.ne1.yahoo.com with HTTP; Thu, 24 Oct 2019 21:45:02 +0000 Received: by smtp420.mail.ne1.yahoo.com (Oath Hermes SMTP Server) with ESMTPA ID eaf5054cc9d2e89fbdd41d6e12cec122; Thu, 24 Oct 2019 21:45:01 +0000 (UTC) From: Casey Schaufler To: netdev@vger.kernel.org Subject: [PATCH v10 05/25] net: Prepare UDS for security module stacking Date: Thu, 24 Oct 2019 14:44:58 -0700 Message-Id: <20191024214500.7356-1-casey@schaufler-ca.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Change the data used in UDS SO_PEERSEC processing from a secid to a more general struct lsmblob. Update the security_socket_getpeersec_dgram() interface to use the lsmblob. There is a small amount of scaffolding code that will come out when the security_secid_to_secctx() code is brought in line with the lsmblob. Reviewed-by: Kees Cook Reviewed-by: John Johansen Signed-off-by: Casey Schaufler --- include/linux/security.h | 7 +++++-- include/net/af_unix.h | 2 +- include/net/scm.h | 8 +++++--- net/ipv4/ip_sockglue.c | 8 +++++--- net/unix/af_unix.c | 6 +++--- security/security.c | 18 +++++++++++++++--- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index cd09e7b1df9f..02ff6250bf2b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1272,7 +1272,8 @@ int security_socket_shutdown(struct socket *sock, int how); int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb); int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, int __user *optlen, unsigned len); -int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid); +int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, + struct lsmblob *blob); int security_sk_alloc(struct sock *sk, int family, gfp_t priority); void security_sk_free(struct sock *sk); void security_sk_clone(const struct sock *sk, struct sock *newsk); @@ -1410,7 +1411,9 @@ static inline int security_socket_getpeersec_stream(struct socket *sock, char __ return -ENOPROTOOPT; } -static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +static inline int security_socket_getpeersec_dgram(struct socket *sock, + struct sk_buff *skb, + struct lsmblob *blob) { return -ENOPROTOOPT; } diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 3426d6dacc45..933492c08b8c 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -36,7 +36,7 @@ struct unix_skb_parms { kgid_t gid; struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK - u32 secid; /* Security ID */ + struct lsmblob lsmblob; /* Security LSM data */ #endif u32 consumed; } __randomize_layout; diff --git a/include/net/scm.h b/include/net/scm.h index 1ce365f4c256..e2e71c4bf9d0 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -33,7 +33,7 @@ struct scm_cookie { struct scm_fp_list *fp; /* Passed files */ struct scm_creds creds; /* Skb credentials */ #ifdef CONFIG_SECURITY_NETWORK - u32 secid; /* Passed security ID */ + struct lsmblob lsmblob; /* Passed LSM data */ #endif }; @@ -46,7 +46,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl); #ifdef CONFIG_SECURITY_NETWORK static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) { - security_socket_getpeersec_dgram(sock, NULL, &scm->secid); + security_socket_getpeersec_dgram(sock, NULL, &scm->lsmblob); } #else static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) @@ -97,7 +97,9 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc int err; if (test_bit(SOCK_PASSSEC, &sock->flags)) { - err = security_secid_to_secctx(scm->secid, &secdata, &seclen); + /* Scaffolding - it has to be element 0 for now */ + err = security_secid_to_secctx(scm->lsmblob.secid[0], + &secdata, &seclen); if (!err) { put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 82f341e84fae..2a5c868ce135 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -130,15 +130,17 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) { + struct lsmblob lb; char *secdata; - u32 seclen, secid; + u32 seclen; int err; - err = security_socket_getpeersec_dgram(NULL, skb, &secid); + err = security_socket_getpeersec_dgram(NULL, skb, &lb); if (err) return; - err = security_secid_to_secctx(secid, &secdata, &seclen); + /* Scaffolding - it has to be element 0 */ + err = security_secid_to_secctx(lb.secid[0], &secdata, &seclen); if (err) return; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index ddb838a1b74c..c50a004a1389 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -143,17 +143,17 @@ static struct hlist_head *unix_sockets_unbound(void *addr) #ifdef CONFIG_SECURITY_NETWORK static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) { - UNIXCB(skb).secid = scm->secid; + UNIXCB(skb).lsmblob = scm->lsmblob; } static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) { - scm->secid = UNIXCB(skb).secid; + scm->lsmblob = UNIXCB(skb).lsmblob; } static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb) { - return (scm->secid == UNIXCB(skb).secid); + return lsmblob_equal(&scm->lsmblob, &(UNIXCB(skb).lsmblob)); } #else static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) diff --git a/security/security.c b/security/security.c index 7879da7025d2..bd685be33b56 100644 --- a/security/security.c +++ b/security/security.c @@ -2059,10 +2059,22 @@ int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, optval, optlen, len); } -int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, + struct lsmblob *blob) { - return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock, - skb, secid); + struct security_hook_list *hp; + int rc = -ENOPROTOOPT; + + hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_dgram, + list) { + if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot)) + continue; + rc = hp->hook.socket_getpeersec_dgram(sock, skb, + &blob->secid[hp->lsmid->slot]); + if (rc != 0) + break; + } + return rc; } EXPORT_SYMBOL(security_socket_getpeersec_dgram); From patchwork Thu Oct 24 21:44:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 1183584 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=schaufler-ca.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=yahoo.com header.i=@yahoo.com header.b="f6HfEnCx"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zglC3T2wz9sPl for ; Fri, 25 Oct 2019 08:45:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729485AbfJXVpG (ORCPT ); Thu, 24 Oct 2019 17:45:06 -0400 Received: from sonic317-39.consmr.mail.ne1.yahoo.com ([66.163.184.50]:36917 "EHLO sonic317-39.consmr.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728760AbfJXVpG (ORCPT ); Thu, 24 Oct 2019 17:45:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1571953502; bh=547HbZVCRc+yzGH5moJGyELgsFj7NzMEkzk7J8bqeQg=; h=From:To:Subject:Date:In-Reply-To:References:From:Subject; b=f6HfEnCxS/p/+lxmIxJ5L8HJeDv/4sMvztuCINFSicp/zrKz0yXkLjDG8SmH2mYf1LQ45FQbV1xkGXrbr1qoEm7sLc2isipGe/QIgGKUhbxFRFu/tutvK2khwnMoUgBvAslZZq91eJXPjkJ5VEiRxDJZ5i23NFxeRfEXtHuol3EnShPnKSsEu6v46dhjdwQaVI0KiIfmsROC2TwPSbldbZx6E73DRpNSyzYfPkrck16SXNORBoZNmgWd4Imp7LlB/o5vlX+E+eZyFuTLo36452iGU9a7qAvNYJU6v+/qWNWBJnrlzZzEepyCz++QqdxYOZF+KEbHyt2o1NvtJrBWlw== X-YMail-OSG: f2Nb3_wVM1lbJdrirJvbeDbAW5UWBoc04f.LD24b5pzlxVSplsUnrRn56wU5r.U Ozgnsp8E7B9MJP7xgXOVceqJVfJhrZK66QjUblaD6N9xxkMCgZWjmXbCwn.4bqgmV3FN1pw._mo9 A720KPxqGNxcXEsag63ehSS7xe_kO4FVrfGOzZcY_d3Mdkj0zXELG10sUlg7tHhvGl7ObEBTEo59 jHO5CYB_KYb2uqPW_nlIUZYVMMXsVcf3IvrTcRLENXNehHcIivoLWzdkySQy1IcPyMgXZDLjxOu1 Beu8LRDudapkRacErB8Z_cDMdm8n6nXeH9vfklAKNhbfOLC2zqeknnYtqbPDQ4LTTCW9cz34zynZ WCuTmiPSux1yFjAvKOYGypvOj4Jus27niJpcOSTV.G9_oqRyIzVdVliH6Bx.oSk6q6E7XkH3qSw9 vyttxopTkcxaP9BtvpNacsQ325i_IwmigteErBfqMcYlNnz6pWbzdlFHNJquYP2iy5c9vGC9xmrf a80TYjQbZj1JXxvWHADaMCU.B67bXZAxrchEVh9aeY4OESPdCMCBAg2TX1VvW_wpWKq2zpr2TmEc RrQ4iHbX3_Xd5nEy7RLksulk7AkHrnfeqxvOIIQpP30hVmnZllEFwBZ3jNzIMu5NZtK_7gT9yA0H SYmqWNIP.VGeggXDZCDMqX.qTtLxWsMC36QZjBWGveELdFWRDxavCtKRm_S_0goMhZ7c.FbEVvsr afJacgwnfP_U_FHomszIFT5okDJhuzSJjMFBaxVqxPeFk6Oo6lSXVR4_U563YT3_HIzNT2Aw.HhG PbjcPxjlAkF_z11OCRzeyrqTm4Zw9mfOkbqpMEsqIgQ0tDZN_Vy2d8P5FTZwwD5l.K_KSd6Y9Bbk 06s6ah0tzK_qmPVZnaY2c1Zfys7m1Mi2m0Rj.V4BEjJ.gLZKXGipgMudxsKf0awDRUks7sQjoo4F cYKaqqDDYqifopWQpJCsaf8ebtGzpEPymR7ofLt1WDSiqBvop2Utr92SwOKMQgrplyuG5KxHxNz2 J.hKZsU3qqyyBNWMNc7lxr51LlZBo0xB4ynSQ_V3QT6PajR_N600IECXazcoCahwAu8654gKytI1 lzroZVYM3Hd7tcCQJQMmEox6xGH2peYew4zGYbTkbCusMPfAQVtir6f.vR.O8TesUbJWnAh_voRs .4lT0LJlRV.BmxlKff4N.AKzFD7dIyczdmEq8qDjZbzczZCcf4d0x3Ji4ipWyTG.8jIbk.NkKgE7 0V_iLEwjwPiDECOH0BSVibUWZSUwlxzcKGqOE6zgj9ZOEZfyortSve8i3Du_fYFdR_K5s53J5_fn OOQmc.hQNXSCCe.FtBnCtlQ_P3ZUc7xgi6zSd7Rb7O6uGK1VNGgFaZ.Ahm5EbC4DL65eAPVDnTCl 86PoMXxo- Received: from sonic.gate.mail.ne1.yahoo.com by sonic317.consmr.mail.ne1.yahoo.com with HTTP; Thu, 24 Oct 2019 21:45:02 +0000 Received: by smtp420.mail.ne1.yahoo.com (Oath Hermes SMTP Server) with ESMTPA ID eaf5054cc9d2e89fbdd41d6e12cec122; Thu, 24 Oct 2019 21:45:01 +0000 (UTC) From: Casey Schaufler To: netdev@vger.kernel.org Subject: [PATCH v10 19/25] NET: Store LSM netlabel data in a lsmblob Date: Thu, 24 Oct 2019 14:44:59 -0700 Message-Id: <20191024214500.7356-2-casey@schaufler-ca.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191024214500.7356-1-casey@schaufler-ca.com> References: <20191024214500.7356-1-casey@schaufler-ca.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Netlabel uses LSM interfaces requiring an lsmblob and the internal storage is used to pass information between these interfaces, so change the internal data from a secid to a lsmblob. Update the netlabel interfaces and their callers to accommodate the change. This requires that the modules using netlabel use the lsm_id.slot to access the correct secid when using netlabel. Reviewed-by: Kees Cook Reviewed-by: John Johansen Signed-off-by: Casey Schaufler --- include/net/netlabel.h | 8 ++-- net/ipv4/cipso_ipv4.c | 6 ++- net/netlabel/netlabel_kapi.c | 6 +-- net/netlabel/netlabel_unlabeled.c | 57 +++++++++++------------------ net/netlabel/netlabel_unlabeled.h | 2 +- security/selinux/hooks.c | 2 +- security/selinux/include/security.h | 1 + security/selinux/netlabel.c | 2 +- security/selinux/ss/services.c | 4 +- security/smack/smack.h | 1 + security/smack/smack_lsm.c | 5 ++- security/smack/smackfs.c | 10 +++-- 12 files changed, 50 insertions(+), 54 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 72d6435fc16c..6c550455e69f 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -180,7 +180,7 @@ struct netlbl_lsm_catmap { * @attr.mls: MLS sensitivity label * @attr.mls.cat: MLS category bitmap * @attr.mls.lvl: MLS sensitivity level - * @attr.secid: LSM specific secid token + * @attr.lsmblob: LSM specific data * * Description: * This structure is used to pass security attributes between NetLabel and the @@ -215,7 +215,7 @@ struct netlbl_lsm_secattr { struct netlbl_lsm_catmap *cat; u32 lvl; } mls; - u32 secid; + struct lsmblob lsmblob; } attr; }; @@ -429,7 +429,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net, const void *addr, const void *mask, u16 family, - u32 secid, + struct lsmblob *lsmblob, struct netlbl_audit *audit_info); int netlbl_cfg_unlbl_static_del(struct net *net, const char *dev_name, @@ -537,7 +537,7 @@ static inline int netlbl_cfg_unlbl_static_add(struct net *net, const void *addr, const void *mask, u16 family, - u32 secid, + struct lsmblob *lsmblob, struct netlbl_audit *audit_info) { return -ENOSYS; diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index f0165c5f376b..eb4939f38a14 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1481,7 +1481,8 @@ static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def, buffer[0] = CIPSO_V4_TAG_LOCAL; buffer[1] = CIPSO_V4_TAG_LOC_BLEN; - *(u32 *)&buffer[2] = secattr->attr.secid; + /* only one netlabel user - the first */ + *(u32 *)&buffer[2] = secattr->attr.lsmblob.secid[0]; return CIPSO_V4_TAG_LOC_BLEN; } @@ -1501,7 +1502,8 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, const unsigned char *tag, struct netlbl_lsm_secattr *secattr) { - secattr->attr.secid = *(u32 *)&tag[2]; + /* only one netlabel user - the first */ + secattr->attr.lsmblob.secid[0] = *(u32 *)&tag[2]; secattr->flags |= NETLBL_SECATTR_SECID; return 0; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index ee3e5b6471a6..724d44943543 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -210,7 +210,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain, * @addr: IP address in network byte order (struct in[6]_addr) * @mask: address mask in network byte order (struct in[6]_addr) * @family: address family - * @secid: LSM secid value for the entry + * @lsmblob: LSM data value for the entry * @audit_info: NetLabel audit information * * Description: @@ -224,7 +224,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net, const void *addr, const void *mask, u16 family, - u32 secid, + struct lsmblob *lsmblob, struct netlbl_audit *audit_info) { u32 addr_len; @@ -244,7 +244,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net, return netlbl_unlhsh_add(net, dev_name, addr, mask, addr_len, - secid, audit_info); + lsmblob, audit_info); } /** diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 4716e0011ba5..57ede7781c8f 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -80,7 +80,7 @@ struct netlbl_unlhsh_tbl { #define netlbl_unlhsh_addr4_entry(iter) \ container_of(iter, struct netlbl_unlhsh_addr4, list) struct netlbl_unlhsh_addr4 { - u32 secid; + struct lsmblob lsmblob; struct netlbl_af4list list; struct rcu_head rcu; @@ -88,7 +88,7 @@ struct netlbl_unlhsh_addr4 { #define netlbl_unlhsh_addr6_entry(iter) \ container_of(iter, struct netlbl_unlhsh_addr6, list) struct netlbl_unlhsh_addr6 { - u32 secid; + struct lsmblob lsmblob; struct netlbl_af6list list; struct rcu_head rcu; @@ -233,7 +233,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) * @iface: the associated interface entry * @addr: IPv4 address in network byte order * @mask: IPv4 address mask in network byte order - * @secid: LSM secid value for entry + * @lsmblob: LSM data value for entry * * Description: * Add a new address entry into the unlabeled connection hash table using the @@ -244,7 +244,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, const struct in_addr *addr, const struct in_addr *mask, - u32 secid) + struct lsmblob *lsmblob) { int ret_val; struct netlbl_unlhsh_addr4 *entry; @@ -256,7 +256,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, entry->list.addr = addr->s_addr & mask->s_addr; entry->list.mask = mask->s_addr; entry->list.valid = 1; - entry->secid = secid; + entry->lsmblob = *lsmblob; spin_lock(&netlbl_unlhsh_lock); ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list); @@ -273,7 +273,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, * @iface: the associated interface entry * @addr: IPv6 address in network byte order * @mask: IPv6 address mask in network byte order - * @secid: LSM secid value for entry + * @lsmblob: LSM data value for entry * * Description: * Add a new address entry into the unlabeled connection hash table using the @@ -284,7 +284,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, const struct in6_addr *addr, const struct in6_addr *mask, - u32 secid) + struct lsmblob *lsmblob) { int ret_val; struct netlbl_unlhsh_addr6 *entry; @@ -300,7 +300,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; entry->list.mask = *mask; entry->list.valid = 1; - entry->secid = secid; + entry->lsmblob = *lsmblob; spin_lock(&netlbl_unlhsh_lock); ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list); @@ -379,7 +379,7 @@ int netlbl_unlhsh_add(struct net *net, const void *addr, const void *mask, u32 addr_len, - u32 secid, + struct lsmblob *lsmblob, struct netlbl_audit *audit_info) { int ret_val; @@ -388,7 +388,6 @@ int netlbl_unlhsh_add(struct net *net, struct netlbl_unlhsh_iface *iface; struct audit_buffer *audit_buf = NULL; struct lsmcontext context; - struct lsmblob blob; if (addr_len != sizeof(struct in_addr) && addr_len != sizeof(struct in6_addr)) @@ -421,7 +420,7 @@ int netlbl_unlhsh_add(struct net *net, const struct in_addr *addr4 = addr; const struct in_addr *mask4 = mask; - ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); + ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, lsmblob); if (audit_buf != NULL) netlbl_af4list_audit_addr(audit_buf, 1, dev_name, @@ -434,7 +433,7 @@ int netlbl_unlhsh_add(struct net *net, const struct in6_addr *addr6 = addr; const struct in6_addr *mask6 = mask; - ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); + ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, lsmblob); if (audit_buf != NULL) netlbl_af6list_audit_addr(audit_buf, 1, dev_name, @@ -451,8 +450,7 @@ int netlbl_unlhsh_add(struct net *net, unlhsh_add_return: rcu_read_unlock(); if (audit_buf != NULL) { - lsmblob_init(&blob, secid); - if (security_secid_to_secctx(&blob, &context) == 0) { + if (security_secid_to_secctx(lsmblob, &context) == 0) { audit_log_format(audit_buf, " sec_obj=%s", context.context); security_release_secctx(&context); @@ -487,7 +485,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, struct audit_buffer *audit_buf; struct net_device *dev; struct lsmcontext context; - struct lsmblob blob; spin_lock(&netlbl_unlhsh_lock); list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr, @@ -507,10 +504,8 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, addr->s_addr, mask->s_addr); if (dev != NULL) dev_put(dev); - if (entry != NULL) - lsmblob_init(&blob, entry->secid); if (entry != NULL && - security_secid_to_secctx(&blob, &context) == 0) { + security_secid_to_secctx(&entry->lsmblob, &context) == 0) { audit_log_format(audit_buf, " sec_obj=%s", context.context); security_release_secctx(&context); @@ -551,7 +546,6 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, struct audit_buffer *audit_buf; struct net_device *dev; struct lsmcontext context; - struct lsmblob blob; spin_lock(&netlbl_unlhsh_lock); list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list); @@ -570,10 +564,8 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, addr, mask); if (dev != NULL) dev_put(dev); - if (entry != NULL) - lsmblob_init(&blob, entry->secid); if (entry != NULL && - security_secid_to_secctx(&blob, &context) == 0) { + security_secid_to_secctx(&entry->lsmblob, &context) == 0) { audit_log_format(audit_buf, " sec_obj=%s", context.context); security_release_secctx(&context); @@ -927,9 +919,8 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb, if (ret_val != 0) return ret_val; - /* scaffolding with the [0] */ return netlbl_unlhsh_add(&init_net, - dev_name, addr, mask, addr_len, blob.secid[0], + dev_name, addr, mask, addr_len, &blob, &audit_info); } @@ -977,10 +968,8 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb, if (ret_val != 0) return ret_val; - /* scaffolding with the [0] */ return netlbl_unlhsh_add(&init_net, - NULL, addr, mask, addr_len, blob.secid[0], - &audit_info); + NULL, addr, mask, addr_len, &blob, &audit_info); } /** @@ -1092,8 +1081,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, struct net_device *dev; struct lsmcontext context; void *data; - u32 secid; - struct lsmblob blob; + struct lsmblob *lsmb; data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid, cb_arg->seq, &netlbl_unlabel_gnl_family, @@ -1131,7 +1119,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, if (ret_val != 0) goto list_cb_failure; - secid = addr4->secid; + lsmb = (struct lsmblob *)&addr4->lsmblob; } else { ret_val = nla_put_in6_addr(cb_arg->skb, NLBL_UNLABEL_A_IPV6ADDR, @@ -1145,11 +1133,10 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, if (ret_val != 0) goto list_cb_failure; - secid = addr6->secid; + lsmb = (struct lsmblob *)&addr6->lsmblob; } - lsmblob_init(&blob, secid); - ret_val = security_secid_to_secctx(&blob, &context); + ret_val = security_secid_to_secctx(lsmb, &context); if (ret_val != 0) goto list_cb_failure; ret_val = nla_put(cb_arg->skb, @@ -1500,7 +1487,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, &iface->addr4_list); if (addr4 == NULL) goto unlabel_getattr_nolabel; - secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid; + secattr->attr.lsmblob = netlbl_unlhsh_addr4_entry(addr4)->lsmblob; break; } #if IS_ENABLED(CONFIG_IPV6) @@ -1513,7 +1500,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, &iface->addr6_list); if (addr6 == NULL) goto unlabel_getattr_nolabel; - secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid; + secattr->attr.lsmblob = netlbl_unlhsh_addr6_entry(addr6)->lsmblob; break; } #endif /* IPv6 */ diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h index 3a9e5dc9511b..dcff99695c97 100644 --- a/net/netlabel/netlabel_unlabeled.h +++ b/net/netlabel/netlabel_unlabeled.h @@ -225,7 +225,7 @@ int netlbl_unlhsh_add(struct net *net, const void *addr, const void *mask, u32 addr_len, - u32 secid, + struct lsmblob *lsmblob, struct netlbl_audit *audit_info); int netlbl_unlhsh_remove(struct net *net, const char *dev_name, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c9e377d13f0e..b07f9b8c7670 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6656,7 +6656,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct sk_security_struct), }; -static struct lsm_id selinux_lsmid __lsm_ro_after_init = { +struct lsm_id selinux_lsmid __lsm_ro_after_init = { .lsm = "selinux", .slot = LSMBLOB_NEEDED }; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index b5b7c5aade8c..f0ca3879ba48 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -68,6 +68,7 @@ struct netlbl_lsm_secattr; extern int selinux_enabled; +extern struct lsm_id selinux_lsmid; /* Policy capabilities */ enum { diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index c40914a157b7..120d50c1bcac 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -122,7 +122,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( return NULL; if ((secattr->flags & NETLBL_SECATTR_SECID) && - (secattr->attr.secid == sid)) + (secattr->attr.lsmblob.secid[selinux_lsmid.slot] == sid)) return secattr; return NULL; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ec62918521b1..508dfba8607b 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3592,7 +3592,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, if (secattr->flags & NETLBL_SECATTR_CACHE) *sid = *(u32 *)secattr->cache->data; else if (secattr->flags & NETLBL_SECATTR_SECID) - *sid = secattr->attr.secid; + *sid = secattr->attr.lsmblob.secid[selinux_lsmid.slot]; else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { rc = -EIDRM; ctx = sidtab_search(sidtab, SECINITSID_NETMSG); @@ -3665,7 +3665,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state, if (secattr->domain == NULL) goto out; - secattr->attr.secid = sid; + secattr->attr.lsmblob.secid[selinux_lsmid.slot] = sid; secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; mls_export_netlbl_lvl(policydb, ctx, secattr); rc = mls_export_netlbl_cat(policydb, ctx, secattr); diff --git a/security/smack/smack.h b/security/smack/smack.h index 0a5a2a296c1a..809f9486708b 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -320,6 +320,7 @@ void smk_destroy_label_list(struct list_head *list); * Shared data. */ extern int smack_enabled; +extern struct lsm_id smack_lsmid; extern int smack_cipso_direct; extern int smack_cipso_mapped; extern struct smack_known *smack_net_ambient; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 17a652f96bd5..8b2730e02044 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3765,7 +3765,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, /* * Looks like a fallback, which gives us a secid. */ - return smack_from_secid(sap->attr.secid); + return smack_from_secid( + sap->attr.lsmblob.secid[smack_lsmid.slot]); /* * Without guidance regarding the smack value * for the packet fall back on the network @@ -4583,7 +4584,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct socket_smack), }; -static struct lsm_id smack_lsmid __lsm_ro_after_init = { +struct lsm_id smack_lsmid __lsm_ro_after_init = { .lsm = "smack", .slot = LSMBLOB_NEEDED }; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index faf2ea3968b3..6a4c468c200c 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -1150,6 +1150,7 @@ static void smk_net4addr_insert(struct smk_net4addr *new) static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + struct lsmblob lsmblob; struct smk_net4addr *snp; struct sockaddr_in newname; char *smack; @@ -1281,10 +1282,13 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, * this host so that incoming packets get labeled. * but only if we didn't get the special CIPSO option */ - if (rc == 0 && skp != NULL) + if (rc == 0 && skp != NULL) { + lsmblob_init(&lsmblob, 0); + lsmblob.secid[smack_lsmid.slot] = snp->smk_label->smk_secid; rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, - &snp->smk_host, &snp->smk_mask, PF_INET, - snp->smk_label->smk_secid, &audit_info); + &snp->smk_host, &snp->smk_mask, PF_INET, &lsmblob, + &audit_info); + } if (rc == 0) rc = count; From patchwork Thu Oct 24 21:45:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Casey Schaufler X-Patchwork-Id: 1183585 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=schaufler-ca.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=yahoo.com header.i=@yahoo.com header.b="WRDM33mg"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zglD1FjZz9sPp for ; Fri, 25 Oct 2019 08:45:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729549AbfJXVpH (ORCPT ); Thu, 24 Oct 2019 17:45:07 -0400 Received: from sonic306-28.consmr.mail.ne1.yahoo.com ([66.163.189.90]:37463 "EHLO sonic306-28.consmr.mail.ne1.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729033AbfJXVpG (ORCPT ); Thu, 24 Oct 2019 17:45:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1571953504; bh=oUzl4GeCHb4TsNNt33aui+mLMgHF+10V6sz7nUNFjYM=; h=From:To:Subject:Date:In-Reply-To:References:From:Subject; b=WRDM33mgPptHeiIZpYMWASx1m48oKjFa4oxMJtmfIsibvQpTxDYXkaeVSijex9Aj10nnWwktk6ty79OPqsCjG9PgSmk5LTrTBlA3cL7QDfRrISuVVWRHRhhq77cJv4oXAuLC6ziPeVGBt06/mpcPSWTcO4I1GQ1mlbtS3QtyBizgl9m9LwX4fmZLRbQ5v2cNxlIfuAXm74qECsx0YCanHHu7My3g8QKIuQhfZWyNRM2ax4Zl32oPE66wEZdr+nzx78wZ4lV2vy+C3A1coHNx/oiOPBD6pnwBKeYO4WYXUfwDCWEr+JnscC9vpeUgZz9922qLu60T6zNL0a95VuI46w== X-YMail-OSG: yL9fKP4VM1mFcmepgbbcjDsgvNfbQQC0Eht6IEkB7XfrpJXGBpCL6HC7SucbmyM 1kiVGjZ1qGf95HkzNkzsK.J5rOFq7E68x0gudmEi5f8AWLNmaaPwWGL1mFQHR.S8ZfB.Uwb.vfOl LN8jqZYYv.I3xxNRBecBvSAlZE70zoE01nqNd2LtdG5UIMH0XtjoPT705iAlX6vITDbgcXtcv6Bn eCnF484mEVWqfya6U0VQyPfBJ46sgMs505iLr1JPmGUepI34YCMPhSj.2BfoktLkezarrTjAt6EW aWYOiULHuCZSnPDRqL3iGF_bVNumytSeWbRh.6T.Asm3Hy8eyeeCZN2x_dIder10_JyE64.U1RQZ shpLfnPd68nTQCA7_av6ClLov5IhFh_sR7bR9Oc7_hhjG.KKii_6JO8C5iJ1mfpBkSb2LSLNhoan aUxao5CLqK_yNCfSCI5cA2lmvJ8C1Bgty3HC0G4E3aZIrZVDwjZ6XxPTD9uLfJ8BBZWs6tT9zueh kymaCyb32oKM2UjWWbmUvx56hWqBqrzDhZAYgIASyk1flxynf57wfTp4Ak6JDVfGPNDKXD5jyzRH t9lfHd65NErBY2oTJESz8fYDpy8n2P4Oqfs3kuHvzyg8yJzTC4ecXhbHvh7W0mAvk0NuOWuKxgb4 hjRXxq3f7jSmkO77mCNllbK73r4RaJ98VV.NUGXcSvLwe4E4L790kEN9TKOm6d9GKNTAaipzQMYo 5JCUwlYU5_JEDRK4x47qgFmzg1gi8xaxudPGVA4pQOU_wEzcz0PO5JurlhSrW3ixx6XBC7pfDhB6 IlDp1jxs.Ybp_zqQB8Gi2.caTC_Gu.W_.PKQZdWJ1wIzCTVPGJx4rovpTNCGm6gQJ65OLRgejzGc w.vcIVSkp453iklEoNrn1pJtvp13D9hlv_Xh1aSveFUkyUMMX6YGVjzflnDmXSPSguy6CouFVfMp m6RMxeWhSQuefxbpemyfvpegfGdw_7.FgfkQPDs_ffjrJ0bQobODn2l34MBa_6.5vp4xTiPLC5Nq 2qhLPBPz69Igg75lqLRnltm3IYiNAQUcVA59YwCnqhvoII6Gemc6Xcr2C5FnqX_nM4_54mv3izsv 6c5QAuPTirDYx408veFWHrB5mHT2m.kg9ajZ3S_D_ctciHRvU43OSS.iMD.4wrHPi99zQ228w3Dw 1ji80EIL6A4iJN_JOPdANW4C7V7opQfUZH4O9oBlUeQEsjQqF.7Wsq2mIPI2mq4n7zXQ48TR_rY_ QYUPt5rSDh6ZZtDC7hH6KRzjrnYOLFe3Y7wrQVo7tfulfLSBmZfIDgAudTEiJbQ1b6qn5hZpjCba NidM6ofPgvxK.dfcj3epvO.tQtY3y33ySEivxHQcYlWXqTJg08RIyyy56oJKtYgsREZYjEQ-- Received: from sonic.gate.mail.ne1.yahoo.com by sonic306.consmr.mail.ne1.yahoo.com with HTTP; Thu, 24 Oct 2019 21:45:04 +0000 Received: by smtp420.mail.ne1.yahoo.com (Oath Hermes SMTP Server) with ESMTPA ID eaf5054cc9d2e89fbdd41d6e12cec122; Thu, 24 Oct 2019 21:45:01 +0000 (UTC) From: Casey Schaufler To: netdev@vger.kernel.org Subject: [PATCH v10 23/25] NET: Add SO_PEERCONTEXT for multiple LSMs Date: Thu, 24 Oct 2019 14:45:00 -0700 Message-Id: <20191024214500.7356-3-casey@schaufler-ca.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191024214500.7356-1-casey@schaufler-ca.com> References: <20191024214500.7356-1-casey@schaufler-ca.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The getsockopt SO_PEERSEC provides the LSM based security information for a single module, but for reasons of backward compatibility cannot include the information for multiple modules. A new option SO_PEERCONTEXT is added to report the security "context" of multiple modules using a "compound" format lsm1\0value\0lsm2\0value\0 This is expected to be used by system services, including dbus-daemon. The exact format of a compound context has been the subject of considerable debate. This format was suggested by Simon McVittie, a dbus maintainer with a significant stake in the format being usable. Signed-off-by: Casey Schaufler --- arch/alpha/include/uapi/asm/socket.h | 1 + arch/mips/include/uapi/asm/socket.h | 1 + arch/parisc/include/uapi/asm/socket.h | 1 + arch/sparc/include/uapi/asm/socket.h | 1 + include/linux/lsm_hooks.h | 9 +- include/linux/security.h | 11 ++- include/uapi/asm-generic/socket.h | 1 + kernel/audit.c | 4 +- net/core/sock.c | 7 +- net/netlabel/netlabel_unlabeled.c | 9 +- net/netlabel/netlabel_user.c | 2 +- security/apparmor/lsm.c | 20 ++--- security/security.c | 118 +++++++++++++++++++++++--- security/selinux/hooks.c | 20 ++--- security/smack/smack_lsm.c | 31 +++---- 15 files changed, 164 insertions(+), 72 deletions(-) diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 976e89b116e5..019e5fa8bcda 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -121,6 +121,7 @@ #define SO_RCVTIMEO_NEW 66 #define SO_SNDTIMEO_NEW 67 +#define SO_PEERCONTEXT 68 #if !defined(__KERNEL__) diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index d41765cfbc6e..df8d984d76ed 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -132,6 +132,7 @@ #define SO_RCVTIMEO_NEW 66 #define SO_SNDTIMEO_NEW 67 +#define SO_PEERCONTEXT 68 #if !defined(__KERNEL__) diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 66c5dd245ac7..9ae358309f46 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -113,6 +113,7 @@ #define SO_RCVTIMEO_NEW 0x4040 #define SO_SNDTIMEO_NEW 0x4041 +#define SO_PEERCONTEXT 0x4042 #if !defined(__KERNEL__) diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 9265a9eece15..e8a53ef65210 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -114,6 +114,7 @@ #define SO_RCVTIMEO_NEW 0x0044 #define SO_SNDTIMEO_NEW 0x0045 +#define SO_PEERCONTEXT 0x0046 #if !defined(__KERNEL__) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 706fd6d3d46e..0187943835aa 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -864,8 +864,8 @@ * SO_GETPEERSEC. For tcp sockets this can be meaningful if the * socket is associated with an ipsec SA. * @sock is the local socket. - * @optval userspace memory where the security state is to be copied. - * @optlen userspace int where the module should copy the actual length + * @optval memory where the security state is to be copied. + * @optlen int where the module should copy the actual length * of the security state. * @len as input is the maximum length to copy to userspace provided * by the caller. @@ -1697,9 +1697,8 @@ union security_list_options { int (*socket_setsockopt)(struct socket *sock, int level, int optname); int (*socket_shutdown)(struct socket *sock, int how); int (*socket_sock_rcv_skb)(struct sock *sk, struct sk_buff *skb); - int (*socket_getpeersec_stream)(struct socket *sock, - char __user *optval, - int __user *optlen, unsigned len); + int (*socket_getpeersec_stream)(struct socket *sock, char **optval, + int *optlen, unsigned len); int (*socket_getpeersec_dgram)(struct socket *sock, struct sk_buff *skb, u32 *secid); int (*sk_alloc_security)(struct sock *sk, int family, gfp_t priority); diff --git a/include/linux/security.h b/include/linux/security.h index 35b03b57bce2..636de93d1a5f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -129,7 +129,7 @@ struct lsmblob { #define LSMBLOB_NEEDED -2 /* Slot requested on initialization */ #define LSMBLOB_NOT_NEEDED -3 /* Slot not requested */ #define LSMBLOB_DISPLAY -4 /* Use the "display" slot */ -#define LSMBLOB_FIRST -5 /* Use the default "display" slot */ +#define LSMBLOB_COMPOUND -5 /* A compound "display" */ /** * lsmblob_init - initialize an lsmblob structure. @@ -1316,7 +1316,8 @@ int security_socket_setsockopt(struct socket *sock, int level, int optname); int security_socket_shutdown(struct socket *sock, int how); int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb); int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len); + int __user *optlen, unsigned len, + int display); int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, struct lsmblob *blob); int security_sk_alloc(struct sock *sk, int family, gfp_t priority); @@ -1450,8 +1451,10 @@ static inline int security_sock_rcv_skb(struct sock *sk, return 0; } -static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) +static inline int security_socket_getpeersec_stream(struct socket *sock, + char __user *optval, + int __user *optlen, + unsigned len, int display) { return -ENOPROTOOPT; } diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 8c1391c89171..b38d080c2802 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -116,6 +116,7 @@ #define SO_RCVTIMEO_NEW 66 #define SO_SNDTIMEO_NEW 67 +#define SO_PEERCONTEXT 68 #if !defined(__KERNEL__) diff --git a/kernel/audit.c b/kernel/audit.c index 45ea36f1f1c5..24a3e8423e84 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1437,7 +1437,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) len = 0; if (lsmblob_is_set(&audit_sig_lsm)) { err = security_secid_to_secctx(&audit_sig_lsm, - &context, LSMBLOB_FIRST); + &context, 0); if (err) return err; } @@ -2112,7 +2112,7 @@ int audit_log_task_context(struct audit_buffer *ab) if (!lsmblob_is_set(&blob)) return 0; - error = security_secid_to_secctx(&blob, &context, LSMBLOB_FIRST); + error = security_secid_to_secctx(&blob, &context, 0); if (error) { if (error != -EINVAL) goto error_path; diff --git a/net/core/sock.c b/net/core/sock.c index 782343bb925b..b0955a34167c 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1412,7 +1412,12 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_PEERSEC: - return security_socket_getpeersec_stream(sock, optval, optlen, len); + return security_socket_getpeersec_stream(sock, optval, optlen, + len, LSMBLOB_DISPLAY); + + case SO_PEERCONTEXT: + return security_socket_getpeersec_stream(sock, optval, optlen, + len, LSMBLOB_COMPOUND); case SO_MARK: v.val = sk->sk_mark; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index cf34c163af20..e2a134286eb7 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -450,8 +450,7 @@ int netlbl_unlhsh_add(struct net *net, unlhsh_add_return: rcu_read_unlock(); if (audit_buf != NULL) { - if (security_secid_to_secctx(lsmblob, &context, - LSMBLOB_FIRST) == 0) { + if (security_secid_to_secctx(lsmblob, &context, 0) == 0) { audit_log_format(audit_buf, " sec_obj=%s", context.context); security_release_secctx(&context); @@ -507,7 +506,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, dev_put(dev); if (entry != NULL && security_secid_to_secctx(&entry->lsmblob, &context, - LSMBLOB_FIRST) == 0) { + 0) == 0) { audit_log_format(audit_buf, " sec_obj=%s", context.context); security_release_secctx(&context); @@ -568,7 +567,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, dev_put(dev); if (entry != NULL && security_secid_to_secctx(&entry->lsmblob, &context, - LSMBLOB_FIRST) == 0) { + 0) == 0) { audit_log_format(audit_buf, " sec_obj=%s", context.context); security_release_secctx(&context); @@ -1139,7 +1138,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd, lsmb = (struct lsmblob *)&addr6->lsmblob; } - ret_val = security_secid_to_secctx(lsmb, &context, LSMBLOB_FIRST); + ret_val = security_secid_to_secctx(lsmb, &context, 0); if (ret_val != 0) goto list_cb_failure; ret_val = nla_put(cb_arg->skb, diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 193200955dbd..b39a009974a8 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c @@ -114,7 +114,7 @@ struct audit_buffer *netlbl_audit_start_common(int type, lsmblob_init(&blob, audit_info->secid); if (audit_info->secid != 0 && - security_secid_to_secctx(&blob, &context, LSMBLOB_FIRST) == 0) { + security_secid_to_secctx(&blob, &context, 0) == 0) { audit_log_format(audit_buf, " subj=%s", context.context); security_release_secctx(&context); } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index c4835d05c5ea..ef6035a4fa7e 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1073,10 +1073,8 @@ static struct aa_label *sk_peer_label(struct sock *sk) * * Note: for tcp only valid if using ipsec or cipso on lan */ -static int apparmor_socket_getpeersec_stream(struct socket *sock, - char __user *optval, - int __user *optlen, - unsigned int len) +static int apparmor_socket_getpeersec_stream(struct socket *sock, char **optval, + int *optlen, unsigned int len) { char *name; int slen, error = 0; @@ -1096,17 +1094,11 @@ static int apparmor_socket_getpeersec_stream(struct socket *sock, if (slen < 0) { error = -ENOMEM; } else { - if (slen > len) { + if (slen > len) error = -ERANGE; - } else if (copy_to_user(optval, name, slen)) { - error = -EFAULT; - goto out; - } - if (put_user(slen, optlen)) - error = -EFAULT; -out: - kfree(name); - + else + *optval = name; + *optlen = slen; } done: diff --git a/security/security.c b/security/security.c index 4e878907f12b..91626536343d 100644 --- a/security/security.c +++ b/security/security.c @@ -691,6 +691,42 @@ static void __init lsm_early_task(struct task_struct *task) panic("%s: Early task alloc failed.\n", __func__); } +/** + * append_ctx - append a lsm/context pair to a compound context + * @ctx: the existing compound context + * @ctxlen: size of the old context, including terminating nul byte + * @lsm: new lsm name, nul terminated + * @new: new context, possibly nul terminated + * @newlen: maximum size of @new + * + * replace @ctx with a new compound context, appending @newlsm and @new + * to @ctx. On exit the new data replaces the old, which is freed. + * @ctxlen is set to the new size, which includes a trailing nul byte. + * + * Returns 0 on success, -ENOMEM if no memory is available. + */ +static int append_ctx(char **ctx, int *ctxlen, const char *lsm, char *new, + int newlen) +{ + char *final; + int llen; + + llen = strlen(lsm) + 1; + newlen = strnlen(new, newlen) + 1; + + final = kzalloc(*ctxlen + llen + newlen, GFP_KERNEL); + if (final == NULL) + return -ENOMEM; + if (*ctxlen) + memcpy(final, *ctx, *ctxlen); + memcpy(final + *ctxlen, lsm, llen); + memcpy(final + *ctxlen + llen, new, newlen); + kfree(*ctx); + *ctx = final; + *ctxlen = *ctxlen + llen + newlen; + return 0; +} + /* * Hook list operation macros. * @@ -2105,8 +2141,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value, hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; - if (lsm == NULL && *display != LSMBLOB_INVALID && - *display != hp->lsmid->slot) + if (lsm == NULL && display != NULL && + *display != LSMBLOB_INVALID && *display != hp->lsmid->slot) continue; return hp->hook.setprocattr(name, value, size); } @@ -2137,7 +2173,7 @@ int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp, */ if (display == LSMBLOB_DISPLAY) display = lsm_task_display(current); - else if (display == LSMBLOB_FIRST) + else if (display == 0) display = LSMBLOB_INVALID; else if (display < 0) { WARN_ONCE(true, @@ -2187,6 +2223,15 @@ void security_release_secctx(struct lsmcontext *cp) struct security_hook_list *hp; bool found = false; + if (cp->slot == LSMBLOB_INVALID) + return; + + if (cp->slot == LSMBLOB_COMPOUND) { + kfree(cp->context); + found = true; + goto clear_out; + } + hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list) if (cp->slot == hp->lsmid->slot) { hp->hook.release_secctx(cp->context, cp->len); @@ -2194,6 +2239,7 @@ void security_release_secctx(struct lsmcontext *cp) break; } +clear_out: memset(cp, 0, sizeof(*cp)); if (!found) @@ -2330,17 +2376,67 @@ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) EXPORT_SYMBOL(security_sock_rcv_skb); int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, - int __user *optlen, unsigned len) + int __user *optlen, unsigned len, + int display) { - int display = lsm_task_display(current); struct security_hook_list *hp; + char *final = NULL; + char *cp; + int rc = 0; + unsigned finallen = 0; + unsigned clen = 0; - hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream, - list) - if (display == LSMBLOB_INVALID || display == hp->lsmid->slot) - return hp->hook.socket_getpeersec_stream(sock, optval, - optlen, len); - return -ENOPROTOOPT; + switch (display) { + case LSMBLOB_DISPLAY: + rc = -ENOPROTOOPT; + display = lsm_task_display(current); + hlist_for_each_entry(hp, + &security_hook_heads.socket_getpeersec_stream, + list) + if (display == LSMBLOB_INVALID || + display == hp->lsmid->slot) { + rc = hp->hook.socket_getpeersec_stream(sock, + &final, &finallen, len); + break; + } + break; + case LSMBLOB_COMPOUND: + /* + * A compound context, in the form [lsm\0value\0]... + */ + hlist_for_each_entry(hp, + &security_hook_heads.socket_getpeersec_stream, + list) { + rc = hp->hook.socket_getpeersec_stream(sock, &cp, &clen, + len); + if (rc == -EINVAL || rc == -ENOPROTOOPT) { + rc = 0; + continue; + } + if (rc) { + kfree(final); + return rc; + } + rc = append_ctx(&final, &finallen, hp->lsmid->lsm, + cp, clen); + } + if (final == NULL) + return -EINVAL; + break; + default: + return -EINVAL; + } + + if (finallen > len) + rc = -ERANGE; + else if (copy_to_user(optval, final, finallen)) + rc = -EFAULT; + + if (put_user(finallen, optlen)) + rc = -EFAULT; + + kfree(final); + return rc; } int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b07f9b8c7670..5b46c1ba614b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4903,10 +4903,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) return err; } -static int selinux_socket_getpeersec_stream(struct socket *sock, - char __user *optval, - int __user *optlen, - unsigned int len) +static int selinux_socket_getpeersec_stream(struct socket *sock, char **optval, + int *optlen, unsigned int len) { int err = 0; char *scontext; @@ -4926,18 +4924,12 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, if (err) return err; - if (scontext_len > len) { + if (scontext_len > len) err = -ERANGE; - goto out_len; - } - - if (copy_to_user(optval, scontext, scontext_len)) - err = -EFAULT; + else + *optval = scontext; -out_len: - if (put_user(scontext_len, optlen)) - err = -EFAULT; - kfree(scontext); + *optlen = scontext_len; return err; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8b2730e02044..507f16adbc41 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3943,28 +3943,29 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) * * returns zero on success, an error code otherwise */ -static int smack_socket_getpeersec_stream(struct socket *sock, - char __user *optval, - int __user *optlen, unsigned len) +static int smack_socket_getpeersec_stream(struct socket *sock, char **optval, + int *optlen, unsigned len) { - struct socket_smack *ssp; - char *rcp = ""; - int slen = 1; + struct socket_smack *ssp = smack_sock(sock->sk); + char *rcp; + int slen; int rc = 0; - ssp = smack_sock(sock->sk); - if (ssp->smk_packet != NULL) { - rcp = ssp->smk_packet->smk_known; - slen = strlen(rcp) + 1; + if (ssp->smk_packet == NULL) { + *optlen = 0; + return -EINVAL; } + rcp = ssp->smk_packet->smk_known; + slen = strlen(rcp) + 1; if (slen > len) rc = -ERANGE; - else if (copy_to_user(optval, rcp, slen) != 0) - rc = -EFAULT; - - if (put_user(slen, optlen) != 0) - rc = -EFAULT; + else { + *optval = kstrdup(rcp, GFP_KERNEL); + if (*optval == NULL) + rc = -ENOMEM; + } + *optlen = slen; return rc; }