From patchwork Fri Dec 22 13:05:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Ricardo Leitner X-Patchwork-Id: 10140533 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 B969660594 for ; Tue, 2 Jan 2018 13:27:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADF14203B9 for ; Tue, 2 Jan 2018 13:27:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A246A2899B; Tue, 2 Jan 2018 13:27:55 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from UCOL19PA11.eemsg.mail.mil (ucol19pa11.eemsg.mail.mil [214.24.24.84]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D79A9203B9 for ; Tue, 2 Jan 2018 13:27:53 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.45,497,1508803200"; d="scan'208";a="412067746" Received: from emsm-gh1-uea11.ncsc.mil ([214.29.60.3]) by UCOL19PA11.eemsg.mail.mil with ESMTP; 02 Jan 2018 13:26:24 +0000 X-IronPort-AV: E=Sophos;i="5.45,497,1508803200"; d="scan'208";a="7610808" IronPort-PHdr: =?us-ascii?q?9a23=3ADvpKUhdjCQ5+HSs98VDQMooHlGMj4u6mDksu8pMi?= =?us-ascii?q?zoh2WeGdxcmyYhyN2/xhgRfzUJnB7Loc0qyK6/mmATRIyK3CmUhKSIZLWR4BhJ?= =?us-ascii?q?detC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBxrwKxd+?= =?us-ascii?q?KPjrFY7OlcS30P2594HObwlSizexfa5+IA+qoQnNq8IbnZZsJqEtxxXTv3BGYf?= =?us-ascii?q?5WxWRmJVKSmxbz+MK994N9/ipTpvws6ddOXb31cKokQ7NYCi8mM30u683wqRbD?= =?us-ascii?q?VwqP6WACXWgQjxFFHhLK7BD+Xpf2ryv6qu9w0zSUMMHqUbw5Xymp4KlxSB/slS?= =?us-ascii?q?wJKTg3/m/KgcB0la5XvQ6tqxl5zoXJYo+aKeB+c7vdc90ES2RPXcFfWC5PAo2h?= =?us-ascii?q?d4sCDfcNMOhGoInmvFYCsQeyCBOwCO711jNEmnn71rA63eQ7FgHG2RQtEdUUv3?= =?us-ascii?q?TOsNr6KqMSUeeox6fUzDXMc+lZ2S3g54jPbxsvp++DXbNsccrX10YvDR7Og1KV?= =?us-ascii?q?qYP/JTOayvoCs2yc7+Z6UeKglW8nqx13ojex3MchkYbJhocPxVDF8SV12po6Jd?= =?us-ascii?q?q9SENiZ9OvDZVetyafN4RsQ8MiRXlluD4gxb0bvZ63ZS0KyJMgxx7FdfOLaZSH?= =?us-ascii?q?4hXmVOuXPDx2h2pldaqiixu9/kWs0O3xWtSu3FpUoSdJjMPAum0V2xDN9sSLVu?= =?us-ascii?q?Zx80K81TqR1A3e5eRJIU4omabGJZMsx6Q/m5UdsUnHGyL7mFv5g7GKekgh5uel?= =?us-ascii?q?6+rnYrvjq5+SKYB5hA7zP6E1lcyxD+k1PQ4DVHWB9+umzr3s50j5Ta1Pjv0xj6?= =?us-ascii?q?bWrojXJd8epq6lGw9V1Zsj6wqnAzemztsYmX4HIUpZeB2dlYjpOkzOIOviAfej?= =?us-ascii?q?g1WjjDdrx/fcMr3nHprNNWTMnK3kfbZ8705Q0AszzdZB6JJIErwNPf3+V0DruN?= =?us-ascii?q?HYExM1KRK4zun5BNlny48SQWePDbWYMKPWv1+I/OUvI+yUaY8Opjn9L/kl5/jz?= =?us-ascii?q?jX42gFMSZq6p3YYRaH+kAPtmOF6UYWbsg9gdEWcKuRAyTOrxiFKYSzJTaHGyX7?= =?us-ascii?q?wk6jEhFI2mFZvDRpyqgLGZ3ie7GZtWaXpaClCMC3jocZ6JW/ULaCKUJ89uiCcE?= =?us-ascii?q?VaS/RI87zhGirgj6y6BoLuDM4C0XqYrj1MRp5+3UjRwy9z50AN6B3GGOVGF0mW?= =?us-ascii?q?UIRz4o3K1kr0x9zkqD0KdjjPxFE9xT++5JXh09NZ7GwOxwE8ryVR7ZfteVVFam?= =?us-ascii?q?Rc2rASkvQd0q3dAOZUd9G8mljh3Y3iqlHaEamKKRCJwz6KLc0GD7J9xhxHbeyK?= =?us-ascii?q?khk14mT9NSOm2hgK5/8RXcCJDNk0WYjKulb7oT3DTK9GuZymqOpk5YWhZqUarZ?= =?us-ascii?q?RXAfelfWrdPh60zfU7+hE64nPxBdxs6FL6tFdsfmjU5aRPv5PtTRfX6xkX+qBR?= =?us-ascii?q?mU3rOMcJbqe2IF0SXcDkgEjx4c/XKYOgg7GCihv3jeDTx1GFLoe0Pj7+9+qHah?= =?us-ascii?q?QU81ywGFdEph1rWv9h4Sn/ycROsZ3qgYtyc5tzV0AFG90srWCtuBoApher5RYd?= =?us-ascii?q?Y54Fte1GLZsRZxPpq6IKB4hV4echp3sF302xVxFIpAjdAgrGk2wwpqNaKYzFRB?= =?us-ascii?q?eiuW3JDxPr3XL3f9/Aq0Zq7YxF7RzdGW+r0V5/QgsVXjuwOpGVQ+/HV7ydVV1G?= =?us-ascii?q?Gc5prSBgoITZ3xSlo39wR9p7zCbCk9/Znb1XtwPqm1qT/PwNcpBPMkyhq5ZNde?= =?us-ascii?q?PriEGBX1E80ACMikMPYqlESxbhIYIOBS87Y5P8C8ePuF366rIf1tnDG8gmRE54?= =?us-ascii?q?B9z1iA9y1mSu7Hx5wF2e2X3hObVzfgi1esqtr4lp1eZTETAGW/0zPpC5RNaa13?= =?us-ascii?q?Z4oLDn2uI8KvzNVkm5HtQ2JY9EKkB14exMCmYx6SYELm3Q1M1UUXpmeqmTCkwD?= =?us-ascii?q?x1jT4pqLaf3C3UzOj4choIJHJLTnF4jVjwOYi0k8waXE+wYggziRSq+F33x6de?= =?us-ascii?q?pKVwNWXTR1lHfzTuJWF4TqSwrqaCY9JI6J4wqiVXXv68YVeBSr7huBYayCXjH2?= =?us-ascii?q?xQxTA+bT6qvI/1nxpkh2KBNHxztmbWedlsxRfD49zRXfBQ0SACRClklzbXHEO8?= =?us-ascii?q?MsK3/dqKjZfMqf2+V2e7Wp1UaynrwpuKtDGn6m1yHR2/g/ezl8X5EQg7zSD7y9?= =?us-ascii?q?5qVT/SoBngYonr0KK6Me18c0lsBV/87dB1Gpt5kocqg5EQw3cajI2P/XUbiWfz?= =?us-ascii?q?Lclb2aXmYXoJRD4L2MLV7BH+2EJ9KnKJxoT5VmiSw8Z6fNm6emIW2iQ8789WE6?= =?us-ascii?q?eY9rpEkjVpolCgtwLefeB9nisByfsp8HMameYJuA4pziqDGLAdAU5YPCL3mhST?= =?us-ascii?q?8tCxsL5XaHyocbiq20p0hcqhA62aogFARHb5fY8vHSxu4cV5K1LBy37z5Z/ieN?= =?us-ascii?q?nLa9IcqAGUnw3Hj+hPJ5I7juAKijZ/OWLhoX0lzPY2jQR00pGnuIiINX1t87i/?= =?us-ascii?q?Ah5EKDL1fdge+iz2jalAhMaWxJqjHo5mGjUWRpvnUeynEDwVtfT9OAaBDicwqn?= =?us-ascii?q?GFFrrDBQWf8ltpr2rTE5C3MHGaPGcZzdN/SxSGOkxfhh0bXDUgkp4/CA+q2NTr?= =?us-ascii?q?cF1l6TAJ+l74thxMx/pwNxblT2ffoBylZSs1SJiDLBta9w9C6F3TMcCE6eJzBS?= =?us-ascii?q?5Y9IW7rAORMmybexhIDWYRV0yHB1HjOqeh6MLF8+ifCOq+IeXBYamSqexeUPeI?= =?us-ascii?q?wIyg3pFg/zmSKsWFJmNiAOEj2kpfQXB5HNzUmzsVRCwRiyLNaMubqQyy+iJps8?= =?us-ascii?q?+/9+7rVxj35YuVDLtSM8tg9AyqgauZMO6Qnil5Iy5C1pwQ3X/I1KQf3FkKhiF0?= =?us-ascii?q?bTWsH64MtSvXQ6LUna9WDwUWZDlvO8tN9a482RNNOcHDgNPvyrF4luI1C0tCVV?= =?us-ascii?q?H5lMGpf9IFLHymNFzdAkaLKLOGJSbQzs7tfay8TKdcjOJOtx2/oTybCVPsPiyf?= =?us-ascii?q?lzn1UBCiKedMjDuBMxxGoIGwaRhtCWn5TNL9dh27Pt53jTsszr0ymnzKNHQTMT?= =?us-ascii?q?xmf0NKtL2Q4jtSgu9jFGxZ8nplMe6Elj6C4ObDLZoWtfprAj9ol+JB+ng60KVa?= =?us-ascii?q?4z1eSPxuhiTSqt9uo1e7kuiA0TdoTBpPqixWhIKQp0ljN7/W9oVbWXbD+hIB92?= =?us-ascii?q?KQCw4Fp9F9EN3gp7hQysTTlKL0MDpC9dPU/c8YB8fKM8KKK2AuPgTzGD7TFgcF?= =?us-ascii?q?SiSrNW7HjUxHjP6S7mGVroQ9qpX0g5UOS7BbVFszFv4BF0tqAscNIJZtUTMii7?= =?us-ascii?q?Kbi9QI5XWmphnLWMpapozHVu6VAfj3MjmZgqNLZwUWzr7jKoQTLpP020pnalZg?= =?us-ascii?q?nYTKH1HfXddCoyF7aQ80ukpN+mBkTmIvw0Lldh+t4HgLGP6omR42jxFyYf4q9D?= =?us-ascii?q?bt/Vg3IEHFpDE3kEYvmtXomiyecDn0LKisR45WEDb0u1I3MpzlXwZ/dReyklB8?= =?us-ascii?q?NDfYW7JRiKNtdWZ1hwDGvZtCAv1cTapfYB8M3/6XYe4o0Vddqim9w09I+/fFA4?= =?us-ascii?q?N4lAQ2aZ6ss25A2wV7Yd4vO6PQP7RGwUJKhq2Svi+lzfs+wA4EJ0kQ92OSdjYI?= =?us-ascii?q?uFYWObgmPSao+PJj6RCakTtZZGcMT+Yqou5t9k4lJuuP1Tzg079eJUCqLOGQNb?= =?us-ascii?q?mZu3LHlc+GWVM/yF8Hl1Rf/bh3zccic1CYV0Yxw7uNDx4JL9bNKRlJb8pO83je?= =?us-ascii?q?ZSKOseLXwZ1rOYW8F+foQPSBtKYSn0KoBgEpH54D7s4ZBJmjzFnYLdv7LL4C0R?= =?us-ascii?q?gt/xrkJFGEDPRPZRKKnywKrN24zJ9ywYZSPCodAXlnPSWx+LnXuhcggOCfU9cu?= =?us-ascii?q?fncaQowEO2orV8Kmni5ZuHJADCWq3u8C1giN8SX8piXRDTn7adpvfvGUag1wCN?= =?us-ascii?q?uu4zUw77C2iULL8pXZP2z6KdViutrI6eMGp5aGC+hZQqR8s0bcgYZXXGamU2jR?= =?us-ascii?q?Ht6pP5LwcZUjbcToCnamVVyykyg6T8PwPNmxMKeHmQToRIZSsImc2jAsL9SwGS?= =?us-ascii?q?ofGxhqoeEP/ax8ZRAZb5o9fxHoqxw0N7ajLweAztWuX2GtJCNNQPZBy+W3fKZY?= =?us-ascii?q?wDcybuCk0nsgVYs1z/O38EIXQ5EKlB7ez+65Z4ZCSSjzBmBdewLXqCojkWhhN/?= =?us-ascii?q?o9wuc4wBPMqlkSKymFevFzZmFYuN8xHk+dIXJzCmUkXVCclpbD7hSq378M4ytX?= =?us-ascii?q?h8xU3vFdsHjiop/fZyqhV7CpqZrPryUtdsQpo6p1MYznI8uJqoneniDBQ5bMsg?= =?us-ascii?q?2JSim6F+BVmtJIOiJXXOFImX05OcwBoYdB81A+Vt05J7NUE6QsuqqqZiB6DSEM?= =?us-ascii?q?yS8ZVoWA3DMGgue91LvalguQcJo4PxwetZVOmN0dXDBqYikGvq+sS53Wl3OYSm?= =?us-ascii?q?gMOAoS4x5A6x4Alo9xe+Dl4ZDHTJxXxj5Xvf17TDXEGoNv91vhRWGcmUL4R+m5?= =?us-ascii?q?k+y1wQJSy+rh0twBVx5lCkhS2fpWlkouKLF4MKQRsJTFsjmUekP+u2Lt1fapJE?= =?us-ascii?q?JLxc3SaVL4EJLPtXDgXS0E5X0UWYhPxWnHFZQVlwp2crwrpVtLIICidEbz/Dkk?= =?us-ascii?q?x4NuH7mjS8+k20wlrXEdRyexEtpBDe5mvEjQWD1/bJChsI/lNIlKQm9M5J2drE?= =?us-ascii?q?9Un193My6kz5pQMcJN7yUNXDhOoDWdoMC9RNdF2cBoE58GOs1/tGvlGKNYJJiR?= =?us-ascii?q?pGU7uqDoyn/c4D08rEu2xDCoFKOiSeJW4XEeEB0zJ2uCskkvE/cs8mDK/1DNqF?= =?us-ascii?q?905f1UBrySgkhqvTlyAIhOBi5X2nChMVtzVmNKs+JAKKTaa8ZcWeU9ZQezOxwi?= =?us-ascii?q?Ev4rx06J/UZqknrifiN9qBBa9D7HXwkoSyYan63hmTsApcG7ITUaUY5HbS09by?= =?us-ascii?q?fZLAKWgTxXswtCZEFrQZ8ZBs1I9K0c3YtR4sXNU12sKT0fUBxkKA04zeJVlVRf?= =?us-ascii?q?v0WAZSDdEQ2oeO7UvR15YcidsMykIOn38Qpcloznt+U4+LkZSH29hQ2hW9beoJ?= =?us-ascii?q?HgtteSrEuBaL/4M/GgYX/GVDXMlw6/iqokD5bQ4yjeKw5bK55kyXU6f5TuFWnL?= =?us-ascii?q?MglYKK4BIUpUS7x6Y81cou9Gf89kZLoJ+ah1CxKfXRPvBJago+RaLlvIXjTeKD?= =?us-ascii?q?iB8vajro3N67zdVfLgadaIx3rdRKJ3JJh64yHhG7j2yY9e5lb22vB1+0NmU1jJ?= =?us-ascii?q?LT6Oo8n6KwMW4MmialHisYc3HTPXB5dwlGTixl1ae8oQWS2q/4wSyIlF53boVe?= =?us-ascii?q?J4zk/zvfVX97Z+7Yk3565myduoJajIM/tXqklnDQaIBgVx6poiGnB/SH5Lbu8X?= =?us-ascii?q?NvjRYbwTjdrypODvC6wX9BqV9vRbadTdPUHBndK/CjWGRhxahwoBrCMaLg+A1/?= =?us-ascii?q?6Eh6B0SNyqpe7i2k435Fi+NBEGxqh35YiY4qqIuPPXbxzJwLgGQKfqQM3zrq4r?= =?us-ascii?q?u0yP+/Ipj6IOdXZzYw28F+gRTMgdyXn8zaoy1yIjD9vDH678+P5ET385kS/gm5?= =?us-ascii?q?F5H1USBPwUGKGG8plAkWgjmuzWLNsWfrpFmmaVGh6uCqUCxmKz6yuLPGllhQnD?= =?us-ascii?q?0xPxQWO291L2qDF3QCvSwNf5k0pVULa3CV1UXyW3JU9yqCmPMxbwtNrrpaQ161?= =?us-ascii?q?k7MmrgtN+WlWuhPrZXE9f+JNyaLyk0vkgYjIYtRty1xIAUBca9IMoL8H5gdPfe?= =?us-ascii?q?7HmrkyBZqaddm4Xe+t2V+unQHXS4iq2arLONxCxXyncmplw/79GgOevI59KUX/?= =?us-ascii?q?Sp2WERTz18uwvaRRK1rKLUr0wMM0yRzEjLgJAKPs1e3XQg0kHm/+0jTdIo+QVQ?= =?us-ascii?q?CInPevQCpSrpNzvs21afZNA3WTeC3DtLBF71FkN4GKck0mLqoM3JjWvQ+0EvRo?= =?us-ascii?q?RodkzmhAZ4AJ8kJk8281gY3DYDHhYRZhyBC7GoH0vlJ5MeVUcfcRSHwKS6eqAv?= =?us-ascii?q?0EJow7Ov/+HSYvZ+B6oMKvZdlhSBnEVfGp8NraIeR69zdEFH+67KvAjiDJLnUO?= =?us-ascii?q?L8mXo3L/21TdhQ8doFuHs6/ga/Wx2g5I9b77kBlJCHaq5EYJbLvMBm7Edr/CUP?= =?us-ascii?q?eTJJgBh+iRO5TO8dqfv74tfBrJqn9uauVagqR+UN9Bg4HWd+gIXqgFAlv97X0/?= =?us-ascii?q?1QSorPiYTw6ApNOWKFuJ7G0xlgLuoDM42rc6x693oZOygeJ2kDPd6Xa/kg/SBt?= =?us-ascii?q?MC/c50FZAs8WY9MXItbNkxhOikL1QLFT6tbbGliABod8ac8o6Xb3yDcy8Zc7Se?= =?us-ascii?q?bv9ju2JZHZ71FQMPJOlyFsm8zYpOkV2/XeEi4X7meFaxJt2CON14GNC+rs/eWL?= =?us-ascii?q?0NzUUVIGETIxU4dZPjWC4harRuuylJXuSQOU8dT+gJcxeUOfXHCxm74FsqlUG+?= =?us-ascii?q?5alir7xiReFpzyh/+NvNqj9HBXtkZeHIhu4hPLHqRfPpNmORX3jcSrSU18CTH5?= =?us-ascii?q?eM7KbBYuv/CWxugU6eVkK0T+fZMbIg4Dy7/i63pVSQtuSLjsslmFXeIRYMZmR+?= =?us-ascii?q?7Fr3BU74JgMKwPPFmGqZz0rzdItko5AAs0Z78xtDBacFfBnBFNUabupLEAkhcc?= =?us-ascii?q?UcJ+uUJUGGKwJngx5zzcWKRRkameFf0V8jKITqAUVEVoKCx+SQuv2JpyY7upge?= =?us-ascii?q?xHsmRekyN/vvcq3TJmRB+ntCziva0N3ywv+K2iuDUHp3NFUv2Ukz3UBlVb0PQK?= =?us-ascii?q?kaAcBm7t6Vy4Z3kCYpX94L1jJcn77okh5HI/YRQ/cCEcW+SvFT3whbuSAoOTqN?= =?us-ascii?q?JcmAKNuMLWYL+xLSgTNqw9yRXnR3h8zgjRgg1l8G4KQjW89t8rOp+xOcE/xiqn?= =?us-ascii?q?AWLbbkoD4rtVsMvtsl4GVPc2aVJkwGh4zsiHRzECRM/RFGYxlAQkb3tLcI5b4x?= =?us-ascii?q?8AC6YomiqIvrVB/gwMZTfUE4el+orXncrT23kyV9RqxmXQpqKbgJMmyntllM1o?= =?us-ascii?q?7iSWonQda/TYU9NwAnj0zopQ0vLxZ/Oxsu0cU4tmzLOhUOMeMsm952S5xY9mWk?= =?us-ascii?q?i/xrQRB1C5KvMMxq/HUye5Tm2VQeqLfHaInzY4Kk79+wKlL1w2aMdPqk8yLPHC?= =?us-ascii?q?hppCmAH7VrN0XCqQr0fBzGM/KeMaax42uIC/dg0EVO4RfemcKvQwz/AlDVsMbm?= =?us-ascii?q?PJHTFoBOOstl6thod7MW164UrmeeTt7hzmMNyKFxkDFY7VsIV8+eS+Rm2bIn9g?= =?us-ascii?q?0BxyM1Vo9+fFCVs+qPVQc5CPktjMn957y/IKd+9xMS0hvd4egoZj6YiS0MeXfh?= =?us-ascii?q?Dd15LyJdDOoviEGP3S1EUqdXtcUroeew/14J86PtEhUb3JAbRZpQgcBbQ9QJE5?= =?us-ascii?q?Mmf+7r17LANycg7XY7S5mdfqpuONZpRKo3/W71QwLDrTuhEZzfy0VwN7ZYiwh3?= =?us-ascii?q?ruOJAwWi5Br9p1BxtkBoRPGMQAoBG8Dp6JnqG7l9+x+0Rnu+8FsarwFurG1NKn?= =?us-ascii?q?0IVtR5Ja/1CEPC7NBKl3hURoluaygvLH0pnrE8PieMgEWfN9QmHfb7/JAIS/Ji?= =?us-ascii?q?iJOsLmdE5M66Sc365hUhWNeCD5WLKLtDaqNPVh/Uo2y491cfHNzDMz9bHb2drz?= =?us-ascii?q?Z2Zdpiu5q36GKodfvxT2ArnFUhZVT+eV2Hp0Fq0QK43v/aEBNsJmiN6R/wV+8h?= =?us-ascii?q?xc38afZaustEnB3gR8b52fZE/o3TspHJIBPAyXL0Qhmynap27bDHAaKdKrbYFp?= =?us-ascii?q?gdCIHln26kJsg2AxdytEHWb1Qdq5J2cWwYS9aReM+QYNCMwMzMCtfkttk6SoQu?= =?us-ascii?q?RsPd1/mO6jrrkA2fJkKj3JSdISayTZNrR7Oj0XCujOuF4leDYLtrE0XsE+Yp3Y?= =?us-ascii?q?cxBPC1uJ1S6nlViK6kbzbdH5kf/RLQ=3D=3D?= X-IPAS-Result: =?us-ascii?q?A2ChBAAliEta/wHyM5BdGgEBAQEBAgEBAQEIAQEBAYJsJik?= =?us-ascii?q?DZnQnjx+OJIFaJ32WLRSBfg0YB4lOQBcBAQEBAQEBAQEBaiiCOCSCSAMDAQIXD?= =?us-ascii?q?RkBGx0BAgECCQEBBRAKKQgDAR0CEQEFARwHEgWIGwM5gTkBAxUBAqU6QI19GAU?= =?us-ascii?q?BHIMLBYNbChknDVmCFwEBCAIBHQIGEoN6gTZcgVaBaTWCQ4MOE0WBUwSGEwEEi?= =?us-ascii?q?kMMiUGOfz2IA4g0hH6MCId1jWKIdAYCCQgUJYEXIAE3gU8yGiOBBIF3CYI8Dxy?= =?us-ascii?q?Bf2CGNgElB4IcAQEB?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by emsm-gh1-uea11.NCSC.MIL with ESMTP; 02 Jan 2018 13:26:14 +0000 Received: from prometheus.infosec.tycho.ncsc.mil (prometheus [192.168.25.40]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id w02DQCxj013026; Tue, 2 Jan 2018 08:26:12 -0500 Received: from tarius.tycho.ncsc.mil (tarius.infosec.tycho.ncsc.mil [144.51.242.1]) by prometheus.infosec.tycho.ncsc.mil (8.15.2/8.15.2) with ESMTP id vBMD7Bt3136495 for ; Fri, 22 Dec 2017 08:07:11 -0500 Received: from goalie.tycho.ncsc.mil (goalie [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id vBMD7BvE025263; Fri, 22 Dec 2017 08:07:11 -0500 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1DEAwBZAj1aWyIbGNZdHAEBAQQBAQoBA?= =?us-ascii?q?YJsJikDZnQnjiqPEoFaJ32WKxSCAQoFGoUcAoROPxgBAQEBAQEBAQEGGhWGAgY?= =?us-ascii?q?aDRkBGx0BAwwGEAoxIQIRAQUBCBQHEoggAzmBOQEDFQECmGtAjX0YBQEcgwsFg?= =?us-ascii?q?18KGScNWYI1AQEBAQEBAQMBAQEBAQEaAgYSg3mBNlyBVoFpNYJDgw4TRYFTBIY?= =?us-ascii?q?TAQSKQgyJQY59PYgBiDCEfowHh3ONX4hzBgIJCBQkgRcfgggyGiOBA4F3CYI8D?= =?us-ascii?q?xyBf2CHNwElB4IcAQEB?= X-IPAS-Result: =?us-ascii?q?A1DEAwBZAj1aWyIbGNZdHAEBAQQBAQoBAYJsJikDZnQnjiq?= =?us-ascii?q?PEoFaJ32WKxSCAQoFGoUcAoROPxgBAQEBAQEBAQEGGhWGAgYaDRkBGx0BAwwGE?= =?us-ascii?q?AoxIQIRAQUBCBQHEoggAzmBOQEDFQECmGtAjX0YBQEcgwsFg18KGScNWYI1AQE?= =?us-ascii?q?BAQEBAQMBAQEBAQEaAgYSg3mBNlyBVoFpNYJDgw4TRYFTBIYTAQSKQgyJQY59P?= =?us-ascii?q?YgBiDCEfowHh3ONX4hzBgIJCBQkgRcfgggyGiOBA4F3CYI8DxyBf2CHNwElB4I?= =?us-ascii?q?cAQEB?= X-IronPort-AV: E=Sophos;i="5.45,441,1508817600"; d="scan'208";a="158126" Received: from emsm-gh1-uea11.ncsc.mil ([214.29.60.35]) by goalie.tycho.ncsc.mil with ESMTP; 22 Dec 2017 08:07:10 -0500 IronPort-PHdr: =?us-ascii?q?9a23=3Ag/073xyyDX+1TwbXCy+O+j09IxM/srCxBDY+r6Qd?= =?us-ascii?q?0uoXLPad9pjvdHbS+e9qxAeQG9mDsrQc06L/iOPJYSQ4+5GPsXQPItRndiQuro?= =?us-ascii?q?EopTEmG9OPEkbhLfTnPGQQFcVGU0J5rTngaRAGUMnxaEfPrXKs8DUcBgvwNRZv?= =?us-ascii?q?JuTyB4Xek9m72/q99pHPfglEniaxba9vJxiqsAvdsdUbj5F/Iagr0BvJpXVIe+?= =?us-ascii?q?VSxWx2IF+Yggjx6MSt8pN96ipco/0u+dJOXqX8ZKQ4UKdXDC86PGAv5c3krgfM?= =?us-ascii?q?QA2S7XYBSGoWkx5IAw/Y7BHmW5r6ryX3uvZh1CScIMb7S60/Vza/4KdxUBLmlS?= =?us-ascii?q?cJOSA3/m/UjcJ/jqxbrQm9qxBj2YPYfJuYOOZicq7bYNgURXBBXsFUVyFZBY2z?= =?us-ascii?q?dZEPAPYfMuZcqIn2ukcArRqiCga2HuPg1zhIjWLw06Ik0uQhDQfG0xI6H9kTt3?= =?us-ascii?q?nUqc/6NL0OXu+ryKnIyi/Pb/dI1jf89IjIdA4uoeuXULJ/dMre00gvFwffglqM?= =?us-ascii?q?rozlOiqY2+IQuGaV6OpgUPigi28hqwxpujig3Nosio3QioIQzVDE8j95z5gvKd?= =?us-ascii?q?KkT057ZNipG4ZTuSGCL4Z6XN4uTm5ytCokxbAKo4C3cSoQxJkpyBPTc+KLf5SU?= =?us-ascii?q?7h7+UeudPCl0iXFqdb+6iRa+7VWsx+P5W8au31tKoC5In9zMu38TyRPf9s2KRe?= =?us-ascii?q?d980ev1zaC0g7T5f9KLE07kKfUMJAhz7A/m5cVrE/NBDX5mF/sg6+Tbkgk+van?= =?us-ascii?q?6+DgYrj+u5+cL5R7hRzjPqkqgsywG/g0PhUUU2eF5+u80abj/ULjTLVPlPI2k6?= =?us-ascii?q?3ZvIrfJcQaoq61Gw5V0oA95BajFzqqzskUkHYdIF5bdx+LlZblNlPULP32Avqz?= =?us-ascii?q?m1Gsny1qx/DCML3hGJLNLn3bnbfkZ7l98VJTxxQ3zdBY/Z5UDq8OIPPvWk/3qt?= =?us-ascii?q?PYFAQ0MwOxw+n9CdV90pkSVn6IAq+cKK/Sq0OH5vozI+mQY48YoC39JOU+5/P1?= =?us-ascii?q?kX84mUMSfamu3ZcNbnC4Be5pL1+WYXrrnNcLCX0KsRYmTOz2lF2CViZeZ22sUK?= =?us-ascii?q?I45zE7Dp+mDIjYS4CxgL2OwCe7HppMamBAEVCDC23kd4qDW/cSO2quJZp6nzgF?= =?us-ascii?q?U6WxY5Mw3hGp8gnhwvxoKfSQsisVqZ7uyvBr6ODJ0xI/7zp5C4KayW7JB2V1mH?= =?us-ascii?q?4YAiQ9wLhXv0Nw0BGA3LJ+jvgeEsZco7tNUwEnJdvHwudnEdHuS0fEeduUTFuO?= =?us-ascii?q?XNqrG3cyQ8g3zttIZFxySPu4iRWW+iOwCLIRkPSxBZc96K7bl1z8Jtp7xmyOgK?= =?us-ascii?q?wolVIrRswJMWCnmqhy7SDcAofIlwOSkKP8JvdU5zLE6GrWlTnGh0pfSgMlCag?= =?us-ascii?q?=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0DFAwBZAj1aWyIbGNZdHAEBAQQBAQoBA?= =?us-ascii?q?YJsJikDZnQnjiqPEoFaJ32WKxSCAQoFGoUcAoROPxgBAQEBAQEBAQEBBRoVXoI?= =?us-ascii?q?4IoJKBhoNGQEbHQEDDAYQCjEhAhEBBQEIFAcSiCADOYE5AQMVAQKYa0CNfRgFA?= =?us-ascii?q?RyDCwWDXwoZJw1ZgjUBAQEBAQEBAwEBAQEBARoCBhKDeYE2XIFWgWk1gkODDhN?= =?us-ascii?q?FgVMEhhMFikIMiUGOfT2IAYgwhH6MB4dzjV+IcwYCCQgUJIEXH4IIMhojgQOBd?= =?us-ascii?q?wmCPA8cgX9ghzcBJQeCHAEBAQ?= X-IPAS-Result: =?us-ascii?q?A0DFAwBZAj1aWyIbGNZdHAEBAQQBAQoBAYJsJikDZnQnjiq?= =?us-ascii?q?PEoFaJ32WKxSCAQoFGoUcAoROPxgBAQEBAQEBAQEBBRoVXoI4IoJKBhoNGQEbH?= =?us-ascii?q?QEDDAYQCjEhAhEBBQEIFAcSiCADOYE5AQMVAQKYa0CNfRgFARyDCwWDXwoZJw1?= =?us-ascii?q?ZgjUBAQEBAQEBAwEBAQEBARoCBhKDeYE2XIFWgWk1gkODDhNFgVMEhhMFikIMi?= =?us-ascii?q?UGOfT2IAYgwhH6MB4dzjV+IcwYCCQgUJIEXH4IIMhojgQOBdwmCPA8cgX9ghzc?= =?us-ascii?q?BJQeCHAEBAQ?= X-IronPort-AV: E=Sophos;i="5.45,441,1508803200"; d="scan'208";a="7430928" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from upbd19pa01.eemsg.mail.mil ([214.24.27.34]) by emsm-gh1-uea11.NCSC.MIL with ESMTP; 22 Dec 2017 13:07:07 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;a67d4ec3-555e-4d56-a8cf-3ffe66145afb Received: from localhost.localdomain (localhost [127.0.0.1]) by UPDCF3IC03.oob.disa.mil (Postfix) with SMTP id 3z381617H3zJnNF; Fri, 22 Dec 2017 13:07:06 +0000 (UTC) Received: from UPBD19PA06.eemsg.mil (unknown [192.168.18.7]) by UPDCF3IC03.oob.disa.mil (Postfix) with ESMTP id 3z38126XXlzJnL2; Fri, 22 Dec 2017 13:07:02 +0000 (UTC) Authentication-Results: upbd19pa06.eemsg.mail.mil; dkim=pass (signature verified) header.i=@gmail.com X-EEMSG-check-008: 283729873|UPBD19PA06_EEMSG_MP6.csd.disa.mil X-EEMSG-check-001: false X-EEMSG-SBRS: 2.7 X-EEMSG-ORIG-IP: 209.85.220.193 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0DbAAB8AD1af8HcVdFdHAEBAQQBAQoBAYJsJoESgRuOKo8SgVonfZYrFIIBCh+FHAKETj8YAQEBAQEBAQEBEwEBCQsLCCYxhSQDAxoNGQEbHQEDDAYQCjEhAhEBBQEcBxKIIAM5gTkBAxUBmG5AjX0YBQEcgwsFg2AKGScNWYI1AQEBAQEBAQMBAQEBAQEaAgYJAQiDeYE2XIFWgWk1gkODDhNFgVMEhhMFikIMiUGOfT2IAYgwhH6MB4dzjV+IcwYCCQgUJIEXH4IIMhojgQOBdwmCPA8cgX9ghzcBJQeCHAEBAQ X-IPAS-Result: A0DbAAB8AD1af8HcVdFdHAEBAQQBAQoBAYJsJoESgRuOKo8SgVonfZYrFIIBCh+FHAKETj8YAQEBAQEBAQEBEwEBCQsLCCYxhSQDAxoNGQEbHQEDDAYQCjEhAhEBBQEcBxKIIAM5gTkBAxUBmG5AjX0YBQEcgwsFg2AKGScNWYI1AQEBAQEBAQMBAQEBAQEaAgYJAQiDeYE2XIFWgWk1gkODDhNFgVMEhhMFikIMiUGOfT2IAYgwhH6MB4dzjV+IcwYCCQgUJIEXH4IIMhojgQOBdwmCPA8cgX9ghzcBJQeCHAEBAQ Received: from mail-qk0-f193.google.com ([209.85.220.193]) by upbd19pa06.eemsg.mail.mil with ESMTP; 22 Dec 2017 13:06:49 +0000 Received: by mail-qk0-f193.google.com with SMTP id 143so19979985qki.2; Fri, 22 Dec 2017 05:06:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zytUe9RH0UkuegVpZ6vkkBoEev/sphq0vMoeIDy1otw=; b=NqwT/ju9tNzt0Zaq0M4X8XclVV8HOtZSytWNiS/ZfWxGTSmrWdZKf4D7Vm28CDHB9W iJmmnbSQBp1iogtWjCj3bW6cSG0FTg9NflFpLo9yFKXFDPjDsg1GZul6U6wzbVCqAfVQ wFe6eCBC0NKZo0V2dZsyg5+0TVIkVYzwBnmFK43NENWDoYe1kIX5YHISqUUJ8cBYWng7 u+O4Autboor5abw15CajrIGtP2JIqJG1JafIIMotzl5T4l+gqR/WwVZpfhcaVsWXN40h YpOw28SGyI4Ooe5Clol4bhbjzKyz08P0B+YJtH1o5Kz6Xh6xJzliuC6K3npKiflwRFGU Z4Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zytUe9RH0UkuegVpZ6vkkBoEev/sphq0vMoeIDy1otw=; b=Yx2cuAFLaC4CwS9EJdeCG2vChjC1OcUVKAhtnlsyJuhnHrZExq3R5/AaYEtUzxr0zi lIYuM6q03mCjYglV1qp4uywNGO7WAXP1YsZpP/MPfTsdQfwrCarpYuDvpjtR2YKJIfuZ yIMquNxU194QQLPaKgg6zLlk1qhW9tm/2gQhosKyKk8vupvEnjo9QPpdY2xLavDlPlmy RDdf5V/Tz62p/FeDkcP1gZvxIa4aCFn/vy2BABdllqXCyBBuATvnIfee2LAndI6ImWmp y4uXzWmUboz7JcuGq68fyAd0md+Ggzm1dTIlIfnc2OhcqAZpcox3VeZcsvDB6IOMSSmm xhaQ== X-Gm-Message-State: AKGB3mLnFBHDTIsdaGU5x3VX065hdNsHVWWoMZoLSNG/borbQ23FoF5+ PgsUDV5E/ou7/E6MdiTox5Sk7svU X-Google-Smtp-Source: ACJfBoux0pjh0Iz6HZ7cFlCN23SzgrkJQZachzrwJvMarc4iFLpxLxbo3YPXYlb9jEQCtYjAMEy0SQ== X-Received: by 10.55.170.142 with SMTP id t136mr16641260qke.114.1513947946922; Fri, 22 Dec 2017 05:05:46 -0800 (PST) Received: from localhost.localdomain.com ([2001:1284:f013:a4f9:5ee0:c5ff:fe34:bf34]) by smtp.gmail.com with ESMTPSA id v73sm3852525qkg.34.2017.12.22.05.05.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 22 Dec 2017 05:05:46 -0800 (PST) X-EEMSG-check-009: 444-444 From: Marcelo Ricardo Leitner To: selinux@tycho.nsa.gov, netdev@vger.kernel.org, linux-sctp@vger.kernel.org, linux-security-module@vger.kernel.org Date: Fri, 22 Dec 2017 11:05:19 -0200 Message-Id: <50f68d9f55e8147d92f4b3c350f05e1eb00f2dc8.1513940757.git.marcelo.leitner@gmail.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: X-Mailman-Approved-At: Tue, 02 Jan 2018 08:24:19 -0500 Subject: [PATCH v3 4/4] selinux: Add SCTP support X-BeenThere: selinux@tycho.nsa.gov X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: Cc: marcelo.leitner@gmail.com, nhorman@tuxdriver.com, vyasevich@gmail.com, sds@tycho.nsa.gov Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Virus-Scanned: ClamAV using ClamSMTP From: Richard Haines The SELinux SCTP implementation is explained in: Documentation/security/SELinux-sctp.rst Signed-off-by: Richard Haines Acked-by: Marcelo Ricardo Leitner --- Documentation/security/SELinux-sctp.rst | 104 ++++++++++++ security/selinux/hooks.c | 278 +++++++++++++++++++++++++++++--- security/selinux/include/classmap.h | 2 +- security/selinux/include/netlabel.h | 15 +- security/selinux/include/objsec.h | 4 + security/selinux/netlabel.c | 128 +++++++++++++-- 6 files changed, 499 insertions(+), 32 deletions(-) create mode 100644 Documentation/security/SELinux-sctp.rst diff --git a/Documentation/security/SELinux-sctp.rst b/Documentation/security/SELinux-sctp.rst new file mode 100644 index 0000000000000000000000000000000000000000..f6a9162d3d61e766e2c36fa001c08a1073c1b02e --- /dev/null +++ b/Documentation/security/SELinux-sctp.rst @@ -0,0 +1,104 @@ +SCTP SELinux Support +===================== + +Security Hooks +=============== + +The ``Documentation/security/LSM-sctp.rst`` document describes how the +following sctp security hooks are utilised:: + + security_sctp_assoc_request() + security_sctp_bind_connect() + security_sctp_sk_clone() + security_inet_conn_established() + + +Policy Statements +================== +The following class and permissions to support SCTP are available within the +kernel:: + + class sctp_socket inherits socket { node_bind } + +whenever the following policy capability is enabled:: + + policycap extended_socket_class; + +SELinux SCTP support adds the ``name_connect`` permission for connecting +to a specific port type and the ``association`` permission that is explained +in the section below. + +If userspace tools have been updated, SCTP will support the ``portcon`` +statement as shown in the following example:: + + portcon sctp 1024-1036 system_u:object_r:sctp_ports_t:s0 + + +SCTP Bind, Connect and ASCONF Chunk Parameter Permission Checks +================================================================ +The hook ``security_sctp_bind_connect()`` is called by SCTP to check +permissions required for ipv4/ipv6 addresses based on the ``@optname`` as +follows:: + + ------------------------------------------------------------------ + | BIND Permission Checks | + | @optname | @address contains | + |----------------------------|-----------------------------------| + | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses | + | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address | + | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address | + ------------------------------------------------------------------ + + ------------------------------------------------------------------ + | CONNECT Permission Checks | + | @optname | @address contains | + |----------------------------|-----------------------------------| + | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses | + | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses | + | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address | + | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address | + ------------------------------------------------------------------ + + +SCTP Peer Labeling +=================== +An SCTP socket will only have one peer label assigned to it. This will be +assigned during the establishment of the first association. Once the peer +label has been assigned, any new associations will have the ``association`` +permission validated by checking the socket peer sid against the received +packets peer sid to determine whether the association should be allowed or +denied. + +NOTES: + 1) If peer labeling is not enabled, then the peer context will always be + ``SECINITSID_UNLABELED`` (``unlabeled_t`` in Reference Policy). + + 2) As SCTP can support more than one transport address per endpoint + (multi-homing) on a single socket, it is possible to configure policy + and NetLabel to provide different peer labels for each of these. As the + socket peer label is determined by the first associations transport + address, it is recommended that all peer labels are consistent. + + 3) **getpeercon**\(3) may be used by userspace to retrieve the sockets peer + context. + + 4) While not SCTP specific, be aware when using NetLabel that if a label + is assigned to a specific interface, and that interface 'goes down', + then the NetLabel service will remove the entry. Therefore ensure that + the network startup scripts call **netlabelctl**\(8) to set the required + label (see **netlabel-config**\(8) helper script for details). + + 5) The NetLabel SCTP peer labeling rules apply as discussed in the following + set of posts tagged "netlabel" at: http://www.paul-moore.com/blog/t. + + 6) CIPSO is only supported for IPv4 addressing: ``socket(AF_INET, ...)`` + CALIPSO is only supported for IPv6 addressing: ``socket(AF_INET6, ...)`` + + Note the following when testing CIPSO/CALIPSO: + a) CIPSO will send an ICMP packet if an SCTP packet cannot be + delivered because of an invalid label. + b) CALIPSO does not send an ICMP packet, just silently discards it. + + 7) IPSEC is not supported as RFC 3554 - sctp/ipsec support has not been + implemented in userspace (**racoon**\(8) or **ipsec_pluto**\(8)), + although the kernel supports SCTP/IPSEC. diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f21f1e0e6452570c48cac09dc5c76a6b726c00eb..9ffa5792f570f0751f7bd46418eec2b3fc6489ae 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -67,6 +67,8 @@ #include #include #include +#include +#include #include #include /* for Unix socket types */ #include /* for Unix socket types */ @@ -4117,6 +4119,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, break; } +#if IS_ENABLED(CONFIG_IP_SCTP) + case IPPROTO_SCTP: { + struct sctphdr _sctph, *sh; + + if (ntohs(ih->frag_off) & IP_OFFSET) + break; + + offset += ihlen; + sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); + if (sh == NULL) + break; + + ad->u.net->sport = sh->source; + ad->u.net->dport = sh->dest; + break; + } +#endif default: break; } @@ -4190,6 +4209,19 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, break; } +#if IS_ENABLED(CONFIG_IP_SCTP) + case IPPROTO_SCTP: { + struct sctphdr _sctph, *sh; + + sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph); + if (sh == NULL) + break; + + ad->u.net->sport = sh->source; + ad->u.net->dport = sh->dest; + break; + } +#endif /* includes fragments */ default: break; @@ -4379,6 +4411,10 @@ static int selinux_socket_post_create(struct socket *sock, int family, sksec = sock->sk->sk_security; sksec->sclass = sclass; sksec->sid = sid; + /* Allows detection of the first association on this socket */ + if (sksec->sclass == SECCLASS_SCTP_SOCKET) + sksec->sctp_assoc_state = SCTP_ASSOC_UNSET; + err = selinux_netlbl_socket_post_create(sock->sk, family); } @@ -4399,11 +4435,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in if (err) goto out; - /* - * If PF_INET or PF_INET6, check name_bind permission for the port. - * Multiple address binding for SCTP is not supported yet: we just - * check the first address now. - */ + /* If PF_INET or PF_INET6, check name_bind permission for the port. */ family = sk->sk_family; if (family == PF_INET || family == PF_INET6) { char *addrp; @@ -4415,7 +4447,13 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in unsigned short snum; u32 sid, node_perm; - if (family == PF_INET) { + /* + * sctp_bindx(3) calls via selinux_sctp_bind_connect() + * that validates multiple binding addresses. Because of this + * need to check address->sa_family as it is possible to have + * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. + */ + if (address->sa_family == AF_INET) { if (addrlen < sizeof(struct sockaddr_in)) { err = -EINVAL; goto out; @@ -4469,6 +4507,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in node_perm = DCCP_SOCKET__NODE_BIND; break; + case SECCLASS_SCTP_SOCKET: + node_perm = SCTP_SOCKET__NODE_BIND; + break; + default: node_perm = RAWIP_SOCKET__NODE_BIND; break; @@ -4483,7 +4525,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ad.u.net->sport = htons(snum); ad.u.net->family = family; - if (family == PF_INET) + if (address->sa_family == AF_INET) ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; else ad.u.net->v6info.saddr = addr6->sin6_addr; @@ -4497,7 +4539,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in return err; } -static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) +/* This supports connect(2) and SCTP connect services such as sctp_connectx(3) + * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt + */ +static int selinux_socket_connect_helper(struct socket *sock, + struct sockaddr *address, int addrlen) { struct sock *sk = sock->sk; struct sk_security_struct *sksec = sk->sk_security; @@ -4508,10 +4554,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, return err; /* - * If a TCP or DCCP socket, check name_connect permission for the port. + * If a TCP, DCCP or SCTP socket, check name_connect permission + * for the port. */ if (sksec->sclass == SECCLASS_TCP_SOCKET || - sksec->sclass == SECCLASS_DCCP_SOCKET) { + sksec->sclass == SECCLASS_DCCP_SOCKET || + sksec->sclass == SECCLASS_SCTP_SOCKET) { struct common_audit_data ad; struct lsm_network_audit net = {0,}; struct sockaddr_in *addr4 = NULL; @@ -4519,7 +4567,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, unsigned short snum; u32 sid, perm; - if (sk->sk_family == PF_INET) { + /* sctp_connectx(3) calls via selinux_sctp_bind_connect() + * that validates multiple connect addresses. Because of this + * need to check address->sa_family as it is possible to have + * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. + */ + if (address->sa_family == AF_INET) { addr4 = (struct sockaddr_in *)address; if (addrlen < sizeof(struct sockaddr_in)) return -EINVAL; @@ -4533,10 +4586,19 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, err = sel_netport_sid(sk->sk_protocol, snum, &sid); if (err) - goto out; + return err; - perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? - TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; + switch (sksec->sclass) { + case SECCLASS_TCP_SOCKET: + perm = TCP_SOCKET__NAME_CONNECT; + break; + case SECCLASS_DCCP_SOCKET: + perm = DCCP_SOCKET__NAME_CONNECT; + break; + case SECCLASS_SCTP_SOCKET: + perm = SCTP_SOCKET__NAME_CONNECT; + break; + } ad.type = LSM_AUDIT_DATA_NET; ad.u.net = &net; @@ -4544,13 +4606,24 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, ad.u.net->family = sk->sk_family; err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); if (err) - goto out; + return err; } - err = selinux_netlbl_socket_connect(sk, address); + return 0; +} -out: - return err; +/* Supports connect(2), see comments in selinux_socket_connect_helper() */ +static int selinux_socket_connect(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + int err; + struct sock *sk = sock->sk; + + err = selinux_socket_connect_helper(sock, address, addrlen); + if (err) + return err; + + return selinux_netlbl_socket_connect(sk, address); } static int selinux_socket_listen(struct socket *sock, int backlog) @@ -4813,7 +4886,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op u32 peer_sid = SECSID_NULL; if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || - sksec->sclass == SECCLASS_TCP_SOCKET) + sksec->sclass == SECCLASS_TCP_SOCKET || + sksec->sclass == SECCLASS_SCTP_SOCKET) peer_sid = sksec->peer_sid; if (peer_sid == SECSID_NULL) return -ENOPROTOOPT; @@ -4926,6 +5000,169 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) sksec->sclass = isec->sclass; } +/* Called whenever SCTP receives an INIT chunk. This happens when an incoming + * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association + * already present). + * The lock is to ensure sksec->sctp_assoc_state. + */ +static DEFINE_SPINLOCK(assoc_lock); +static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, + struct sk_buff *skb) +{ + struct sk_security_struct *sksec = ep->base.sk->sk_security; + struct common_audit_data ad; + struct lsm_network_audit net = {0,}; + u8 peerlbl_active; + u32 peer_sid = SECINITSID_UNLABELED; + u32 conn_sid; + int err = 0; + + if (!selinux_policycap_extsockclass) + return 0; + + spin_lock(&assoc_lock); + + peerlbl_active = selinux_peerlbl_enabled(); + + if (peerlbl_active) { + /* This will return peer_sid = SECSID_NULL if there are + * no peer labels, see security_net_peersid_resolve(). + */ + err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family, + &peer_sid); + if (err) + goto err; + + if (peer_sid == SECSID_NULL) + peer_sid = SECINITSID_UNLABELED; + } + + if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) { + sksec->sctp_assoc_state = SCTP_ASSOC_SET; + + /* Here as first association on socket. As the peer SID + * was allowed by peer recv (and the netif/node checks), + * then it is approved by policy and used as the primary + * peer SID for getpeercon(3). + */ + sksec->peer_sid = peer_sid; + } else if (sksec->peer_sid != peer_sid) { + /* Other association peer SIDs are checked to enforce + * consistency among the peer SIDs. + */ + ad.type = LSM_AUDIT_DATA_NET; + ad.u.net = &net; + ad.u.net->sk = ep->base.sk; + err = avc_has_perm(sksec->peer_sid, peer_sid, sksec->sclass, + SCTP_SOCKET__ASSOCIATION, &ad); + if (err) + goto err; + } + + /* Compute the MLS component for the connection and store + * the information in ep. This will be used by SCTP TCP type + * sockets and peeled off connections as they cause a new + * socket to be generated. selinux_sctp_sk_clone() will then + * plug this into the new socket. + */ + err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid); + if (err) + goto err; + + ep->secid = conn_sid; + ep->peer_secid = peer_sid; + + /* Set any NetLabel labels including CIPSO/CALIPSO options. */ + err = selinux_netlbl_sctp_assoc_request(ep, skb); + +err: + spin_unlock(&assoc_lock); + return err; +} + +/* + * Check if sctp IPv4/IPv6 addresses are valid for binding or connecting + * based on their @optname. + */ +static int selinux_sctp_bind_connect(struct sock *sk, int optname, + struct sockaddr *address, + int addrlen) +{ + int len, err = 0, walk_size = 0; + void *addr_buf; + struct sockaddr *addr; + struct socket *sock; + + if (!selinux_policycap_extsockclass) + return 0; + + /* Process one or more addresses that may be IPv4 or IPv6 */ + sock = sk->sk_socket; + addr_buf = address; + + while (walk_size < addrlen) { + addr = addr_buf; + switch (addr->sa_family) { + case AF_INET: + len = sizeof(struct sockaddr_in); + break; + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; + default: + return -EAFNOSUPPORT; + } + + err = -EINVAL; + switch (optname) { + /* Bind checks */ + case SCTP_PRIMARY_ADDR: + case SCTP_SET_PEER_PRIMARY_ADDR: + case SCTP_SOCKOPT_BINDX_ADD: + err = selinux_socket_bind(sock, addr, len); + break; + /* Connect checks */ + case SCTP_SOCKOPT_CONNECTX: + case SCTP_PARAM_SET_PRIMARY: + case SCTP_PARAM_ADD_IP: + case SCTP_SENDMSG_CONNECT: + err = selinux_socket_connect_helper(sock, addr, len); + if (err) + return err; + + err = selinux_netlbl_sctp_socket_connect(sk, addr); + break; + } + + if (err) + return err; + + addr_buf += len; + walk_size += len; + } + + return 0; +} + +/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */ +static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, + struct sock *newsk) +{ + struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *newsksec = newsk->sk_security; + + /* If policy does not support SECCLASS_SCTP_SOCKET then call + * the non-sctp clone version. + */ + if (!selinux_policycap_extsockclass) + return selinux_sk_clone_security(sk, newsk); + + newsksec->sid = ep->secid; + newsksec->peer_sid = ep->peer_secid; + newsksec->sclass = sksec->sclass; + newsksec->nlbl_state = sksec->nlbl_state; +} + static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req) { @@ -6413,6 +6650,9 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security), LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid), LSM_HOOK_INIT(sock_graft, selinux_sock_graft), + LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request), + LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone), + LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect), LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request), LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone), LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established), diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 35ffb29a69cb00b34a4de5d722eaee46df310a74..099065e0a9e099aaf26b765093796caaf7c365ee 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -175,7 +175,7 @@ struct security_class_mapping secclass_map[] = { { COMMON_CAP2_PERMS, NULL } }, { "sctp_socket", { COMMON_SOCK_PERMS, - "node_bind", NULL } }, + "node_bind", "name_connect", "association", NULL } }, { "icmp_socket", { COMMON_SOCK_PERMS, "node_bind", NULL } }, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index e77a5e307955bf938f293f29a3b7be8421fc3533..70275c5e8ee8b254e3a5e3e4a984080a2810ef1c 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" @@ -52,7 +53,8 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, u32 sid); - +int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, + struct sk_buff *skb); int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); @@ -64,6 +66,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, int level, int optname); int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr); +int selinux_netlbl_sctp_socket_connect(struct sock *sk, struct sockaddr *addr); #else static inline void selinux_netlbl_cache_invalidate(void) @@ -113,6 +116,11 @@ static inline int selinux_netlbl_conn_setsid(struct sock *sk, return 0; } +static inline int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, + struct sk_buff *skb) +{ + return 0; +} static inline int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) { @@ -145,6 +153,11 @@ static inline int selinux_netlbl_socket_connect(struct sock *sk, { return 0; } +static inline int selinux_netlbl_sctp_socket_connect(struct sock *sk, + struct sockaddr *addr) +{ + return 0; +} #endif /* CONFIG_NETLABEL */ #endif diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 1649cd18eb0bed125bb38466506309d26c647f90..be145cfe518a409b8b47b74589949c4ea1d5aabf 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -130,6 +130,10 @@ struct sk_security_struct { u32 sid; /* SID of this object */ u32 peer_sid; /* SID of peer */ u16 sclass; /* sock security class */ + enum { /* SCTP association state */ + SCTP_ASSOC_UNSET = 0, + SCTP_ASSOC_SET, + } sctp_assoc_state; }; struct tun_security_struct { diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2c297b995b169519978c4fdedd981743add3e7cc..75066f5f98fd65b6b939a2ea8f1117149ca21957 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -249,6 +249,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, sk = skb_to_full_sk(skb); if (sk != NULL) { struct sk_security_struct *sksec = sk->sk_security; + if (sksec->nlbl_state != NLBL_REQSKB) return 0; secattr = selinux_netlbl_sock_getattr(sk, sid); @@ -269,6 +270,61 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, return rc; } +/** + * selinux_netlbl_sctp_assoc_request - Label an incoming sctp association. + * @ep: incoming association endpoint. + * @skb: the packet. + * + * Description: + * A new incoming connection is represented by @ep, ...... + * Returns zero on success, negative values on failure. + * + */ +int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep, + struct sk_buff *skb) +{ + int rc; + struct netlbl_lsm_secattr secattr; + struct sk_security_struct *sksec = ep->base.sk->sk_security; + struct sockaddr *addr; + struct sockaddr_in addr4; +#if IS_ENABLED(CONFIG_IPV6) + struct sockaddr_in6 addr6; +#endif + + if (ep->base.sk->sk_family != PF_INET && + ep->base.sk->sk_family != PF_INET6) + return 0; + + netlbl_secattr_init(&secattr); + rc = security_netlbl_sid_to_secattr(ep->secid, &secattr); + if (rc != 0) + goto assoc_request_return; + + /* Move skb hdr address info to a struct sockaddr and then call + * netlbl_conn_setattr(). + */ + if (ip_hdr(skb)->version == 4) { + addr4.sin_family = AF_INET; + addr4.sin_addr.s_addr = ip_hdr(skb)->saddr; + addr = (struct sockaddr *)&addr4; +#if IS_ENABLED(CONFIG_IPV6) + } else { + addr6.sin6_family = AF_INET6; + addr6.sin6_addr = ipv6_hdr(skb)->saddr; + addr = (struct sockaddr *)&addr6; +#endif + } + + rc = netlbl_conn_setattr(ep->base.sk, addr, &secattr); + if (rc == 0) + sksec->nlbl_state = NLBL_LABELED; + +assoc_request_return: + netlbl_secattr_destroy(&secattr); + return rc; +} + /** * selinux_netlbl_inet_conn_request - Label an incoming stream connection * @req: incoming connection request socket @@ -469,7 +525,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, } /** - * selinux_netlbl_socket_connect - Label a client-side socket on connect + * selinux_netlbl_socket_connect_helper - Help label a client-side socket on + * connect * @sk: the socket to label * @addr: the destination address * @@ -478,18 +535,13 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, * Returns zero values on success, negative values on failure. * */ -int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) +static int selinux_netlbl_socket_connect_helper(struct sock *sk, + struct sockaddr *addr) { int rc; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr *secattr; - if (sksec->nlbl_state != NLBL_REQSKB && - sksec->nlbl_state != NLBL_CONNLABELED) - return 0; - - lock_sock(sk); - /* connected sockets are allowed to disconnect when the address family * is set to AF_UNSPEC, if that is what is happening we want to reset * the socket */ @@ -497,18 +549,72 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) netlbl_sock_delattr(sk); sksec->nlbl_state = NLBL_REQSKB; rc = 0; - goto socket_connect_return; + return rc; } secattr = selinux_netlbl_sock_genattr(sk); if (secattr == NULL) { rc = -ENOMEM; - goto socket_connect_return; + return rc; } rc = netlbl_conn_setattr(sk, addr, secattr); if (rc == 0) sksec->nlbl_state = NLBL_CONNLABELED; -socket_connect_return: + return rc; +} + +/** + * selinux_netlbl_socket_connect - Label a client-side socket on connect + * @sk: the socket to label + * @addr: the destination address + * + * Description: + * Attempt to label a connected socket with NetLabel using the given address. + * Returns zero values on success, negative values on failure. + * + */ +int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) +{ + int rc; + struct sk_security_struct *sksec = sk->sk_security; + + if (sksec->nlbl_state != NLBL_REQSKB && + sksec->nlbl_state != NLBL_CONNLABELED) + return 0; + + lock_sock(sk); + rc = selinux_netlbl_socket_connect_helper(sk, addr); release_sock(sk); + + return rc; +} + +/** + * selinux_netlbl_sctp_socket_connect - Label an SCTP client-side socket on a + * connect + * @sk: the socket to label + * @addr: the destination address + * + * Description: + * Attempt to label a connected socket with NetLabel using the given address + * when called by the SCTP protocol layer. The situations handled are: + * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2), whenever a new IP address + * is added or when a new primary address is selected. Note that an SCTP + * connect(2) call happens before the SCTP protocol layer and is handled via + * selinux_netlbl_socket_connect() + * Returns zero values on success, negative values on failure. + * + */ +int selinux_netlbl_sctp_socket_connect(struct sock *sk, struct sockaddr *addr) +{ + int rc; + struct sk_security_struct *sksec = sk->sk_security; + + if (sksec->nlbl_state != NLBL_REQSKB && + sksec->nlbl_state != NLBL_CONNLABELED) + return 0; + + rc = selinux_netlbl_socket_connect_helper(sk, addr); + return rc; }