From patchwork Wed Feb 22 17:03:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Haines X-Patchwork-Id: 9587191 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 0C5BB602A7 for ; Wed, 22 Feb 2017 17:06:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8DBD2846A for ; Wed, 22 Feb 2017 17:06:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD89F284FF; Wed, 22 Feb 2017 17:06:47 +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=-1.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_NONE,T_DKIM_INVALID autolearn=no version=3.3.1 Received: from emsm-gh1-uea10.nsa.gov (emsm-gh1-uea10.nsa.gov [8.44.101.8]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E782E2846A for ; Wed, 22 Feb 2017 17:06:45 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.35,195,1484006400"; d="scan'208";a="4129228" IronPort-PHdr: =?us-ascii?q?9a23=3As8RJRh9Z5EnRqv9uRHKM819IXTAuvvDOBiVQ1KB5?= =?us-ascii?q?1+0XIJqq85mqBkHD//Il1AaPBtSGrasawLuL+4nbGkU4qa6bt34DdJEeHzQksu?= =?us-ascii?q?4x2zIaPcieFEfgJ+TrZSFpVO5LVVti4m3peRMNQJW2aFLduGC94iAPERvjKwV1?= =?us-ascii?q?Ov71GonPhMiryuy+4ZPebgFIiTanfL9/LRq6oAHRu8ILnYZsN6E9xwfTrHBVYe?= =?us-ascii?q?pW32RoJVySnxb4+Mi9+YNo/jpTtfw86cNOSL32cKskQ7NWCjQmKH0169bwtRbf?= =?us-ascii?q?VwuP52ATXXsQnxFVHgXK9hD6XpP2sivnqupw3TSRMMPqQbwoXzmp8qlkSAXsiC?= =?us-ascii?q?waKTA39m/ZgdF0gK5CoR+tohpyyJPWbo6ILvpzZqPTc80HS2RPXchfUDRBD4Gh?= =?us-ascii?q?Y4YBAOUOIelWoJfmp1YVsRuzBxOhCP/1xzNUmHP727Ax3eQ7EQHB2QwtB84AsH?= =?us-ascii?q?XIo9X1LqgSS/26x7TKwzrZbvNW3yny6JPVeR0mu/GMXK5/ccrLxkk1CgzKlkmf?= =?us-ascii?q?ppTlPzyP1+QNtXaU7/F7WO20l24nqgdxoiSxycc2jInGmJ4VxkrY+iV+xYY4PN?= =?us-ascii?q?u1Q1N1b96jFZtfrSCaN41uT8M5XW5ovCc6yrsbuZ+0ZCgK0pMnxxzBZPObb4iE?= =?us-ascii?q?+BXjVPyeITtgi3Jlea6/hxav8Ue70OHzSs600FNSoipdiNbMq3QN2wXW6siATf?= =?us-ascii?q?t95Fmu1SyT2ADU7+FJJ10/m6nDK5M537I9mZUevV7DEyPrgkn6kqCbels+9uS1?= =?us-ascii?q?8+jqYbTrqoWBO4J7iwzyKKUjl86lDek5MQUDWXWQ9/6m273550L5Ra1Hjvgxkq?= =?us-ascii?q?bErp/XPd8bpqulAw9N1YYj9gq/Ay+m0NsGmXkHK0pIeA6dgIjzOlHOPev4Ae2j?= =?us-ascii?q?g1WsjDhrx/fGMqfnAprRNXjMjK3tfbN8605Y0AYzzNZf6IxICrwZPf7+VUD8uM?= =?us-ascii?q?bYAxMkKQC43enqBMtn2o8DQW6PB7WWMKLWsV+G/OIvJOyMaZcOuDnjL/gl5vju?= =?us-ascii?q?jWI2mFMEZqap2oYXaHakEft4OEWUembsg9cdHmcKuQoyVurqiEaYXjJJaHayWL?= =?us-ascii?q?w86ikhCI26FYfDWpytgLuZ0Se5GZ1WYHpJCkyMEXjycYWJQPUMaCWUIs9kiDME?= =?us-ascii?q?TqShRJE71RG1rgP6zKBnLuXM8C0CqZ3jzMR15/HUlRwq9zx0Dd6S3H2OT2FvmW?= =?us-ascii?q?MIQT423L5krExzzleDzKd5jOdFFdxV+/NJTx02NZnGz+x1E9ryQB7Ofs+VSFa6?= =?us-ascii?q?RdWrGT8wTtM1w98LfUl9Ac6vjh7d0CW3BL8VjaaEBIQu8qLb3Xj+Odpyy2rc2K?= =?us-ascii?q?kmlVkmTdNFNXe6ia5n6wjTG4nJnl2EmKm2cKQc2yjN9HuewWeVokFXThRwUaTE?= =?us-ascii?q?XHAYYEvat9L56V3eT7W2E7QoLhNBydKeKqtNctDmkElGS+35ONnFf22xnGKwCg?= =?us-ascii?q?qSybOXcIrmYWMd0zvBCEIciQAc4W6GNRQiBiemu2/fDD1vFVXpY0739Ol+rGq3?= =?us-ascii?q?Tk4yzw2QaU1uzaC1+h0UhfyCVfwfxLQEtzk9qz9sBlayw8rWC8acpwpmZKhTf8?= =?us-ascii?q?s9701d1WLYrAxwJYSgILp4hl4faAR3p0fu2A9rBYpei8Qqq2kqzAVqI6KCzFxB?= =?us-ascii?q?by+Y3Yz3OrDPJGny5gqga6jK1VHfy9ab4aIP6Ow5q1n6pwGoGFEi/29g09lP3H?= =?us-ascii?q?uW/o/KAxYKUZLtTkY38AB3p7LAbSk+4IPUyGZhMaquvT/B3NIpGfEpyhG6f9dQ?= =?us-ascii?q?KKmEDhP9E9UGB8iyL+wng0KmYQ8ePOBT6qE0JdireOGa166uJupgmyimjWtf6o?= =?us-ascii?q?Bnzk2M7zZ8SvLP35sdw/GXwA+HVzP7jFq6tsD3hJxEZTYXHmWl0yTkA5RRZqJq?= =?us-ascii?q?d4YRFWiuO9G3xsl5h5P1QH5Y+kSjB1Qd2M+1YheSdFr93Qpe1EQSu3OnnzG0zz?= =?us-ascii?q?pqnDE1tqCfxjDBw/z+dBobPW5GXGdjgk3oIYiokd8aRlOoYhM3lBS7/0b13LVb?= =?us-ascii?q?pKFlI2nUW0dIcDD8L3t+XauoqrqCf8lP5Ys0sSpKTeu8YEqVSrrmrhQG1CPjGn?= =?us-ascii?q?dRyyogdzG2oJn5mQJ1iH6FJnZpsHXZYd1wxQvY5NHEQ/5R3z4GRC1mhjnMHVWz?= =?us-ascii?q?Jcem/c+Tl5vZteC+TW2hXIVJcSb31YOAqDe75WpyDB2hnvC8hsHnEQ8g0SPhy9?= =?us-ascii?q?ZqVSLIrBDzYoTw06S6MORncVNyBF/78cZ6HZt+koQojpEKxXcanomV/WYAkWrr?= =?us-ascii?q?NdVb2Ln+bGYUST4Q3dHV5Anl2Et+LnOG3I/5TW2dwspnZ9m7fmwWwTgx78ZUB6?= =?us-ascii?q?eI9LZEhzd6okKkrQLNZvhwhi0dyfwq6H4ene4JohYiziKTA70JBklYIDDjlw+S?= =?us-ascii?q?49C5tqVXa36lcaKs20pmgdChELaCrxlEWHnjZ5ciGTV84d9lPF3X133z7p3keN?= =?us-ascii?q?7Wbd8Isx2YjxHAj+9JJ54rkPoFmzZnM3rnvXI50+47kQBu3ZaisYiENWpt+rm5?= =?us-ascii?q?DwVbNjLrYcMT4TftgrhCnsqM2ICvBJphEC0RXJT0VfKoDC4StfP/OgaQFj0zt2?= =?us-ascii?q?yWGaTZHQCC6EdqtXTPHI63N3uPPnkW0c1iRAWBJExYmA0URC81noM9Fg2x2MPh?= =?us-ascii?q?cVt55zAI6l72sBRMzPhkNx7lUmfQvA2ocCs7SICDLBpK6QFP/1/VPtaD7uJ3AS?= =?us-ascii?q?5Y5oeurAqRKmOFfQRFFnwJWleaCFD5Jbmi/8LA8++FBuqkM/TBf7uOqetEV/eH?= =?us-ascii?q?252jyI1m8CiQNs+XJHltE+U72lZfXXB+A8nZlS8ASyoLlyLKas6Wvxm89TNqoc?= =?us-ascii?q?C46vTkQhrv5ZGIC7tQL9pg5wy2jb2EN+6KiyZzMSxY2Y8UxX/U1Lgf20YfiyR0?= =?us-ascii?q?eDmpFbQPqzLNTL7KlaBNFBMbbT18NNdT760gxAZNIdDUhsnz1rFmkv4/E01FWk?= =?us-ascii?q?D5msG1ecwKJHmwNEndCEeFLriGICfEw8XwYaK8UrBflvlbtxiqtTacCU/jMSyJ?= =?us-ascii?q?lyP1WBC3LeFMkCabMQRQuIGnbBliFHPjQ8jgah2nN993liY7zqcoiXPPL2IcNi?= =?us-ascii?q?J8c0xVpL2K8SxYmul/G3BG7nd9K+mEgTyW7/HAKpsNv/trAz50l/lG4HQ0yrtV?= =?us-ascii?q?6jtLRPpplyvTtNFup0uqku6VyjpoSBBOsCpEhJqXvUV+PqXU7oFAVmjf8x0T62?= =?us-ascii?q?WQCggKp9x+B93upa9f1MbAmLj0KDdY/NLe5dEcCNTMKMKbLHohNgLkFyXPAwcC?= =?us-ascii?q?ST6rNHrfh1BGkP2I7X2asIQ1poL3mJUQTr9bVVo1Fu4VC0l+ANMDII13Xi4/kb?= =?us-ascii?q?KBgs8H/2a+rALWRMVcpJzHUeiSAfr3IjaDkbZEfwcIwa//LYkLLY30wVJiZUN1?= =?us-ascii?q?nIvUAErdRstNrTd/bgAur0VC7mN+Qnc12037dgOn+GUTGuKsnh4qlgt+Zvwg+y?= =?us-ascii?q?zt41c4IVrKojA9n1Qvltr+gDCeajjxIL23XYFMBCr+r1IxPY/jQwZpcQ2ymlRp?= =?us-ascii?q?Oy3LR71Lkbtva3tmiAjEuZRRH/5cSLdLYB4Uxf6MYPUp3k5QqiK9xU9I/eHFE4?= =?us-ascii?q?dtlBM2cZ6wqHJNwx5jbNkwJaDKPqpJyVlRibyIviCzzOAxxxERJ0UW/WyOfy4I?= =?us-ascii?q?vVAHOaM9Jyq05OBs7xKNmydbcmgWS/Uquu5q9l86O+mYzCLh07pDJV6qOuyaKK?= =?us-ascii?q?OZtWbAmtCUQlMs1kMIkExF8qZs3cclbUWUS1glzKGNGBQRKcrCNQZVYtJU9HfN?= =?us-ascii?q?ZymOtf7AwZFyP4WmCuDnV+mOtL0XgkKlBgopGZoD7tgZFJm2zE7YNdvnLKICyR?= =?us-ascii?q?g1/gTkOk6FA+pTdxKRjDgHo9qyw4R23YlHOz4dBmt9MT2t5rnJpg4mmvyDU8kq?= =?us-ascii?q?Yn0CRIsLKmo2WNGmmy5ep3lPET630uQfyAef8TD8oiXQASLmYNV9fveUYglgCN?= =?us-ascii?q?as+TUw66K2k0LY8o3CJ2HmMtRvosLA5vkEp5aGFvxUVqJwvF3Gm4lCQHyrXXXP?= =?us-ascii?q?HsCpKJjtcYksbMD0C3agXly5lT01U9/7PMyxIaiQnQHoWYFUvZGG0zA4K8CyDD?= =?us-ascii?q?4eGw1qqOEd/698fhcMY5kmYR7yrQsyLai/IBqe0tq0WWahMCdWT/5czeS6YLxb?= =?us-ascii?q?1SwsYfGmyHE4VJE10/G38VIRRJENlhzewfGjZ5NAXij1G31dfB7CpSU/l2h8LO?= =?us-ascii?q?oyxf0/wBzQu1kGLz+LbPBpaHBDv9wkHlOdP3F2Cms+R1+BgovO+RKj37cX/yRB?= =?us-ascii?q?hdlUyvFFvGL4vpDBfDKmQLarponNsyo8cdgmpLV8MY/5IsqGrpzemCDfTJnLvw?= =?us-ascii?q?2KVy66D+ZVlsJWIC1GXPlCgXslNtAeuYpd9UoxUd8zJ6BOCKkpobCqdTpkDC4J?= =?us-ascii?q?wCAEVoOB3CYNjfym17vciBiQbIwoMAYYv5VantsdTyl2bzsEq6+nVoXZi3GLRX?= =?us-ascii?q?AOIAYT6wRM4wQAmZVrc+/+4YrHVplMxydYo/JpSCfLEIdn90fjQGGMnVf4UOmh?= =?us-ascii?q?k/Cu3Q9K1/3jzN8bVQVlBkdA2eZZiFEoKKptJKkKvo/GqDiIdVn1vGj10uupOE?= =?us-ascii?q?FRydHId13/FIfFunf8UiwY+X0QW4BPzWrSGokMnAViaaYkvlNMLJqhekbk6Dwu?= =?us-ascii?q?355pEKWgVcC321Ylqm4LRz2sE9pAF+5msFXXWDl+Y56zsZvrJo9cT3NX9pCGt1?= =?us-ascii?q?hZl0BtPDKjxppHN8FB+DgMUyZToT+Fptu9VNVD2dNqD58LOtp/oWryF75fNZie?= =?us-ascii?q?pn03tabjynnH9DAgqF263im8G7ekT+JF+G0TAh8pKH6EqkkoFOQh6XvS8krXvV?= =?us-ascii?q?Bq4ehbArmPjUN+oDZ5H5BOCTZJ1WyrL1tpVnlGtv9WKKLLfMxAW/MyfwOgOwQi?= =?us-ascii?q?Ff462EyE5U91kW3lbCxytwta/iHdUBM3VSQOg7fihyMRpd+9NT8dUZJIYi0rbz?= =?us-ascii?q?3ZJAKDhSBXoBFfZllwVJADH9ZF/asX3YhP88rDSEasKD0FUwd4OgI+z/VfiVZJ?= =?us-ascii?q?sF+EdiDFEQqoafHPvwV2fceXsM6mMvD58xlCioz5rOA47aUCSmahmQ21X9/eqY?= =?us-ascii?q?r8uceLtkuKb6j4NOK9bWXGTDjWghC6na0kAIXS/yjPLApbLIF3yXU+YZf7D27L?= =?us-ascii?q?IQ9LJ6McJ0tVU6B6ddVGrf5bZ89iZKYG57VtCgiBRhzxBIyltONGIUrLRTTCMy?= =?us-ascii?q?WB9fSyoZ7U7bzYUuXgetCAx3PcTK5tOJd19yX7Ea/w0YBC4kr2xutt9kRiRFjG?= =?us-ascii?q?KS+Bts7uJgcW68S5a0TtoIUpHSvID5d0jnXt3FtMd80NQy2l6J4Y0o9W6G7sSe?= =?us-ascii?q?Jk1Uj+qO9S97565oQs/r9m19y0KrnIKfRGr0BoHwKYBgN0+ZUxGGJ/XXxeYvcN?= =?us-ascii?q?KPfNeqQUldvhq+7rGKAL6hCZ5uJUZMDbKEHGn8mwFiuTSQdYnAsbrz4VMBec3e?= =?us-ascii?q?afm6BoUcalufT52kU17likMBEJ0bBt6p2Y+qeToO/XaAXRwqYaVqf2QcP8s6oj?= =?us-ascii?q?t1mU5fI6iL4EYnZ1bBG/EOgBSs4dwX/tzbgxzSIwCczMAq7g9eVYV3I+gzLggY?= =?us-ascii?q?xyEEsQGvMIB7qE54Bekn0/m+zDOd0carpClXqXFR64Dr8Czmam6zeNIGZ7nB7B?= =?us-ascii?q?zgr9QX637F/qty93WzXMz9bkkkpRSLa3GV1eXy2zOU93qDmPJhbntMLruaQp60?= =?us-ascii?q?E7KnHrtNSXm2a6JbxXGdfwKMabISkuq1IdlIcxScC32YAHBdq9J88c8HNkYfvE?= =?us-ascii?q?7GOriCtBrL1Zh4fF58GV5/HXHWWhj6KGqrWC3jZYymMisVE48NCgOenE58eWTP?= =?us-ascii?q?Swy2YRUyB/thPDXxGvrLzboUoUOUuW30jVg4EKIstW3X8j1kHh/uQjRsw89BlG?= =?us-ascii?q?HIbae/wCvSzzOCfzwVuHZdI3UjKT0zpRHlLwC1V4Ga482GzqvM3TjnfQ50coRp?= =?us-ascii?q?RseEz7mBx3FZs3JVgq6FgNzSoJCRINZgyDDLG0GUTlKpMJVU4CaRub27i6fr04?= =?us-ascii?q?3VZpzrOu4+/Tavd8B7EWO/ZYgQOPk0JXGpUMsa0RWLh8YUNS9LbLpgj+DIjqR+?= =?us-ascii?q?TpmmA0NfKrWcBa7cAYt3w57wakWxWg6IlM77AHiJCJbKFIe57Ms95g701//z4A?= =?us-ascii?q?ajRNgARjjxO+Se0coPvj4t3bvZez5OahSrsiR+IN9xcuH2R+lZzwgFI9rt7Ly+?= =?us-ascii?q?dQUIrViZ7w8ApVOX6FpJ7a0wVgKeoJM4+rfrdg93AcKigbOX0PPcSZa+M94y9r?= =?us-ascii?q?PzXf/VpCDd0QZdkAJsrChRhUilH1WLFU7sfbG16ZBJ1peM809Gf30y468YciXe?= =?us-ascii?q?n88jO2Iorf715VNfNZkCpsjM7CpPQSwffKEycX4GKZahZvzSOAypmNF+7w8v+R?= =?us-ascii?q?yNHQTF4JAik2XJpDKzWY5AynXO21lI/zXQ+O7c/zmp0+flqKRnOthKQFrrpMEe?= =?us-ascii?q?lYhyXjxDdeCpz6h/Kbstqr8mtXtURLEJ1t4h3BGaVfOIh7OBvjm8mzXEd8Gjfw?= =?us-ascii?q?eMHadxopouqWxf0A4+ZgOEvkY48UPBYEx6j96XpPQQtkUKT2sUqBXeINeNtmT+?= =?us-ascii?q?vJrmxP6Y1+L68AJl6dq4LxozhVqVA2Dw4paKMqoTxBbEbOhhBVV7zyuLEelgsW?= =?us-ascii?q?ScR5tlNUGWKsJGI+4CLKVatPg6mLFvMV7jWTQ7cKU0VpLiNxXRO1149ze7uyh/?= =?us-ascii?q?xHtH1Jnj9lqvgwzzNmXAe8uTHrp68V1jIv5re4tCkGuXxCSemeiDnHCVFCzPQM?= =?us-ascii?q?kKcdBG3v6Viib3kZbIr9+qNrJcL++ok9+34/ewksfzUaXeS8DCH9l7+HAo6Vv9?= =?us-ascii?q?1AnxOCpMLObbu3LSgTKLs90w7jSGZh3Qjehhpo93ELQjq45t8+OIq9Idolxjav?= =?us-ascii?q?GWXDcVYM5aVJsNf+tVEVV+Y2bFJhz39l0seZWi0MSsvPG3w2jgg/c2lEdoxM6Q?= =?us-ascii?q?MCHakynjmIprVG/h0TYDrMHYSq5pLQndzR1XcgQtlkwGPWpquYhpIly3BllNZ0?= =?us-ascii?q?4TSIuHsMbeDYVNVsAnfr3IdF1eP+f+mtsvwASIZ+yrShV/8CMs+59WSq2JVqXl?= =?us-ascii?q?KlyakfHlq4Nu8D3bTbUya+RG2GWOSLbXKDnzIkPU7z/xWoKEM4aNtSpU8nLuTC?= =?us-ascii?q?noJclxHmUb5sRyWQu0XUzGo4POMeagI5pYanewsRTOILYOicP+cuyuUkCFQQd3?= =?us-ascii?q?/JATd2C+iuvF6vgod7NXtg4UHhbOXj6A/mNsWdGgUeHY7csJFx5eSwRnidNn94?= =?us-ascii?q?0B1yIE50+v/QF1Q1se9dfYiendzUh9lgyu4FcPFtMSwhtdIJnIJs95WU2t+QcR?= =?us-ascii?q?7N1pbyOc3Vov+ADv3dz0QrenlaUr0dYQP0+4U1IMU0W7jSHbtFpxQTG7I2QJs7?= =?us-ascii?q?N2f+7Kt0Nh98chbNZLSohcnnvv6LZppRp3LN8lIwLTvTux4dxfywVwB7aY6lh2?= =?us-ascii?q?nqKpAqWj1Bt8FtCgdhHIZXHsMArgmnA52TmKygid++4UB6u+gMsaXuDPDGztK5?= =?us-ascii?q?0JttX5JC/0yEIC7RBLV3gkRilum9menP0p/tCc75YtMEUO97QnLZar/YAIqwNy?= =?us-ascii?q?iCOsXme05J67Scyq52Ug2NZCDlWKqLrDWkNPJg4Uoh0Ix5cu3TzDgj77zA3dvy?= =?us-ascii?q?YGZbpjy9onGVLptf60fKBfffXxJSRvqJ6mFlHbcYbYHs7ucBLcQiwMSA4wl09D?= =?us-ascii?q?lC3tWKI6ygrk/UxE12bpPaLErs2yY8R4YKOhC/PlU2jW/esHTdDmxWLtK4Jsl1?= =?us-ascii?q?nNaVEhvt6lF/mGE1fG5BG3bnSsmKNGge2sK+eBeK+xxRA9YEhe63dlYytreuRu?= =?us-ascii?q?lwJpVFheKqua0AkdZtNS7CX9BaPyXKI79tIjpRD/nApEQyYhEarbc5QIE1aoaS?= =?us-ascii?q?IEkfKkeP1TvyzRfe0U3zb9Gs0KeJICAL8nRI1r7F1TlMpxKlufaCmcDjUarWbJ?= =?us-ascii?q?fxXPLINyolTD6aTywoEUm14Vekp+YEvP2ALGcEvF8UZiOSCAgOpqFgqtTeAXPT?= =?us-ascii?q?me19c50Qmv+aQzr/RTZ7lKUsHCZLs16DQ/4YGgnLYH/tmm1cuBatJvVU53Lqc6?= =?us-ascii?q?WYxrZJW+wRGoZMd+eWTMfYefBfITcokS4UOPi9f93asbk51lPITW0EE6jH7lGe?= =?us-ascii?q?S1SWQvOEzTLxQYoVp5Q0ujYv+t/InC94CafIP7GEqDO17464ijqYue3ZVmkwbE?= =?us-ascii?q?w1gP4CDHOHwBZeNGEOE8sVt131Qq6ce0ZM02okie101BAXYgRzU2Nh0nlNkfaj?= =?us-ascii?q?Hs1WU0UUjGKzQPEcalB4Ei8w91eQ4gLuedwApdzTR2hG+7sOTIodK+Mo6JPWOK?= =?us-ascii?q?sL2/sp2ihpoCkkvCWcFV9diRiF86XIFqJm2rJC/XU4/+1xXkyXWDPffG3HxZan?= =?us-ascii?q?Bs9M3ipuv27r19DVvuFsM7taoZt1AFEUDiJqPtrd5yxOUXno2AuuuBa2BDaeID?= =?us-ascii?q?Uf4DYPPiEFc/h6wPJ1sBbPbNbO9V2fu7gnqES1FQbYQoazjYdGDsDvyBWQdThA?= =?us-ascii?q?cTLtEYt/7PlKipJaZaIheJj7GFvdNiDgAQ+C/SMB7h7npvKsF8UOimEflLg8bc?= =?us-ascii?q?rkVJQQDMXImTR/z2tMybIRwmCLRNDSfJv074p/H35dGIO6TCzRYZnJNi/+/NAK?= =?us-ascii?q?05EjDA7GcuQRPGtBv6k9oWfjblWl4q/64i6LMqyiczGlfsoJNcL72CF1nq/dO9?= =?us-ascii?q?a2tLR5An0d8P15184=3D?= X-IPAS-Result: =?us-ascii?q?A2EgAgAaxK1Y/wHyM5BeFgQBAQEBAgEBAQEIAQEBARUBAQE?= =?us-ascii?q?BAgEBAQEIAQEBAYMmYYEJjlWdZYoBGyUiD4h7VwEBAQEBAQEBAgECXyiCMyIJB?= =?us-ascii?q?D0KAy4BAQEBAQEBAQEBAQEBAQEBGgIIBRgrAQEgAhcNEwYBDSAMAgMJAgUSKQg?= =?us-ascii?q?IAwEtFRgHCwUYBIdnA4FRAQMVBAqwYTomAoJhBYEChFmCaAEZBAiEP4k+DyWBM?= =?us-ascii?q?BEBA4V+BYkSkn6GdIsigghTiA4MhiiINYpwWHgIIRQfU4Q8Dx2BYXUBh1cBDRc?= =?us-ascii?q?HghABAQE?= Received: from unknown (HELO tarius.tycho.ncsc.mil) ([144.51.242.1]) by emsm-gh1-uea10.nsa.gov with ESMTP; 22 Feb 2017 17:06:21 +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 v1MH6JXs002067; Wed, 22 Feb 2017 12:06:19 -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 v1MH4diq227288 for ; Wed, 22 Feb 2017 12:04:39 -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 v1MH4d49001507 for ; Wed, 22 Feb 2017 12:04:39 -0500 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A1D+AABZxK1Yh8oAFEFeFgQBAQEBAgEBAQEIAQEBAYQygQmOVZ1lhiiEHAwihXSDXgECAQEBAQECEwEBAQoLCQodhUANGQE4ARWBKRKICAOBUQEDFQQKsGE6gwkFgQKEWYJcAQEIAhoECIQ/iT4PJYFFgmUMgw0FiRKSfoZ0iyKCCFOIGoYoiDWKcIFXIRQfhQ8PEQyBYXUBh1cBJAeCEAEBAQ X-IPAS-Result: A1D+AABZxK1Yh8oAFEFeFgQBAQEBAgEBAQEIAQEBAYQygQmOVZ1lhiiEHAwihXSDXgECAQEBAQECEwEBAQoLCQodhUANGQE4ARWBKRKICAOBUQEDFQQKsGE6gwkFgQKEWYJcAQEIAhoECIQ/iT4PJYFFgmUMgw0FiRKSfoZ0iyKCCFOIGoYoiDWKcIFXIRQfhQ8PEQyBYXUBh1cBJAeCEAEBAQ X-IronPort-AV: E=Sophos;i="5.35,195,1484024400"; d="scan'208";a="5953964" Received: from emsm-gh1-uea11.corp.nsa.gov (HELO emsm-gh1-uea11.nsa.gov) ([10.208.41.37]) by goalie.tycho.ncsc.mil with ESMTP; 22 Feb 2017 12:04:11 -0500 IronPort-PHdr: =?us-ascii?q?9a23=3ADZP0PxzzNCD1wgjXCy+O+j09IxM/srCxBDY+r6Qd?= =?us-ascii?q?2uwWIJqq85mqBkHD//Il1AaPBtSGrasawLuL+4nbGkU4qa6bt34DdJEeHzQksu?= =?us-ascii?q?4x2zIaPcieFEfgJ+TrZSFpVO5LVVti4m3peRMNQJW2aFLduGC94iAPERvjKwV1?= =?us-ascii?q?Ov71GonPhMiryuy+4ZPebgFIiTanfL9/LRq6oAHRu8ILnYZsN6E9xwfTrHBVYe?= =?us-ascii?q?pW32RoJVySnxb4+Mi9+YNo/jpTtfw86cNOSL32cKskQ7NWCjQmKH0169bwtRbf?= =?us-ascii?q?VwuP52ATXXsQnxFVHgXK9hD6XpP2sivnqupw3TSRMMPqQbwoXzmp8qFmQwLqhi?= =?us-ascii?q?gaLT406GHZhNJtgqxVoxyvoAdyz5LIbIyPKPZzZL/Rcc8cSGFcXshRTStBAoak?= =?us-ascii?q?YoUTDuoOIeZYoJPnp1QTsBCwBxOjBOLpyjBWnX/9wKo30/4gEQ7a3AwvBcgOv2?= =?us-ascii?q?nMo9rpLKgSUfq6zKjOzTrddPNbwizy6JTJchAnvfGDQ6hwcczPxkkzDQ/KklKQ?= =?us-ascii?q?qYn8Mj6Ty+8DvW+b7+96WuKujW4qsxpxrSarxsctjInJm40Uykje9SV+woY6O8?= =?us-ascii?q?G3SFJhbd6jCptQuDmWN4R3QsM+Q2FopT01xqcatp68eSgG0IwnyATCa/yDaoSI?= =?us-ascii?q?5xXjVOGLIThmnn5qZLW/hxO0/EO9yeP8TtG53VdKoyZfjNXAqmoB2wDJ5sSZVv?= =?us-ascii?q?dx4F+t1DWO2gzJ9+1JLkE5mbDaJpMj2LI9l5kevELeFSHsgkr2lrWZdkA89+io?= =?us-ascii?q?9evnZrLmq4eGN497jQH+L7gultChDegiKQcOQ3KX+eC71L3l/UD1WqlFjuUqna?= =?us-ascii?q?ndt5DaONkUqrSlDA9SyIoj9hW/Ay+n0NQeg3YHMEpIdROHgoTzJV3CPOr0Aeul?= =?us-ascii?q?j1iyjDtn2ejKPrj7DZXMKnjDnq3hfbF460NE0gozzMxQ55JOBbEbPf38QlP+u8?= =?us-ascii?q?TYDhAjMgy0xfjoCM5m24wFRWKPA6mZML/Mvl+S4OIgPfWMaJUJtzb6Lvgp/+Tu?= =?us-ascii?q?gmMhmV8BYamp2oMaaGumEfRiIkWZZ2fsg9gaHGcWvgsxUOzqiFqYXT5VfHa9Rb?= =?us-ascii?q?gw5j48CIK4Xs//QdW2jbiA2jqrNoFHbWBBTFaXGDHncJvAE/MNbj+CZ9RqjiQs?= =?us-ascii?q?S7esUcki2AuouQu8zKBoaqLQ+ysFpdf42dNo/ezPhFQ38jBpC8m1zW6AVSd3k3?= =?us-ascii?q?kOSjtw27pw8mJnzVLW66lzg/VCGZRz7vJPXxxyYYTdxOxzEdzFUTXBd9aPRU2O?= =?us-ascii?q?SMmnBy08VNQ835kFZEMrSIbqtQzKwyf/W+xdrLeMHpFhqq8=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0EPAQAaxK1Yh8oAFEFeFgQBAQEBAgEBA?= =?us-ascii?q?QEIAQEBARYBAQEDAQEBCQEBAYQHgQmOVZ1lhiiDWRsoDCKFdINeAQEBAQEBAQE?= =?us-ascii?q?CAQIQAQEBCgsJCh0vgjMgCwQ9CgMuAQEBAQEBAQEBAQEBAQEBARoCCAUYKwE6D?= =?us-ascii?q?RkBOAEVgSkSiAgDgVEBAxUECrBhOoMJBYEChFmCXAEBCAIaBAiEP4k+DyWBRYJ?= =?us-ascii?q?lDIMNBYkSkn6GdIsigghTiBqGKIg1inCBWCEUH4UPDxEMgWF1AYdXASQHghABA?= =?us-ascii?q?QE?= X-IPAS-Result: =?us-ascii?q?A0EPAQAaxK1Yh8oAFEFeFgQBAQEBAgEBAQEIAQEBARYBAQE?= =?us-ascii?q?DAQEBCQEBAYQHgQmOVZ1lhiiDWRsoDCKFdINeAQEBAQEBAQECAQIQAQEBCgsJC?= =?us-ascii?q?h0vgjMgCwQ9CgMuAQEBAQEBAQEBAQEBAQEBARoCCAUYKwE6DRkBOAEVgSkSiAg?= =?us-ascii?q?DgVEBAxUECrBhOoMJBYEChFmCXAEBCAIaBAiEP4k+DyWBRYJlDIMNBYkSkn6Gd?= =?us-ascii?q?IsigghTiBqGKIg1inCBWCEUH4UPDxEMgWF1AYdXASQHghABAQE?= X-IronPort-AV: E=Sophos;i="5.35,195,1484006400"; d="scan'208";a="3379525" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from rgout0203.bt.lon5.cpcloud.co.uk (HELO rgout02.bt.lon5.cpcloud.co.uk) ([65.20.0.202]) by emsm-gh1-uea11.nsa.gov with ESMTP; 22 Feb 2017 17:04:07 +0000 X-OWM-Source-IP: 86.146.67.68 (GB) X-OWM-Env-Sender: richard_c_haines@btinternet.com X-Junkmail-Premium-Raw: score=8/50, refid=2.7.2:2017.2.14.234516:17:8.707, ip=, rules=NO_URI_FOUND, NO_CTA_URI_FOUND, NO_MESSAGE_ID, NO_URI_HTTPS, TO_MALFORMED Received: from localhost.localdomain (86.146.67.68) by rgout02.bt.lon5.cpcloud.co.uk (9.0.019.13-1) (authenticated as richard_c_haines@btinternet.com) id 58482B9707A702A8; Wed, 22 Feb 2017 17:04:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=btinternet.com; s=btcpcloud; t=1487783047; bh=WSyCOTe6L5WcgRTXD21k3mFg3/ByO8tJ8BV2nL04+DA=; h=From:To:Cc:Subject:Date:Message-Id:X-Mailer; b=ZEKGI0/fGZrfAV6cowA53gxyQuYSbVw9ilRrnVOvU2GUBXavSMCI/qZAHMLVQ1KMi2GwZPCSngpyG8ZQ97bN4fPkcSgQi+cN4uMJkbz0+BZhY0BGojL94kSN+8EuYE7tO8fjvVsSQfsH0oRoEBuiL7Dkty5oqImlun88Ib/pSbM= From: Richard Haines To: selinux@tycho.nsa.gov, linux-sctp@vger.kernel.org, linux-security-module@vger.kernel.org Subject: [RFC v2 PATCH 2/2] kernel: Add SELinux SCTP protocol support Date: Wed, 22 Feb 2017 17:03:59 +0000 Message-Id: <20170222170359.5433-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.9.3 X-BeenThere: selinux@tycho.nsa.gov X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: MIME-Version: 1.0 Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Virus-Scanned: ClamAV using ClamSMTP Add SELinux support for the SCTP protocol. The SELinux-sctp.txt document describes how the patch has been implemented. Patches to assist the testing of this kernel patch are: 1) Support new SCTP portcon statement used by SCTP tests in the selinux-testsuite [1]. 2) Add SCTP tests to the selinux-testsuite [2]. Built and tested on Fedora 25 with linux-4.9.9 kernel. [1] http://arctic.selinuxproject.org/~rhaines/selinux-sctp/selinux-Add-support-for-the-SCTP-portcon-keyword.patch [2] http://arctic.selinuxproject.org/~rhaines/selinux-sctp/selinux-testsuite-Add-SCTP-test-support.patch Signed-off-by: Richard Haines --- Documentation/security/SELinux-sctp.txt | 178 ++++++++++++++++++++++++++ include/net/sctp/structs.h | 7 ++ net/sctp/sm_make_chunk.c | 12 ++ net/sctp/sm_statefuns.c | 20 +++ net/sctp/socket.c | 42 ++++++- security/selinux/hooks.c | 213 ++++++++++++++++++++++++++++++-- security/selinux/include/classmap.h | 3 + 7 files changed, 466 insertions(+), 9 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..ada666f --- /dev/null +++ b/Documentation/security/SELinux-sctp.txt @@ -0,0 +1,178 @@ + SCTP SELinux Support + ====================== + +Testing - selinux-testsuite +============================ +There is a patch available that adds SCTP/SELinux tests to the +selinux-testsuite. This is available from: + +http://arctic.selinuxproject.org/~rhaines/selinux-sctp/selinux-testsuite-Add-SCTP-test-support.patch + +These tests require libsepol to support the new sctp portcon statement. +A patch is available from: + +http://arctic.selinuxproject.org/~rhaines/selinux-sctp/selinux-Add-support-for-the-SCTP-portcon-keyword.patch + +Before running these tests, read the selinux-testsuite/README.sctp as it is +also possible to run the lksctp-tools/src/func_tests that are available from: + +https://github.com/sctp/lksctp-tools + + +Security Hooks +=============== + +The Documentation/security/LSM-sctp.txt document describes how the following +sctp security hooks are utilised: + security_sctp_assoc_request() + security_sctp_accept_conn() + security_sctp_sk_clone() + security_sctp_addr_list() + + +Policy Statements +================== +A new object class "sctp_socket" has been introduced with the following SCTP +specific permissions: association bindx_add connectx + +The permissions are explained in the sections below. + +Kernel policy language +----------------------- +class sctp_socket +class sctp_socket inherits socket { node_bind name_connect association + bindx_add connectx } + +CIL policy language +-------------------- +(classcommon sctp_socket socket) +(class sctp_socket (node_bind name_connect association bindx_add connectx)) +(classorder (unordered sctp_socket)) + +If the SELinux userspace tools have been updated, then the portcon statement +may be used as shown in the following example: + (portcon sctp (1024 1035) (system_u object_r sctp_port_t ((s0) (s0)))) + +Rule validation parameters used when 'network_peer_controls = 1': +------------------------------------------------------------------------------- +Rule Source Target Class Permissions +------------------------------------------------------------------------------- +allow socket_t socket_t : sctp_socket { bindx_add connectx }; [1] +allow socket_t port_t : sctp_socket { name_bind name_connect }; [2] +allow socket_t node_t : sctp_socket { node_bind }; +allow socket_t peer_t : sctp_socket { association }; + +[1] setsockcreatecon(3) may be used to create a new labeled socket. +[2] The port types may differ for name_bind and name_connect. + + +SCTP Bind, Connect and ASCONF Chunk Parameter Permission Checks +================================================================ +The hook security_sctp_addr_list() is called by SCTP to check permissions +required for ipv4/ipv6 addresses based on the @optname as follows: + + ------------------------------------------------------------------ + | BINDX_ADD 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_PARAM_ADD_IP | One or more ipv4 / ipv6 addresses | + | SCTP_PARAM_SET_PRIMARY | Single ipv4 or ipv6 address | + ------------------------------------------------------------------ + +A summary of the @optname entries is as follows: + + SCTP_SOCKOPT_BINDX_ADD - Allows additional bind addresses to be + associated after (optionally) calling + bind(3). + sctp_bindx(3) adds a set of bind + addresses on a socket. + + SCTP_SOCKOPT_CONNECTX - Allows the allocation of multiple + addresses for reaching a peer + (multi-homed). + sctp_connectx(3) initiates a connection + on an SCTP socket using multiple + destination addresses. + + SCTP_PRIMARY_ADDR - Set local primary address. + + SCTP_SET_PEER_PRIMARY_ADDR - Request peer sets address as + association primary. + +Note that to support Dynamic Address Reconfiguration the following +parameters must be enabled on both endpoints (or the appropriate +setsockopts): + /proc/sys/net/sctp/addip_enable + /proc/sys/net/sctp/addip_noauth_enable + +then the following *_PARAM_*'s are sent to the peer in an +ASCONF chunk when the corresponding @optname's are present: + + @optname ASCONF Parameter + SCTP_SOCKOPT_BINDX_ADD -> SCTP_PARAM_ADD_IP + SCTP_SET_PEER_PRIMARY_ADDR -> SCTP_PARAM_SET_PRIMARY + + +SCTP Peer Labeling and Permission Checks +========================================= +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, the "association" permission will be checked as +follows: + + allow socket_t peer_t : sctp_socket { association }; + +This allows policy to decide whether to allow or deny associations from peers, +as there can be multiple associations on a single socket. These associations +could come from any of the policy allowed peers, however it could be that +these are required by other services but sctp associations are not allowed +from all of them. + +NOTES: + 1) If peer labeling is not enabled, then the peer context will always be + SECINITSID_UNLABELED (unlabeled_t in Reference Policy). + + 2) If peer labeling is supported, getpeercon(3) may be used by userspace + to retrieve the sockets peer context. + + 3) 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). + + 4) 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, + except for the following issue that requires further work to resolve: + + a) SCTP does not support "cmsg_type == SCM_SECURITY" in datagrams for + ipv4 or ipv6, therefore CIPSO/CALIPSO will fail unless TCP type + sockets are used. See the SCTP tests in the selinux-testsuite where + pass/fail configurations are noted. + + 6) 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/include/net/sctp/structs.h b/include/net/sctp/structs.h index 11c3bf2..d54a767 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1287,6 +1287,13 @@ struct sctp_endpoint { __u16 active_key_id; __u8 auth_enable:1, prsctp_enable:1; + + /* Security identifiers from incoming (COOKIE-ECHO) connection. + * These are set by security_sctp_accept_conn() and used by + * security_sctp_sk_clone() to set sids on newsock. + */ + u32 secid; + u32 peer_secid; }; /* Recover the outter endpoint structure. */ diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9e9690b..648b63b 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3056,6 +3056,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, if (af->is_any(&addr)) memcpy(&addr, &asconf->source, sizeof(addr)); + if (security_sctp_addr_list(asoc->ep->base.sk, + SCTP_PARAM_ADD_IP, + (struct sockaddr *)&addr, + af->sockaddr_len)) + return SCTP_ERROR_REQ_REFUSED; + /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address * request and does not have the local resources to add this * new address to the association, it MUST return an Error @@ -3122,6 +3128,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, if (af->is_any(&addr)) memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); + if (security_sctp_addr_list(asoc->ep->base.sk, + SCTP_PARAM_SET_PRIMARY, + (struct sockaddr *)&addr, + af->sockaddr_len)) + return SCTP_ERROR_REQ_REFUSED; + peer = sctp_assoc_lookup_paddr(asoc, &addr); if (!peer) return SCTP_ERROR_DNS_FAILED; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8ec20a6..363793c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -315,6 +315,13 @@ sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net, sctp_unrecognized_param_t *unk_param; int len; + /* Update socket peer label if first association then check + * whether association allowed. + * See Documentation/security/LSM-sctp.txt for details. + */ + if (security_sctp_assoc_request(ep->base.sk, chunk->skb)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + /* 6.10 Bundling * An endpoint MUST NOT bundle INIT, INIT ACK or * SHUTDOWN COMPLETE with any other chunks. @@ -508,6 +515,13 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, struct sctp_chunk *err_chunk; struct sctp_packet *packet; + /* Update socket peer label if first association then check + * whether association allowed. + * See Documentation/security/LSM-sctp.txt for details. + */ + if (security_sctp_assoc_request(ep->base.sk, chunk->skb)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); @@ -812,6 +826,12 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, goto nomem_aiev; } + /* Received COOKIE-ECHO so store security info in ep. + * See Documentation/security/LSM-sctp.txt for details. + */ + if (security_sctp_accept_conn((struct sctp_endpoint *)ep, chunk->skb)) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + /* Add all the state machine commands now since we've created * everything. This way we don't introduce memory corruptions * during side-effect processing and correclty count established diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6cbe5bd..995de4b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1009,6 +1009,12 @@ static int sctp_setsockopt_bindx(struct sock *sk, /* Do the work. */ switch (op) { case SCTP_BINDX_ADD_ADDR: + /* Allow security module to validate bindx addresses. */ + err = security_sctp_addr_list(sk, SCTP_SOCKOPT_BINDX_ADD, + (struct sockaddr *)kaddrs, + addrs_size); + if (err) + goto out; err = sctp_bindx_add(sk, kaddrs, addrcnt); if (err) goto out; @@ -1329,9 +1335,17 @@ static int __sctp_setsockopt_connectx(struct sock *sk, if (__copy_from_user(kaddrs, addrs, addrs_size)) { err = -EFAULT; } else { + /* Allow security module to validate connectx addresses. */ + err = security_sctp_addr_list(sk, SCTP_SOCKOPT_CONNECTX, + (struct sockaddr *)kaddrs, + addrs_size); + if (err) + goto out_free; + err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); } +out_free: kfree(kaddrs); return err; @@ -2858,6 +2872,8 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, { struct sctp_prim prim; struct sctp_transport *trans; + struct sctp_af *af; + int err; if (optlen != sizeof(struct sctp_prim)) return -EINVAL; @@ -2865,6 +2881,17 @@ static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval, if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) return -EFAULT; + /* Allow security module to validate address but need address len. */ + af = sctp_get_af_specific(prim.ssp_addr.ss_family); + if (!af) + return -EINVAL; + + err = security_sctp_addr_list(sk, SCTP_PRIMARY_ADDR, + (struct sockaddr *)&prim.ssp_addr, + af->sockaddr_len); + if (err) + return err; + trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id); if (!trans) return -EINVAL; @@ -3184,6 +3211,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) return -EADDRNOTAVAIL; + /* Allow security module to validate address. */ + err = security_sctp_addr_list(sk, SCTP_SET_PEER_PRIMARY_ADDR, + (struct sockaddr *)&prim.sspp_addr, + af->sockaddr_len); + if (err) + return err; + /* Create an ASCONF chunk with SET_PRIMARY parameter */ chunk = sctp_make_asconf_set_prim(asoc, (union sctp_addr *)&prim.sspp_addr); @@ -7683,8 +7717,6 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) net_enable_timestamp(); - - security_sk_clone(sk, newsk); } static inline void sctp_copy_descendant(struct sock *sk_to, @@ -7714,6 +7746,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, struct sk_buff *skb, *tmp; struct sctp_ulpevent *event; struct sctp_bind_hashbucket *head; + struct sctp_endpoint *oldep = oldsp->ep; /* Migrate socket buffer sizes and all the socket level options to the * new socket. @@ -7829,6 +7862,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, newsk->sk_state = SCTP_SS_ESTABLISHED; } + /* Set newsk security attributes from oldsk and connection + * security attribute from ep as described in + * Documentation/security/LSM-sctp.txt + */ + security_sctp_sk_clone(oldep, oldsk, newsk); release_sock(newsk); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7f4387f..c0be892 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -65,6 +65,8 @@ #include #include #include +#include +#include #include #include /* for Unix socket types */ #include /* for Unix socket types */ @@ -1284,8 +1286,11 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc case PF_INET6: switch (type) { case SOCK_STREAM: + case SOCK_SEQPACKET: if (default_protocol_stream(protocol)) return SECCLASS_TCP_SOCKET; + else if (protocol == IPPROTO_SCTP) + return SECCLASS_SCTP_SOCKET; else return SECCLASS_RAWIP_SOCKET; case SOCK_DGRAM: @@ -4033,6 +4038,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; } @@ -4106,6 +4128,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; @@ -4317,8 +4352,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in /* * 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. + * Multiple address binding for SCTP is supported via + * selinux_sctp_addr_list(). */ family = sk->sk_family; if (family == PF_INET || family == PF_INET6) { @@ -4376,6 +4411,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; @@ -4415,10 +4454,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; @@ -4439,11 +4480,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; @@ -4714,7 +4765,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; @@ -4827,6 +4879,149 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) sksec->sclass = isec->sclass; } +static int selinux_sctp_assoc_request(struct sock *sk, struct sk_buff *skb) +{ + struct sk_security_struct *sksec = sk->sk_security; + struct common_audit_data ad; + struct lsm_network_audit net = {0,}; + u8 peerlbl_active; + int err; + + peerlbl_active = selinux_peerlbl_enabled(); + + if (sksec->peer_sid == SECINITSID_UNLABELED && peerlbl_active) { + /* Here because this is the first association on this + * socket that is always unlabeled, therefore set + * sksec->peer_sid to new peer ctx. For further info see: + * Documentation/security/SELinux-sctp.txt + */ + err = selinux_skb_peerlbl_sid(skb, sk->sk_family, + &sksec->peer_sid); + if (err) + return err; + } + + ad.type = LSM_AUDIT_DATA_NET; + ad.u.net = &net; + ad.u.net->sk = sk; + + err = avc_has_perm(sksec->sid, sksec->peer_sid, sksec->sclass, + SCTP_SOCKET__ASSOCIATION, &ad); + return err; +} + +static int selinux_sctp_accept_conn(struct sctp_endpoint *ep, + struct sk_buff *skb) +{ + struct sk_security_struct *sksec = ep->base.sk->sk_security; + int err; + u32 connsid; + u32 peersid; + + /* Have COOKIE ECHO so compute the MLS component for the connection + * and store the information in ep. This will only be used by + * TCP/peeloff connections as they cause a new socket to be generated. + * selinux_sctp_sk_clone() will then plug this into the new socket + * as described in Documentation/security/LSM-sctp.txt + */ + err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family, &peersid); + if (err) + return err; + + err = selinux_conn_sid(sksec->sid, peersid, &connsid); + if (err) + return err; + + ep->secid = connsid; + ep->peer_secid = peersid; + + return 0; +} + +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; + + newsksec->sid = ep->secid; + newsksec->peer_sid = ep->peer_secid; + newsksec->sclass = sksec->sclass; + selinux_netlbl_sk_security_reset(newsksec); +} + +/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting based + * on their @optname. + */ +static int selinux_sctp_addr_list(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; + + switch (optname) { + case SCTP_SOCKOPT_BINDX_ADD: + err = sock_has_perm(current, sk, SCTP_SOCKET__BINDX_ADD); + break; + case SCTP_SOCKOPT_CONNECTX: + err = sock_has_perm(current, sk, SCTP_SOCKET__CONNECTX); + break; + /* These need just BIND or CONNECT permissions. */ + case SCTP_PRIMARY_ADDR: + case SCTP_SET_PEER_PRIMARY_ADDR: + case SCTP_PARAM_SET_PRIMARY: + case SCTP_PARAM_ADD_IP: + 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 PF_INET: + len = sizeof(struct sockaddr_in); + break; + case PF_INET6: + len = sizeof(struct sockaddr_in6); + break; + default: + return -EPROTONOSUPPORT; + } + + 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: + err = selinux_socket_connect(sock, addr, len); + break; + } + + if (err) + return err; + + addr_buf += len; + walk_size += len; + } + return 0; +} + static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req) { @@ -6252,6 +6447,10 @@ static struct security_hook_list selinux_hooks[] = { 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_accept_conn, selinux_sctp_accept_conn), + LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone), + LSM_HOOK_INIT(sctp_addr_list, selinux_sctp_addr_list), 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 1f1f4b2..b76ed42 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -165,5 +165,8 @@ struct security_class_mapping secclass_map[] = { { COMMON_CAP_PERMS, NULL } }, { "cap2_userns", { COMMON_CAP2_PERMS, NULL } }, + { "sctp_socket", + { COMMON_SOCK_PERMS, "node_bind", "name_connect", "association", + "bindx_add", "connectx", NULL } }, { NULL } };