From patchwork Tue May 15 08:25:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn via Selinux X-Patchwork-Id: 10400363 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 68ED8601C8 for ; Tue, 15 May 2018 08:27:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A1CE1FFE6 for ; Tue, 15 May 2018 08:27:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3E4CF27816; Tue, 15 May 2018 08:27:59 +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=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham 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 C404227D0C for ; Tue, 15 May 2018 08:27:55 +0000 (UTC) Received: from emsm-gh1-uea11.ncsc.mil ([214.29.60.3]) by USFB19PA14.eemsg.mail.mil with ESMTP; 15 May 2018 08:27:53 +0000 X-IronPort-AV: E=Sophos;i="5.49,403,1520899200"; d="scan'208";a="13293193" IronPort-PHdr: =?us-ascii?q?9a23=3AF46ZJhc/ZdtAKq3WVdOe+mwZlGMj4u6mDksu8p?= =?us-ascii?q?Mizoh2WeGdxcq6YR2N2/xhgRfzUJnB7Loc0qyK6/umATRIyK3CmUhKSIZLWR?= =?us-ascii?q?4BhJdetC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBx?= =?us-ascii?q?rwKxd+KPjrFY7OlcS30P2594HObwlSizexfb1/IA+qoQnNq8IbnZZsJqEtxx?= =?us-ascii?q?XTv3BGYf5WxWRmJVKSmxbz+MK994N9/ipTpvws6ddOXb31cKokQ7NYCi8mM3?= =?us-ascii?q?0u683wqRbDVwqP6WACXWgQjxFFHhLK7BD+Xpf2ryv6qu9w0zSUMMHqUbw5Xy?= =?us-ascii?q?mp4KlxSB/slSwJKTg3/m/KgcB0la5XvQ6tqxl5zoHTfIyYOuZycr7Ecd8GWG?= =?us-ascii?q?ZKQ8JdWzFBD4+5aYYEEugPMvtCr4Tlp1UAswawCwevCu3o0TJEmmP60Lcm3+?= =?us-ascii?q?k7DQ3KwAotFM8OvnTOq9X1Mb8fX/y0zKbUzTXMdelW1irg44bKaB8hoPeMUq?= =?us-ascii?q?xrccHM10kvFhnKhUiNp4P7OzOV1+INs3WU7uF9Uu+vkHAoqwVwojip28cthZ?= =?us-ascii?q?LEhp4Vy1/Y9SV5x5w5JdujSEFhe9KkH5xQtz+DOoZwX8gsQHlotT4nxrAJtp?= =?us-ascii?q?O3ZigHxIk9yxLBZPGLbZKE7g/7WOuSIDp0nm9pdbywihqo8UWtxPfwWtS13V?= =?us-ascii?q?tLqCdOj8PCuWoX1xPJ78iKUv59/kC81jmRzw3T8eREIVwslarcNp4h3qY8lp?= =?us-ascii?q?oNvkTHGS/7gFn2g7WMdkUl5+io8P7rYqnmp5CAN490jRvyMqIylcykHes0KA?= =?us-ascii?q?0OX2mf+eik1b3j+1P2QKlSg/ErnaTUv4rWKMQGqqKjHQNY3Zgv5wyiAzu+1d?= =?us-ascii?q?QXh3gHLFZLeBKdiIjpPknDIOvmAve7glSsliprxv/fMrL6BZXNM37Dn6v/cr?= =?us-ascii?q?Zm8ENc1Aoywsxf55JTEL0BJunzVVXruNzXCR85LRS4w/z7B9VlyoMeRWWPD7?= =?us-ascii?q?ebMKPVt1+H/P4vI+mWa48Tozv9Kf8l5/jrjXAjgl8dYbem3YEMaHyiGfRmOU?= =?us-ascii?q?qZa2L2gtgdCWcKohY+TOvyhV2AUz5cfWq9X6En5jE8DoKmDJnDS5ujgLyFwS?= =?us-ascii?q?e6EYZZZn1AClCQDHfkbYKEW+0DaCiKOM9ujiQEVaS9S48mzRyurBH1xKF5Ie?= =?us-ascii?q?rS+y0YqZXj2cN05+LNix496yZ4D8OH02GCV2t0hH8HRycq3KBjpkxw0kqM0a?= =?us-ascii?q?9+g/xeCNNc+fdJUgYhOJHG0eN6EdfyVhjGfteTR1asWs+mDi0pTtIt398OZF?= =?us-ascii?q?5wFMi+jh/ZxSqnGKMal7uOBJMo6K3cxGTxK9x7y3nYyKkrl0MmTddXNW26mq?= =?us-ascii?q?5/8BDeB4/Pk0WFiamqcboT3CvT+2ef12qPvFpVUAloUarbW3AfY1HZrdX95k?= =?us-ascii?q?zZSL+vBq4rMgxbyc6NMqFKcMHmjU1aRPf/P9TTe2Kwmma3BRaO3b6MaY7qd3?= =?us-ascii?q?wc3CXbEkQElRoc/WyFNQg/GCeuvXjSDDpwGlLze0ns6/VxqGunTk8oyAGHd1?= =?us-ascii?q?Nu16Kv9R4PhPycUOge3qoetyc7qjV0B06939bMBNWcuQVtZqJcYcky4F1fz2?= =?us-ascii?q?LWqxR9PoC8L6BlnlMffQV3v0fr1xppEIVNisYqo203wwp1M6KXyktBdymf3Z?= =?us-ascii?q?DyJLLYNnXy8Aqoa67M1VHUyMyW9bsX6PQkt1XjuxmkFkQ483p91dlaz3qc5o?= =?us-ascii?q?7RAQoXSZLxU1879wN0prHBeCU94JnU1XJ0O6murjDCw84pBPciyhu4fNdQKq?= =?us-ascii?q?CEFAjvE8ABBMihMu8qm1+0bh4eO+BS7qE0Ndu8d/SawK6rIPpgnDW+gGtd/Y?= =?us-ascii?q?99yEOM+DRmSuPTxZkK3/SY0hGAVzfmg1erqtr3lpxcZTEOAmq/zjDpC5JLaa?= =?us-ascii?q?12Y4kLEnuuIs2wxthlnJ7iR39Y+0ClB1Ma2c+mYwCeb1rj0g1MzU4Xu2ComT?= =?us-ascii?q?OkzzxolDEktrCf0zHTzOn5exoHP2FKSHNkjVjyPYi+l8oaU1Swbwg1iBul4l?= =?us-ascii?q?73x7NVpKRlKGnTWltIcjPtL2FkVauxuL+CbNRJ6J8ytyVYTvi8a0iASrHhux?= =?us-ascii?q?sazz/jH2xGyTE1bT6qvon5kAJgiGKGN3tzsmTWedtryhfC4dzQX/lR3iAJRC?= =?us-ascii?q?NgkznYGkC8P8W1/dWTj5rDrOG+WH69Vp1Uaynn15+PtCu85W1sDh2yhPSzmt?= =?us-ascii?q?zhEQcgyy/70MNmVSLSrBbzeoPrzbi1Mfp7fkl0A1/x8856GoBlkossnZ0Qwm?= =?us-ascii?q?YVhpGU/XoBjGfyPs5W2bnmbHoMQz4LwsLa4BP/1E1lMH2J25rzVm+Bzct5e9?= =?us-ascii?q?m6fmQW1zon78BNDKeU6KJLnTFprVq/owPceuN9nioBxvs18nIahPsJuAU1xC?= =?us-ascii?q?WHHr8SBVVYPTDrlxmQ7NCxsqNXZH20fLizykV+m8uhDLecrQFAQnr5fY0iHS?= =?us-ascii?q?Bo5MVlLF3MyGHz6p3jeNTIddIcrACUkxPegOhNMp0xkOYKijR9OW/moH0l0P?= =?us-ascii?q?A0jQZ13Z2gp4iHLHht/LilDRFGOD31YNkT+j7zgqpEmMaZwZyvFI17GjoXRJ?= =?us-ascii?q?voUe6oEDUKuPT5MQaBDSYxqmmdGbXCHQ+T8kFmoGzTE5qzLXGYOGEZzcl+RB?= =?us-ascii?q?maPEFfmBobXCg+npMiCg+qxdDhcUdg6jAf/FH4rAFAyuVyNxnwSm3fvhunai?= =?us-ascii?q?8oSJiDKxpb9gJC5kfRMcOA9e9zGiZY/pOvrAOTNmybewRIDWYMWkOaHVzjOK?= =?us-ascii?q?eh5cXY+eiCGuW+N+fOYamJqeFGWfeH35Sv0pdh/zaJLciPMGdtAOA82kpZR3?= =?us-ascii?q?95A97ZmzINSyMJiy3Nc9SXpBCm+i14tsq/6ujkWBrz5YuTDLtfKchg9Ayzga?= =?us-ascii?q?eEMe6QmDt1JC1G1pwS33/Iybke3FkUiy10cTmiD6gAvzbXTK3Mgq9XEwIbay?= =?us-ascii?q?RrOctG9aIzwBRCOdXBhdPzyr54ieU1BkxfWlP9n8Glf8sKI3uyNFnfHkaEKK?= =?us-ascii?q?yGJSHXw8Hwea68T6dQg/9Mtx2oojubHU7jPi6Ylzn1WRCvMOdMgzudPBNCuY?= =?us-ascii?q?GyaBJtBXLkTNL8ZR2xKMV3giEuwb0omnPKMnYRPiNnfE9Kqr2Q7DhYgulkG2?= =?us-ascii?q?Bb9XpqM/WLlzyC7+bGLpYWsP1rAjl7lu9B/Hs7y6FV7DxfRPBvlirdtMJuo0?= =?us-ascii?q?qhkumJ0DZnVwBOqjlTjoKRoUpiIbnZ9oVHWXvc+hIN7GGQCxAUqNt+EdDgob?= =?us-ascii?q?5fysLIlK7pLzdC6d3U99MGB8fIMMKHLGYhMR3xFTHPDQsFQjmrNWfEikNAjv?= =?us-ascii?q?6d7XyVoYI8qpT2n5oOULBbXkQvFvwGEkRlAMACIJBvUzw+nr6UltAI6mSloR?= =?us-ascii?q?nWXMVVoJbHVveIDvXuLDaWlr5EZhQSzbP/N4QTOZXx21Z+ZVligITKB03QUM?= =?us-ascii?q?hRoi1maw84ul9N8H9/T2It3ULqcRmt4HgNGv63hRM5lgx+YeEx+zj2+Fc3Ok?= =?us-ascii?q?DGpC0un0ktgd/lmyyecCbtLKesWoFbEyj0t0gxM5PjRAZ1aQyynVB6OzrfQr?= =?us-ascii?q?JRjqdgdXp1hwPGvptPA/FcR7VeYBAM3fGXe+ko0VNEpyWh20BI/+/FBIBhlA?= =?us-ascii?q?stap6ss2hP2wR4bN42JKzcPqxJwUZMhqiWpC+nyvgxwBMCJ0YK6G6SYjAHuF?= =?us-ascii?q?cWObY8PSqn4uxs5BeZlDtCYmgDSv0qovxy9kMnJeuBzzjs07hdJUCtL+afNb?= =?us-ascii?q?+Wu3Dclc6URVM9zl4HmFNb/bh3zMgjaFGZWFo1zLuLEBQIO9HCJh9JYMpP7n?= =?us-ascii?q?jTfDqOsOXXzZJzIYq9CvjiTfWSu6YMnkKkAAEpEpwI7sQGBJmjzkfYLMbgLL?= =?us-ascii?q?MexhUt4hnrKE+CDPRTdxKBiC0HrN2nzJ9rwYldISkQAX5jPiWz57bXoBIqgf?= =?us-ascii?q?WYUdgqZXcaW5cLOWgtWM2mgSJZuWpPDCWv2OID1AeC9yP8pjjXDDTkc9pjZf?= =?us-ascii?q?KUZRRwCNG2+TQy6LW5iV/X85rEPG72L9JitcHT6ekCvZaIF+tUTaVhs0fbg4?= =?us-ascii?q?RXXXiqU2/THtGrP5fwboktbdrzCna8SFOykCk6T8brM9arN6SIjxzoSZxSsI?= =?us-ascii?q?aFwDApLdW9GS0GGxdsu+ED47pxahYdbJo9ehPnrRkxN7KhLweCydWhWXytKD?= =?us-ascii?q?tMQ/lY1+W6aKRdzzAwYe+i1HsgUpY6wvGt8U4LRZEFkhHexfGnZ4lFSSb9A2?= =?us-ascii?q?FTdR/TqCQ+jGVuKuEywuIjzxzSqlkcLyqHdOp3Z2xYp9s8H0+dIW1qCmokQF?= =?us-ascii?q?+RlZbM4gy20L8O5CZSg9FU0elBsHj/oJDfei6sV7K3ppXVqSYgasImo6JpO4?= =?us-ascii?q?z5PsSGrI/eniDYTJTIqA2KSjS6F/1BldVLPCJYWuNHmX87NswCuIpB70UxVs?= =?us-ascii?q?M/J7xACKksur6qZiB+DS4X1yMZUZ2P3CAaiOemx7TajguQcIglMBEcvpROmM?= =?us-ascii?q?cSUy53YiMbpa+sTYbWmnSFSmcVPggc8x5A5AUalo9/Zurl+pbHTIdQyz5KpP?= =?us-ascii?q?J5Si7LGYNy91v4VG6WnVn4SPOuk+Gy0wNd1vTs3cUfWB54FEhS2v1WmlEuKL?= =?us-ascii?q?5pN6kappTKvSOQdUPmoGLtz/OrJEFWyc3QbVL4FoTEtW34Ui0S4nAUQIhPyH?= =?us-ascii?q?bEFZsMjwV5cqErpE5XIICnfEb+6CYox4NzH7m3Tcqr3UoqrW4aRye2FNpME/?= =?us-ascii?q?tpsEjKWD1jeZyrq47oO5RTQm9R5J2SsE1VkENzPC6l0ZBcMd1C4iYQXDhTpj?= =?us-ascii?q?WQpMeySMpG2cJtE58APtJ/tGznFKNCJpeRv2U8uqbzxX/B5zA8rFC6yS2zG6?= =?us-ascii?q?CiVeJW5WkeFRgyKmuDtEYvF/Ms/XnW8l/TqFB45eBbBqKAjU9pujZyAohOBi?= =?us-ascii?q?pV1XCiN1lzTn5GvPtBJavIbcNcWOc9ZQWzOxMgCPEqxUqJ8l9onX3heSx9qh?= =?us-ascii?q?Na+zzBXwkzTSQVnqriliAfqs69PT8XUI5HbTIkbyjZMQ2bgjxXsAxZa050R5?= =?us-ascii?q?ATGsxF9K0D3YtI4srCTl6hJjoLXBN+Kg410+dTmEBYvUqEfiDdCBaneuzUsh?= =?us-ascii?q?1rZ8uRqtCmLOjh9gddloznqPw497kER3C+gw2iX83Rr4/mud2WrUaOcKD4M/?= =?us-ascii?q?OibnPfUDfMig2/iqk+A5nM4SfTLBJRK4Nmxno8fZjhFWnLMAxeJ6IAO0pUT7?= =?us-ascii?q?11acldr+BBYM9kZbwJ9rNzCRKBWhPvApagrP1cIlbUXzTeID2L8vajroLL8b?= =?us-ascii?q?zdVe/ga9SQx3bdXa14IIp15CLmG7fuzY9e4FD52uls9kN9TVjJLTyBoM7mJg?= =?us-ascii?q?MR68moblHisYExHTPKHJdwl2LgxkRaeMoTRy2l7ogYyI9D53nqUu941Fb8sP?= =?us-ascii?q?FJ97Z484Y3+65mxd2yJajMNfRQqVVnDQSMBgV26pUtB3ByR2JLbe8LL/fRZq?= =?us-ascii?q?AZgtrwq+3sEqwX9RmV+/BYadTbJkHOgM+/CiqGRRxDhgcBpiYQLhGA2P6dh6?= =?us-ascii?q?90VcGlqPD72k035Vi+IAQGzLdw6oia4aeIuPXYbx3KzbgDQKTqQN38rqg0sU?= =?us-ascii?q?OI+fIkjKIOenByYwC/H+gdS88dxmPkza80yCIhCN7MEKz79/5CTX05mCjsm5?= =?us-ascii?q?dnH1UZAvkUB6aE/ZxCnmcknOzULt8WcqFHmmuUEB6rDL8DxmCx6yuWJmlljQ?= =?us-ascii?q?vC0xfuTmOv9FX2tzN3QTPQz9f/lUpYTr+3BUNJUiqoP094tSmDPAvutNr5o6?= =?us-ascii?q?Q69lo2MnD+tNKQiGShJK5XH9fhK9CGJik0vl0XhoUrRtOzwYAbBca9INAJ/X?= =?us-ascii?q?F7afve7X+rkyBfrKpcgore49ua+vPJEnm8gayarK+NxDNDynQiu1Ew9MygPO?= =?us-ascii?q?nU59KWW/Soy3oRTyBntgvFRB61r7zWoksaOUOVzUjLn5YKMctB3Xki0UHm5v?= =?us-ascii?q?YsT84v9AlEEYbAffwCryjpODTo2Vaff843Vi6G3jtWH1P6C0N3F7Qn1WLros?= =?us-ascii?q?3JiWnf9EEySol3bUznigR9D58kJkI19FgX3i0DHBAWZhCaF7GpC17qLYkFVU?= =?us-ascii?q?gfcRSIxqW6eqMs0EJvxbOg+fHcYvZhB6oXMfZdlBSBkEJcGpIMvq0UWKh8dE?= =?us-ascii?q?NF9K7LugjiDJDqX+D8mnosKfK1Qs5b8ccDt3sh+wq/XASv6ZNC77YdlZCJeb?= =?us-ascii?q?VJYYDWs8Bg80hn5TAOditXgBh8lR+5Uv4TpPrl4tfFtJqk8OGuVLwiR+8P7R?= =?us-ascii?q?g7G3x+j4fsgFAkudzX2P1TSpfLhoTj8ABAOHqKuIfG0xZiKeoBMZ+rfK16+3?= =?us-ascii?q?UBOSceO2oEPcCKZPkk/y9tLDLT6kRNAswSY9MYIM3NmQdThk3yRr5T8svbGl?= =?us-ascii?q?mFC4Z8bM0o63T4yCo18JQmSOrg7iG5JYzH5VFXI/xDlDlslM7FpOUNx/rSCT?= =?us-ascii?q?QY4X6daxdv2SOO0ZiNC/H3/eWX09HZTFYGEyE5UotHIzqC4wOnTPKvlJr1Sg?= =?us-ascii?q?OU9tPzgJUmeUKfWnOxh78Fvr9RH+BPjCv73z5eFp36hv+OvNqs7XFYtltZH4?= =?us-ascii?q?pp6h3FAqpfNI1hORvkjsmrWlR8BizndcHWcRouuOyWyv0Q7OV+M0v+eJIUIx?= =?us-ascii?q?MFy7L88npVTQpuRaXovlaYQ+Ieft9mR+7FrnxP74JvNbMPNkCHpJP2tjdItE?= =?us-ascii?q?w2AAgxZb8xsDxVbE/OkRZRW6bppbEAiwwcUcVjtU9LA2KwN3o05yDbWqRNkK?= =?us-ascii?q?mRFPsV/y2RTqMQXUVoPCd+Tgi72Zp0fbumg+xHvnlAnixjvPggyyZmSwekuS?= =?us-ascii?q?3wu6IN3iot+L68tDUGt31KUOGekyPTBFVYy/QKi6YcBGr45Vy6fnYDcJP44K?= =?us-ascii?q?N7KsT46Ykh/3M/bA0mfy0HXuSgCCbwgriKAoOVs9JcgxiNt9vIbbOpKygdKK?= =?us-ascii?q?g9wwr5R3dhygjegApo8GwTTzq78tAkIpm9NN0+xiqsHmjbaEoM4r1Xv8Tsr1?= =?us-ascii?q?ILS/E2aVx5ymV5zseHXjENRNDIG2stgAgrd2FEcJNb6RAEDKQpgzeIvqxD/g?= =?us-ascii?q?4KejfUFpqq9pPXncfS1nk3Vc1qyX7Opq2ZmpMq12Vomt1s7i6UuXQda/LXXt?= =?us-ascii?q?RpAnjyyodf0/Lxa++qsuAdR4ts0K6hX+MaMsm/5Wu2341nWkihxrsABFe5KO?= =?us-ascii?q?sDya3AUye5SG2XRfiLc3KSkDknKELy4wenLkEvYsdQs0A9KvfChoJblwD5Vb?= =?us-ascii?q?N0RyOQpULUzWA6NeMadhk2uJu8ewERTe4efe6cJe80zP05ElsMYGfDHTFqBO?= =?us-ascii?q?+urV6tgI97Nm1l4Urgfevt8gHmMN2VGhQfD47ar5hx9uK+RmKAP39g0RJzMF?= =?us-ascii?q?Nz9+fFGFQ7rvVcfIqJndjMm9R71vYId/V3Pi0+vd4cgZlu6ZSS0MeWcRHRyY?= =?us-ascii?q?vyJd7VoviEGfHfyVolen1CWLoDfQz1/5k6PsI+W7DLH7tZuBMcBbIgQJwgLG?= =?us-ascii?q?f876d0Ixl2cgHPZbS4mM7qpviEZpFMvX/Z8kowLDvAux0E0vG0VgJ7b5W2iH?= =?us-ascii?q?jzI509XSxBoMN3ChtnHYpPHMUAoxChA5GKhKG3k9+x9F1+u+8NqafwDvfK28?= =?us-ascii?q?ij0IV1X5ha4leLPCrLCKlvhURqkv69gvPd3Zn2DMPtY9IEVO5jTm7EbL/JAJ?= =?us-ascii?q?m/JyqNN8/9YUJK7rCR3b1jXhiRai31RbeKuSylOfl85EU00I14fO7dzDw36L?= =?us-ascii?q?Hb3cP/amZBpieisXGJNIFQ7EbXCuPGQx1bUfqF/3xkHa0Rc4T07/wDPsc+wN?= =?us-ascii?q?id5Qlz8CpN0NGDI6e/sk/AwF50dZXeLEbwwyo5Q5UFIAyjMUswhm/UsnPQAW?= =?us-ascii?q?5dLse4KclimsyVAQH16EZtgW4tZnROGmvuRdiPImgWwNmxZBGL9AJNE9YMgf?= =?us-ascii?q?S3eUgmua2uU+VnJpJFmeCzubkfi9ZmNznPRNRGPyHXNLJ7OSFRAfvLpFgpZB?= =?us-ascii?q?4Errc0V5wpZZmOPEwHMECAxTn0zQvZy0L4bdOs1KGXICsP9HhM0qzI0TxRpw?= =?us-ascii?q?mipfaWnNfjXq3YbJD3QvHfKDYpBXmmQmEpHEKo/0q0k+YVt/qfZ2EEqxYbZT?= =?us-ascii?q?zBMgMLorFTqo3qD2TTkPdvNL0DhfaXQGikUixzlKMoChFAgkCFQvwODiHcc3?= =?us-ascii?q?7nnGdGvgG+YPRL+CS2Qaefw/9vWucWC5FAOt2QQt3VYrhAJj5grTgdOeChb5?= =?us-ascii?q?WItLs901TVXUMFAqLI8xuYV0fQTfuCkWG4Fb4JtpQ573J7sunbmTV6RvnF?= X-IPAS-Result: =?us-ascii?q?A2DYAwC0mfpa/wHyM5BcGgEBAQEBAgEBAQEIAQEBAYMYK?= =?us-ascii?q?2EhWxUTi3hejBRkggoai0aHbBQLgVYmAxABh1ghNBgBAgEBAQEBAQIBaxwMg?= =?us-ascii?q?jUMgm8CFw1VAwkCSAgDAWMJBYJeQAIogT8BAQEVAwGtAzODdFaDf4IniCUOg?= =?us-ascii?q?gWBD4JWgwSCDQGFagKHJgoIhGCBIIp+CYVniF+BQT2GB4R2kggcOIFSKwgCG?= =?us-ascii?q?AghD4FrGnkJghcXh02GS255AQEBKItwK4IZAQE?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by emsm-gh1-uea11.NCSC.MIL with ESMTP; 15 May 2018 08:27:52 +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 w4F8Ro30024376; Tue, 15 May 2018 04:27:51 -0400 Received: from tarius.tycho.ncsc.mil (tarius.infosec.tycho.ncsc.mil [144.51.242.1]) by prometheus.infosec.tycho.ncsc.mil (8.15.2/8.15.2) with ESMTP id w4F8Q4CO129179 for ; Tue, 15 May 2018 04:26:04 -0400 Received: from goalie.tycho.ncsc.mil (goalie [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id w4F8QB6K024304 for ; Tue, 15 May 2018 04:26:11 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1DOAQA3mfpalywYGNZcGgEBAQEBAgEBA?= =?us-ascii?q?QEIAQEBAYMYKGR8KIt4XowUgm4ai0aHbBSBZCYRhECDGCE0GAECAQEBAQEBAhQ?= =?us-ascii?q?BAQEBAQYYBktODAEIAYRxDRkBOAEVgTIJgyMCKIE+AQMVAwGtATOCcAV/ZINqB?= =?us-ascii?q?4IbBAiHKXyCE4EPglaDBIINAYVqAocmCgiEYIEgin4JBYViiF+BQT2GB4R2kgg?= =?us-ascii?q?cggozGiODEwmCCwwOCYNFhAiGS255K4g2gkF5K4IZAQE?= X-IPAS-Result: =?us-ascii?q?A1DOAQA3mfpalywYGNZcGgEBAQEBAgEBAQEIAQEBAYMYKGR?= =?us-ascii?q?8KIt4XowUgm4ai0aHbBSBZCYRhECDGCE0GAECAQEBAQEBAhQBAQEBAQYYBktOD?= =?us-ascii?q?AEIAYRxDRkBOAEVgTIJgyMCKIE+AQMVAwGtATOCcAV/ZINqB4IbBAiHKXyCE4E?= =?us-ascii?q?PglaDBIINAYVqAocmCgiEYIEgin4JBYViiF+BQT2GB4R2kggcggozGiODEwmCC?= =?us-ascii?q?wwOCYNFhAiGS255K4g2gkF5K4IZAQE?= X-IronPort-AV: E=Sophos;i="5.49,403,1520913600"; d="scan'208";a="277056" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.34]) by goalie.tycho.ncsc.mil with ESMTP; 15 May 2018 04:26:08 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3A/BaEhBHs9icoZKnXEudzrZ1GYnF86YWxBRYc79?= =?us-ascii?q?8ds5kLTJ76ps6ybnLW6fgltlLVR4KTs6sC17KN9fi4EUU7or+5+EgYd5JNUx?= =?us-ascii?q?JXwe43pCcHRPC/NEvgMfTxZDY7FskRHHVs/nW8LFQHUJ2mPw6arXK99yMdFQ?= =?us-ascii?q?viPgRpOOv1BpTSj8Oq3Oyu5pHfeQpFiCazbL9oMBm6sRjau9ULj4dlNqs/0A?= =?us-ascii?q?bCrGFSe+RRy2NoJFaTkAj568yt4pNt8Dletuw4+cJYXqr0Y6o3TbpDDDQ7KG?= =?us-ascii?q?81/9HktQPCTQSU+HQRVHgdnwdSDAjE6BH6WYrxsjf/u+Fg1iSWIdH6QLYpUj?= =?us-ascii?q?mk8qxlSgLniD0fOjA57m/Zl8J+gqFcrh+6uxBz35TZbJ2POfZiYq/Qe84RS2?= =?us-ascii?q?pbXsZWUixMGp+yb4oTAOoBJ+lYtZTyrEYMoxSkBAmsAv3gyiRVjXLxx6060v?= =?us-ascii?q?guEQHc0ww6At0BqGjbo831NKgIUOC1yrfHzS7YYvxNxTf96Y7Icgw/rvGWW7?= =?us-ascii?q?J/b9bRxVMzGAPCi1WdsIroNC6W2OQVq2WX8fdsWO21h2I5pAx9uCajy8g2ho?= =?us-ascii?q?TGiY8Z0lPJ+CRjzIooK9C1R1R3bN6qHZdKqi2XNop7T8U/SG9yoik60KcJuZ?= =?us-ascii?q?ujcSgK1psnwxnfZuSJfIWW+xztUuicLCliin95ZL6yhgy+/la+xe35Tcm030?= =?us-ascii?q?xGri9fndnNsnABzRnT6smDSvdl/0eh3yiA1xzL5+1aPEw5mrDXJ4Auz7IqiJ?= =?us-ascii?q?Yevl7PEyD5lUnuia+ZbEQk+uym6+T9ZbXmo4eRN5V1ig7iMqQhgNa/DvkgPQ?= =?us-ascii?q?cSR2eb+f6z1Lzl/ULnW7VHleY5krXYsJDcOcQUuLS5AwlL3YY/8RqwEzCm0N?= =?us-ascii?q?EAkXkdMF1FYA6Hj5TuO1zWO/D3E/O/g1WqkDd2yPHLJaHhA5XRIXjDl7ftZ7?= =?us-ascii?q?B961VGxwYpwtBf4IxUBqkBIP3tXk/xs8TVDhs+MwOo2ennDNV91oQFWWKTGK?= =?us-ascii?q?OZNKTSvkOS6eIrPuaMY4oVtyz8K/gj//LujHk5lkEBfaSx3pYaaWq0EuloLk?= =?us-ascii?q?iWe3bhgtkMHX0Xsgc/TeHmkFiCXiRSZ3a2UaI8/DY7CIe+AIrEXICtgaCO3C?= =?us-ascii?q?ehEZ1Me29JEkyDHm/od4qeWvcMbjydItR6nzMfSbihSokh1Q2wuw/gzbpoMP?= =?us-ascii?q?bU9jcEupLk0dh4/vXflQsu+jxsE8Sdz2aNQnlzk2MSRj85wKB/rlZnylieya?= =?us-ascii?q?d3n+RXFdxJ6PNIVAc1K4XcwvdhBNDuWwLBeMuJR0i8QtWgHz4xUsg9zMMJY0?= =?us-ascii?q?Z4AtiulgrD0DayA78Ji7yLA4Q5/6XH33fvI8Z9ynDG1LQujlQ9XstONXGphq?= =?us-ascii?q?549wTJAY7JiF+Wm7yldaQbwi7A7WGOxneQsUFcTQ5wSrnFUm4FZkXLrNT451?= =?us-ascii?q?3NQqeyBedvDgwU0sOGK61XevX1nF5GQ7HlI92YbGWvyEmqAhPd/LKHbIPwdy?= =?us-ascii?q?091STbBVNMxxoS9naPLwQJDRChqmPYASdGH07uZV/h6+9ztDWwSUpinFLCVF?= =?us-ascii?q?Foy7fgok1dvvebUf5Ghuhe6i48tzV5Gkq81NvKCt2G4hBsZ7hYfchtugVa3m?= =?us-ascii?q?Xd7l1lN8X8aa1vg0URNQF+vkeo0hRzWc1Mkskv+Wsn1g9/M7ifyhsBdD6JlY?= =?us-ascii?q?z3PfXML2D2+FHna6Pf1lzEltfD0q0T6fIkpk/lsR3vHU0n/g=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0BkAgD5mPpalywYGNZcGwEBAQEDAQE?= =?us-ascii?q?BCQEBAYMYKGR8KIt4XowUgm4ai0aHbBSBZCYRhECDFyE0GAECAQEBAQEBAgE?= =?us-ascii?q?TAQEBAQEGGAZLDEIMAQgBgV0ignINGQE4ARWBMgmDIwIogT4BAxUDAax/M4J?= =?us-ascii?q?wBX9kg2oHghsECIcpfIITgQ+CVoMEgg0BhWoChyYKCIRggSCKfgkFhWKIX4F?= =?us-ascii?q?BPYYHhHaSCByCCjMaI4MTCYILDA4Jg0WECIZLbnkriDaCQXkrghkBAQ?= X-IPAS-Result: =?us-ascii?q?A0BkAgD5mPpalywYGNZcGwEBAQEDAQEBCQEBAYMYKGR8K?= =?us-ascii?q?It4XowUgm4ai0aHbBSBZCYRhECDFyE0GAECAQEBAQEBAgETAQEBAQEGGAZLD?= =?us-ascii?q?EIMAQgBgV0ignINGQE4ARWBMgmDIwIogT4BAxUDAax/M4JwBX9kg2oHghsEC?= =?us-ascii?q?IcpfIITgQ+CVoMEgg0BhWoChyYKCIRggSCKfgkFhWKIX4FBPYYHhHaSCByCC?= =?us-ascii?q?jMaI4MTCYILDA4Jg0WECIZLbnkriDaCQXkrghkBAQ?= X-IronPort-AV: E=Sophos;i="5.49,403,1520899200"; d="scan'208";a="11783578" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from ucol3cpa06.eemsg.mail.mil ([214.24.24.44]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 15 May 2018 08:26:07 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;c16bd901-a9a4-467c-be6f-f0f6c9b861a4 X-EEMSG-check-008: 589006710|UCOL19PA14_EEMSG_MP12.csd.disa.mil X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.200 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0APAQD5mPpah8gAFEFcGgEBAQEBAgEBAQEIAQEBAYMYgQx8KIt4Xo8CGotGh2wUgWQQFhGEQIM4NBgBAgEBAQEBAQIUAQEBCA0JCCgjDEIMAQgBhHENGQE4ARWBMgmDIwIogT4BAxUErH8zgnAFf2SDageCGwQIhymDD4EPglaDBIINAYVqAocmCgiEYIEgin4JBYViiF+BQT2GB4R2kggcggozGiODEwmCCwwOCYNFhAiGS255K4g2gkF5K4IZAQE X-IPAS-Result: A0APAQD5mPpah8gAFEFcGgEBAQEBAgEBAQEIAQEBAYMYgQx8KIt4Xo8CGotGh2wUgWQQFhGEQIM4NBgBAgEBAQEBAQIUAQEBCA0JCCgjDEIMAQgBhHENGQE4ARWBMgmDIwIogT4BAxUErH8zgnAFf2SDageCGwQIhymDD4EPglaDBIINAYVqAocmCgiEYIEgin4JBYViiF+BQT2GB4R2kggcggozGiODEwmCCwwOCYNFhAiGS255K4g2gkF5K4IZAQE Received: from rgout0201.bt.lon5.cpcloud.co.uk (HELO rgout02.bt.lon5.cpcloud.co.uk) ([65.20.0.200]) by ucol19pa14.eemsg.mail.mil with ESMTP; 15 May 2018 08:26:04 +0000 X-OWM-Source-IP: 86.134.53.166 (GB) X-OWM-Env-Sender: richard_c_haines@btinternet.com X-RazorGate-Vade-Classification: clean X-RazorGate-Vade-Verdict: clean 0 X-VadeSecure-score: verdict=clean score=0/300, class=clean X-SNCR-VADESECURE: CLEAN X-RazorGate-Vade-Verdict: clean 0 X-RazorGate-Vade-Classification: clean X-RazorGate-Vade: gggruggvucftvghtrhhoucdtuddrgedthedrvdejgddtvdcutefuodetggdotefrodftvfcurfhrohhfihhlvgemuceutffkvffkuffjvffgnffgvefqofdpqfgfvfenuceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofestddtredtredttdenucfhrhhomheptfhitghhrghrugcujfgrihhnvghsuceorhhitghhrghruggptggphhgrihhnvghssegsthhinhhtvghrnhgvthdrtghomheqnecukfhppeekiedrudefgedrheefrdduieeinecurfgrrhgrmhephhgvlhhopehlohgtrghlhhhoshhtrdhlohgtrghlughomhgrihhnpdhinhgvthepkeeirddufeegrdehfedrudeiiedpmhgrihhlfhhrohhmpeeorhhitghhrghruggptggphhgrihhnvghssegsthhinhhtvghrnhgvthdrtghomheqpdhrtghpthhtohepoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqedprhgtphhtthhopeeoshgvlhhinhhugiesthihtghhohdrnhhsrgdrghhovheqnecuvehluhhsthgvrhfuihiivgeptd Received: from localhost.localdomain (86.134.53.166) by rgout02.bt.lon5.cpcloud.co.uk (9.0.019.26-1) (authenticated as richard_c_haines@btinternet.com) id 5AF326F9008DD17B; Tue, 15 May 2018 09:26:00 +0100 X-EEMSG-check-009: 444-444 To: selinux@tycho.nsa.gov Date: Tue, 15 May 2018 09:25:53 +0100 Message-Id: <20180515082553.30310-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.14.3 Subject: [RFC PATCH 1/1] selinux-testsuite: Add binder tests 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: From: Richard Haines via Selinux Reply-To: Richard Haines Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Virus-Scanned: ClamAV using ClamSMTP Add binder tests. See tests/binder/test_binder.c for details on message flows to test security_binder*() functions. Signed-off-by: Richard Haines --- README.md | 8 + defconfig | 8 + policy/Makefile | 2 +- policy/test_binder.te | 83 +++++++ tests/Makefile | 2 +- tests/binder/Makefile | 7 + tests/binder/check_binder.c | 80 +++++++ tests/binder/test | 131 +++++++++++ tests/binder/test_binder.c | 543 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 862 insertions(+), 2 deletions(-) create mode 100644 policy/test_binder.te create mode 100644 tests/binder/Makefile create mode 100644 tests/binder/check_binder.c create mode 100644 tests/binder/test create mode 100644 tests/binder/test_binder.c diff --git a/README.md b/README.md index c9f3b2b..60a249e 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,14 @@ directory or you can follow these broken-out steps: The broken-out steps allow you to run the tests multiple times without loading policy each time. +Note that if leaving the test policy in-place for further testing, the +policy build process changes a boolean: + On policy load: setsebool allow_domain_fd_use=0 + On policy unload: setsebool allow_domain_fd_use=1 +The consequence of this is that after a system reboot, the boolean +defaults to true. Therefore if running the fdreceive or binder tests, +reset the boolean to false, otherwise some tests will fail. + 4) Review the test results. As each test script is run, the name of the script will be displayed followed diff --git a/defconfig b/defconfig index 7dce8bc..dc6ef30 100644 --- a/defconfig +++ b/defconfig @@ -51,3 +51,11 @@ CONFIG_CRYPTO_USER=m # This is enabled to test overlayfs SELinux integration. # It is not required for SELinux operation itself. CONFIG_OVERLAY_FS=m + +# Android binder implementations. +# These are enabled to test the binder controls in +# tests/binder; they are not required for SELinux operation itself. +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_DEVICES="binder" +# CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set diff --git a/policy/Makefile b/policy/Makefile index 8ed5e46..5a9d411 100644 --- a/policy/Makefile +++ b/policy/Makefile @@ -25,7 +25,7 @@ TARGETS = \ test_task_getsid.te test_task_setpgid.te test_task_setsched.te \ test_transition.te test_inet_socket.te test_unix_socket.te \ test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \ - test_ibpkey.te test_atsecure.te + test_ibpkey.te test_atsecure.te test_binder.te ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true) TARGETS += test_bounds.te diff --git a/policy/test_binder.te b/policy/test_binder.te new file mode 100644 index 0000000..c4ad2ae --- /dev/null +++ b/policy/test_binder.te @@ -0,0 +1,83 @@ + +attribute binderdomain; + +# +################################## Manager ################################### +# +type test_binder_mgr_t; +domain_type(test_binder_mgr_t) +unconfined_runs_test(test_binder_mgr_t) +typeattribute test_binder_mgr_t testdomain; +typeattribute test_binder_mgr_t binderdomain; +allow test_binder_mgr_t self:binder { set_context_mgr call }; +allow test_binder_mgr_t device_t:chr_file { ioctl open read write map }; +allow test_binder_mgr_t self:capability { sys_nice }; +allow test_binder_client_t test_binder_mgr_t:fd use; + +# +################################# Client #################################### +# +type test_binder_client_t; +domain_type(test_binder_client_t) +unconfined_runs_test(test_binder_client_t) +typeattribute test_binder_client_t testdomain; +typeattribute test_binder_client_t binderdomain; +allow test_binder_client_t self:binder { call }; +allow test_binder_client_t test_binder_mgr_t:binder { call transfer impersonate }; +allow test_binder_client_t device_t:chr_file { ioctl open read write map }; +# For fstat: +allow test_binder_client_t device_t:chr_file getattr; + +# +############################## Client no call ################################ +# +type test_binder_client_no_call_t; +domain_type(test_binder_client_no_call_t) +unconfined_runs_test(test_binder_client_no_call_t) +typeattribute test_binder_client_no_call_t testdomain; +typeattribute test_binder_client_no_call_t binderdomain; +allow test_binder_client_no_call_t device_t:chr_file { ioctl open read write map }; + +# +############################ Client no transfer ############################# +# +type test_binder_client_no_transfer_t; +domain_type(test_binder_client_no_transfer_t) +unconfined_runs_test(test_binder_client_no_transfer_t) +typeattribute test_binder_client_no_transfer_t testdomain; +typeattribute test_binder_client_no_transfer_t binderdomain; +allow test_binder_client_no_transfer_t test_binder_mgr_t:binder { call }; +allow test_binder_client_no_transfer_t device_t:chr_file { ioctl open read write map }; + +# +########################## Manager no fd {use} ############################### +# +type test_binder_mgr_no_fd_t; +domain_type(test_binder_mgr_no_fd_t) +unconfined_runs_test(test_binder_mgr_no_fd_t) +typeattribute test_binder_mgr_no_fd_t testdomain; +typeattribute test_binder_mgr_no_fd_t binderdomain; +allow test_binder_mgr_no_fd_t self:binder { set_context_mgr call }; +allow test_binder_mgr_no_fd_t device_t:chr_file { ioctl open read write map }; +allow test_binder_mgr_no_fd_t self:capability { sys_nice }; +allow test_binder_client_t test_binder_mgr_no_fd_t:binder { call transfer }; + +# +########################### Client no impersonate ############################ +# +type test_binder_client_no_im_t; +domain_type(test_binder_client_no_im_t) +unconfined_runs_test(test_binder_client_no_im_t) +typeattribute test_binder_client_no_im_t testdomain; +typeattribute test_binder_client_no_im_t binderdomain; +allow test_binder_client_no_im_t self:binder { call }; +allow test_binder_client_no_im_t test_binder_mgr_t:binder { call transfer }; +allow test_binder_client_no_im_t device_t:chr_file { ioctl open read write map }; +allow test_binder_client_no_im_t test_binder_mgr_t:fd use; +allow test_binder_client_no_im_t device_t:chr_file getattr; + +# +############ Allow these domains to be entered from sysadm domain ############ +# +miscfiles_domain_entry_test_files(binderdomain) +userdom_sysadm_entry_spec_domtrans_to(binderdomain) diff --git a/tests/Makefile b/tests/Makefile index 27ed6eb..7607c22 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ SUBDIRS:= domain_trans entrypoint execshare exectrace execute_no_trans \ task_setnice task_setscheduler task_getscheduler task_getsid \ task_getpgid task_setpgid file ioctl capable_file capable_net \ capable_sys dyntrans dyntrace bounds nnp_nosuid mmap unix_socket \ - inet_socket overlay checkreqprot mqueue mac_admin atsecure + inet_socket overlay checkreqprot mqueue mac_admin atsecure binder ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && echo true),true) ifneq ($(shell ./kvercmp $$(uname -r) 4.7),-1) diff --git a/tests/binder/Makefile b/tests/binder/Makefile new file mode 100644 index 0000000..a60eeb3 --- /dev/null +++ b/tests/binder/Makefile @@ -0,0 +1,7 @@ +TARGETS = check_binder test_binder + +LDLIBS += -lselinux + +all: $(TARGETS) +clean: + rm -f $(TARGETS) diff --git a/tests/binder/check_binder.c b/tests/binder/check_binder.c new file mode 100644 index 0000000..3d553a0 --- /dev/null +++ b/tests/binder/check_binder.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v]\n" + "Where:\n\t" + "-v Print binder version.\n", progname); + exit(-1); +} + +int main(int argc, char **argv) +{ + int opt, result, fd; + char *driver = "/dev/binder"; + bool verbose; + void *mapped; + size_t mapsize = 1024; + struct binder_version vers; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + fd = open(driver, O_RDWR | O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "Cannot open: %s error: %s\n", + driver, strerror(errno)); + exit(-1); + } + + /* Need this or no VMA error from kernel */ + mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED) { + fprintf(stderr, "mmap error: %s\n", strerror(errno)); + close(fd); + exit(-1); + } + + result = ioctl(fd, BINDER_VERSION, &vers); + if (result < 0) { + fprintf(stderr, "ioctl BINDER_VERSION: %s\n", + strerror(errno)); + goto brexit; + } + + if (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION) { + fprintf(stderr, + "Binder kernel version: %d differs from user space version: %d\n", + vers.protocol_version, + BINDER_CURRENT_PROTOCOL_VERSION); + result = -1; + goto brexit; + } + + if (verbose) + fprintf(stderr, "Binder kernel version: %d\n", + vers.protocol_version); + +brexit: + munmap(mapped, mapsize); + close(fd); + + return result; +} diff --git a/tests/binder/test b/tests/binder/test new file mode 100644 index 0000000..434ae32 --- /dev/null +++ b/tests/binder/test @@ -0,0 +1,131 @@ +#!/usr/bin/perl +use Test::More; + +BEGIN { + $basedir = $0; + $basedir =~ s|(.*)/[^/]*|$1|; + + # allow binder info to be shown + $v = $ARGV[0]; + if ($v) { + if ( $v ne "-v" ) { + plan skip_all => "Invalid option (use -v)"; + } + } + + # check if binder driver available and the kernel/userspace versions. + if ( system("$basedir/check_binder 2> /dev/null") != 0 ) { + plan skip_all => + "Binder not supported or kernel/userspace versions differ"; + } + else { + plan tests => 6; + } +} + +if ($v) { + if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_binder_mgr_t $basedir/test_binder -v manager"; + } + + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + + # Verify that authorized client can transact with the manager. + $result = + system "runcon -t test_binder_client_t $basedir/test_binder -v client"; + ok( $result eq 0 ); + + # Verify that client cannot call manager (no call perm). + $result = system +"runcon -t test_binder_client_no_call_t $basedir/test_binder -v client 2>&1"; + ok( $result >> 8 eq 9 ); + + # Verify that client cannot communicate with manager (no impersonate perm). + $result = system +"runcon -t test_binder_client_no_im_t $basedir/test_binder -v client 2>&1"; + ok( $result >> 8 eq 102 ); + + # Verify that client cannot communicate with manager (no transfer perm). + $result = system +"runcon -t test_binder_client_no_transfer_t $basedir/test_binder -v client 2>&1"; + ok( $result >> 8 eq 9 ); + + # Kill the manager. + kill TERM, $pid; + + # Verify that client cannot become a manager (no set_context_mgr perm). + $result = + system + "runcon -t test_binder_client_t $basedir/test_binder -v manager 2>&1"; + ok( $result >> 8 eq 4 ); + +# Start manager to test that selinux_binder_transfer_file() fails when fd { use } is denied by policy. + if ( ( $pid = fork() ) == 0 ) { + exec + "runcon -t test_binder_mgr_no_fd_t $basedir/test_binder -v manager"; + } + + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server, however the fd passed will not be valid for manager +# domain and binder will return BR_FAILED_REPLY. + $result = + system + "runcon -t test_binder_client_t $basedir/test_binder -v client 2>&1"; + ok( $result >> 8 eq 9 ); + + # Kill the manager + kill TERM, $pid; +} +else { + if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_binder_mgr_t $basedir/test_binder manager"; + } + + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + + # Verify that authorized client can transact with the manager. + $result = + system "runcon -t test_binder_client_t $basedir/test_binder client"; + ok( $result eq 0 ); + + # Verify that client cannot call manager (no call perm). + $result = system + "runcon -t test_binder_client_no_call_t $basedir/test_binder client 2>&1"; + ok( $result >> 8 eq 9 ); + + # Verify that client cannot communicate with manager (no impersonate perm). + $result = system + "runcon -t test_binder_client_no_im_t $basedir/test_binder client 2>&1"; + ok( $result >> 8 eq 102 ); + + # Verify that client cannot communicate with manager (no transfer perm). + $result = system +"runcon -t test_binder_client_no_transfer_t $basedir/test_binder client 2>&1"; + ok( $result >> 8 eq 9 ); + + # Kill the manager. + kill TERM, $pid; + + # Verify that client cannot become a manager (no set_context_mgr perm). + $result = + system "runcon -t test_binder_client_t $basedir/test_binder manager 2>&1"; + ok( $result >> 8 eq 4 ); + +# Start manager to test that selinux_binder_transfer_file() fails when fd { use } is denied by policy. + if ( ( $pid = fork() ) == 0 ) { + exec "runcon -t test_binder_mgr_no_fd_t $basedir/test_binder manager"; + } + + select( undef, undef, undef, 0.25 ); # Give it a moment to initialize. + +# Verify that authorized client can communicate with the server, however the fd passed will not be valid for manager +# domain and binder will return BR_FAILED_REPLY. + $result = + system "runcon -t test_binder_client_t $basedir/test_binder client 2>&1"; + ok( $result >> 8 eq 9 ); + + # Kill the manager + kill TERM, $pid; +} +exit; diff --git a/tests/binder/test_binder.c b/tests/binder/test_binder.c new file mode 100644 index 0000000..8881cce --- /dev/null +++ b/tests/binder/test_binder.c @@ -0,0 +1,543 @@ +/* + * This is a simple binder client/server(manager) that only uses the + * raw ioctl commands. It does not rely on a 'service manager' as in + * the Android world as it only uses one 'target' = 0. + * + * The transaction/reply flow is basically: + * Client Manager + * ======== ========= + * + * Becomes context manager + * Send transaction + * requesting file + * descriptor from + * the Manager + * ---------------------------------------> + * Manager replies with its + * binder file descriptor + * <-------------------------------------- + * Check fd valid, if so send + * TF_ONE_WAY transaction to Manager + * using the received fd + * ---------------------------------------> + * End of tests so Manager + * waits to be killed + * Client exits + * + * Using binder test policy the following will be validated: + * security_binder_set_context_mgr() binder { set_context_mgr } + * security_binder_transaction() binder { call impersonate } + * security_binder_transfer_binder() binder { transfer } + * security_binder_transfer_file() fd { use } + * + * TODO security_binder_transfer_file() uses BPF if configured in kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uint32_t target; /* This will be set to '0' as only need one target */ +static bool verbose; + +static int binder_parse(int fd, uintptr_t ptr, size_t size, char *text); + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-v] manager | client\n" + "Where:\n\t" + "-v Print context and command information.\n\t" + "manager Act as binder context manager.\n\t" + "client Act as binder client.\n" + "\nNote: Ensure this boolean command is run when " + "testing after a reboot:\n\t" + "setsebool allow_domain_fd_use=0\n", progname); + exit(1); +} + +static const char *cmd_name(uint32_t cmd) +{ + switch (cmd) { + case BR_NOOP: + return "BR_NOOP"; + case BR_TRANSACTION_COMPLETE: + return "BR_TRANSACTION_COMPLETE"; + case BR_INCREFS: + return "BR_INCREFS"; + case BR_ACQUIRE: + return "BR_ACQUIRE"; + case BR_RELEASE: + return "BR_RELEASE"; + case BR_DECREFS: + return "BR_DECREFS"; + case BR_TRANSACTION: + return "BR_TRANSACTION"; + case BR_REPLY: + return "BR_REPLY"; + case BR_FAILED_REPLY: + return "BR_FAILED_REPLY"; + case BR_DEAD_REPLY: + return "BR_DEAD_REPLY"; + case BR_DEAD_BINDER: + return "BR_DEAD_BINDER"; + case BR_ERROR: + return "BR_ERROR"; + /* fallthrough */ + default: + return "Unknown command"; + } +} + +void print_trans_data(struct binder_transaction_data *txn) +{ + printf("\thandle: %ld\n", (unsigned long)txn->target.handle); + printf("\tcookie: %lld\n", txn->cookie); + printf("\tcode: %u\n", txn->code); + switch (txn->flags) { + case TF_ONE_WAY: + printf("\tflag: TF_ONE_WAY\n"); + break; + case TF_ROOT_OBJECT: + printf("\tflag: TF_ROOT_OBJECT\n"); + break; + case TF_STATUS_CODE: + printf("\tflag: TF_STATUS_CODE\n"); + break; + case TF_ACCEPT_FDS: + printf("\tflag: TF_ACCEPT_FDS\n"); + break; + default: + printf("Unknown flag: %u\n", txn->flags); + } + printf("\tsender pid: %u\n", txn->sender_pid); + printf("\tsender euid: %u\n", txn->sender_euid); + printf("\tdata_size: %llu\n", txn->data_size); + printf("\toffsets_size: %llu\n", txn->offsets_size); +} + + +static int send_reply(int fd, struct binder_transaction_data *txn_in) +{ + int result; + unsigned int writebuf[1024]; + struct flat_binder_object obj; + struct binder_write_read bwr; + struct binder_transaction_data *txn; + + if (txn_in->flags == TF_ONE_WAY) { + if (verbose) + printf("No reply to BC_TRANSACTION as flags = TF_ONE_WAY\n"); + return 0; + } + + if (verbose) + printf("Sending BC_REPLY\n"); + + writebuf[0] = BC_REPLY; + txn = (struct binder_transaction_data *)(&writebuf[1]); + + memset(txn, 0, sizeof(*txn)); + txn->target.handle = txn_in->target.handle; + txn->cookie = txn_in->cookie; + txn->code = txn_in->code; + txn->flags = TF_ACCEPT_FDS; + + memset(&obj, 0, sizeof(struct flat_binder_object)); + obj.hdr.type = BINDER_TYPE_FD; + obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; + obj.binder = txn->target.handle; + obj.cookie = txn->cookie; + /* The binder fd is used for testing as it allows policy to set + * whether the Client/Manager can be allowed access (fd use) or + * not. For example test_binder_mgr_t has: + * allow test_binder_client_t test_binder_mgr_t:fd use; + * whereas test_binder_mgr_no_fd_t does not allow this fd use. + * + * This also allows a check for the impersonate permission later as + * the Client will use this (the Managers fd) to send a transaction. + */ + obj.handle = fd; + + txn->data_size = sizeof(struct flat_binder_object); + txn->data.ptr.buffer = (uintptr_t)&obj; + txn->data.ptr.offsets = (uintptr_t)&obj + + sizeof(struct flat_binder_object); + txn->offsets_size = sizeof(binder_size_t); + + memset(&bwr, 0, sizeof(bwr)); + bwr.write_buffer = (unsigned long)writebuf; + bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn); + + result = ioctl(fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, "%s ioctl BINDER_WRITE_READ: %s\n", + __func__, strerror(errno)); + return -1; + } + + return result; +} + +/* This retrieves the requested Managers file descriptor, then using this + * sends a simple transaction to trigger the impersonate permission. + */ +static void extract_fd_and_respond(struct binder_transaction_data *txn_in) +{ + int result; + uint32_t cmd; + struct stat sb; + struct binder_write_read bwr; + struct flat_binder_object *obj; + struct binder_transaction_data *txn; + unsigned int readbuf[32]; + unsigned int writebuf[1024]; + binder_size_t *offs = (binder_size_t *)(uintptr_t)txn_in->data.ptr.offsets; + + /* Get the fbo that contains the Managers binder file descriptor. */ + obj = (struct flat_binder_object *) + (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs); + + /* fstat this just to see if a valid fd */ + result = fstat(obj->handle, &sb); + if (result < 0) { + fprintf(stderr, "Not a valid fd: %s\n", strerror(errno)); + exit(100); + } + + if (verbose) + printf("Retrieved Managers fd: %d st_dev: %ld\n", + obj->handle, sb.st_dev); + + /* Send response using Managers fd to trigger impersonate check. */ + writebuf[0] = BC_TRANSACTION; + txn = (struct binder_transaction_data *)(&writebuf[1]); + memset(txn, 0, sizeof(*txn)); + txn->target.handle = target; + txn->cookie = 0; + txn->code = 0; + txn->flags = TF_ONE_WAY; + + txn->data_size = 0; + txn->data.ptr.buffer = (uintptr_t)NULL; + txn->data.ptr.offsets = (uintptr_t)NULL; + txn->offsets_size = 0; + + memset(&bwr, 0, sizeof(bwr)); + bwr.write_buffer = (unsigned long)writebuf; + bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn); + + bwr.read_size = sizeof(readbuf); + bwr.read_consumed = 0; + bwr.read_buffer = (uintptr_t)readbuf; + + result = ioctl(obj->handle, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "CLIENT ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + exit(101); + } + + if (verbose) + printf("Client read_consumed: %lld\n", bwr.read_consumed); + + cmd = binder_parse(obj->handle, (uintptr_t)readbuf, + bwr.read_consumed, + "Client using Managers FD"); + + if (cmd == BR_FAILED_REPLY || + cmd == BR_DEAD_REPLY || + cmd == BR_DEAD_BINDER) { + fprintf(stderr, + "Client using Managers received FD failed response\n"); + exit(102); + } +} + +/* Parse response, reply as required and then return last CMD */ +static int binder_parse(int fd, uintptr_t ptr, size_t size, char *text) +{ + uintptr_t end = ptr + (uintptr_t)size; + uint32_t cmd; + + while (ptr < end) { + cmd = *(uint32_t *)ptr; + ptr += sizeof(uint32_t); + + if (verbose) + printf("%s command: %s\n", text, cmd_name(cmd)); + + switch (cmd) { + case BR_NOOP: + break; + case BR_TRANSACTION_COMPLETE: + break; + case BR_INCREFS: + case BR_ACQUIRE: + case BR_RELEASE: + case BR_DECREFS: + ptr += sizeof(struct binder_ptr_cookie); + break; + case BR_TRANSACTION: { + struct binder_transaction_data *txn = + (struct binder_transaction_data *)ptr; + + if (verbose) { + printf("BR_TRANSACTION data:\n"); + print_trans_data(txn); + } + + /* The manager sends reply that will contain its fd */ + if (send_reply(fd, txn) < 0) { + fprintf(stderr, "send_reply() failed.\n"); + return -1; + } + ptr += sizeof(*txn); + break; + } + case BR_REPLY: { + struct binder_transaction_data *txn = + (struct binder_transaction_data *)ptr; + + if (verbose) { + printf("BR_REPLY data:\n"); + print_trans_data(txn); + } + + /* Client extracts the Manager fd, and responds */ + extract_fd_and_respond(txn); + ptr += sizeof(*txn); + break; + } + case BR_DEAD_BINDER: + break; + case BR_FAILED_REPLY: + break; + case BR_DEAD_REPLY: + break; + case BR_ERROR: + ptr += sizeof(uint32_t); + break; + default: + if (verbose) + printf("%s Parsed unknown command: %d\n", + text, cmd); + return -1; + } + } + + return cmd; +} + +int main(int argc, char **argv) +{ + int opt, option, result, fd, count; + uint32_t cmd; + pid_t pid; + char *driver = "/dev/binder"; + char *context; + void *mapped; + size_t mapsize = 2048; + struct binder_write_read bwr; + struct flat_binder_object obj; + struct binder_transaction_data *txn; + unsigned int readbuf[32]; + unsigned int writebuf[1024]; + + target = 0; /* Only need one target - the Manager */ + verbose = false; + + while ((opt = getopt(argc, argv, "v")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 1) + usage(argv[0]); + + if (!strcmp(argv[optind], "manager")) + option = 1; + else if (!strcmp(argv[optind], "client")) + option = 2; + else + usage(argv[0]); + + fd = open(driver, O_RDWR | O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "Cannot open %s error: %s\n", driver, + strerror(errno)); + exit(1); + } + + /* Need this or "no VMA" error from kernel */ + mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED) { + fprintf(stderr, "mmap error: %s\n", strerror(errno)); + close(fd); + exit(2); + } + + /* Get our context and pid */ + result = getcon(&context); + if (result < 0) { + fprintf(stderr, "Failed to obtain SELinux context\n"); + result = 3; + goto brexit; + } + pid = getpid(); + + switch (option) { + case 1: /* manager */ + if (verbose) { + printf("Manager PID: %d Process context:\n\t%s\n", + pid, context); + } + + result = ioctl(fd, BINDER_SET_CONTEXT_MGR, 0); + if (result < 0) { + fprintf(stderr, + "Failed to become context manager: %s\n", + strerror(errno)); + result = 4; + goto brexit; + } + + readbuf[0] = BC_ENTER_LOOPER; + bwr.write_size = sizeof(readbuf[0]); + bwr.write_consumed = 0; + bwr.write_buffer = (uintptr_t)readbuf; + + bwr.read_size = 0; + bwr.read_consumed = 0; + bwr.read_buffer = 0; + + result = ioctl(fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "Manager ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + result = 5; + goto brexit; + } + + while (true) { + bwr.read_size = sizeof(readbuf); + bwr.read_consumed = 0; + bwr.read_buffer = (uintptr_t)readbuf; + + result = ioctl(fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "Manager ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + result = 6; + goto brexit; + } + + if (bwr.read_consumed == 0) + continue; + + if (verbose) + printf("Manager read_consumed: %lld\n", + bwr.read_consumed); + + cmd = binder_parse(fd, (uintptr_t)readbuf, + bwr.read_consumed, "Manager"); + } + break; + + case 2: /* client */ + if (verbose) { + printf("Client PID: %d Process context:\n\t%s\n", + pid, context); + } + + writebuf[0] = BC_TRANSACTION; + txn = (struct binder_transaction_data *)(&writebuf[1]); + memset(txn, 0, sizeof(*txn)); + txn->target.handle = target; + txn->cookie = 0; + txn->code = 0; + txn->flags = TF_ACCEPT_FDS; + + memset(&obj, 0, sizeof(struct flat_binder_object)); + obj.hdr.type = BINDER_TYPE_WEAK_BINDER; + obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; + obj.binder = target; + obj.handle = 0; + obj.cookie = 0; + + txn->data_size = sizeof(struct flat_binder_object); + txn->data.ptr.buffer = (uintptr_t)&obj; + txn->data.ptr.offsets = (uintptr_t)&obj + + sizeof(struct flat_binder_object); + txn->offsets_size = sizeof(binder_size_t); + + memset(&bwr, 0, sizeof(bwr)); + bwr.write_buffer = (unsigned long)writebuf; + bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn); + + /* Expect client to get max two responses: + * 1) From the above BC_TRANSACTION + * 2) The responding BC_REPLY from send_reply() + * unless an error. + */ + count = 0; + while (count != 2) { + bwr.read_size = sizeof(readbuf); + bwr.read_consumed = 0; + bwr.read_buffer = (uintptr_t)readbuf; + + result = ioctl(fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "Client ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + result = 8; + goto brexit; + } + + if (verbose) + printf("Client read_consumed: %lld\n", + bwr.read_consumed); + + cmd = binder_parse(fd, (uintptr_t)readbuf, + bwr.read_consumed, "Client"); + + if (cmd == BR_FAILED_REPLY || + cmd == BR_DEAD_REPLY || + cmd == BR_DEAD_BINDER) { + result = 9; + goto brexit; + } + count++; + } + break; + + default: + result = -1; + } + +brexit: + free(context); + munmap(mapped, mapsize); + close(fd); + + return result; +}