From patchwork Thu Jan 11 11:31:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Haines X-Patchwork-Id: 10158035 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 6D2D9601A1 for ; Thu, 11 Jan 2018 13:43:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4EEEA28773 for ; Thu, 11 Jan 2018 13:43:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4339228794; Thu, 11 Jan 2018 13:43:11 +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 USFB19PA12.eemsg.mail.mil (uphb19pa09.eemsg.mail.mil [214.24.26.83]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9447F28773 for ; Thu, 11 Jan 2018 13:43:07 +0000 (UTC) Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.2]) by USFB19PA12.eemsg.mail.mil with ESMTP/TLS/AES256-SHA; 11 Jan 2018 13:43:04 +0000 X-IronPort-AV: E=Sophos;i="5.46,344,1511827200"; d="scan'208";a="7527872" IronPort-PHdr: =?us-ascii?q?9a23=3AkGBj7BO1nry7IqC56B0l6mtUPXoX/o7sNwtQ0KIM?= =?us-ascii?q?zox0L/T6pcbcNUDSrc9gkEXOFd2Cra4c0qyH6+u8CCQp2tWoiDg6aptCVhsI24?= =?us-ascii?q?09vjcLJ4q7M3D9N+PgdCcgHc5PBxdP9nC/NlVJSo6lPwWB6nK94iQPFRrhKAF7?= =?us-ascii?q?Ovr6GpLIj8Swyuu+54Dfbx9HiTahfL9+NhG7oRneusQZhYZpN7o8xAbOrnZUYe?= =?us-ascii?q?pd2HlmJUiUnxby58ew+IBs/iFNsP8/9MBOTLv3cb0gQbNXEDopPWY15Nb2tRbY?= =?us-ascii?q?VguA+mEcUmQNnRVWBQXO8Qz3UY3wsiv+sep9xTWaMMjrRr06RTiu86FmQwLmhy?= =?us-ascii?q?cdMz4y7X/ZhMp+gqlGpB6tvgFzz5LRbIyTKfFwfL7SfckCSGRBQMhfWS9PDISh?= =?us-ascii?q?YYsXDecNIOhVoJfmp1YVsReyGROhCP/1xzNUmnP727Ax3eQ7EQHB2QwtB84AsH?= =?us-ascii?q?XIo9X1LqgSS/26x7TKwzrZbvNW3yny6JPVeR0mu/GMXK5/ccrLxkk1CgzKlkmf?= =?us-ascii?q?ppTlPzyP1+QNtXaU7/F7WO20l24nqgdxoiSxycc2jInGmJ4VxkrY+iV+xYY4PN?= =?us-ascii?q?u1Q1N1b96jFZtfrSCaN41uT8M6WW5opSI6xqQDuZ68eygK0oooywTDZPyAdoiF?= =?us-ascii?q?5A/oWuWJITpgmX5od72yiwyy/ES90OHwSMa53EhQoiZYitXBtXEA2wbO5sWJRf?= =?us-ascii?q?Zx5Fmt1SqT2wzJ9O1JJUY5nrfBJZE72L4/jJ8TvFzGHi/xhUr5krebdl4h+ui0?= =?us-ascii?q?8+TnZajmpoOEO490lA7+NqMul9SjAesiKAgOXnWb+f+m2L3//Uz2XLVKjvosnq?= =?us-ascii?q?nfrJ/aPtgUqrS8Aw9U1oYv8xe/DzG439QEhXQLMV1IdR2dg4XpJl3COu70APih?= =?us-ascii?q?j1i2jTtn3/XGMafgApXJIHjDirDhfbNl5k5H1gUzydFf55RJCrAOOf78QUjxtM?= =?us-ascii?q?HeDhAlLQO02P3qCMl914wCWWKPBbWVMKXJsVCS/O4vLO6MZJENtDbnN/cl/+Lu?= =?us-ascii?q?jWM+mVIFf6mp2p0XZ2qkHvRmOUqZZ2HhgtUGEWcMuwoxVvfqiEGcXj5JfHa+Ra?= =?us-ascii?q?U85is0CIi+F4fMWpitgKCd3Ce8BpBWZGJGBUqQHnfrbIWEXPEMaCOMIsJ6nDwE?= =?us-ascii?q?UaWhSoA62hGzsg/616dnIvDT+i0CupLpzMJ16PHLlREu6Tx0CNyQ0m+MT2Fwm2?= =?us-ascii?q?MHWSU20btxoUNj11iD1rJ4jOZAFdxJ4PNJUBk1OoLAz+BgDNDyQA3BdM+TSFm6?= =?us-ascii?q?WtWmHS0xTtUpztATf0l9HtKijhbf3ya3GLIViaKEBIY18qPd2HjxIdxxy3DY26?= =?us-ascii?q?k9l1MmWNdANXW6hq5j8AjeH5PGk1mDmKawbqkTwCnN9GKfwmWUp0FYTBR8UaPb?= =?us-ascii?q?UnADfkHWt8j25lveT7+yDrQqKgtAyM+FKqtMcdDpiFFGSO7iONTYeW6xnX2/BQ?= =?us-ascii?q?yLxrONcorlZX8R3CPDB0gYiwoT52qJNRAiBie9pGLTFDJuFUj1bEPq7eZ+qWi7?= =?us-ascii?q?Q1QxzwGSbk1tzqG1+xAOhfCGTPMTxL0Esj87qzpoBFa9w87WC92YqgpiZqpcYt?= =?us-ascii?q?Q94Epc2GLarQN9PZugL714il4ZaQR3sFvk1w9rBYVYjcgqsHQqwRJoJq2FylNB?= =?us-ascii?q?di2X3YrrN7LNNmby+Qqja6nM2lHRyNyW4LsA6Owkq1X/uwGkDlAi/Gh63NRO3H?= =?us-ascii?q?uc45rLABAUUZ3vTkY97wJ6qK3CYikh+4PU0mVhMbK6sj/Y3NIpH/clxw27f9dZ?= =?us-ascii?q?N6OFGgryHNccB8S0LuwlhUSpZAoePO9O7K40I9+md/ye1a+lJulgmC6mgnpd4I?= =?us-ascii?q?BmyU+M6TRzSvTT0JYYxvGUxAyHVy3zjF25qMD4hZhEZS0OHmq40SXkAo9RZql2?= =?us-ascii?q?fYkVEmejONe4yctkh57qQXJY80SjB1we0s+zZRWSd0D93RFX1UkPv3ynmDe3zy?= =?us-ascii?q?BzkzEztKaQwCzOw+PkdBoIIWNLQGhijVH2LoiuiNAWRk+obxImlBG9/0b127Bb?= =?us-ascii?q?pLhjL2nUWUpIeyn2L3p+UqeprbqNfcpP6JIusSVKX+WxekuaSqb8oxsc0iPsA3?= =?us-ascii?q?BeyCo9dz60ppXzhwZ6h36FLHZvsHrZftl9xQ3Y5NzYQf5ewCAGSzV/iTjZHVW8?= =?us-ascii?q?JMSp8smPl5vZteC+TW2hXIVJcSb31YOAqDe75WpyDB28gf+znMbnHBM50SDl0d?= =?us-ascii?q?lqTiPIowjgYoXx0KS6K+1ndFFyBFDg88p6Bp1+kowoiZEIw3cam5GV8mQfkWjp?= =?us-ascii?q?N9VbxbzxbGAWSD4W2N7a/hLl2FZ5InKSwIL5S2+dzdd/aNm0ZWMWwC094N5QBK?= =?us-ascii?q?eS8rNEgTN/okCkogLJffh9gjAdxOMw6H4cnu4EoxQtziOADbASB0VYOzLjlwiQ?= =?us-ascii?q?5dCksKpXfHqvcaS31EdmhdCuFqyCogVHVXnle5ciAS9x4txxMF3W1n3/8IbkeM?= =?us-ascii?q?PfbdgLrB2bjw/Aj/RJKJI2jvcKizBoOWThvX0izu42lhJu0o+ns4iAMWVi5rq5?= =?us-ascii?q?AgRfNj33ecwc5i3tgbxZnsaM0IClBo9hFSkTXJv0UfKoFyoftfH9OAaKFD0ztG?= =?us-ascii?q?ubGabFEgCF80pmqWzAE4ywN36LPnYZ1cttSAObJENBnAAeRC86kYIhFgC22Mzh?= =?us-ascii?q?d1905ioL6l/2sBdMz/hnNx34UmbfvwqncCs7SJ2FIBpR9AFC6F/fMdaC4eJrAy?= =?us-ascii?q?FY4pqhoRSDKmyBeQtHEHoJVVaCB1D/Obmu/sLN/PKECeq7NffOZq+OqeNGXfeS?= =?us-ascii?q?2Z2vypdm/yqLNsiXOHliFec02lJbXX1iFcTZmi8PSzcLlyLDbs6bog2z+itroc?= =?us-ascii?q?C+6vvrXBjj5YyVC7tdKd9v4Qy5gb+fN+6MgyZ0MS5Y2Y0XynDWzrgf3UISiyZ1?= =?us-ascii?q?ejmsD7sPqzDCQLjXmq9NAB4RczlzO9dQ76IgwglNPtbWhcju2bJ/iv41CkxFVU?= =?us-ascii?q?D6ms2zfswFPX2yOEncBEmVMLSGJDvLw9z4YK6nVbJRjP9UtwCruTqBHU7sJCiD?= =?us-ascii?q?lyLuVxCpK+1MizubPBNGsoGnbhltEXTjTM7hahCjK9B3jDI2wboyhn7RKGETLy?= =?us-ascii?q?Nzc0JXob2W9y9Yhe9/G2NZ5Hp/MeaEgzqZ7/XfKpsOq/RrDT57l/xE73khzLtV?= =?us-ascii?q?9D9LRPpwmCTIr95up0qpku6AyzZ9VxpOsDlLjpqRvUp+IaXZ6oVAWXHc8RIR6m?= =?us-ascii?q?WQDg4Gp8FiCtzupa9QzMPAlLj0KDhc8NLZ5tcTB8/RKM2bKnUhKgbpFCTSDAQb?= =?us-ascii?q?UT6hLXvfiFBFkPGO6n2VqYA3qpvsmZoKVLBWT1k1FvQUCkRrAtMCPIt3XjMjkb?= =?us-ascii?q?6eksEE/3y+owfNRM9CpJDISuqSAenzKDaelbREYQUHzqn8LYkINY373FdiakVg?= =?us-ascii?q?k4TMAErQXtFNrjdnbgAqvEVH6GJ+QXEr20L5dgOt52ceFeSqkR4tlARxe/4t+y?= =?us-ascii?q?vs41osPVXKpTEwn1Q2mdXrmTCRaiD+LaeqUYFQFSX0q1A7MonnTAZtcQ2ygUtk?= =?us-ascii?q?OS/ZSLJWibtgc31khxHYuZtOAvNTV7NLYAUXxf2NYPUoy1tcoD29xUBb/evFFY?= =?us-ascii?q?dilAwyfJGxtX1AxQNjY8MuJaHLPqVJ1EJQhqWAvy+zyO8+3BIeJ1wM8GOOeC8E?= =?us-ascii?q?okoIOac6JyCw5Oxj9RSCmydfeGgLT/cqpvVq9lkjNOSGziPg1KVOKk+3N+yCNa?= =?us-ascii?q?+ZvHLAlcGQSFMqykwIj1VF/aRx0co7aEqbSUQvzLqXFxQUOsvPMh1ab81X9HfP?= =?us-ascii?q?ZymOqvnNzYhzP4qjCuDiVfWOu7oMgkK4AAYpGJwB7tgAHpmp10HYMcfnLb4exB?= =?us-ascii?q?ow5QTqJE+KA+9TdBKNjjgHv9m1zIVr0olFOjEdHWJ9PD2t6bbTpw8lnOSMU88z?= =?us-ascii?q?YnYaWIsEMXQ2V9ehliFCvnRPFj+33vsXyAif9TP8oDrfDCXkZdp5ePiUfQ9sCM?= =?us-ascii?q?2x+Tgn6Ke5l1jX/47EKG7nK9RtpMXP6fgAqJadC/JYV759s13Tm4NAXXylT3bP?= =?us-ascii?q?EcKpJ5j3c4QsYsH0Cne+Uly7lT01Stz8M8uzIaeTgAHnX4BUvJOc3DA5Os+3Di?= =?us-ascii?q?seFAtop+Ef+KJ8YhUOY4A9YR7pqws+N6u/IAOD0tu2WmijNCFYQuVYw+ihe7NX?= =?us-ascii?q?yC8sYfOgx3s7UpE21e+3/lARRJsSlBHR2e6jZ5VCUSj0AnFdYR/ApTA+l2d6Le?= =?us-ascii?q?sy3v0/zwnWsVYCNzCLdeppaGNAv9E9ClOSIWl2CmQiSF+GiIrP+Ais0K4O/yFF?= =?us-ascii?q?hdZbzfVFsGTivp/YeD+tVranponVsyohaNgmord+MY/4L8uHqpzRgCLQQIPXsg?= =?us-ascii?q?2fXy6wD+BalcRIICJEXPlInnkoOckctopb6ko+SNs+J71JCKkjvb2rZyBrDSgO?= =?us-ascii?q?wi8dUIOAwSENgvym17vciBiQbIwoMAYYv5VantsdTyl2bzsEq6+5SoXWkXWISm?= =?us-ascii?q?sQLQcS7ARM5R4AmZRqcuDj/oXIUIdGyyRKrPJsTivLCp5o+kP6SmGQnVj3VvGh?= =?us-ascii?q?nPKs3Q1M0PLsyNkaVQV4CUhF2elWkE4oJ6t2K6kUpYHKtTCJeVn9vGL3x+usPE?= =?us-ascii?q?NRxtHMd13kEIrFsnLxUjEb+X0RXoJP1G3TFZEJnAZjbqYkuklMKpi8ekni/zwk?= =?us-ascii?q?25hpH76gWMCr3Vklt2wJRyO3HNdaFu5prkrXWCV7bJCvtprlIY9eQmhK+J2Ss1?= =?us-ascii?q?1ZilliMzalyZpALMFA+jwMXD9RrjiGodS9VtZD1tFsD58QPNhwpm3xGKVaN5iN?= =?us-ascii?q?u3c2oKDgymfF+zAgt1e33CmzFLKlQOJY5WIeHh4kKHiZqkkqE+Qj6HzS8kzXvl?= =?us-ascii?q?By4ehbGqCFjV9trzZlApBOGjFJ2Gi+IFR9UHZKr+dXJLnbfsFHX/YyYhqvNAAk?= =?us-ascii?q?Gv49w0yF50d0kmnlYyZqrAtV5zjdXxUoVSkSmrrtgyMRpdynOTAAV5JFdjEhby?= =?us-ascii?q?DbKw2FhyxYoBFfZFx0VJwDBNZK5a0b15NO/sXeUUasNT0FXBt6OwIgyvpfiVRM?= =?us-ascii?q?v1iEeS3GFgqocuvPsgdrcsiPqs6pMO758x1Dio/9t+A47aoDTWW8mQKxWdDes5?= =?us-ascii?q?P8ttqSu0uSbqf3LfOzbmLaQTjRiRCwma0kAIPU/yjSNwpbL4d1yWY+bZjmE27L?= =?us-ascii?q?MgxMJ7gHKEpDSaB6ddJGr/hYZ8B+YqYJ/rRtBhadSRPxA4GvqeRGLlLPRTTfMy?= =?us-ascii?q?qB8/awoYTI7bDHTujgfMOMzW7dQ61rJpd69SX7G7Dy3I9c4EX23Plt9ll9SVfb?= =?us-ascii?q?LS+Mt8jhKRkN5Mm5cUvupJspEi3KAJ1oinri2llAd9YLQy2t6JkYzpdZ5W3xSe?= =?us-ascii?q?J+10j/quxS979q6Ykt+b9p0tu0Jb3PKftGrU9nHwKUCRtw+pUqGmh/SHhbYvUN?= =?us-ascii?q?J/fJYaQZkcfupvjxF6wW9BKV/OhZZsHcJ03bm8m/DTacSQdfnAoarD4XIQSd2+?= =?us-ascii?q?SCm69uRsavvfL51V4141iiMh4Gy6hg6pue9aqMuuDXdAfRzLgDWqXxXcP8srUs?= =?us-ascii?q?tF2U5f04lb4BYHZ5Ywu5H+gBTsQd3Hvvzbg2zSIwFMPOB7bg+OVGV385hT/glY?= =?us-ascii?q?5yEEgRGvMOB7WL5Z5enmA6m+PHKtIWbrpOmmGVFR6rCrUC02Kk6zOLIGl5hRHD?= =?us-ascii?q?yxPwQWK27FLtqC93XyvNwMn5kkpUULm3Cl1eXyy3Nk9kqDmPJhbntMLruaQp60?= =?us-ascii?q?E7Km3ktdOXm2S7JLxaBNb/K8KAISYquF0blpoxRsag2YoDA9qyPM8R8G1ibvvZ?= =?us-ascii?q?826kiC5Bo7xJhoXE4MGV++nXHWG6gK2Hr7WA3yxXyn8lsl4h8N+gK+vO59qQQ/?= =?us-ascii?q?uyzWoRSD1/uwTZVR6vtrPbt0wUOVCM0ErTgIwFJM1Z0mU41kDo4+gjWtEz+BxF?= =?us-ascii?q?FoneY/MCpDbzOCb7wFuEe9I4TDWe3CdXHlP7Fll4Aqs81HjzvM3Xj3fQ/UMnRo?= =?us-ascii?q?1qe0zgnxx3AJ0yKVgx51gP3ioDDQ8NZAiUDL6yH0TqM5cEVUgYZBSD3bi6Zrk4?= =?us-ascii?q?3U1pzbOy/+/fd+p8CLQRNvxFlA6BgEBbGo4Ksa0ZWL98dEFS9KjLpgjlDIjrWO?= =?us-ascii?q?PmmmQ0Nf20RMBa7M8YumAm4gmhXRqh6Y1M46wdiJ+Waq5OeYLMs9xk70d7+T4P?= =?us-ascii?q?cTRAjwR9jxyjTe8Rv/zs4t/fsJqs6+ahSrwtR/kJ+BcoB2RylZzwgEosodvPze?= =?us-ascii?q?dTVpXViZjj8ABKO3OKvYHa0x9gKeoBNY2mZ7Ng93QdKCgYOX0OIdSXa/4m4y9u?= =?us-ascii?q?KzXf/VpCDd0QZdkAJsrChRhUilH1WLFU7sfbFUOXC5xod8wx8mT5xzY78Zo6Uu?= =?us-ascii?q?b95z67Pp/f71RXMPNFkipgjtXCpPIawfDKEigY/WGZawRpwiOF05SNCfHw/eWK?= =?us-ascii?q?yN3OS1wGHio2U5pAKzuD+AynQPG1lJboUg6P9M/zgYw+e1iURnOsnaQJqKBMHv?= =?us-ascii?q?Bcii/jxDhRCpj1h+6Js9qr8GZXt0NHH5x17RDeHKVfI4h0ORX/lsmwXER8ATH/?= =?us-ascii?q?eM7MfBo0pOWW3vsM4/l5N0bmZ48UPBwEy7z+6XdOQAphUrj2sUiFXe4LYttpVu?= =?us-ascii?q?/EpGhP6Y18M68PIESdpJvyozdHrFA2BwEoZ6E0rjxebUTOhwpVW6D1uLEckAcc?= =?us-ascii?q?V8B2uVNUE2KqJG0+/ybHVbhSjKSJCvwV8jWSTrQJU0VsMyN+Xw261Y5re7uogf?= =?us-ascii?q?BHqH1Jkjl6oPgw3DxsXAG8tjH0p6IRxTIg/6m1tCkAuXxAVeiejybIBklAzPsU?= =?us-ascii?q?iacQEXDi5kKgYHMbdov9/KFnJdj89Ykm+3k/ZBQjfy4FXeSnECzwjbmHAo+IsN?= =?us-ascii?q?JamhGNvt/CbbmtIigOLr490w7sR2Bh0gjCmxZl6HAETSum7N84P4i9IsIlxi20?= =?us-ascii?q?GWjHalYD/L5GvNH2tV4RQ+s8cUlhz3l70sibWi0NQ9TCG34yjgggc2pEapxC6R?= =?us-ascii?q?geF6kmmTuIu65G/gYPYDjKDoul4I7QndzT2Xk8S9dqyXjapqqfhpMlyHdlgc97?= =?us-ascii?q?7jaSuHQOcOzVS8FsDWb31ode0ezxee6gs+EGSItjzbSuTuUCMs299mes35VqQE?= =?us-ascii?q?ClzKwEH1WlKO8D2qvbUyC9RGyWQeSLaWmMkConPUPp4BmoL0E3aN1UoEMnNevC?= =?us-ascii?q?nJFcnRX7UbxoXiWQuUPbzGs7POMdcwI5ppyqexQOTOELfOicOekuz+EiCFsWcX?= =?us-ascii?q?DGAzF6C+movl6xhIJ7IWlv4V3mYeTx9QDrKN+SGhgCEY7HoZ994Pi6RmOaOX98?= =?us-ascii?q?1x1/J0h0+P3ZF1Q2rONcdIyRndfIjdRhzeEFb+ttMTE6utMLn4Js85Wb0MeLcR?= =?us-ascii?q?HXyZb/Ps/VovmeA/LBy0Qqe2daUqcWYA/v4IU6JNE5UaXJHbRFpRQcGbQ6QJs5?= =?us-ascii?q?Omfz7q50LwRzfRXKabSphMnquuKLZpxJp3/Z7lIwMD3QuxsdxfyoVQZ7dYylh2?= =?us-ascii?q?3uIJAsQTJMt99tCh5hHItVAcMArhGnDoWSmK6hjt++5UJ6t/UNsarqBfDAzM65?= =?us-ascii?q?0JlpX5hG+UyLOy7cBLJlgkRgkuu/g/TN34LvCcz8Y9MEVel6QmnDarPcGIWwNC?= =?us-ascii?q?6OaYrAfBtd/rqd1q9pegmAbyD+GaydvWurM+sgqUM21oB1YsLNwzE3qbLWwt3/?= =?us-ascii?q?YydcvCjn5XqIMoZPqUfBGfT2QR1ZU7yG/XxjEKlRapH7sK8KMNo/0J2H7gJu9j?= =?us-ascii?q?VewY6AJKS8qkLkxE12b9TYIVHv1iJ/XpMFczqlNk55u27Sqn3HDTx8J8miJNIl?= =?us-ascii?q?1MyUBRzk/UVGklYtb29HF3HAT8uQP3QWwcSzeEuB8wcdXIVLpPK+ZUNt7v76cu?= =?us-ascii?q?JvIJgQ3LzyuQ=3D=3D?= X-IPAS-Result: =?us-ascii?q?A2B7AwCcaFda/wHyM5BWCBoBAQEBAQIBAQEBCAEBAQGDFSk?= =?us-ascii?q?DZnQnjx+NaoJ+jTiJEIF/JQeJW0MUAQEBAQEBAQEBAWoogjgkgk8CFw0ZATgBA?= =?us-ascii?q?gMJAgVDCAMBWhIFiB4DOoE6AQMVAwGxKDqDCwWBAoRhgUYBJQQIhCuBNl+DQIJ?= =?us-ascii?q?4gw4TRASBSgoEhhMFikgMiUaPSogLjS+DDJEPmGA2IoFQMhojgnwJgjwPHIFne?= =?us-ascii?q?Il1ASUHgh0BAQE?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 11 Jan 2018 13:43:00 +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 w0BDg7ul004137; Thu, 11 Jan 2018 08:42:22 -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 w0BBVgoe120175 for ; Thu, 11 Jan 2018 06:31:42 -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 w0BBVYto027684; Thu, 11 Jan 2018 06:31:34 -0500 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1BpBwCPSldaWycbGNZWCBwBAQEEAQEKA?= =?us-ascii?q?QGDFSkDZnQnjx+NaoJ+jTiIfBSCAg8ahRyEP0AXAQEBAQEBAQEBBhoVhiINGQE?= =?us-ascii?q?4ARWBDhsSiCMDOoE6AQMVAwGyBzqDCwWBAoRjgUYBAQgcBAiEK4E2X4NAgniDD?= =?us-ascii?q?hNEBIFKCgSGEwWKSAyJRo9KiAuNL4MMkQ+YYCABggcyGiOCfAmCPA8cgWd4iXU?= =?us-ascii?q?BJQeCHQEBAQ?= X-IPAS-Result: =?us-ascii?q?A1BpBwCPSldaWycbGNZWCBwBAQEEAQEKAQGDFSkDZnQnjx+?= =?us-ascii?q?NaoJ+jTiIfBSCAg8ahRyEP0AXAQEBAQEBAQEBBhoVhiINGQE4ARWBDhsSiCMDO?= =?us-ascii?q?oE6AQMVAwGyBzqDCwWBAoRjgUYBAQgcBAiEK4E2X4NAgniDDhNEBIFKCgSGEwW?= =?us-ascii?q?KSAyJRo9KiAuNL4MMkQ+YYCABggcyGiOCfAmCPA8cgWd4iXUBJQeCHQEBAQ?= X-IronPort-AV: E=Sophos;i="5.46,344,1511845200"; d="scan'208";a="171764" Received: from emsm-gh1-uea11.ncsc.mil ([214.29.60.35]) by goalie.tycho.ncsc.mil with ESMTP; 11 Jan 2018 06:31:33 -0500 IronPort-PHdr: =?us-ascii?q?9a23=3AZNTaYxTQKXP1nTC8d6TEsV1rLtpsv+yvbD5Q0YIu?= =?us-ascii?q?jvd0So/mwa6zYheN2/xhgRfzUJnB7Loc0qyK6/mmATRIyK3CmUhKSIZLWR4BhJ?= =?us-ascii?q?detC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBxrwKxd+?= =?us-ascii?q?KPjrFY7OlcS30P2594HObwlSizexfa5+IA+qoQnNq8IbnZZsJqEtxxXTv3BGYf?= =?us-ascii?q?5WxWRmJVKSmxbz+MK994N9/ipTpvws6ddOXb31cKokQ7NYCi8mM30u683wqRbD?= =?us-ascii?q?VwqP6WACXWgQjxFFHhLK7BD+Xpf2ryv6qu9w0zSUMMHqUbw5Xymp4qF2QxHqlS?= =?us-ascii?q?gHLSY0/nzXhMJugqxVoxWvqgdjz4LIeoyZKOBzcr/Bcd4cWGFPXtxRVytEAo6k?= =?us-ascii?q?c4UPDvYOPeZCoInnulQFsBmwChOtBOPp1DBInWL90Kog0+QgDQ7G3BYvH8gTv3?= =?us-ascii?q?vMsNr6LKcSXvq0zKnO0zrDdOhb1izh6IjJdBAhve+DXah2ccXP1UkjDR/KjlKV?= =?us-ascii?q?qYH8OT6ey+oDs2+e7+V6VOKvjXYqqxlrrTiywscgk4zJhoUSylDe6yp12po6Jd?= =?us-ascii?q?q9SEN9fNWqE4NQujmEO4drTc4uWX9ktSkgxrEYu5O3ZiYHxZA/yxPcavGLaZWE?= =?us-ascii?q?7xzsWeqLPzt0mG5pdKihixu290Wr1/fyWdOu0FlQqypIitnMuW4J1xzU8sWHV+?= =?us-ascii?q?N98Vy81jqS0w3T8vtLLVw1mKbBNZEu3LswloEcsUjZGy/5gkT2jKuMekUh++io?= =?us-ascii?q?7/zrYrTgppCCK495kh/yPrkhl8ClH+g1PRICU3aZ9Oim2rDu+VX1QLBQgf03lq?= =?us-ascii?q?nZvoraJcMepqOhGQ9V05os6xalADe8zdsXhWUII0pFeB2djojpPU/BIOvjAPik?= =?us-ascii?q?n1SskTFrx+zYMb37BJXCMGTDnK39crZ67k5Q0BAzwsxH55JIFrEBJ+r+WlTsu9?= =?us-ascii?q?zDFRI5Lwy1zPrnCNV6zI8eX3mPDbWDPKPdtl+I+PolI/OQa48NpDb9N/8l6ub1?= =?us-ascii?q?jXAnnV8dfK+p3YYYaX2jAvRnI1mWYXrrgtsbF2cKpRAxQPbliF2FTz4AL0q1Cr?= =?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?A0BsBwBQSldaWycbGNZWCBwBAQEEAQEKA?= =?us-ascii?q?QGDFSkDZnQnjx+NaoJ+jTiIfBSCAg8ahRyEP0AXAQEBAQEBAQEBAQUaFV6COCK?= =?us-ascii?q?Cag0ZATgBFYEOGxKIIwM6gToBAxUDAbIGOoMLBYEChGOBRgEBCBwECIQrgTZfg?= =?us-ascii?q?0CCeIMOE0QEgUoKBIJxDIMWBYpIDIlGj0qIC40vgwyRD5hgIAGCBzIaI4J8CYI?= =?us-ascii?q?8DxyBZ3iJdQElB4IdAQEB?= X-IPAS-Result: =?us-ascii?q?A0BsBwBQSldaWycbGNZWCBwBAQEEAQEKAQGDFSkDZnQnjx+?= =?us-ascii?q?NaoJ+jTiIfBSCAg8ahRyEP0AXAQEBAQEBAQEBAQUaFV6COCKCag0ZATgBFYEOG?= =?us-ascii?q?xKIIwM6gToBAxUDAbIGOoMLBYEChGOBRgEBCBwECIQrgTZfg0CCeIMOE0QEgUo?= =?us-ascii?q?KBIJxDIMWBYpIDIlGj0qIC40vgwyRD5hgIAGCBzIaI4J8CYI8DxyBZ3iJdQElB?= =?us-ascii?q?4IdAQEB?= X-IronPort-AV: E=Sophos;i="5.46,344,1511827200"; d="scan'208";a="7987235" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from upbd19pa06.eemsg.mail.mil ([214.24.27.39]) by emsm-gh1-uea11.NCSC.MIL with ESMTP; 11 Jan 2018 11:31:30 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;fdf19207-fd7d-457f-af57-5d355b58a4bc Received: from localhost.localdomain (localhost [127.0.0.1]) by UPDCF3IC14.oob.disa.mil (Postfix) with SMTP id 3zHNxY451yzJ3cp; Thu, 11 Jan 2018 11:31:29 +0000 (UTC) Received: from UPDC3CPA01.eemsg.mil (unknown [192.168.18.8]) by UPDCF3IC14.oob.disa.mil (Postfix) with ESMTP id 3zHNxW5GNVzJ3dT; Thu, 11 Jan 2018 11:31:27 +0000 (UTC) Authentication-Results: UPDC3CPA01.eemsg.mail.mil; dkim=permerror (key too small) header.i=@btinternet.com X-EEMSG-check-008: 177569901|UPDC3CPA01_EEMSG_MP17.csd.disa.mil X-EEMSG-check-001: false X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.129 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0CZAAC+SFdah4EAFEFWCBsBAQEBAwEBAQkBAQGDFYESdCePH5BojTiIfBSCAg8ahRyEfxcBAQEBAQEBAQETAQEBCgsJCCgvhUQNGQE4ARWBKRKIIwM6gToBAxUEsX86gwsFgQKEY4FGAQEIHAQIhCuBNoQfgniDDhNEBIFKCgSCcQyDFgWKSAyJRo9KiAuNL4MMkQ+YYCECggUyGiOCfAmCPA8QDIFneIl1ASUHgh0BAQE X-IPAS-Result: A0CZAAC+SFdah4EAFEFWCBsBAQEBAwEBAQkBAQGDFYESdCePH5BojTiIfBSCAg8ahRyEfxcBAQEBAQEBAQETAQEBCgsJCCgvhUQNGQE4ARWBKRKIIwM6gToBAxUEsX86gwsFgQKEY4FGAQEIHAQIhCuBNoQfgniDDhNEBIFKCgSCcQyDFgWKSAyJRo9KiAuNL4MMkQ+YYCECggUyGiOCfAmCPA8QDIFneIl1ASUHgh0BAQE Received: from rgout0602.bt.lon5.cpcloud.co.uk (HELO rgout06.bt.lon5.cpcloud.co.uk) ([65.20.0.129]) by UPDC3CPA01.eemsg.mail.mil with ESMTP; 11 Jan 2018 11:31:26 +0000 X-OWM-Source-IP: 86.134.200.29 (GB) X-OWM-Env-Sender: richard_c_haines@btinternet.com X-Junkmail-Premium-Raw: score=10/50, refid=2.7.2:2018.1.11.105716: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.200.29) by rgout06.bt.lon5.cpcloud.co.uk (9.0.019.13-1) (authenticated as richard_c_haines@btinternet.com) id 5A025DDB06372F3E; Thu, 11 Jan 2018 11:31:23 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=btinternet.com; s=btcpcloud; t=1515670286; bh=5CVAfovQyjJqwBmDJ0P+ljtIq8+3n9nq3s6d7YL1SOU=; h=From:To:Cc:Subject:Date:Message-Id:X-Mailer; b=pb731B2/x6ylwNi+M7PApD3Om9sJkE0MzBeObyzjCdM1YfULDr+rc/weCwdV1en/GeOCBepobcTpJQZaYVRMCLqnmqZiCecqbPBtEMknAVhnVHTDBR7MncjFWmlm0XylZq/5Sv/fD+WW3XfpnFwtqQdW8bMPXo64Qe7rIA0bWHs= 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: Thu, 11 Jan 2018 11:31:06 +0000 Message-Id: <20180111113106.6746-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.14.3 X-Mailman-Approved-At: Thu, 11 Jan 2018 08:42:05 -0500 Subject: PATCH V5 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 The SELinux SCTP implementation is explained in: Documentation/security/SELinux-sctp.rst Signed-off-by: Richard Haines Acked-by: Neil Horman --- V5 Change: Rework selinux_netlbl_socket_connect() and selinux_netlbl_socket_connect_locked as requested by Paul. Documentation/security/SELinux-sctp.rst | 157 ++++++++++++++++++ security/selinux/hooks.c | 280 +++++++++++++++++++++++++++++--- security/selinux/include/classmap.h | 2 +- security/selinux/include/netlabel.h | 21 ++- security/selinux/include/objsec.h | 4 + security/selinux/netlabel.c | 133 +++++++++++++-- 6 files changed, 565 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 0000000..2f66bf3 --- /dev/null +++ b/Documentation/security/SELinux-sctp.rst @@ -0,0 +1,157 @@ +SCTP SELinux Support +===================== + +Security Hooks +=============== + +``Documentation/security/LSM-sctp.rst`` describes the following SCTP security +hooks with the SELinux specifics expanded below:: + + security_sctp_assoc_request() + security_sctp_bind_connect() + security_sctp_sk_clone() + security_inet_conn_established() + + +security_sctp_assoc_request() +----------------------------- +Passes the ``@ep`` and ``@chunk->skb`` of the association INIT packet to the +security module. Returns 0 on success, error on failure. +:: + + @ep - pointer to sctp endpoint structure. + @skb - pointer to skbuff of association packet. + +The security module performs the following operations: + IF this is the first association on ``@ep->base.sk``, then set the peer + sid to that in ``@skb``. This will ensure there is only one peer sid + assigned to ``@ep->base.sk`` that may support multiple associations. + + ELSE validate the ``@ep->base.sk peer_sid`` against the ``@skb peer sid`` + to determine whether the association should be allowed or denied. + + Set the sctp ``@ep sid`` to socket's sid (from ``ep->base.sk``) with + MLS portion taken from ``@skb peer sid``. This will be used by SCTP + TCP style sockets and peeled off connections as they cause a new socket + to be generated. + + If IP security options are configured (CIPSO/CALIPSO), then the ip + options are set on the socket. + + +security_sctp_bind_connect() +----------------------------- +Checks 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 | + ------------------------------------------------------------------ + + +``Documentation/security/LSM-sctp.rst`` gives a summary of the ``@optname`` +entries and also describes ASCONF chunk processing when Dynamic Address +Reconfiguration is enabled. + + +security_sctp_sk_clone() +------------------------- +Called whenever a new socket is created by **accept**\(2) (i.e. a TCP style +socket) or when a socket is 'peeled off' e.g userspace calls +**sctp_peeloff**\(3). ``security_sctp_sk_clone()`` will set the new +sockets sid and peer sid to that contained in the ``@ep sid`` and +``@ep peer sid`` respectively. +:: + + @ep - pointer to current sctp endpoint structure. + @sk - pointer to current sock structure. + @sk - pointer to new sock structure. + + +security_inet_conn_established() +--------------------------------- +Called when a COOKIE ACK is received where it sets the connection's peer sid +to that in ``@skb``:: + + @sk - pointer to sock structure. + @skb - pointer to skbuff of the COOKIE ACK packet. + + +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 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 f5d3047..24d6f39 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 */ @@ -4126,6 +4128,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; } @@ -4199,6 +4218,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; @@ -4388,6 +4420,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); } @@ -4408,11 +4444,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; @@ -4424,7 +4456,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; @@ -4478,6 +4516,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; @@ -4492,7 +4534,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; @@ -4506,7 +4548,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; @@ -4517,10 +4563,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; @@ -4528,7 +4576,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; @@ -4542,10 +4595,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; @@ -4553,13 +4615,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) @@ -4822,7 +4895,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; @@ -4935,6 +5009,171 @@ 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). + */ +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; + + 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; + } + + /* 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); +} + +/* 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; + + /* As selinux_sctp_bind_connect() is called by the + * SCTP protocol layer, the socket is already locked, + * therefore selinux_netlbl_socket_connect_locked() is + * is called here. 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_socket_connect(). + */ + err = selinux_netlbl_socket_connect_locked(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; + selinux_netlbl_sctp_sk_clone(sk, newsk); +} + static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req) { @@ -6422,6 +6661,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 cc35695..167c20a 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -176,7 +176,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 75686d5..0fae720 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,9 +54,11 @@ 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); +void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk); int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff *skb, @@ -65,6 +68,8 @@ 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_socket_connect_locked(struct sock *sk, + struct sockaddr *addr); #else static inline void selinux_netlbl_cache_invalidate(void) @@ -114,6 +119,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) { @@ -123,6 +133,10 @@ static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) { return; } +static inline void selinux_netlbl_sctp_sk_clone(struct sock *sk, sock *newsk) +{ + return; +} static inline int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) { @@ -146,6 +160,11 @@ static inline int selinux_netlbl_socket_connect(struct sock *sk, { return 0; } +static inline int selinux_netlbl_socket_connect_locked(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 1649cd1..be145cf 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 aaba667..0863c56 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); @@ -270,6 +271,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 @@ -319,6 +375,22 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) sksec->nlbl_state = NLBL_UNSET; } +/** + * selinux_netlbl_sctp_sk_clone - Copy state to the newly created sock + * @sk: current sock + * @newsk: the new sock + * + * Description: + * Called whenever a new socket is created by accept(2) or sctp_peeloff(3). + */ +void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) +{ + struct sk_security_struct *sksec = sk->sk_security; + struct sk_security_struct *newsksec = newsk->sk_security; + + newsksec->nlbl_state = sksec->nlbl_state; +} + /** * selinux_netlbl_socket_post_create - Label a socket using NetLabel * @sock: the socket to label @@ -470,7 +542,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 * @@ -479,18 +552,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 */ @@ -498,18 +566,61 @@ 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_locked - Label a client-side socket on + * connect + * @sk: the socket to label + * @addr: the destination address + * + * Description: + * Attempt to label a connected socket that already has the socket locked + * with NetLabel using the given address. + * Returns zero values on success, negative values on failure. + * + */ +int selinux_netlbl_socket_connect_locked(struct sock *sk, + struct sockaddr *addr) +{ + struct sk_security_struct *sksec = sk->sk_security; + + if (sksec->nlbl_state != NLBL_REQSKB && + sksec->nlbl_state != NLBL_CONNLABELED) + return 0; + + return selinux_netlbl_socket_connect_helper(sk, addr); +} + +/** + * 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; + + lock_sock(sk); + rc = selinux_netlbl_socket_connect_locked(sk, addr); release_sock(sk); + return rc; }