From patchwork Sat Dec 30 17:20:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Haines X-Patchwork-Id: 10140527 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 80D00601A1 for ; Tue, 2 Jan 2018 13:27:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 76AD4203B9 for ; Tue, 2 Jan 2018 13:27:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6B4BC2899B; Tue, 2 Jan 2018 13:27:49 +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 USFB19PA14.eemsg.mail.mil (uphb19pa11.eemsg.mail.mil [214.24.26.85]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9E635203B9 for ; Tue, 2 Jan 2018 13:27:46 +0000 (UTC) Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.2]) by USFB19PA14.eemsg.mail.mil with ESMTP; 02 Jan 2018 13:27:45 +0000 X-IronPort-AV: E=Sophos;i="5.45,497,1508803200"; d="scan'208";a="7209366" IronPort-PHdr: =?us-ascii?q?9a23=3ARdX/9B8SroYPRP9uRHKM819IXTAuvvDOBiVQ1KB6?= =?us-ascii?q?2+sUIJqq85mqBkHD//Il1AaPAd2Cra0dwLaH+4nbGkU4qa6bt34DdJEeHzQksu?= =?us-ascii?q?4x2zIaPcieFEfgJ+TrZSFpVO5LVVti4m3peRMNQJW2aFLduGC94iAPERvjKwV1?= =?us-ascii?q?Ov71GonPhMiryuy+4ZLebxlViDanY75+MRq6oArVu8ILnYZsN6E9xwfTrHBVYe?= =?us-ascii?q?pW32RoJVySnxb4+Mi9+YNo/jpTtfw86cNOSL32cKskQ7NWCjQmKH0169bwtRbf?= =?us-ascii?q?VwuP52ATXXsQnxFVHgXK9hD6XpP2sivnqupw3TSRMMPqQbwoXzmp8qlkSAXsiC?= =?us-ascii?q?waKTA39m/ZgdF0gK5CvR6tuxlzzojJa4+XKfV+ZLvQc9MES2RPXchfUDFPApu+?= =?us-ascii?q?YocSAecOI/1YopLhq1cStxayGROhCP/zxjJOm3T43bc60+MkEQzewAIgHs4BsH?= =?us-ascii?q?TOo9XvKagZTOK7w7PJzTXFcfxWwir25Y/SchAgvf6MXah/cdDMxkY3CwzKllWQ?= =?us-ascii?q?ppbkPzOTyOsNqHOW4PF8VeKujW4ntx9+oiKpxsgylonFnJ4aylfB9Shgxos+ON?= =?us-ascii?q?O2SEl+YdG+EZtQsTmXN5NsTcM/R2FkoSM6yroBuZ6hYicG0ogoxxnaa/GBboOG?= =?us-ascii?q?4QrjWf6MLTp3i39pYrKyiwuo/US+xeDwSNO43EtSoidGk9TArG0B2hPc58SdV/?= =?us-ascii?q?dw8Uas1SyO2g3S7OxPPFo6mrDBK5E7x749jp8TsUPeESDogEj2l6qWdlk8+uiv?= =?us-ascii?q?9uTnfq3qpp+COI9wjQHzKrguldalAeQ5LwgORHKX+fi81bL//U35R69Gjvsqna?= =?us-ascii?q?nCrJ/WP8Ebpq+9AwNN04Yj7QiwDyu+3dgFknQKI0hJdRKag4TzJV3DL+70Ae2i?= =?us-ascii?q?j1i0lTdk3fHGPrnvApXXKXjDla/sfa1j5E5YyQozy81f5p1NBr4aJ/LzR0nxu8?= =?us-ascii?q?DGAR8iKAG03+bmB8l91oMZQ26PBLSZP7nIvV+H4eIvPfGAZJUJtzblN/gl+/nu?= =?us-ascii?q?gGc7mV8ae6mmx4cXaHCiEfRgOEiZY33sgtEEEWgQpQo+UPLliEeZUTJJYHayRa?= =?us-ascii?q?087CkhCI26FYfDWpytgLuZ0Se5HJ1ZfHxJClOXEXfvcYWEWukMZTmcIs9ljzwF?= =?us-ascii?q?WqOuS5In1RGyqQ/20b1nLvDb+icAr5LsyMB15/HPlRE17TF1AcWd02WIT25qhG?= =?us-ascii?q?MFXDE2075irkx60FeMy7B4g+ZfFdxR+fxGThs6OYTbz+xgBND4QhjBccuRSFa6?= =?us-ascii?q?XtWmBik8Qc8tzN8LZEZ9Hcmigg3Y0iq0HbAVjb2LBZ0z8qLaxXTxIdhyy2re3q?= =?us-ascii?q?k7k1YmWtdPNXGhhqNn6gfTG5TGk1+Cmqm2cqQc2TLC+32YzWqSpk1YVhB/Ubnd?= =?us-ascii?q?V3AFekTWtcj55l/FT7K2CbUmMwxByciZJ6tPbt3llFRGRPH5NNTYeW2xgWSwBR?= =?us-ascii?q?eWxrySdobqfXsS3DnFAkgejw8T5WqGNRQ5Biq5rWLeFiZhFVTzbEPt6ulzs3a7?= =?us-ascii?q?Tlc1zw2TdE1g2aG19gQShfyGRPMZxqgEtzs5qzVoAFa92MrbC9maqApie6VcfM?= =?us-ascii?q?gw4FRd2mLasAx9I4asL6d4hl4Raw53pV/h1w1rCoVclsgntGklwxdoKaKZzlxB?= =?us-ascii?q?bSiV0orsNb3SMGXy+wqva6HO0FHEzNmW4rsP6Og/q1j7pgGmC1ct/m5o09lQ3H?= =?us-ascii?q?qQ/JPKAxQOUZjpSEY46wB6p63GYik6/47UznNsMbOzsj/Zx9IkH/AlyhCnf9ZR?= =?us-ascii?q?NaOLDgnyH9ccB8ewNOwgg0KpYQ4cPOBO6K40ONurdvWc166vIOZvgiimjX9c7Y?= =?us-ascii?q?BjzE2M7TFzSvPN35ofxPGYxASHXS/mjFi9qsD3hZxEZTYKE2q5yCjkAIpRabNp?= =?us-ascii?q?fYsQE2ihPde3xtJki57qQX5Y+0apB0ka18+xZRqSc1v90BVO1UQWvXOnhSy4zy?= =?us-ascii?q?Zunz41rqqf2yrOw+v5eRoDO25LQnNtjU3rIYSuiNAaRkeoZRAzlBS5/Ub627Rb?= =?us-ascii?q?pKNnImnXQEdIZDT2I3h5UqSusrqCYshP6I4nsChMS+S8eVGaSrj8oxQGyCPvBW?= =?us-ascii?q?1eyy4ndzuyoJX2gwR6iH6BLHZ0tHfZY8ZwxRPb5NPCX/5ewj0GRSdjhDnMG1iz?= =?us-ascii?q?I8Kp8c+Tl5fZveC0T3ihWYFLcSn30YOAszO25W50Dh25hPC+gd7nHhY80S/g0d?= =?us-ascii?q?llSznIoAz7Yonx2KSwKfhncVVwBF/g98p6HZlzkpMqi5EN3XgVmI2V8mABkWfv?= =?us-ascii?q?L9pbw7nzbGcWRTEV2d7V+xLp2FZkLnKU3YL2SmuSwsVmZ9mgbWMZxDgx78ZUB6?= =?us-ascii?q?eI9LZEhzd6okKkrQLNZvhwhikdyf0z53MBneEJvhciziWHDrAUA0ZYITTmlw6U?= =?us-ascii?q?4NCmsKVXeGGvfKCo1EVkgNChCKqPrR1dWHblepYuBCFw4d95MF7W133z8I7kcs?= =?us-ascii?q?HKbd0Prh2UjwvAj+9NJZI/jPUKgzZnOWX4vXA+xe40kwFh3ZagvIedM2Vt5qW5?= =?us-ascii?q?AhxGOTLpe8Mf4DbtjbxRnsyOxYCgAo1hGikXXJvvVf+oFSgdtfDjNwmQDD08tm?= =?us-ascii?q?2UFqDEEA+Z9khms2nPHIyxOHGPOnYV19NiSweBJEZHmgAbQC06noIlFgCt3MHh?= =?us-ascii?q?al115z4L6l79sBRMzuVoNhnkX2jFuAioby04SJ+FLBpZ9gtC/VvaMdSC7uJvGC?= =?us-ascii?q?FV5pOhrBaTJWOGfARHF2cJWlCDB1D4JbSh/8XP8+2CCuq5NfvObq2EqfZCWPeQ?= =?us-ascii?q?2ZKvzoxm8i6KNsWVJHZiF+U711FNXXB4AcTZgCkPSyIWlyLLdcGboguz+ixtoc?= =?us-ascii?q?C76vjrXxjv5YSXAbtILdpv4wy2gbuEN+OInCZ2Ny1X2Y0KxX/J1Lgf20UfiyBw?= =?us-ascii?q?eDazD7sMrynNTLjfmqVPFR4UdztzNNdU76I7xgRCItXUhtTx1r55lf41F0xFWU?= =?us-ascii?q?b6ms63ecMGOXq9O03DBEaKMrSGODLKztrrbqK8U71Qkf5Uuwe+uDmBD0/jJTOD?= =?us-ascii?q?lz/zWxCoK+FMgzmRPAZCt4GlbhZtFW/jQcr9ZR26P993ijs2zKYpiXzULmEcMC?= =?us-ascii?q?Jzc0VXor2X9yNYje11G3Zd4Xp9MemEhyGZ4vHCJZYZq/RrHDp7mvld4HQi1bRV?= =?us-ascii?q?6iRES+Z0mCvWtdFupF6nnvOIyjp9XxpEsixLi56TvUV+JaXZ8YFNWWrD/BII92?= =?us-ascii?q?mQERMKptp7Bd3poK9Q0N/Pm7zwKDpZ793U+s4cCNTOJ8KcLHotKxzpFyDIDAEd?= =?us-ascii?q?Vz6kKXnfh1BBkPGV7nCVrZg7qpzyl5cVT79bU1I1Fv0EBUR5ANwCIJB3XjY6nr?= =?us-ascii?q?KBis4H+2a+pgHLRMpGppDHSu6SAfL3JTafk7ZLfR8IzKj7LYQULY37x1Ztal9h?= =?us-ascii?q?nITJGkrcR9ZNrTN9bgUsukVC7GB+TnEv20Licg6t+mEcFeWqkREskAtxfeQt+S?= =?us-ascii?q?z37Fc2PFrFuSwwkEcpmdX/nz+QcCT9LKGuUoFKEyD0rVQ+MovnQwZpag2/hVFr?= =?us-ascii?q?NDDCR7JXkrRva2RriA7HtJRVB/FcV6pEbAUXxfGNaPUiyU5cpTm/xU9b+evFDo?= =?us-ascii?q?NvmxYwfp6yrnJPxhljYcUvKqzKPqpJyVZRhrmQsSC0y+Ax2g4eJ1oN8W+Ifi4H?= =?us-ascii?q?plAIPKE8JyW05uxs9RCCmzxbdWgIUPoquOxl9kU8OuSH1C/g3LhDKl2rO+yYNa?= =?us-ascii?q?OZtHDKldSUTVMoykMIi05F8KBt0cg9d0qUVkYvzKaeFhkSKcXCLgRVYNZI+3jI?= =?us-ascii?q?YSaCq+PNzoxpP4+lDODnUfeOtLoIgkKjBAspA4UM7sEGHpmw0EHZLdzqI6MEyR?= =?us-ascii?q?Qt/gvkP0+JDPJXdxKXiD0Hud2wzIdr3YlBITEQGX9yMSG25rnLuAAlmP+DXdcw?= =?us-ascii?q?YncdWIsLLGk7V9a7myFDuXRMFTe30v8DxAiE8TD8ujzaDCPgYNp7ePeUeRRsBc?= =?us-ascii?q?mt9joh9ai7kkTY/YjAJ27kL9RiocXA6fkappqdDPNUV7Z9uV/Gm4ZEX3yqT3LP?= =?us-ascii?q?EdmtKpj/doksbNj0CnKkXVy6kD86Utn+M82sLqeShwHkX4FUsJOU3Do7L8+yCi?= =?us-ascii?q?keGwtsp+EE/K98fwsDY5snbh7osAQ+M7e/Lh+B3NuzWWigNTxYQuJDwuW9YrxY?= =?us-ascii?q?0zAjbvSmyHc6SJE10fW3+1YXRJ4WlhHe2eqjZ45GXCjpAHNdYQLPqjEimmh9LO?= =?us-ascii?q?Y92Pk/zw3MsVkdNTCLe+hpaG1Lv9E8GVOSL295CnA9R1OGi4rM/BKs1agI/yRB?= =?us-ascii?q?h9ZUzfFFsH/ms57Rej6jRKyrqZTQsyohd9cmoLZ8MY39LcSYqpzShDvfTIPfsg?= =?us-ascii?q?edSi61C+JamsRMICJfWPRInHsqOdYFuYVf9UoxV8E+J7NUBagivL+qbyZrDSoV?= =?us-ascii?q?zS8ESoyAxyYOguGi1LvGjh2QaogtMAQYsJVehdsQSzR5YjkDpK+lTYnWlHSJSm?= =?us-ascii?q?kKIAcS8QRD/xgMloluceD5+IDIVoNDyyZKo/JoVSvGDpho913nSm6IhVj3VvCh?= =?us-ascii?q?nPK13QJIzPPhyd4bWAZhBkhbwuZZjEooKLVsJKkXsY/GqDiIdVn1vGj10uupOE?= =?us-ascii?q?FRydHId13/FIfFqW38UigH9H0IWYNPzWrQGY4UkwVndKYhvE9ML5y+ekbi+zwk?= =?us-ascii?q?wJxkH7miWsCx3VklqWsJSjy3HNVfE+FmqEzYWDl7bJCxspnlPI9SQmBI8p2Ht1?= =?us-ascii?q?hZiFltMzK+yZdEKcFN5SADUSNSrjqDp9u9VtdD2dNoAJARONt/vWnyGL9cMpiL?= =?us-ascii?q?v3I2oqDvymPe+z0krFe12Si8G66iQOJd5GARBgIpJ2GCpUY1FOss7n3e8lbTvV?= =?us-ascii?q?Bo5+1bHKSAjV1toDZhGZBDHi1G1X65IFhvTnRKrutXJb/JfMxbRvk9eQWgOwci?= =?us-ascii?q?FfI82UyG4110l2/jYyNurgta5zzdXw4sWCkPnLjihD0epdu7OTIBT5JIaishYD?= =?us-ascii?q?nbJw2HniBYoQhQZ1tsW58HHtZP46sb0pdM/sreVUasLjkIXAR5NgIky/VQiFJD?= =?us-ascii?q?vV6DeSDaEAqob+rAvQNxfceNts6mNvD58B1AioP9v+Ay778DSGG+mQ2xXdDeqJ?= =?us-ascii?q?fxtsGQtkSQaqj3LvaxYWLFTDjQlxC/n6kkD5jN/yjXLgVbN4N2yX0+YZjuEWTL?= =?us-ascii?q?JwhJJ7oHJ0pHUqB3cddGrfpAZ89jY6YJ/bViBgycSxPqBYyvqOVGLlfPSjTfNS?= =?us-ascii?q?qB9Pe/rZjU7bzHRujqftaMyGrfQ6JrIpd67iH2G7Xw3o9Y9Er2wPBt+V5kRlXd?= =?us-ascii?q?LyCOttLhJhgM5MW4cEvtoIEpFyvMAJhsiHrt2l1Ad80PTi2s9JQV05JZ6HD1Se?= =?us-ascii?q?5i00jztuNS96N+5oks/7Bp09q0KrvOKfRHq09oHAKYBgJw9pUiGGJ/XXxeYvcN?= =?us-ascii?q?KPfNeqQUlcbuq+HrGKwQ7B2a4fdZZcHGJ0HGncm/ESqcRAdBnAoOpj8WNAyc1+?= =?us-ascii?q?SKm6VsU8aqufD52l4x41i5NhMJ0Kpi5YOa9aqTuO/WbxzRwKMfWqf2R8P8sLIs?= =?us-ascii?q?u1+T5fI+jrIOfHJ6YxG/GugHSsEd3nvgzbwtzS80F8PDBLfg9f5YWnI3gD3vhp?= =?us-ascii?q?d9H08MFfMMB7qL+oZekXkklOzFLNEWdbpCmmmXHx6+DrAC0WKr6zeQIGR9gBHO?= =?us-ascii?q?0hTwTHi27FDorS53XzHMz9blkkpaTLW3A1ldXzaxM09irDyPJBbotMbwuakt7U?= =?us-ascii?q?E3M3bru8iRm2a6I7NYAdH/K8KALiUuo1IXlpIxTMS12Y8HAdq9PMsR8HZmY/TF?= =?us-ascii?q?6mOriCFArL1Fh4rf/sGV4u/YHWSkj6CBt7qNwy1XxWYislEi8NCgMevO6MeQT/?= =?us-ascii?q?SvzWYRQD91uxHdUB6ttrzbs1cUNFST0EjRhIwFItFZ3Hc/1kH85+gvWckz+xta?= =?us-ascii?q?FobBYfMCuD/yNSDswVmFf9I4Sime0jVQHlLvEll0Aqs813zqvMLPi3jQ/0ckRo?= =?us-ascii?q?5qd0zonRZ3FZk3KVox6FgLxSoOCQcNZgqBDL62GUTlLZAJVUwCaRSbwre6er04?= =?us-ascii?q?3VBowr+14u/cc/B8DbIXNvlBlg6OgERbGpUOvK0RXr18fUNd9KnQpgTlEIjoQf?= =?us-ascii?q?zmlXs2Nf2oTcFX6sQZuGU44ge/XRWs85FD4KgHiJqQbK5LfYDMvNxg70dg/TMA?= =?us-ascii?q?ai5NjwJjgB6iTe8co+Tj4tzasJW28OauSLgiSPkX9xQuAGR+lZTwikg5od7Lz+?= =?us-ascii?q?dcVpHViYPn/QBIJH6Kvpra0xZiJucVLoKrfaxv93MZKCgCKXMOOsCWa/on4yN3?= =?us-ascii?q?NjXc+UBCCNsWZdwEJMrNhRxUikrxVbFc6sXbAUSYB55uec4n6WT3yTY18YYzU+?= =?us-ascii?q?v75z+2IIrQ71dTMP9ZiyVsjt3CrvAPwfXOECgX/WWZax9tzyOAzJmNC/Dw8f+Q?= =?us-ascii?q?x9HUU1MGAzM5UoZcJDqE4gynReu1mY73UgOV9M/8mpY+e1+RRnCrmqQKrLpMG/?= =?us-ascii?q?ZaiirnxjheCpz1h/WNvtqt9mtYrFtHHZ137R3YBapfP5J7OQ/imsmsXEh8CTP1?= =?us-ascii?q?eNvIeRo2pOqW2uAM7v18N0Tga48bLBYExqn06HVPSAthVqL2skyfXe0PeNtsUO?= =?us-ascii?q?nEoWxN6YJ8N68PO0CQpJPurjdPplE5HgspaLsrozxBcUnOmgxVVLrutL4GlAQc?= =?us-ascii?q?TcZzuVVQFmKoJGI++z3HWLxXjKmRCP0V6jKTTqgPU0V0LCxzWBa12JRye7uzg/?= =?us-ascii?q?9LqGRGnjlyoPIyyTxpWAO8uTHwp6IKwT8g5LC4tDAatHxZT+WRjyTIBktHzPgQ?= =?us-ascii?q?i6cTFWri40SmYHYfdIvy/KVnJcP4+Ikk4nQ/YhYjfyodUOSiES7wjKSIAoqRv9?= =?us-ascii?q?JanhKNvtvBbaOrJygIKrs90Q7jR2R60gXGhxln7m0LQim74d8/IIW9Ptolxja2?= =?us-ascii?q?GWfFaVkA+KRJsNH+tVQTVus5dUthwHl/0siAXiANXMvPG2IvgQg+Z2REd5ZD6R?= =?us-ascii?q?EBGqkthTaIubJG8R8IbzfOFYSl4ZLQncbO2XkyV9tqwXjWpqKdjJMwzHJlg890?= =?us-ascii?q?7jKJuHkKeezXTctsAnnr1ohB0uH/ZvStsuUCSIR40rShVOENPtOk+Wus15VgQl?= =?us-ascii?q?WlyagGH1qlLO8Dwa/WUim9SW2CWOSEb3aDki08Mk7z+RmoNEM4ZN1Nr08nPevI?= =?us-ascii?q?noRcmBH5UbNoWiWQokfWzGsnMewEbA82oIOndBYRTO4NZuiTOfQuwOcgB1QSdX?= =?us-ascii?q?PJGzV5C/Ouu163gId7I2lg4Vn9Yen19gDmMd2SGgQLEILDqp5x+Oe6Rn6aOXJ7?= =?us-ascii?q?zR19Jk909+DFG1Q2rO9cfI6bncLMiNRjze4Fa/BtPDU4utEJho1j6YiU0MGNcR?= =?us-ascii?q?zK0JbyJNfVreacA/3eyUQqZ25bXqAeYQPv6IUwJsQ5VKHLHbtFoRQcArA3QJ47?= =?us-ascii?q?OGfy86F7Nxh+chPXZLSogsnqof+LZpRUp3/K9F4wKjnTuwEbwPyuUQN7d4yqh2?= =?us-ascii?q?n1IJ0oRDJBqtptCgF8HItOAMMNtAynDISRmK6lit+94UR6u/UFsaDoEPDFyMy5?= =?us-ascii?q?35ltX5hd/UGLJzjRBKx3jUlkjem/menA3YfrCcPjeNIEU+57TnTDarDYAoXsYg?= =?us-ascii?q?6Jb9nxf09A7q60zKNyUhLXYjvwGaWBqmnsMvh47Ugl4pJ3cfCVzzE36bzfntzo?= =?us-ascii?q?aCUToialsG7ML5BD9HTUCuHEGRFZU/yI9CBiB6JTJY/18voedMcvy8WG4hViqT?= =?us-ascii?q?FF3NaBLoC/oULWnEF2b5TWKA3uwSlqd5MNJUGFMEAsiHXV4lTUAHJRNYDwM8hm?= =?us-ascii?q?gN+PAivm0El4mGcgfUZLBmvuWdqLP2UHncm5YVvZp0pwE98fkrvvKgYDvaqoRL?= =?us-ascii?q?wtY81I?= X-IPAS-Result: =?us-ascii?q?A2DmAgBuiEta/wHyM5BVCBoBAQEBAQIBAQEBCAEBAQGDEik?= =?us-ascii?q?DZnQnjx+OJIJ+jTOIehSBfiUHiU5BFgEBAQEBAQEBAQFqKII4JIJPAhcNGQE4A?= =?us-ascii?q?QIDCQIFQwgDAVoSBYgbAzmBOQEDFQMBs3Y6IQKCaAWBAoRagUYmBAiEDIE2XIM?= =?us-ascii?q?/gniDDhNFgUkKBIYTBYpDDIlBjzyIA40lgwmJNIdNmD8mAy+BTzIaI4J7CYI8D?= =?us-ascii?q?xyBZ3iGNgElB4IcAQEB?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 02 Jan 2018 13:27:44 +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 w02DRgP7014030; Tue, 2 Jan 2018 08:27:43 -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 vBUHLrf0091632 for ; Sat, 30 Dec 2017 12:21:53 -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 vBUHLox6028347; Sat, 30 Dec 2017 12:21:53 -0500 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1BqBQDlyUdaf3UYGNZUCBwBAQEEAQEKA?= =?us-ascii?q?QGDEilpdCePH44jgn6NMoh6FIIBDxqFHIQyQRYBAQEBAQEBAQETAQELFoYhDRk?= =?us-ascii?q?BOAEVgSkSiCADOYE5AQMVAwGqajohAoJoBYEChFiBRgEBCBwECIQMgTZcgz+Ce?= =?us-ascii?q?IMOE0WBSQoEhhMFikMMiUGPPIgDjSWDCYk0h02YPyYOgXMyGiOCewmCPA8cgWd?= =?us-ascii?q?4hkcBJQeCHAEBAQ?= X-IPAS-Result: =?us-ascii?q?A1BqBQDlyUdaf3UYGNZUCBwBAQEEAQEKAQGDEilpdCePH44?= =?us-ascii?q?jgn6NMoh6FIIBDxqFHIQyQRYBAQEBAQEBAQETAQELFoYhDRkBOAEVgSkSiCADO?= =?us-ascii?q?YE5AQMVAwGqajohAoJoBYEChFiBRgEBCBwECIQMgTZcgz+CeIMOE0WBSQoEhhM?= =?us-ascii?q?FikMMiUGPPIgDjSWDCYk0h02YPyYOgXMyGiOCewmCPA8cgWd4hkcBJQeCHAEBA?= =?us-ascii?q?Q?= X-IronPort-AV: E=Sophos;i="5.45,481,1508817600"; d="scan'208";a="161685" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.34]) by goalie.tycho.ncsc.mil with ESMTP; 30 Dec 2017 12:21:52 -0500 IronPort-PHdr: =?us-ascii?q?9a23=3AqB69uxf31awmMlHb15JyasMClGMj4u6mDksu8pMi?= =?us-ascii?q?zoh2WeGdxcW9bR7h7PlgxGXEQZ/co6odzbaO6ua+BCdZuczJmUtBWaQEbwUCh8?= =?us-ascii?q?QSkl5oK+++Imq/EsTXaTcnFt9JTl5v8iLzG0FUHMHjew+a+SXqvnYdFRrlKAV6?= =?us-ascii?q?OPn+FJLMgMSrzeCy/IDYbxlViDanbr5+MAi6oR/Qu8QWjoduN7o9xgXUqXZUZu?= =?us-ascii?q?pawn9lK0iOlBjm/Mew+5Bj8yVUu/0/8sNLTLv3caclQ7FGFToqK2866tHluhnF?= =?us-ascii?q?VguP+2ATUn4KnRpSAgjK9w/1U5HsuSbnrOV92S2aPcrrTbAoXDmp8qlmRAP0hC?= =?us-ascii?q?oBKjU09nzchM5tg6JBuB+vuhxxzZDabo+WM/RzZb/Rcc8ASGZdRMtdSzBND4Wh?= =?us-ascii?q?ZIUPFeoBOuNYopHhqVsPsRS+BROjBPnyxTRVhHH5x6w60+I/HgHdwQctGMgOsH?= =?us-ascii?q?XIo9X1LqgSS/26w7HUwjrbb/NZwzb96I7WfRA6uvyDRq5wccvXyUkzCQzFlFOQ?= =?us-ascii?q?ppL5Pz+PyusNtG2b4vNmWOmyhWAnrARxrSKuxscqkoTJnpgayk3A9SlgxYY1It?= =?us-ascii?q?q4SFRlbtK+DJRQsCSaOo1rSc0hW2FloDg2xqAJtJKhYiQHx44rywDQZvCdboSE?= =?us-ascii?q?/xDuWP6SLDp5nn5pZb2yihmo/US9xeDxV9O43VdLoydDj9LCrGoC1wbJ5ciCUv?= =?us-ascii?q?Z9/lmu2TKI1w3L9+FLPUc0la7GJ5Ml2r4/jIcfvErZEiDohkr2ibSWdko+9uit?= =?us-ascii?q?8evnY7HmqoWZN491jgHyKqUumsqhDuQkKgUCQXWX9Oum2LH98kD1WqtGg/Isnq?= =?us-ascii?q?XErZzXJ9wXpqujDA9U1oYj5Qy/DzCj0NkAh3kHLU5KeBKdgIjzJl7BOOz3Au+/?= =?us-ascii?q?g1u2kTdrwe7JPqb6D5rWMnjDkbHhfapj5E5Gzgo808xf64hIBbEGJfL/QlXxu8?= =?us-ascii?q?DADh8lLwy0xP7qCM5g2YMFQm+PHq+YP7/SsV+P/O4vJfKMa5UPtDbyLPgl+ebk?= =?us-ascii?q?jWUlll8FYampwZwXZWijHvt4J0WZYHzsgsoOEGoRogo/TPDliF2FUTJJYXayRL?= =?us-ascii?q?gz6is0CIKhE4eQDryq1aeM2Ca9A41+enFNClfKF2zhMYqDRbNEbi+OLsJ/uiIL?= =?us-ascii?q?WKLnSII70xyq8gjgxP4vKuvS5z1drpn/zPBr6ODJ0xI/7zp5C4KayW7JB2V1mH?= =?us-ascii?q?4YAiQ7171loFBsj1KE3bV8jtRGGtFJofBESAE3Mdjb1eMpJcr1X1f7f9yJQUyq?= =?us-ascii?q?CvWvADc8VZpl2d4FY09nF+KpuRDK3iynGJcfi72NGJEu9K/AmXP2IpAumD79yK?= =?us-ascii?q?A9ggx+EYN0Pmq8i/sn+g=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0BsBQDQykdaf3UYGNZUCBwBAQEEAQEKA?= =?us-ascii?q?QGDEilpdCePH44jgn6NMoh6FIIBDxqFHIQyQRYBAQEBAQEBAQEBEgEBCxZdgjg?= =?us-ascii?q?igmoNGQE4ARUSgRcSiCADOYE5AQMVAwGqbDohAoJoBYEChFiBRgEBCBwECIQMg?= =?us-ascii?q?TZcgz+CeIMOE0WBSQoEgnEMgxYFikMMiUGPPIgDjSWDCYk0h02YPyYOgXMyGiO?= =?us-ascii?q?CewmCPA8cgWd4hkcBJQeCHAEBAQ?= X-IPAS-Result: =?us-ascii?q?A0BsBQDQykdaf3UYGNZUCBwBAQEEAQEKAQGDEilpdCePH44?= =?us-ascii?q?jgn6NMoh6FIIBDxqFHIQyQRYBAQEBAQEBAQEBEgEBCxZdgjgigmoNGQE4ARUSg?= =?us-ascii?q?RcSiCADOYE5AQMVAwGqbDohAoJoBYEChFiBRgEBCBwECIQMgTZcgz+CeIMOE0W?= =?us-ascii?q?BSQoEgnEMgxYFikMMiUGPPIgDjSWDCYk0h02YPyYOgXMyGiOCewmCPA8cgWd4h?= =?us-ascii?q?kcBJQeCHAEBAQ?= X-IronPort-AV: E=Sophos;i="5.45,481,1508803200"; d="scan'208";a="7188473" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from unknown (HELO ucol19pa13.eemsg.mail.mil) ([214.24.24.117]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 30 Dec 2017 17:21:51 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;ec51d767-ca29-40bf-a422-a540ec941117 Authentication-Results: UCOL3CPA03.eemsg.mail.mil; dkim=permerror (key too small) header.i=@btinternet.com X-EEMSG-check-008: 491405460|UCOL3CPA03_EEMSG_MP18.csd.disa.mil X-EEMSG-check-001: false X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.202 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0CaAACRx0dah8oAFEFUCBwBAQEEAQEKAQGDEoESdCePH5EhjTKJDoIBDxqFHIR0FQEBAQEBAQEBARMBAQEIDQkIKC+FRA0ZATgBFYEpEoggAzmBOQEDFQSqazqDCwWBAoRYgUYBJQQIhAyBNoQbgniDDhNFgUkKBIJxDIMWBYpDDIlBjzyIA40lgwmRAZg/NYFyMhojgnsJgjwPEAyBZ3iGRwElB4IcAQEB X-IPAS-Result: A0CaAACRx0dah8oAFEFUCBwBAQEEAQEKAQGDEoESdCePH5EhjTKJDoIBDxqFHIR0FQEBAQEBAQEBARMBAQEIDQkIKC+FRA0ZATgBFYEpEoggAzmBOQEDFQSqazqDCwWBAoRYgUYBJQQIhAyBNoQbgniDDhNFgUkKBIJxDIMWBYpDDIlBjzyIA40lgwmRAZg/NYFyMhojgnsJgjwPEAyBZ3iGRwElB4IcAQEB Received: from rgout0203.bt.lon5.cpcloud.co.uk (HELO rgout02.bt.lon5.cpcloud.co.uk) ([65.20.0.202]) by UCOL3CPA03.eemsg.mail.mil with ESMTP; 30 Dec 2017 17:21:47 +0000 X-OWM-Source-IP: 86.144.146.66 (GB) X-OWM-Env-Sender: richard_c_haines@btinternet.com X-Junkmail-Premium-Raw: score=10/50, refid=2.7.2:2017.12.30.165416: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.144.146.66) by rgout02.bt.lon5.cpcloud.co.uk (9.0.019.13-1) (authenticated as richard_c_haines@btinternet.com) id 59D91D940864360D; Sat, 30 Dec 2017 17:20:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=btinternet.com; s=btcpcloud; t=1514654507; bh=dEPBaf7/BZuKj3K1d/Cdca40laAjuFCBH1AtAukyQss=; h=From:To:Cc:Subject:Date:Message-Id:X-Mailer; b=F7ye/fkXd2fBsV5BZOkGrZQGQtnv0Y3vl0NRdO4DT0bhWpyu01jz1kkPGWz+6iZMfEAtBoE6hiA/62EFD3ae8Cw2gUh/IjCe45g2rzbEI+0mf7tmTeCUwBuoUKvFMpsnaHTHCdeYuf7OJXCGT4DDyXFAL7E6BpH0EsSn/yytIoE= 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: Sat, 30 Dec 2017 17:20:35 +0000 Message-Id: <20171230172035.15837-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.14.3 X-Mailman-Approved-At: Tue, 02 Jan 2018 08:24:19 -0500 Subject: [PATCH V4 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 Reviewed-by: Marcelo Ricardo Leitner --- 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 | 138 ++++++++++++++-- 6 files changed, 570 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..0a566e3 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,66 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) netlbl_sock_delattr(sk); sksec->nlbl_state = NLBL_REQSKB; rc = 0; - goto socket_connect_return; + return rc; } secattr = selinux_netlbl_sock_genattr(sk); if (secattr == NULL) { rc = -ENOMEM; - goto socket_connect_return; + return rc; } rc = netlbl_conn_setattr(sk, addr, secattr); if (rc == 0) sksec->nlbl_state = NLBL_CONNLABELED; -socket_connect_return: + return rc; +} + +/** + * selinux_netlbl_socket_connect - Label a client-side socket on connect + * @sk: the socket to label + * @addr: the destination address + * + * Description: + * Attempt to label a connected socket with NetLabel using the given address. + * Returns zero values on success, negative values on failure. + * + */ +int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) +{ + int rc; + struct sk_security_struct *sksec = sk->sk_security; + + if (sksec->nlbl_state != NLBL_REQSKB && + sksec->nlbl_state != NLBL_CONNLABELED) + return 0; + + lock_sock(sk); + rc = selinux_netlbl_socket_connect_helper(sk, addr); release_sock(sk); + return rc; } + +/** + * selinux_netlbl_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); +}