From patchwork Tue Oct 17 13:59:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Haines X-Patchwork-Id: 10012219 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 7BD5760235 for ; Tue, 17 Oct 2017 14:46:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7DD3328936 for ; Tue, 17 Oct 2017 14:46:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 728F628939; Tue, 17 Oct 2017 14:46:54 +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_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from upbd19pa07.eemsg.mail.mil (upbd19pa07.eemsg.mail.mil [214.24.27.82]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A07428936 for ; Tue, 17 Oct 2017 14:46:51 +0000 (UTC) Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.2]) by upbd19pa07.eemsg.mail.mil with ESMTP/TLS/AES256-SHA; 17 Oct 2017 14:46:50 +0000 X-IronPort-AV: E=Sophos;i="5.43,391,1503360000"; d="scan'208";a="4819201" IronPort-PHdr: =?us-ascii?q?9a23=3AjeTKgReCf5rhR4lCZZ+B4wEtlGMj4u6mDksu8pMi?= =?us-ascii?q?zoh2WeGdxcmzYBKN2/xhgRfzUJnB7Loc0qyK6/imADBLsc7JmUtBWaQEbwUCh8?= =?us-ascii?q?QSkl5oK+++Imq/EsTXaTcnFt9JTl5v8iLzG0FUHMHjew+a+SXqvnYdFRrlKAV6?= =?us-ascii?q?OPn+FJLMgMSrzeCy/IDYbxlViDanbr5+MAm6oR/MusQZjodvKbo9wQbVr3VVfO?= =?us-ascii?q?hb2XlmLk+JkRbm4cew8p9j8yBOtP8k6sVNT6b0cbkmQLJBFDgpPHw768PttRnY?= =?us-ascii?q?UAuA/WAcXXkMkhpJGAfK8hf3VYrsvyTgt+p93C6aPdDqTb0xRD+v4btnRAPuhS?= =?us-ascii?q?waOTE56mXXgdFugqxdrhyquhhzz5fJbI2JMfZzeL7Wc9EHSmpbRstfVzJPDI2/?= =?us-ascii?q?YYUIEuQBJeRVo5TzqlQQthuzHhWgCP/1xzNUnHL6wbE23uI8Gg/GxgwgGNcOvW?= =?us-ascii?q?zIotX0KKgSUfq6zLPVwj7ebf1Zwzb96I7WfRA6vPqBWqhwccvNxkkvDQzFlEif?= =?us-ascii?q?ppT5MDyN1uQCqWmb7+x+WuK0kGMosB1xojmpxscwlIbJnIQVxU7Y9Slj3Ik1It?= =?us-ascii?q?i4RVd9bNW5HpVQsCSaOJF3QsMkW2xooDw1yqACuZKieSgKz5MnxwTBZPCdb4eI?= =?us-ascii?q?5RfjWeCMKjl7nHJoYK+zihm9/ES6yuDwS9O43EhFoyZbiNXAq2gB2h/S58SdV/?= =?us-ascii?q?dw8Eis1SyP2g3d8O1IPEE5mbTdJpU82LA/jIATvl7GHiLunUX2i7KZeVs89+iz?= =?us-ascii?q?7uTnfq3mppiBN49okg3+Mrohmsi4AekgLggBRXKb+eWh1L3450H5XLVLgeE2kq?= =?us-ascii?q?neqpzaI9gUprWlDANP14Yj6hK/Ay+n0NQeg3YHMEpIdA+IgoXmIV3DIO30Ae2h?= =?us-ascii?q?j1mjjjtn3e3KMqXkAprXL3jDlLnhfax6605Z0Acz1s5Q55ZVCrEHPfLyVVb9u8?= =?us-ascii?q?ffDh8kNQy73/joCM5m24MCWWOAHq+ZMKTIvV+O/eIgOfOAZIASuDbjM/Ql/eLh?= =?us-ascii?q?jWclmV8BeqmkxZkXaHe+Hvt8P0WZYWDjgtEaHGcIuQo+Sunqh0eZUT5PeXmyRb?= =?us-ascii?q?k86is8CIK8AofJXpqtj6CZ3CenAp1WYXhLClKOEXjya4qEWOwMaCWUIs9gjDwJ?= =?us-ascii?q?TrahS4s81RChrwD61rxnLvbJ+iECspLjztd17fXJlR4u7Tx0E9id02aVQmB6n2?= =?us-ascii?q?MIQzo2075loUFmxFeMz7V3g/tCFdNJ//NJSAA6NZzCwONmF9D+QAXBfs2GSFy+?= =?us-ascii?q?WNWpHSkxTs4tw98Je0tyBsmtjhXE3yqsH78ZiqeGBIIq/aLG3njwJsF9y3Dc2K?= =?us-ascii?q?knkVYmXtNFNXe6ia5n6wjTG4nJnl2EmKa2b6scxjXA+3uEzWqLoE5XShVwUbnf?= =?us-ascii?q?UXAZeETWsczz5lneQL+2FbQnLgxBxNaCK6pLbd3pi05LRPLnONjHYmKxnX28BR?= =?us-ascii?q?CSybOWb4rqensd0zvHBEgCjQ8T4W6MNRIiCSe5v2LeEDtuGErhY0P26+Z+rm+0?= =?us-ascii?q?Tk4vzwyRak1hz7u19gcOhf2SUPMfxLUEuD0uqz9sBlayw8rWC8acpwpmZKhcYs?= =?us-ascii?q?ky4FRA1WLErAF9PYavL6Nlhl4DaQh3uFnu1xpvAIVajccqtG8qzBZ1Ka+AylxO?= =?us-ascii?q?aimY3ZHuNb3NMWT95gyga6vM1lHZytaW9b8F6O4kpFX7oAGpCk0i/m1909ZIzn?= =?us-ascii?q?SR/ZrKDA8dUJ7rVEY46QR6ranAYiYh/4PUyWFsMa6svz/Z1dIpHuwlyg28f9pE?= =?us-ascii?q?K6OEEgjyEsMfB8e0LuwmgV6pYQwYPOpK7q47I9umd+ea2K6sJOthkiipjWBb4I?= =?us-ascii?q?9jyEKM7DFxSvDW0JYf2P6Yww6HWy37jFe7vcD9gZpEai0KHmqj1SjkA5ZcZrFv?= =?us-ascii?q?cokWCGehOcm3y85iiJ7qXn5X6ESsB0ga2MOzfxqdcUD91xVK1UsLuXynhTe4zz?= =?us-ascii?q?tsnjEvr6qf2CjOzPr5dBccIGFEWnNijVD2LYizldAaU1CibxI1mxu9+Ub6269b?= =?us-ascii?q?qbxhL2nSXUhIYy/2L3t4XqSstrqCZMhP6JwzvCVTUeS8Z0qVSqT6oxcA1CPjBW?= =?us-ascii?q?Rezighdz62opX5gwB6iGWFIXZ3rXrZYt1wyQ7E5NPCQf5R3zwGRDR3iDTMHVi8?= =?us-ascii?q?J9ip/dOVl5jfqeCyTWShWYNPcSPz14OPqDO75XF2AR24h/2zgNrnEQw+0SDlzd?= =?us-ascii?q?llSSLIrRjnb4nwyqS1LflnclNvBF/m5MpwApt+nZcohJEMxXgagY2Y/XkZnmf1?= =?us-ascii?q?KtVWwqH+Y2QLRT4Qxd7a/hTl1FdkLnKTyILzTm+dzdd5Z9mmfmMW3Tow79hQB6?= =?us-ascii?q?eJ6LxLgzN1rUC+rQLNf/d9hCwQyeY16HEEmeEJoxAhzj6aArAPB0lXITLjlxqP?= =?us-ascii?q?79Cko6VYenyjcb6u20pihdqhFq2NohlAWHblfZcvBTFw7sNiP1/Xzn3z7JzreN?= =?us-ascii?q?nKYdIVqBKUjw/Kj/JJJ5IpivoKmS1nNHrlvXI/1u47iQdj0o27vIibK2Rh5ay5?= =?us-ascii?q?DQReNjHvYMMT4D7th75EnsmKx4CvAolhGjITUZvmV/2oFi4StfPiNwuVHj0ztG?= =?us-ascii?q?qUGb3FHQCF8EdmtXXPE5K1OH6LOHkV19JiRAOSJEZHmgAbQC06noIlFgCt3MHh?= =?us-ascii?q?dV125jQV5lHmthtM1vhnOAPkX2fZugiodiw0R4SFIxpO8A5O/UHVPtKC7uhrBS?= =?us-ascii?q?FX4oWhrBCRKmycfwlIF3sFW0KeC1DmJLau4d7A8uiDC+WkM/TOZK+CqetEV/eH?= =?us-ascii?q?3ZivyJdp/y6QNsWTOXlvF/M72lBdUn9kAMTWgTMPSzAQlyLWdMOUvguz+ihtos?= =?us-ascii?q?C46vTrVxrl5ZGTBLtKLdVv5xe2jL+FN+6Knil5MS5Y24gCxX/J0rgfx0ISiy9v?= =?us-ascii?q?dzmrC7sAszLCTKPKla9TFRIbbDlzNMRQ5aImwgZNIdLbis/y1rNglv46FUxKWk?= =?us-ascii?q?LnmsGoecwKJHqwNFLZC0mVKruKPzrLw9v4YamkU71fkP1UtwGsuTacC0LsJS+M?= =?us-ascii?q?mz7tVxCuKuFMkDqbMAZFuI6jbhlhE3PjQ8ziah26Nt93kDI3zKYoiXLKL24cLC?= =?us-ascii?q?N8f1lDr7KK8SNYmfJ/G2pb4npiN+mElD6T7/PEJZYOrftrHiN0mvpB73Q7xLtV?= =?us-ascii?q?6ydESedolyTMtdFuokupku+VxjpgShpOpS5BhJiXskV6JaXZ6p5AVG7e8xIC92?= =?us-ascii?q?qQFQoFqsBiCt33pa9QzN3Pm7jyKDdG6N3U+sQdC9LTKMKdP3orKQDpFyLMDAsZ?= =?us-ascii?q?UT6rMnnSh1BakPGX7HGVtJ86q5nyl5oIUbBbTls1Ge0ZCkl+ANMCJ5J3US8+nr?= =?us-ascii?q?6AkM4E/3y+owfNRM9CpJDISuqSAenzKDaelbREZBsJwbfmIokIM4373EJialdk?= =?us-ascii?q?k4TWB0rQXddNoih/YQMupkVC7mR+RHUp2035cgOt/GMTFfmskx4wlARxe+At+S?= =?us-ascii?q?zv41cwPVrKuDE/kE8qmdXmgDCdajjxI7msXYtOESr7q1AxMo/nQwZydQCyh1Jr?= =?us-ascii?q?NCzaSL1LlbtvaWBrhRTHtptOA/5TUKpEYBEIxfGNefop0U5QqiO5yk9b/eHFE4?= =?us-ascii?q?dtlBM2cZ6wqHJNwx9sbNkzJazWOaVG0FxQhqOVsyCyyO8x2ggeK1wK8GOIdy4C?= =?us-ascii?q?oFYIOaU+Jyq04uxs7hSPlCZZd2gSVvolv+lq+1gnNOSa1SLg1LBCKluvOOODMq?= =?us-ascii?q?OZoWnAldKIQ18q0EMHiVVF96Bs0cg/a0qUS1wvzLyJGhQNMsrCMx9ab8xT9XjU?= =?us-ascii?q?ZiuOvuPNwY9vM4W6DODoQveEtLwIjUK8AAYpA4MM49waHpay1EHYLMHnLKMKyB?= =?us-ascii?q?g2+AvrI1CFA+hTdxKQjDcLuce/w4Fr3YNFPDESHX19MTmr5rbQvgIqnPuDXNIx?= =?us-ascii?q?YncGXosFNmk7V9C7my9ZpXtPFyO70uQHxwie9zX8vDjfDCHgb9p/Y/eZfQljCN?= =?us-ascii?q?W3+Toj7ae5kVvX85XYJ2H9M9RtoMTC5vgbp5mdDfNYVLd9s1rGl4leWXOqT3bF?= =?us-ascii?q?EcSpKJjod4kscdv0B26hXVOhjTI4VN3+M8uzLqeWmwHoXpxbsJOb3Tw5Ms+9DD?= =?us-ascii?q?4eEQ9qp+4f/KJ8eREDY50jbB7nqgQ+Nqi/IAOG3dWrWGuiNCVZQOJezeqgYbxb?= =?us-ascii?q?1S0sbvW1yHE4VJE10/G38VIRRJENlhze3/CjZ4hCXijzHXxdfx7PqzIgmWZ8LO?= =?us-ascii?q?g/3uAxzQjUvlkbNjCEaPZmaHdYv90mA1OdP2l2AHIiR1CAlYrD/hKs37cK8itH?= =?us-ascii?q?hdlUy+pFv2Pls5/DejKjQrKrpovRsyoha9gmrKlxMY3sIsuGqJPekCbQTIPVsg?= =?us-ascii?q?GfVi61CeZakMBKIC1EWPlIhX0lOcsetItP80Y+Ssc+J71KCKktvL+qaiFpDS8M?= =?us-ascii?q?wiAHSYyMxjsCgv2z27HCjBefbIwiMAAYsJVFmtYSSTR2Yj4YpKO5VIXbjG6ESm?= =?us-ascii?q?kKIAcP9gtA/gQAmZFsfur9+orHUIdMyyJKo/JzSibLF59o90flRWGSn1f4Teuu?= =?us-ascii?q?k/Cz3QNS1//s1cEbVwB5CUhY3elWl08oJ6pwK6gfpILKtSWIdUzitmL31OSmPE?= =?us-ascii?q?VRydHTd1DgA4rFr3DzUisA+XAPRI9Pz3/eFZIOkwp5dqkrpVNMIJy4dUbk/TAk?= =?us-ascii?q?wZpmH6WgX8Cx21kltWoGRzutE9dZF+Fmt1fXVSZ5Y5y3rZXqII9eQmlO952Bs1?= =?us-ascii?q?1ZilliMzalyZpALMFA+j4MUyJVoTqHuNu9VdZO1tJoAJ8UOtdwpXP9F71eOJSL?= =?us-ascii?q?pH02oLPvwGfD+z8gqFe62CmzG6igQuJb+G0RBB4kKHmApUk0EeQs6HvS/U7QvV?= =?us-ascii?q?xu+edUGKSPh11roDlhBpBOGipJ1Xe9IltoQnlJr/lWJabIf8FSWPQ9eRivOxki?= =?us-ascii?q?GvE8xEyJ4Vt4nXHnbCxurgFa4TzSXxEoVSkJhbfggScepd+6Nj8aUZ1IcS4sby?= =?us-ascii?q?PCKwKFhy9bogpQa0Z3VJ8HGNpF/a8U3ZdM9MrYVUmsMT0FXABlNg8gyfpfjlJD?= =?us-ascii?q?v1+FdiDBFgeobvHPsgBtfciNssGpKuj5/B1dhYPjquw48L8DR3K+kw23Xd/et5?= =?us-ascii?q?P8tsGNtkaWaKf4KfOzbmHcQzXXkBCwgaskD4PQ8CjNMQpbLJ16xmQ4YZT7Dm7L?= =?us-ascii?q?JxtGLboBJ0VHTaB6dclGoudCas9mYqkJ46htBgmDRhz1Boyit/xGLkvXRTTCLi?= =?us-ascii?q?WO7u2/rpjV7bzGU+TgYdaMx3nfSaJtIph68SX7G6vt0YJG+Er5wPFt9k1gSVjB?= =?us-ascii?q?Li+Oss/sJh8R68mkbUviuYclHTXID5dsiHDt3F1Pd9ILQy2295QV0JVZ6HLrRO?= =?us-ascii?q?J51Ejztfde97hi6Yk5+bBm09y0JbvIKfRHrUBnHgWUBh90+Zk3B2h/XW9RaPcL?= =?us-ascii?q?KPjNZaQZkdzuq+fvGqwR6R2a5+tZad/dKEHagMW/CzacSRtfnAcasjMaKwSR1v?= =?us-ascii?q?Gfl69zU8alqvDz2lgx7FimMh4G0Ldt6J+Y9aWSoO/YcQDRzaQEW6jtXc7ztagj?= =?us-ascii?q?u0KM6v0iiL4Oe3Z6bxehEOcDSs4X3n3gwrwyzSIwD8PDGKrt+PpYV3I8nj/tgJ?= =?us-ascii?q?59EEsLFfMTB7qE55xenn0/m+zbKNIZbrxClnyIFR6+Hb8I0WSr5DePIGl5nhHO?= =?us-ascii?q?1An9QWGy7F/ztiJ4RDXDztf9nUpPV7m3A0hSUzCvOUBmrDOFJBDou8bvuaQp8E?= =?us-ascii?q?E2NXTptNOMlWS7IrxYA9byJMeCLikoul0YkIc9Rtu12YAUAdC9Osse8GlibvvC?= =?us-ascii?q?7GOmizROo6Zch4vQ+M6V+PTXHWW4j6KAtrWNwCtVxWQ/vV4i9N+vLOzO58eNQ/?= =?us-ascii?q?SyzWkdVSB/uxHOXxStsLzUs0gUOVCX0EfMgIEKJstW3WUk2UHm6ukjR8gz9AZH?= =?us-ascii?q?GobbefwCoTHzOD3pwVeQeN83TjOR0ydLEVL1H1h4H7I82GHqsMLKi3jQ4VsoSZ?= =?us-ascii?q?d0d0D9ghx3FYo4I1o36FcL2ioDDRQNaReDAbG0H0TqM48EWlIFaRuZx7W1Z6Y3?= =?us-ascii?q?3UJywrOz/uDTdvZzB7AQNvpHiA6BgkRbEIoMsaICWLJ8Z0Nd9KnPqwjtEYfnRe?= =?us-ascii?q?bplWYwNfCuRsBa8NwZuGUi4gmlWhqg8o1P77AFh5CUbqREe4TDvNhg70d74j4C?= =?us-ascii?q?biNNjwZ5jxOlVuAco+fv4sPFv5qs6+auUrstRuoM+hgwGWt+lZvxj0o5rdHRye?= =?us-ascii?q?hcVpXfiZ7j/wBVP36KpIHa3gFgJuoMMY2kYK1t+GkAJygaI3IOPMSZa+Mg4yBz?= =?us-ascii?q?LDrT50ZOAsQWZdMXJMDNgxxbilX1WLFP8crWAlqYC4B1d8A04Gr41is48Z49Uu?= =?us-ascii?q?n67j+5O4zf7l9KP/NZjyVsj8jOpO4LzvrOECIX+2WWawBpwiOezJmAE/nw8vmX?= =?us-ascii?q?yNHPTl8IAyE4XYFcJDqE5AymSfG4lJrsUgyO7M/8nogydEWKRny+hK4FqLpDEf?= =?us-ascii?q?ZciiXn2ThTDoL1h/WVs9qq8mdYql1HEIJu7RLYGaRfP5N7OQ/7lsmqXUV8GCr/?= =?us-ascii?q?eN/OeRoqpeWWx/0A4+NgOEvifYUbOA4Ly6rm6XpJSQtjUL/2vkiDUuIXf9ZmTO?= =?us-ascii?q?7EoW1U6YJnMK8DJl+dpIblrj1QslA5HBcpaKMsrjxdbkTOnhNaW6j6uL4EkQYd?= =?us-ascii?q?X8R2uUlSFmKsIm4+4STIVbhNhqmLFPMV6imTTrAJU0hwPSN+RxS12ZtwdLutmf?= =?us-ascii?q?BKqXhGniR7oPgrzzNqXh28tjPwp6gVwzIv5Km4tCkduXxCVuiekSfICFVbzPQN?= =?us-ascii?q?iaccCmri5kKnbXkGbYvy/KNnKtr6+Ykm+XQ/bg0pfzcaUuS4FyHwk6SID5STsN?= =?us-ascii?q?JdgR6Ao9nObb6vIigRKLs9zQjvR35j3QjChBxo6ncEQi287N84I4WwIcMlxiur?= =?us-ascii?q?GWjYc1YB+aFJv9HytV4MSus5d1VhzH9l0seZWi0HXNbPFHotjgg4dWVEd4pO5g?= =?us-ascii?q?QEGKkunjaFpbJG/gUTYDfIDoSl5JffktrS1Xk6V9dqyXrcpreZiZMyzH1lh9R0?= =?us-ascii?q?4zaWuHQVc+zXSdVsA3b01odbx+zzfPCtsucASIt91ruuTOUCMs64+Wut2ZVqXE?= =?us-ascii?q?Clyq4ZH1qjP+8J3q3bXDu9SW2EReSLdHCBnzgnPU725BmoNkM4ZdxLrk88N+vC?= =?us-ascii?q?g4BTlxflUbxqXCmQokXbzGM7O+MAaw02oJunexANTOMJaemcPfIuwPwiB1QSdH?= =?us-ascii?q?LJGCp2C/OssVGzhoR7PG9g4Uria+T37g/mKMeSGgUDEYPCqZ5x/eK1S3mZOX9k?= =?us-ascii?q?1hJyJ1V09+bDGFQtrO9TbYiekcLWh9tlze4Pb+1tPjElut4PhoJj7pGZ0MOLcR?= =?us-ascii?q?HX05bzKsjZovyZA/3E00QqYXpXUrsDbgPz4IU2JNk5W6fcHbFBpxQTGbA6QIA9?= =?us-ascii?q?N2f27Kx0Nx18cgrQZLSyn8nrqeWHaJRIp3/W8F0wNjnTuwUZxfGvTgx0cYqqh3?= =?us-ascii?q?PsL5A0XT1BstJtBgFhHItVFMMKtxCnDIKMmKGnl9+x/Ft3u+oQvqXsCvDK1dK5?= =?us-ascii?q?34JqUphE5EyLOijeBK1qgkRjk+Szje3M0p7rCcPtYdkETvR0QnbZar/aGYWyMj?= =?us-ascii?q?CONdj/e05B6LGRy695UhONZCD5WKqGqSKkNPV44UkhzIx3YvbTxiQ3777HwNvy?= =?us-ascii?q?e31bpiC7oH6LMZtf60bKBfbfXxJPUveF9nxqHagJYov17usONsYiwNeE6Qlp8D?= =?us-ascii?q?tCyNeFI7SmrkLUwUJ7e5fbI1fo1is6QoQKPgqwMVEtgW7YrXTdB25QLs66Jslx?= =?us-ascii?q?056pCUn26k1wn3w9TnJQEWrvA9GKMC4U3Nz6LAuH6A5GEf4dkOOtP001rKu/Ta?= =?us-ascii?q?9vIJoB0eGrsqgX1M1iNznnWsdXJWfTIaVwMz4XCf/A4BAsYxgZo/0uV4wof5mS?= =?us-ascii?q?MQYCN0udzS7a0wTPywv3esaq2aLPJzwZoVtdyLeQ6zlHpwCjtb65i8zlXauROI?= =?us-ascii?q?v3V/7bKiYSXQaaTDU0HF2B80ulveYJpvyVPSEUpVVCMXHaMxIauq069YuYNWTU?= =?us-ascii?q?g+A2OcRSiQ=3D=3D?= X-IPAS-Result: =?us-ascii?q?A2A2AgCAF+ZZ/wHyM5BVCBoBAQEBAgEBAQEIAQEBARYBAQE?= =?us-ascii?q?DAQEBCQEBAYMIKQNkbiePDY5DgnOVOBCCASUHigpBFgEBAQEBAQEBAQEBaiiCO?= =?us-ascii?q?CSCSQIXDRkBOAECAwkCBUMIAwFaEgWIFQMwgTcBAxUDAawqOoMJBYEChGCCSSY?= =?us-ascii?q?ECIMugTZRgzuCdoMAE4ICCgSGCwWKDgqJG44Yh1+Mf5MllykmBSyBWTQhJYNCC?= =?us-ascii?q?YIDQQ8cgWh1iDsBJQeCFgEBAQ?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 17 Oct 2017 14:45:33 +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 v9HEjOgf028732; Tue, 17 Oct 2017 10:45:25 -0400 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 v9HEFmV3045458 for ; Tue, 17 Oct 2017 10:15:48 -0400 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 v9HEFlib013769; Tue, 17 Oct 2017 10:15:47 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1C6AQANEOZZfyQbGNZVCBsBAQEDAQEBC?= =?us-ascii?q?QEBAYMzKWduJ48NjkOCcZU4EIIEDxqFHIRtQBcBAgEBAQEBAQETAQELFoYbDRk?= =?us-ascii?q?BOAEVgSkSiBoDMIE3AQMVAwGsJTqDCQWBAoRggkkBAQgcBAiDLoE2UYM7gnaDA?= =?us-ascii?q?BOCAgoEhgsFig4KiRuOGIdfjH+TJZcpIAGCDzQhJYNCCYJEDxyBaHWINgElB4I?= =?us-ascii?q?WAQEB?= X-IPAS-Result: =?us-ascii?q?A1C6AQANEOZZfyQbGNZVCBsBAQEDAQEBCQEBAYMzKWduJ48?= =?us-ascii?q?NjkOCcZU4EIIEDxqFHIRtQBcBAgEBAQEBAQETAQELFoYbDRkBOAEVgSkSiBoDM?= =?us-ascii?q?IE3AQMVAwGsJTqDCQWBAoRggkkBAQgcBAiDLoE2UYM7gnaDABOCAgoEhgsFig4?= =?us-ascii?q?KiRuOGIdfjH+TJZcpIAGCDzQhJYNCCYJEDxyBaHWINgElB4IWAQEB?= X-IronPort-AV: E=Sophos;i="5.43,391,1503374400"; d="scan'208";a="86227" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.34]) by goalie.tycho.ncsc.mil with ESMTP; 17 Oct 2017 10:15:36 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3Ay7xMch8TWz7pNf9uRHKM819IXTAuvvDOBiVQ1KB2?= =?us-ascii?q?1OgcTK2v8tzYMVDF4r011RmVBd2dsq4P1LOempujcFRI2YyGvnEGfc4EfD4+ou?= =?us-ascii?q?JSoTYdBtWYA1bwNv/gYn9yNs1DUFh44yPzahANS47xaFLIv3K98yMZFAnhOgpp?= =?us-ascii?q?POT1HZPZg9iq2+yo9JDffxlEiCCgbb59Ixm7rxjdvdQKjIV/Lao81gHHqWZSde?= =?us-ascii?q?RMwmNoK1OTnxLi6cq14ZVu7Sdete8/+sBZSan1cLg2QrJeDDQ9LmA6/9brugXZ?= =?us-ascii?q?TQuO/XQTTGMbmQdVDgff7RH6WpDxsjbmtud4xSKXM9H6QawyVD+/6apgVR3mhz?= =?us-ascii?q?odNzMh7W/ZitJ+gqxYrhymvBFz35LYbZuJOPdkYq/RYdUXTndBUMZLUCxBB5ux?= =?us-ascii?q?YZcOD+UdPeZXtZP9qEYTphW8HwasBeXvxSFThnTr2qA6yeUhHh3G3AM6BdIBrW?= =?us-ascii?q?zbo8ntO6cSS++1za/IwivYb/5Nwjj99InIchY9of6SR7Jwd9TeyVU1GwzZiVWQ?= =?us-ascii?q?rJXoMjWI3eoDtGib6vBvVeOpi2M/swF+uCWvxsM1honMgYIVzUrE+jtjzIkpIt?= =?us-ascii?q?24TUh2asOnHptIryyWKZZ6T8w4T212tys20KMKtJyhcCUEyZkr3x3SZv2df4SV?= =?us-ascii?q?7B/uW/ydLDd2iX5/Zb6yhgi+/E69wePmTMa0ykxFri9dn9nMqH8N0xvT59CaSv?= =?us-ascii?q?tl5UiuxCuD2gTL6u5ePUw5m7DXJIA/zb41jZoTvl7PHirsl0X3iK+abEAk+ums?= =?us-ascii?q?6+j/Y7XmoIGTN5Nshw3gL6gjldazDfo3PwQUQWSW+/6w2bPi8EHhRbVFlPw2kq?= =?us-ascii?q?3XsJDAIsQbo7a0AxVU0ok/6xawFS2m38kAknYbNF1FeAiIj4nvO17QO/D1Fuyw?= =?us-ascii?q?g0itkDdt2/DJIKfhApPTIXjfirvuYbF960tExAop0d9f/45UCq0GIP/rQU/+qc?= =?us-ascii?q?fYAwQlMw203+nnCNJ92pkYWWKUGKCVKqzSsViW5ug3OemDeJcVuCrhK/gi//Pu?= =?us-ascii?q?lmE2mVscfamvwJsWZ2u1HuhmIkqFYXrshc0NEWERvgUkVuDqh1qCUSAAL0q1Cr?= =?us-ascii?q?kx4jA9FZKOEZbIRofrhqeImii8ANkeYG1aBl2SOWnnep/CWPoWbi+WZMh7nXhM?= =?us-ascii?q?UbmnVp9kzhqyrCfkxLd9aOnZ4CsVsdTkztcxr+nSkwwisCd5BNmH0n2cCmRzkn?= =?us-ascii?q?4MShco061l509w0FGO1e5/mfMLO8ZU4qZzUww6PITQh8xzCtb/QUqVZNaCSF+8?= =?us-ascii?q?TuKtNjE4T9Q82PcEf0d7B9i4iB3fmSGtBulGxPSwGJUo//eEjDDKLMFnxiOe2Q?= =?us-ascii?q?=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0CRAgA7D+ZZfyQbGNZVCBwBAQQBAQoBA?= =?us-ascii?q?RcBAQQBAQoBAYMIKWduJ48NjkOCcZU4EIIEDxqFHIRtQBcBAQEBAQEBAQEBARI?= =?us-ascii?q?BAQsWXYI4IoJkDRkBOAEVgSkSiBoDMIE3AQMVAwGsGzqDCQWBAoRggkkBAQgcB?= =?us-ascii?q?AiDLoE2UYM7gnaDABOCAgoEgm0MgxIFig4KiRuOGIdfjH+TJZcpIAGCDzQhJYN?= =?us-ascii?q?CCYJEDxyBaHWINgElB4IWAQEB?= X-IPAS-Result: =?us-ascii?q?A0CRAgA7D+ZZfyQbGNZVCBwBAQQBAQoBARcBAQQBAQoBAYM?= =?us-ascii?q?IKWduJ48NjkOCcZU4EIIEDxqFHIRtQBcBAQEBAQEBAQEBARIBAQsWXYI4IoJkD?= =?us-ascii?q?RkBOAEVgSkSiBoDMIE3AQMVAwGsGzqDCQWBAoRggkkBAQgcBAiDLoE2UYM7gna?= =?us-ascii?q?DABOCAgoEgm0MgxIFig4KiRuOGIdfjH+TJZcpIAGCDzQhJYNCCYJEDxyBaHWIN?= =?us-ascii?q?gElB4IWAQEB?= X-IronPort-AV: E=Sophos;i="5.43,391,1503360000"; d="scan'208";a="4817034" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from upbd19pa03.eemsg.mail.mil ([214.24.27.36]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 17 Oct 2017 14:15:28 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;5ae8a563-3588-43ad-b23c-36b4b1a9e9d8 Received: from localhost.localdomain (localhost [127.0.0.1]) by UPDCF3IC12.oob.disa.mil (Postfix) with SMTP id 3yGcT86R44z1pF2m; Tue, 17 Oct 2017 14:07:24 +0000 (UTC) Received: from UPDC3CPA04.eemsg.mil (unknown [192.168.18.11]) by UPDCF3IC12.oob.disa.mil (Postfix) with ESMTP id 3yGcT44TZQz1pF2K; Tue, 17 Oct 2017 14:07:20 +0000 (UTC) Authentication-Results: UPDC3CPA04.eemsg.mail.mil; dkim=permerror (key too small [TEST]) header.i=@btinternet.com X-EEMSG-check-008: 196264780|UPDC3CPA04_EEMSG_MP20.csd.disa.mil X-EEMSG-check-001: false X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.121 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0CjAQAeDOZZh3kAFEFVCINjgRBujzSmbBCCBB2FKIUtFwMBAQEBAQEBEwEBAQgNCQgoL4U+JgE4ARWBKRKITYE3ARgErEyDCQWBAoRggm8ECIMugTaHAoUVCgSGCwWKDokljhiHX4x/kyWXKSABgg80ISWGLoF0iSsBJQeCFgEBAQ X-IPAS-Result: A0CjAQAeDOZZh3kAFEFVCINjgRBujzSmbBCCBB2FKIUtFwMBAQEBAQEBEwEBAQgNCQgoL4U+JgE4ARWBKRKITYE3ARgErEyDCQWBAoRggm8ECIMugTaHAoUVCgSGCwWKDokljhiHX4x/kyWXKSABgg80ISWGLoF0iSsBJQeCFgEBAQ Received: from rgout0101.bt.lon5.cpcloud.co.uk (HELO rgout01.bt.lon5.cpcloud.co.uk) ([65.20.0.121]) by UPDC3CPA04.eemsg.mail.mil with ESMTP; 17 Oct 2017 14:00:00 +0000 X-OWM-Source-IP: 86.134.53.162 (GB) X-OWM-Env-Sender: richard_c_haines@btinternet.com X-Junkmail-Premium-Raw: score=10/50, refid=2.7.2:2017.10.17.134816:17:10.433, ip=, rules=__HAS_FROM, __FRAUD_WEBMAIL_FROM, __TO_MALFORMED_2, __TO_NO_NAME, __HAS_CC_HDR, __MULTIPLE_RCPTS_CC_X2, __CC_NAME, __CC_NAME_DIFF_FROM_ACC, __SUBJ_ALPHA_END, __HAS_MSGID, __SANE_MSGID, __HAS_X_MAILER, __FROM_DOMAIN_IN_ANY_CC1, __TO_IN_SUBJECT, __ANY_URI, __URI_WITH_PATH, __FRAUD_BODY_WEBMAIL, __CP_URI_IN_BODY, __URI_IN_BODY, __URI_NOT_IMG, __NO_HTML_TAG_RAW, BODY_SIZE_10000_PLUS, __MIME_TEXT_P1, __MIME_TEXT_ONLY, __URI_NS, HTML_00_01, HTML_00_10, __FRAUD_WEBMAIL, __FROM_DOMAIN_IN_RCPT, __CC_REAL_NAMES, MULTIPLE_RCPTS, __PHISH_SPEAR_STRUCTURE_1, TO_IN_SUBJECT, __MIME_TEXT_P, NO_URI_HTTPS, URI_WITH_PATH_ONLY Received: from localhost.localdomain (86.134.53.162) by rgout01.bt.lon5.cpcloud.co.uk (9.0.019.13-1) (authenticated as richard_c_haines@btinternet.com) id 5974506408C5404E; Tue, 17 Oct 2017 14:59:59 +0100 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=btinternet.com; s=btcpcloud; t=1508248801; bh=KIPK/BGKvqZJ+o6+WcEipgYAKgKDsJmdRdkTEvihkEM=; h=From:To:Cc:Subject:Date:Message-Id:X-Mailer; b=rv4Ho0hnjIt0fVhMVS6xFtR/HcaVAyyk+KIpwEKJ/GNWTEUVgWm4ebqKMzBIwneUR0vFcbFcGUNgb9jlLM0TfgH8/5yCcgRBhjXqV9UEVmyUZzl7t1mdAkXJozGe1xLGfPsJuC5EmesBOjnHw6ncdWvlZxabObvFfe/+98DKHLg= X-EEMSG-check-009: 444-444 From: Richard Haines To: selinux@tycho.nsa.gov, netdev@vger.kernel.org, linux-sctp@vger.kernel.org, linux-security-module@vger.kernel.org Date: Tue, 17 Oct 2017 14:59:53 +0100 Message-Id: <20171017135953.4419-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.13.6 X-Mailman-Approved-At: Tue, 17 Oct 2017 10:36:38 -0400 Subject: [RFC PATCH 5/5] 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 The SELinux SCTP implementation is explained in: Documentation/security/SELinux-sctp.txt Signed-off-by: Richard Haines --- Documentation/security/SELinux-sctp.txt | 108 +++++++++++++ security/selinux/hooks.c | 268 ++++++++++++++++++++++++++++++-- security/selinux/include/classmap.h | 3 +- security/selinux/include/netlabel.h | 9 +- security/selinux/include/objsec.h | 5 + security/selinux/netlabel.c | 52 ++++++- 6 files changed, 427 insertions(+), 18 deletions(-) create mode 100644 Documentation/security/SELinux-sctp.txt diff --git a/Documentation/security/SELinux-sctp.txt b/Documentation/security/SELinux-sctp.txt new file mode 100644 index 0000000..32e0255 --- /dev/null +++ b/Documentation/security/SELinux-sctp.txt @@ -0,0 +1,108 @@ + SCTP SELinux Support + ====================== + +Security Hooks +=============== + +The Documentation/security/LSM-sctp.txt 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; + +The SELinux SCTP support adds the additional permissions that are explained +in the sections below: + association bindx connectx + +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: + + ------------------------------------------------------------------ + | BINDX Permission Check | + | @optname | @address contains | + |----------------------------|-----------------------------------| + | SCTP_SOCKOPT_BINDX_ADD | One or more ipv4 / ipv6 addresses | + ------------------------------------------------------------------ + + ------------------------------------------------------------------ + | BIND Permission Checks | + | @optname | @address contains | + |----------------------------|-----------------------------------| + | SCTP_PRIMARY_ADDR | Single ipv4 or ipv6 address | + | SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address | + ------------------------------------------------------------------ + + ------------------------------------------------------------------ + | CONNECTX Permission Check | + | @optname | @address contains | + |----------------------------|-----------------------------------| + | SCTP_SOCKOPT_CONNECTX | One or more ipv4 / ipv6 addresses | + ------------------------------------------------------------------ + + ------------------------------------------------------------------ + | CONNECT Permission Checks | + | @optname | @address contains | + |----------------------------|-----------------------------------| + | SCTP_SENDMSG_CONNECT | Single ipv4 or ipv6 address | + | SCTP_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses | + | 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 supports multiple endpoints with multi-homing on a single socket + it is recommended that peer labels are consistent. + + 3) getpeercon(3) may be used by userspace to retrieve the sockets peer + context. + + 4) If using NetLabel be aware 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 rfc3554 - 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 33fd061..c3e9600 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 */ @@ -4119,6 +4121,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; } @@ -4192,6 +4211,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; @@ -4381,6 +4413,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); } @@ -4401,11 +4437,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; @@ -4417,7 +4449,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 (family == PF_INET || address->sa_family == AF_INET) { if (addrlen < sizeof(struct sockaddr_in)) { err = -EINVAL; goto out; @@ -4471,6 +4509,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; @@ -4485,7 +4527,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 (family == PF_INET || address->sa_family == AF_INET) ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; else ad.u.net->v6info.saddr = addr6->sin6_addr; @@ -4510,10 +4552,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; @@ -4521,7 +4565,14 @@ 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 (sk->sk_family == PF_INET || + address->sa_family == AF_INET) { addr4 = (struct sockaddr_in *)address; if (addrlen < sizeof(struct sockaddr_in)) return -EINVAL; @@ -4534,11 +4585,21 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, } err = sel_netport_sid(sk->sk_protocol, snum, &sid); + if (err) goto out; - 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; @@ -4815,7 +4876,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; @@ -4928,6 +4990,183 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) sksec->sclass = isec->sclass; } +/* Called whenever SCTP receives an INIT or INIT_ACK chunk */ +static int selinux_sctp_assoc_request(struct sctp_endpoint *ep, + struct sk_buff *skb, + int sctp_cid) +{ + 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; + + if (!selinux_policycap_extsockclass) + return 0; + + 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) + return 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) + return err; + } + + if (sctp_cid == SCTP_CID_INIT) { + /* Have INIT when incoming connect(2), sctp_connectx(3) + * or sctp_sendmsg(3) (with no association already present), + * so 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) + return err; + + ep->secid = conn_sid; + ep->peer_secid = peer_sid; + + /* Set any NetLabel labels including CIPSO/CALIPSO options. */ + return selinux_netlbl_sctp_assoc_request(ep, skb); + } + + return 0; +} + +/* + * 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; + + switch (optname) { + case SCTP_SOCKOPT_BINDX_ADD: + err = sock_has_perm(sk, SCTP_SOCKET__BINDX); + break; + case SCTP_SOCKOPT_CONNECTX: + err = sock_has_perm(sk, SCTP_SOCKET__CONNECTX); + break; + /* These need SOCKET__BIND or SOCKET__CONNECT permissions that will + * be checked later. + */ + case SCTP_PRIMARY_ADDR: + case SCTP_SET_PEER_PRIMARY_ADDR: + case SCTP_PARAM_SET_PRIMARY: + case SCTP_PARAM_ADD_IP: + case SCTP_SENDMSG_CONNECT: + break; + default: + err = -EINVAL; + } + if (err) + return err; + + /* 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(sock, addr, len); + 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) { @@ -6416,6 +6655,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 b9fe343..b4b10da 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -173,7 +173,8 @@ struct security_class_mapping secclass_map[] = { { COMMON_CAP2_PERMS, NULL } }, { "sctp_socket", { COMMON_SOCK_PERMS, - "node_bind", NULL } }, + "node_bind", "name_connect", "association", "bindx", + "connectx", NULL } }, { "icmp_socket", { COMMON_SOCK_PERMS, "node_bind", NULL } }, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 75686d5..835a0d6 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -33,6 +33,7 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" @@ -53,7 +54,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); @@ -114,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) { diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 6ebc61e..660f270 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -130,6 +130,11 @@ 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 aaba667..7d5aa15 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -250,6 +250,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); @@ -271,6 +272,41 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, } /** + * 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; + + 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; + + rc = netlbl_sctp_setattr(ep->base.sk, skb, &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 * @@ -481,7 +517,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, */ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) { - int rc; + int rc, already_owned_by_user = 0; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr *secattr; @@ -489,7 +525,16 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state != NLBL_CONNLABELED) return 0; - lock_sock(sk); + /* Note: When called via connect(2) this happens before the socket + * protocol layer connect operation and @sk is not locked, HOWEVER, + * when called by the SCTP protocol layer via sctp_connectx(3), + * sctp_sendmsg(3) or sendmsg(2), @sk is locked. Therefore check if + * @sk owned already. + */ + if (sock_owned_by_user(sk) && sksec->sclass == SECCLASS_SCTP_SOCKET) + already_owned_by_user = 1; + else + 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 @@ -510,6 +555,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state = NLBL_CONNLABELED; socket_connect_return: - release_sock(sk); + if (!already_owned_by_user) + release_sock(sk); return rc; }