From patchwork Mon May 21 16:33:37 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: 10415885 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 D52F6600CC for ; Mon, 21 May 2018 16:35:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C09FA288BA for ; Mon, 21 May 2018 16:35:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B263228938; Mon, 21 May 2018 16:35:16 +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 upbd19pa10.eemsg.mail.mil (upbd19pa10.eemsg.mail.mil [214.24.27.85]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E31D4288BA for ; Mon, 21 May 2018 16:35:10 +0000 (UTC) Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.2]) by upbd19pa10.eemsg.mail.mil with ESMTP/TLS/AES256-SHA; 21 May 2018 16:35:07 +0000 X-IronPort-AV: E=Sophos;i="5.49,426,1520899200"; d="scan'208";a="12005770" IronPort-PHdr: =?us-ascii?q?9a23=3AjCJQsxOsbXglilhdEZEl6mtUPXoX/o7sNwtQ0K?= =?us-ascii?q?IMzox0LPz/ocbcNUDSrc9gkEXOFd2Cra4c0KyO6+jJYi8p2d65qncMcZhBBV?= =?us-ascii?q?cuqP49uEgeOvODElDxN/XwbiY3T4xoXV5h+GynYwAOQJ6tL1LdrWev4jEMBx?= =?us-ascii?q?7xKRR6JvjvGo7Vks+7y/2+94fcbglUijexe69+IAmrpgjNq8cahpdvJLwswR?= =?us-ascii?q?XTuHtIfOpWxWJsJV2Nmhv3+9m98p1+/SlOovwt78FPX7n0cKQ+VrxYES8pM3?= =?us-ascii?q?sp683xtBnMVhWA630BWWgLiBVIAgzF7BbnXpfttybxq+Rw1DWGMcDwULs7Vy?= =?us-ascii?q?6i76N2QxH2jikJOSMy/GXOhsBtkK5XpRSsrAF9zYHJeoGYLPpwcL3Ac90URm?= =?us-ascii?q?RPWd1cWzBdDo6mc4cCFfYNMfpeooLgp1UOtxy+BQy0Ce3zyz9Hmn/20rcg0+?= =?us-ascii?q?s8DArI3hYvH9MIsHvKt9X+KbkSUeGvw6LV0DvMcfdW2Tb76IjVfREqvPaBXa?= =?us-ascii?q?lufsrVyEkvER7Fj1qLpIz5PzKayuQNs2+B4+pmTuKgkXQrqw52ojix38ohjJ?= =?us-ascii?q?TCiIENyl3c6Cl0z4k4Kce4RUJme9KoDpRduz+AO4drWs8vQHxktDwnxrAIp5?= =?us-ascii?q?K3ZicHxZY9yxLBa/GKfI6F6Q/5WumLOzd3nndldaq6hxa17Eev1PXxVtKx0F?= =?us-ascii?q?ZWtipFlcTMtmwV2xzT9MeHTvx981+92TmVzQDT6/xEIVsumarHK58u3r4wlp?= =?us-ascii?q?0JvUTFAiD2g1n5gLWTdkUl/uik8+XnYrP4qZ+AL4J4lw7zP6s0lsG/HOg0KB?= =?us-ascii?q?YCUmeF9eimybHv5Uj5T69Ljv0ynKnZqpfaJcEDq66iHQBV1ocj6xCiDzapyd?= =?us-ascii?q?gXhn4HLE9DeB2bkYfpIErDIOz4DPijg1Ssly1nx/bdPrL7GJnNIX/DkKn5cb?= =?us-ascii?q?Zn90Fc0BYzzcxY559MCLEBJ/TzVVXttNzYFBA5NRe5w+TgCNV704MRQ3mPAr?= =?us-ascii?q?OHP6PIql+E/OUvI/ODZIUNojbyN+Al5+LyjX8+gVIdf6up0oELZ3C7BfRmJE?= =?us-ascii?q?OZYXvygtoaH2cKuhc+TePxh12fVz5Te2uyU7g75jEhB4KsFZ3DSZy1gLydwC?= =?us-ascii?q?e7GYVbZnhYBV+XD3jocYSEW+sLaC+JI89ujCILWqa7R48mzxGuuxfwy6B7Ie?= =?us-ascii?q?rM5i0YqZXj2cBo6O3UkxEy8yF7ANqZ02GMVGx7hH0HRyUx3Kxlpkx90FiD27?= =?us-ascii?q?Big/NEDdxT++9JUgAiOJHB0+x1EcryVxndcdeOTVapXs+pASotTt4rxd8BfV?= =?us-ascii?q?p9Ec24jh/fxyqqH6MVl7uTCZw19KLcw2b+J8JjxHbDyqYhk0MmQ8tUOG2hnq?= =?us-ascii?q?5w6Q7TB4vTnEWYk6albqMc3SHX+GeE12qOs1lSUBRsXqXdQXAfekzWoMzn6U?= =?us-ascii?q?PaVbCuE7UnMhBaxM6aMKRKcNzpjU5eRPfnItvRf3y+l323BRaSybOGdJDqdH?= =?us-ascii?q?kF3CXBFEgElBge/HiHNQg6AyeuvXjeASdgFV3xfkzs9vN+p2mjTk8uyAGKbV?= =?us-ascii?q?Nu2Kap+hIPgvycUfwT1KoeuCg9szV0AEq939XOBtqOvQpuZqNcbs884Fdczm?= =?us-ascii?q?/ZshR9Pp25I6B5iF8eaB57v0T01xV4Eo9Ai9QlrGs2zApuLqKVyFBBeCmb3Z?= =?us-ascii?q?D3J73aMWry8wqsa67Rx1HSytGW+r0A6P4gsVXsoBmpFlY+83Vgy9RayWaT5o?= =?us-ascii?q?/LDAUMS5L8SVw4+AR/p73AZSk9/YzU32V2Maaoqj/Cx84pBOw9xxm8ZdhfNL?= =?us-ascii?q?2LFBTuE8waAMijM/cqlESobh0aOuBS6K80MNm8e/uAxqGrIP5qnCi6gmRf/I?= =?us-ascii?q?B9zkWM+jJmSuHVwpkI2P6Y3g6IVjvmileurNz3k5heZT4OBmq/1TTkBIlJa6?= =?us-ascii?q?1pc4YLE2CuI9arxthlnJ7tXXlY9VCmB1wc3s+lYxySYELh3QdIz0QYvWSnmT?= =?us-ascii?q?ekzzxzizwooLCQ3CjSw+v8bhoHIXVGRHd8glf2Ooe0ktUaUFKvbwgzmxuv/V?= =?us-ascii?q?z6yLRDpKRjM2nTRl9Ffzb3L25+TquwsaCCb9RT55MotiVXVuu8bEueSr78pR?= =?us-ascii?q?sVyTnjH2xEyDA8bTGqtY3znwZmh2KFMHZzsH3ZdNl0xRfe/9zcWedd3iEYSy?= =?us-ascii?q?l8iDnXAEW8Ptay8NWPj5fDs+a+V2O9WZ1IayXry52PtDej721wHRK/h+yzms?= =?us-ascii?q?HgEQUiyy/70N1qVSHWoxbmfobr0Kq7PPl8fkl1GFD88NB2GoZkkos/nJsQw2?= =?us-ascii?q?QVho2J/Xoblmf+KdZb1rz4bHoWXjMLwMDa4A7+2E1lMH2J25j1VnKHwstuf9?= =?us-ascii?q?O6eH8Z2joh78BWD6eZ9KREkjFoolq8sw3ReeJynjEByfQw8n4XmPwJuBEzwS?= =?us-ascii?q?WHGbAeB1JYPSvxlxSS89+xsqtXZGG1cbi/ykVyh9ahA6+eogtEQnb2Zo8iHT?= =?us-ascii?q?Ns7sV4KF/Mznvz5Zz/ddnOa9Icqx2Unw3Gj+dLNJI7juAKijZ/OWLhoX0lzP?= =?us-ascii?q?Y2jQR00pGnuIiKMHli/KOlAh9YLzH1adkc+jf3gaZZhMaW0JilHo99FTUTQJ?= =?us-ascii?q?voUfWoHSoRtfXnMwaBDiYxqnKcGbrREw+Q9ltmr27PE5CsMnGYOmMVzdN8Sx?= =?us-ascii?q?mBPEZfmhwbXC0mnp4lEQCn3MLhf11/5jAN4V74rwBByux2OBbiVWffvh2nai?= =?us-ascii?q?8uSJiYLhpZ8B1N51vPPcyZ9OJzEDlS/oe9owyVNmybewNIAHkUVUOYAlDjOb?= =?us-ascii?q?+u5cXd/+WDGOqxMeHOYbSPqOxZUfeE35Sv3ZV6/zyULMWAImFiD+En2kpERX?= =?us-ascii?q?15Fd7ZlCsSRCwMjS3NadKbpBCn+iBstM+w7PHrVBjo5YuVBLtYKc9v9Ayuga?= =?us-ascii?q?efK+6Qgz50KTBC1pwW3X/I0KMS3FATiyF0bDmtDboAtS/LTK3KnK9YEx8bZD?= =?us-ascii?q?l3NMdS6KI8xAZNM9bBitzpzr54kuI1C1BdWFP6gc6lYsgKI2CmNFPbH0aHLq?= =?us-ascii?q?+GKiPXzM3teqOzV7lQjORStx2ttjeWCFPsPzSZlzn0TBCjK+9NgzuHPBxFv4?= =?us-ascii?q?G9dAxhCW/5TNLpche7KsN4jSUqwb0ogXPHLWgcMTl4c0NJsLKQ9jhVje9hFG?= =?us-ascii?q?xb6XppN+6EmzyW7+PAMJYZreNrAjhol+Jd+Hk10LpV7C5DRPxzgybds8BhrE?= =?us-ascii?q?qnkuaVzDprSh1OqixEhIiTp0VtJb3Z9oVcWXbD5B8C92qQBA4Up9R7EdDvvL?= =?us-ascii?q?hQxcbJlKL2MjhC8tbU8tAbB8nbMs6HN2AhMRXxEj7OEAQFVSKrNX3Yh0FFjP?= =?us-ascii?q?GS8XiVooIgqpjrmZsBVLlbW0cvFvMdFEtlH8cPL4twXjMhjbGUltUI5WakoB?= =?us-ascii?q?nXWspaoojNVuiODvX3NDaZkb5EagMKwbP4LYUTLor720hjallmgovHAE/QXd?= =?us-ascii?q?FRoi17cAA4ukJN8GJxTmcrwULqdhut4GMPFf6zhhM2jBVxbv4p9Dr34Fc3IU?= =?us-ascii?q?HKpDcqn0k3gtXlgjGRfCT3LKiuQYFcEzD0uFQpMpPnXwZ1ahW/nVZ6OzffWb?= =?us-ascii?q?1elaFgenxriALHopRPGORcQrBDYB8e3fGXfesn0FRGpiWh20BH+fPPCYF+mw?= =?us-ascii?q?sybZ6ss3VA1hp+Y9EvO6zQJbdGzkNLi62UpC+ozOcxwQEFJ0kT7GySZTQIuE?= =?us-ascii?q?0UNrgmPSao+PJj6RCakTtZZGcMT+Yqou5t9k4lP+SAyDjg3KBFKkGwMOySNK?= =?us-ascii?q?yZu27dlcKSRVMwzEwInVFf/bdqyccjb1aUV0c3wbuKCRsJMcvCKQdIb8td73?= =?us-ascii?q?XcYSGOseDRzp1vJIW9CvrkTemQu6YImkikBhomH5wQ7sQdGZmhyF3YLcbiLL?= =?us-ascii?q?4C1RUt5ATqKU6YA/RIeBOEiiwIr9u5zJBpwYlXPisdDnllMSWr+rbXoRcnj+?= =?us-ascii?q?CHXNc3fngVQJMLNnc2Wc28nC5ZuW5PASKs3eIY0geC6SbwpirNDDXmadpseu?= =?us-ascii?q?uUbwt2CN6q4TU/77S2iVnP/5rFOW76M89vtcXS5uMEuZmHEehUQqNns0bcgY?= =?us-ascii?q?VYQGaqU2HXG96vO5fwc5UsbcDzCnuiSFy/jTM1QNvxPNaqKqiImhnmS59Jvo?= =?us-ascii?q?eBwD0tMtSwGS0ZGxd1u+4M/rl8ZREZb5o9fxHoqxw0N7ajLweAztWuX2GtJC?= =?us-ascii?q?NKQPld1+q1e6dawDYrbu++zHsgT481z/Or8UETWJ4KjgvSxfG5Z4lRSSLzAG?= =?us-ascii?q?BSex3TpSolkGhsLvwyzf0lwBPPqlYRKCyLdPZzZ2xaod48AVKSIXN5Cmo8Rl?= =?us-ascii?q?+cgorD4hKi378I5StdmsxY0etbv3jippXfei6jWLS3qZXJtCotddYnr7dtPo?= =?us-ascii?q?zjI8uGsZLekSbcTJTLsw2KTjC1GORAlthXOiJYT+FCmXs5NswepYpB9U0xW9?= =?us-ascii?q?87J7NVEqkspa6laSZlDS4Uwi8UTI2B0yYEguig37vakQqQf4k5MBAetpVNnM?= =?us-ascii?q?cdWTZsYiwCvK+jS5nWl2icR2gTJwcT6R5D5BgOl493euDl7pHFTJpLyz5RuP?= =?us-ascii?q?J7TDfEFoNv91vgUWGWgF74SPq7n+yuxwJSw+rm0sMHVx5nFUhd2+FWm1MyJ7?= =?us-ascii?q?FtNqkQuJTGsjyTeEP7vWLtyfemK0JLxc3SaVL4EJLPtXDgXS0E5X0UWYhPxW?= =?us-ascii?q?nDFZQVlgp0c7orqElJII+9YEr+4SIrx5hxFbmiSc+r30olrWoBRyqyE9pOEf?= =?us-ascii?q?tmv0jTWDJ4eJ2ktYvqO41KQmBO/J2StU1ZnF9qMy6jxppWM9tN7SIUXDhTvT?= =?us-ascii?q?Wdu8O/SM9E2cBoFJIDP8lwu2zjF6NeJJievWA5tqbpynDH5zA2qE26yymrG6?= =?us-ascii?q?+kU+JZ+HUTGhk0KGuDq0kgFe8s/3zO/VDKt1B74/1UBqOTjUlrpjZyAIxODC?= =?us-ascii?q?5T1X+5N1RzUGVGs+JCJavOfcxTX+U+aB2yNxEwDvMpw0uJ/URoknjjeCxyqh?= =?us-ascii?q?FW+ybDUAkoTSMVmKvimSUCqsG7Pj8XU4hIYis8YCfFMQ2bhTtavBJYa0F0RZ?= =?us-ascii?q?8VHMpK+7YG0oRK5MbCT1ijKT0dVhx4Kg04yeZflVJEsEiAYSDdFhaoeuzSvR?= =?us-ascii?q?1rZsqRt8mpLOnj/AhblIzntvw4978ZSH2igwGtRsrer4DkvN2QqkSObLv4M/?= =?us-ascii?q?G7YXLZUDjMlw6/iqk5AJTR4ijTNBZbK4Ngxno6YJjhDmrLMgpaJ64BIEpbT6?= =?us-ascii?q?96Y81cou9Gf89kZLoJ+ah1CxKCXBzvHIivo+daLlbPXzvRNT6M8uqhroLP9r?= =?us-ascii?q?zSVfLvZtSSyHrdRaJ4IIt64yHhG7j2yY9e5lb22vB1+0N4U1fGKSeBrM/lJg?= =?us-ascii?q?wR+smvbU7ivoAtHTPKAZd/jHvtyVtGd8oMWSGq944YyJxB4nbqVe14ylTzsP?= =?us-ascii?q?FV97R864k4+bZpycmuJafVNPtVr1RqAgSOCQVs7ZUtB3JzR2ZPbe8NMP3RZ7?= =?us-ascii?q?gWjdjyq+DrEKwa8BKV+/FYadvDI0HOhMy/ByqBRhNahwgBqCQVLg2G2/6Cga?= =?us-ascii?q?90Rt6vpfLl1UI1/1i+MhkGwahv5YeF/6qFv+rXYAXRzLcaQKjqR8Xzrrs2t0?= =?us-ascii?q?OU+/IkiKYEenZpbA2/DOgdSskdy3/mzaAu1i8sEsXDH7f69P5CUXI5kCjglI?= =?us-ascii?q?pmH1UKAPMUAKaE/ZhDnmcihePVLNoWcrpNmmyXDx6rDqcCyWK36yuQOGRlhx?= =?us-ascii?q?bO0xfsQWO88lD7tip4QSrWwNfljEVVSre2BUBIXyqqIk90qjWPMxT0tNDvo6?= =?us-ascii?q?Q68Fk2MnD4tNKKjGahPKhXH8j/KdGHLyk7uk8YjJorRtO1wYAbA929INUP/3?= =?us-ascii?q?5icvvS8WSrkzVOo61fnYrR/tmV+unLHXmnl6CaqrSMyypCxXckplw/8c6vNu?= =?us-ascii?q?3Q6NKWWfio0HwRTyhnsQvbQxG1sqDbr0wTOUGTy0jLmZcKP99D0nk610Hm+P?= =?us-ascii?q?AjT8gu9AVaDYvPe/QCqi3tNzTu3FafedU3VjOE3DdNGVL1C1Z4ErAm2G3spM?= =?us-ascii?q?LJiWvQ+1owS4lobUPnmQB4D4U2KEIq8lgXwTMPERMTZhCfDbGoA1nlLIQfWE?= =?us-ascii?q?gbcxuHwKS1eqc53E102LOv5/Xfbe9iCKoXMPZSkAqOkEJcGpIMvq0UWKh8dE?= =?us-ascii?q?NF9K7LugjiDJDqX/f8mnoqK/K1XsBa/Nsdt3sj/gawWRqg5o1e77YAkpyIcL?= =?us-ascii?q?BLYYTUtsBm80hn/SIPdjBKgBVngBO2T+YcpPzk4tjct5ao8fihVKIsR+UR6h?= =?us-ascii?q?g1CH9zj5/uj1A5odDYzf1QSovLhoTj6ApNOWKFuJ7G0xlgLuoDM4SrfLd8+H?= =?us-ascii?q?UAIygRPWkOMcCXa/k75C9tKy7T6kdHAs4DatIUJs3NmRpbikfxQrFc6tLbGk?= =?us-ascii?q?OEC4d0b80o4Hb4yCsu8ZclT+ju5zm4JZHZ71FQMPJOlypslNfYq+gT3/XeEi?= =?us-ascii?q?8X4WOWaxJt2CON14GNC+rs/eWL0NzUVVQGHi4wU4tHODWC+QinRveom5ToUw?= =?us-ascii?q?OU7NTzgJE/dE+LWHyxnboFvbxIEeFdiyX3xD5eGZ7ph/iNqdqj9HNXtkFbEI?= =?us-ascii?q?Z09RDFGbtfMY99ORnjksmrW1VzBir4eMHPbBYuv/CWxugU6eVkK0T+fZMbIg?= =?us-ascii?q?4Dy7/i63paUAVuSLDyvluCU+Meft1mR+3YrnxP74JvNbMPNkCHpJP2tjdItE?= =?us-ascii?q?w2AAgxZb8/qjxacUfPkxNRW6bwo7MAkQwcUdh4uUBQA26wPnwx5ybfX6RPkK?= =?us-ascii?q?aREOAV8imUTqEWVkVoMyB+QxCy2Jh1ebumh/NHsmRAnixjpvgmyTpmSwWguS?= =?us-ascii?q?f0vaICxSog+K2ktDUGoXFKVfuRkyHUCVhY1/QKiaAcC2r+6VyifnYMcZH+4L?= =?us-ascii?q?59JcTv7YMh+WgwYQ0/fy0aWuStEy/wgL2MAoyOqNJTmgWAucTPbb+2KCgdKK?= =?us-ascii?q?49yRb9SHRn1Qjehhlo+nMRQjq89N8kOJm9OcE9yyumAWjbblcM7b9Xv8bqsF?= =?us-ascii?q?4LTfc2aUl/z2l51ciHXCINTtTVG2kplggkdXlEcJVb5B8dE6knnC2FvrFC/g?= =?us-ascii?q?4OezfUDoWl9ZXMncfSx3YyU81mxmTIqa2ZnpkqymFqm8to7i6Sv3Qfb+jYU8?= =?us-ascii?q?5qAnju2YZT0Oj+Z/S2suAbU4tr07WhX+UEMsmk42e2349qWkC9zLQEA1W5KP?= =?us-ascii?q?MDxqvcUyq9TG2XQ/iEc2iNnzY/NU7//geoLlwxaMhUq089M+3ChoNTlgH7Vr?= =?us-ascii?q?N0XCqQr0fBzGM/KeMaax42uIC/dgwIVuERZO+cKvM1zf0jDlsMc3/JHSxrC+?= =?us-ascii?q?+5sV6tgJJ3O3N+7kXmee7t6BzpMMOOGhkYFo7Xtpxx+fm9RmKbI39gzQZyMV?= =?us-ascii?q?Jy9+jFElQ+qO5cf4yWndjKiNRxyfQFeOt1MS0hpt4TnZpu6ZKa0MePbR7cz5?= =?us-ascii?q?X/KMrLoveGGf3fzkUremZcUrYDZwP6+Zk6MsY5W7LNGbtZugwRBaw9QJM9LW?= =?us-ascii?q?jx8KF0LARocg7Nfri0hs7qqf6RaZtQunDW6VcwIz3dux0F0vC0TAp7YI62h3?= =?us-ascii?q?jqI508WyhNo8BjBxd4BodCFMENoxC5D5OUl6y3k9qx9Fl7u+8Ov6rwEPfK1N?= =?us-ascii?q?Gh0oh2RZha5FCEPDbLC6lxn0tqlvi9je/A0pbrCMPif80LVPNgT2Hedr/GH4?= =?us-ascii?q?O/Ki6QNcLmfU5J7aKc3KhlXRWWYSD0RrKKtDe4O/V8/UU71ot4cfLUwTw37r?= =?us-ascii?q?HUxNvyaHtBpii+tXGGKINQ7FzQCuzfWRJbV+GF/X1+Eq0LbIv08vsOPsI4wN?= =?us-ascii?q?ia/QZz8C5O39eCI6ikt0LAwlh7eo7DLEv1xyY5XpEHLROkMUQxmm/UsWjdAH?= =?us-ascii?q?RAIcikLslhmtCVDgf36EVrlmEtYXBBF3PwSdeLJWcbw96+ZBGN9A9TCNsDhP?= =?us-ascii?q?C4eUo5tq20VOlpNY5ImfmqtbobkdZpLDvDRM5BPy7KNrN2MT1RDvvWqVUufx?= =?us-ascii?q?UJrbw1WpouZZiSPkwHKlqOySLzzATcyUD4a4/k6KHcOysS83Na35rZwDNMoE?= =?us-ascii?q?+/ov/fjcr9FPjCYIreQO/ZMC1jUCqTAzs1DxWT9E+gqsYD6cCZKmcWuFxcQi?= =?us-ascii?q?uTDgMI7vR1rNPQB3XfruZUfJQLgv2BcyrsSStkmbA0CzoNvkeJFaktDw7TOk?= =?us-ascii?q?Xgi2pVogDqBvZN+3/+J6OZz+JuVugXBJZcOqmCTt/Zf+1ODys5nTUefuCndp?= =?us-ascii?q?vTqKhvgQGAdncQD6SdrA7Wd0WRWPHJgmuzUA=3D=3D?= X-IPAS-Result: =?us-ascii?q?A2CfAACB9AJb/wHyM5BcGQEBAQEBAQEBAQEBAQcBAQEBA?= =?us-ascii?q?YMYK2F9FROLeV+MFGSCChqTNhQLgVYmAxABhlshNBgBAgEBAQEBAQIBaxwMg?= =?us-ascii?q?jUkglcCFwEMVQMJAkgIAwFaCQkFgl1AAiiBPwEBARUDAalmM4N0VoN3gg+IN?= =?us-ascii?q?Q6CBYEPgleDBIINAYVqAocqCoRsgSKLCgmFaohigUI+hg6EepIcHDiBUisIA?= =?us-ascii?q?hgIIQ+Baxp5CYIXF4dNhktueQEBASiMTCuCGQEB?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 21 May 2018 16:34:56 +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 w4LGY0Ql027319; Mon, 21 May 2018 12:34:15 -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 w4LGXtwI015874 for ; Mon, 21 May 2018 12:33:55 -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 w4LGXxG6027317; Mon, 21 May 2018 12:33:59 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1BiAACB9AJblywYGNZcGgEBAQEBAgEBA?= =?us-ascii?q?QEIAQEBAYMYKGR9KIt5X4wUgm4akzYUgWQmEYRAghshNBgBAgEBAQEBAQIUAQE?= =?us-ascii?q?BAQEGGAZLhVUBDBkBOAEVgSkJCYMiAiiBPgEDFQMBqWYzgnAFf2SDYgeCAwQIh?= =?us-ascii?q?zl8ghOBD4JXgwSCDQEihUgChyoKhGyBIosKCQWFZYhigUI+hg6EepIcHIIKMxo?= =?us-ascii?q?jgxMJggsMDgmDRYQIhktueSuMTCuCGQEB?= X-IPAS-Result: =?us-ascii?q?A1BiAACB9AJblywYGNZcGgEBAQEBAgEBAQEIAQEBAYMYKGR?= =?us-ascii?q?9KIt5X4wUgm4akzYUgWQmEYRAghshNBgBAgEBAQEBAQIUAQEBAQEGGAZLhVUBD?= =?us-ascii?q?BkBOAEVgSkJCYMiAiiBPgEDFQMBqWYzgnAFf2SDYgeCAwQIhzl8ghOBD4JXgwS?= =?us-ascii?q?CDQEihUgChyoKhGyBIosKCQWFZYhigUI+hg6EepIcHIIKMxojgxMJggsMDgmDR?= =?us-ascii?q?YQIhktueSuMTCuCGQEB?= X-IronPort-AV: E=Sophos;i="5.49,426,1520913600"; d="scan'208";a="281734" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.34]) by goalie.tycho.ncsc.mil with ESMTP; 21 May 2018 12:33:53 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3APzPSyxLnERuPifxD99mcpTZWNBhigK39O0sv0r?= =?us-ascii?q?FitYgXKPn6rarrMEGX3/hxlliBBdydt6ofzbKO+4nbGkU4qa6bt34DdJEeHz?= =?us-ascii?q?Qksu4x2zIaPcieFEfgJ+TrZSFpVO5LVVti4m3peRMNQJW2aFLduGC94iAPER?= =?us-ascii?q?vjKwV1Ov71GonPhMiryuy+4ZLebxlGiTanfb9+MAi9oBnMuMURnYZsMLs6xA?= =?us-ascii?q?HTontPdeRWxGdoKkyWkh3h+Mq+/4Nt/jpJtf45+MFOTav1f6IjTbxFFzsmKH?= =?us-ascii?q?w65NfqtRbYUwSC4GYXX3gMnRpJBwjF6wz6Xov0vyDnuOdxxDWWMMvrRr0yRD?= =?us-ascii?q?+s7bpkSAXwhSkHKTA37W/ZhM93gq9AvB6tuwZyz5LObY2JKPZzeL7Wc9MARW?= =?us-ascii?q?pGW8ZcTzBPAoKgYIsPFeUBJ/tXpJT/qVQUrBu+AxejBPjywTJPnH/23LE10+?= =?us-ascii?q?Q7HgHcwQMvB84Bv2zUrNrvNacSV/66zLLTwDrYc/NW2DH96JTWfRA7p/GDQ6?= =?us-ascii?q?5wfdDNxkkoEgPIl1OdopHmMTONzukBrXWX4uV6We6xhGMrsR99rze1ysojhY?= =?us-ascii?q?TFnoEYxk3e+Slkzos5O8e0RUF5bNK+Dpddty6XOo1rSc04WW5oojw1yrgetJ?= =?us-ascii?q?67YicKzJMnygbRZPGZaoaG5BzuWfiLLzpkmH5oeaiziAis/kil0e38WdO40F?= =?us-ascii?q?NQoSpEltnArHUN1x3X6sSfS/t9+Fmu2SqX2gzN9+1JLlo4mbTUJpI73LI9mY?= =?us-ascii?q?AfvEvMEyPunUX5lq6WdkEq+uiy7OTnZ63rpoWdN4BoigHxKL4uldGnDuskKg?= =?us-ascii?q?cOX3KU+eW61LL95k30W65FjuE3kqnfrJDVO94bpqinDA9JyIos9xG/DzK+3N?= =?us-ascii?q?QCgXYHNE5FeA6Aj4XxIFHBPev4AOyjg1WsjDhrx/fGMqfnApXWNHfPirjhfb?= =?us-ascii?q?Fj60RE0go80chf545ICrEGOP/zQVH+tNjZDh8/Lgy1zP3qCMl914wCWWKPBb?= =?us-ascii?q?WVMKXJsVCS/O4vLO6MZJENtDb9Nfcl4/nugGc9mV8aYaamx58XaHC/HvR9P0?= =?us-ascii?q?WVe37sgtAdHmgQugoxUevqiFiYXj5SYXa+R6M85jclB4K6FYrORZ2hjKac0C?= =?us-ascii?q?q1AJFafG9LB1KWHXv2d4iJVO8AaCeILc9gljwEW6KhS4gk1Ry2swL60btnIf?= =?us-ascii?q?bU+iICr5LsycB66PHLmhEy7zN0DsKd3H+WT2xvhWwIWz423KZjoUNj0FeD17?= =?us-ascii?q?Z3g+BCGdNP4PNJVx43OYbGz+NmE9DyRh7BftCRRVuhWNWmAC0+TtIrzN8Ufk?= =?us-ascii?q?lyA8mtgQjD3yWwAr8VkaKEBIcv/63Hw3jxJsB9y2rY26k7iVkpXNdPOXe6ia?= =?us-ascii?q?548gjeHpbFk1+FmKayaaQcwCnN+X+EwGqVoU5YSxV9UbnFXH8DZkvWqs715k?= =?us-ascii?q?XZT7C0E7gnPQxBydCbJ6dScN3mkU1GROv/ONTZe2+8nHywCgiMxrONaorqZm?= =?us-ascii?q?oc0T7BCEkEjw8T/XGGORI4Bie6uW3SFjNuFVXxY0719+R1tW22TkspzwGRc0?= =?us-ascii?q?1uyaC19AMUhf2dVfwexq4I628drGBvEVK82c/GI8aRrApmOqNHaJUy50kDnX?= =?us-ascii?q?nVrCRhL5egKOZknVdYfANp7G300BAiMIRLkcEwoDsKxQt0JLnQhElAfDORx5?= =?us-ascii?q?zHMYrXI2j08QuHYbLX3E3TytCb5uEE7/Fu+Aarhx2gCkd3qyYv6NJSyXbJvs?= =?us-ascii?q?+QXgMPTZL8VFo2/BFmprbcJzMw/J7QyWY8a/uJmRjmgPkRLbN5jButesxQdq?= =?us-ascii?q?aNFQu0FsweVICiK+0vzkCkdBcJJvpV7uZ0PM63P+eB3+awOe9kmHPujWlO7I?= =?us-ascii?q?1nlEPZ3yBgS+jU0owDzu3e1QyCWg=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0BiAABS8wJblywYGNZcGgEBAQEBAgE?= =?us-ascii?q?BAQEIAQEBAYMYKGR9KIt5X4wUgm4akzYUgWQmEYRAghshNBgBAgEBAQEBAQI?= =?us-ascii?q?BEwEBAQEBBhgGSwyCNSKCcgEMGQE4ARWBKQkJgyICKIE+AQMVAwGpZTOCcAV?= =?us-ascii?q?/ZINiB4IDBAiHOXyCE4EPgleDBIINASKFSAKHKgqEbIEiiwoJBYVliGKBQj6?= =?us-ascii?q?GDoR6khwcggozGiODEwmCCwwOCYNFhAiGS255K4xMK4IZAQE?= X-IPAS-Result: =?us-ascii?q?A0BiAABS8wJblywYGNZcGgEBAQEBAgEBAQEIAQEBAYMYK?= =?us-ascii?q?GR9KIt5X4wUgm4akzYUgWQmEYRAghshNBgBAgEBAQEBAQIBEwEBAQEBBhgGS?= =?us-ascii?q?wyCNSKCcgEMGQE4ARWBKQkJgyICKIE+AQMVAwGpZTOCcAV/ZINiB4IDBAiHO?= =?us-ascii?q?XyCE4EPgleDBIINASKFSAKHKgqEbIEiiwoJBYVliGKBQj6GDoR6khwcggozG?= =?us-ascii?q?iODEwmCCwwOCYNFhAiGS255K4xMK4IZAQE?= X-IronPort-AV: E=Sophos;i="5.49,426,1520899200"; d="scan'208";a="12005730" 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; 21 May 2018 16:33:51 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;5e799df5-80b9-44bd-ad3a-2f27bf067a4b X-EEMSG-check-008: 282859253|UCOL3CPA04_EEMSG_MP19.csd.disa.mil X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.124 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0A/AAA89AJbh3wAFEFcGQEBAQEBAQEBAQEBAQcBAQEBAYMYgQx9KIt5X48CGpM2FIFkEBYRhECCPDQYAQIBAQEBAQECFAEBAQoLCQgoIwyFSQEMGQE4ARWBKQkJgyICKIE+AQMVBKllM4JwBX9kg2IHggMECIc5gw+BD4JXgwSCDQEihUgChyoKhGyBIosKCQWFZYhigUI+hg6EepIcHIIKMxojgxMJggsMDgmDRYQIhktueSuMTCuCGQEB X-IPAS-Result: A0A/AAA89AJbh3wAFEFcGQEBAQEBAQEBAQEBAQcBAQEBAYMYgQx9KIt5X48CGpM2FIFkEBYRhECCPDQYAQIBAQEBAQECFAEBAQoLCQgoIwyFSQEMGQE4ARWBKQkJgyICKIE+AQMVBKllM4JwBX9kg2IHggMECIc5gw+BD4JXgwSCDQEihUgChyoKhGyBIosKCQWFZYhigUI+hg6EepIcHIIKMxojgxMJggsMDgmDRYQIhktueSuMTCuCGQEB Received: from rgout0104.bt.lon5.cpcloud.co.uk (HELO rgout01.bt.lon5.cpcloud.co.uk) ([65.20.0.124]) by UCOL3CPA04.eemsg.mail.mil with ESMTP; 21 May 2018 16:33:47 +0000 X-OWM-Source-IP: 81.132.47.254 (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: gggruggvucftvghtrhhoucdtuddrgedthedrfeelgddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuueftkffvkffujffvgffngfevqffopdfqfgfvnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffosedttdertdertddtnecuhfhrohhmpeftihgthhgrrhguucfjrghinhgvshcuoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqeenucfkphepkedurddufedvrdegjedrvdehgeenucfrrghrrghmpehhvghloheplhhotggrlhhhohhsthdrlhhotggrlhguohhmrghinhdpihhnvghtpeekuddrudefvddrgeejrddvheegpdhmrghilhhfrhhomhepoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqedprhgtphhtthhopeeorhhitghhrghruggptggphhgrihhnvghssegsthhinhhtvghrnhgvthdrtghomheqpdhrtghpthhtohepoehsughssehthigthhhordhnshgrrdhgohhvqedprhgtphhtthhopeeoshgvlhhinhhugiesthihtghhohdrnhhsrgdrghhovheqnecuvehluhhsthgvrhfuihiivgeptd Received: from localhost.localdomain (81.132.47.254) by rgout01.bt.lon5.cpcloud.co.uk (9.0.019.26-1) (authenticated as richard_c_haines@btinternet.com) id 5AFAEA6F00867DA9; Mon, 21 May 2018 17:33:43 +0100 X-EEMSG-check-009: 444-444 To: selinux@tycho.nsa.gov, sds@tycho.nsa.gov Date: Mon, 21 May 2018 17:33:37 +0100 Message-Id: <20180521163337.15043-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.17.0 Subject: [RFC V3 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 | 7 + policy/Makefile | 4 + policy/test_binder.te | 120 +++++++ tests/Makefile | 4 + tests/binder/Makefile | 7 + tests/binder/check_binder.c | 80 +++++ tests/binder/test | 89 +++++ tests/binder/test_binder.c | 684 ++++++++++++++++++++++++++++++++++++ 9 files changed, 1003 insertions(+) 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..c48d3cc 100644 --- a/defconfig +++ b/defconfig @@ -51,3 +51,10 @@ 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_DEVICES="binder" +CONFIG_ANDROID_BINDER_IPC=y diff --git a/policy/Makefile b/policy/Makefile index 5e07ee2..15e3a0c 100644 --- a/policy/Makefile +++ b/policy/Makefile @@ -63,6 +63,10 @@ ifeq ($(shell grep -q nnp_transition $(POLDEV)/include/support/all_perms.spt && export M4PARAM += -Dnnp_nosuid_transition_permission_defined endif +ifeq ($(shell grep -q binder $(POLDEV)/include/support/all_perms.spt && echo true),true) +TARGETS += test_binder.te +endif + ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6)) TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te, $(TARGETS)) endif diff --git a/policy/test_binder.te b/policy/test_binder.te new file mode 100644 index 0000000..0589396 --- /dev/null +++ b/policy/test_binder.te @@ -0,0 +1,120 @@ + +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 test_binder_provider_t:binder call; +allow test_binder_mgr_t device_t:chr_file { ioctl open read write }; +allow_map(test_binder_mgr_t, device_t, chr_file) +allow test_binder_mgr_t self:capability { sys_nice }; +allow test_binder_provider_t test_binder_mgr_t:fd use; +fs_getattr_tmpfs(test_binder_mgr_t) +allow test_binder_mgr_t tmpfs_t:file { read write open }; +allow_map(test_binder_mgr_t, tmpfs_t, file) +fs_manage_tmpfs_dirs(test_binder_mgr_t) +fs_manage_tmpfs_files(test_binder_mgr_t) + +# +########################## 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 test_binder_provider_t:binder { call }; +allow test_binder_mgr_no_fd_t device_t:chr_file { ioctl open read write }; +allow_map(test_binder_mgr_no_fd_t, device_t, chr_file) +allow test_binder_provider_t test_binder_mgr_no_fd_t:binder { call transfer impersonate }; +fs_getattr_tmpfs(test_binder_mgr_no_fd_t) +allow test_binder_mgr_no_fd_t tmpfs_t:file { read write open }; +allow_map(test_binder_mgr_no_fd_t, tmpfs_t, file) +fs_manage_tmpfs_dirs(test_binder_mgr_no_fd_t) +fs_manage_tmpfs_files(test_binder_mgr_no_fd_t) + +# +########################## Service Provider ################################ +# +type test_binder_provider_t; +domain_type(test_binder_provider_t) +unconfined_runs_test(test_binder_provider_t) +typeattribute test_binder_provider_t testdomain; +typeattribute test_binder_provider_t binderdomain; +allow test_binder_provider_t self:binder { call }; +allow test_binder_provider_t test_binder_mgr_t:binder { call transfer impersonate }; +allow test_binder_provider_t device_t:chr_file { ioctl open read write }; +allow_map(test_binder_provider_t, device_t, chr_file) +# For fstat: +allow test_binder_provider_t device_t:chr_file getattr; +fs_getattr_tmpfs(test_binder_provider_t) +allow test_binder_provider_t tmpfs_t:file { read write open }; +allow_map(test_binder_provider_t, tmpfs_t, file) +fs_manage_tmpfs_dirs(test_binder_provider_t) +fs_manage_tmpfs_files(test_binder_provider_t) + +# +#################### Service Provider no call ################################ +# +type test_binder_provider_no_call_t; +domain_type(test_binder_provider_no_call_t) +unconfined_runs_test(test_binder_provider_no_call_t) +typeattribute test_binder_provider_no_call_t testdomain; +typeattribute test_binder_provider_no_call_t binderdomain; +allow test_binder_provider_no_call_t device_t:chr_file { ioctl open read write }; +allow_map(test_binder_provider_no_call_t, device_t, chr_file) +fs_getattr_tmpfs(test_binder_provider_no_call_t) +allow test_binder_provider_no_call_t tmpfs_t:file { read write open }; +allow_map(test_binder_provider_no_call_t, tmpfs_t, file) +fs_manage_tmpfs_dirs(test_binder_provider_no_call_t) +fs_manage_tmpfs_files(test_binder_provider_no_call_t) + +# +#################### Service Provider no transfer ############################# +# +type test_binder_provider_no_transfer_t; +domain_type(test_binder_provider_no_transfer_t) +unconfined_runs_test(test_binder_provider_no_transfer_t) +typeattribute test_binder_provider_no_transfer_t testdomain; +typeattribute test_binder_provider_no_transfer_t binderdomain; +allow test_binder_provider_no_transfer_t test_binder_mgr_t:binder { call }; +allow test_binder_provider_no_transfer_t device_t:chr_file { ioctl open read write }; +allow_map(test_binder_provider_no_transfer_t, device_t, chr_file) +fs_getattr_tmpfs(test_binder_provider_no_transfer_t) +allow test_binder_provider_no_transfer_t tmpfs_t:file { read write open }; +allow_map(test_binder_provider_no_transfer_t, tmpfs_t, file) +fs_manage_tmpfs_dirs(test_binder_provider_no_transfer_t) +fs_manage_tmpfs_files(test_binder_provider_no_transfer_t) + +# +#################### Service Provider no impersonate ########################## +# +type test_binder_provider_no_im_t; +domain_type(test_binder_provider_no_im_t) +unconfined_runs_test(test_binder_provider_no_im_t) +typeattribute test_binder_provider_no_im_t testdomain; +typeattribute test_binder_provider_no_im_t binderdomain; +allow test_binder_provider_no_im_t self:binder { call }; +allow test_binder_provider_no_im_t test_binder_mgr_t:binder { call transfer }; +allow test_binder_provider_no_im_t device_t:chr_file { ioctl open read write }; +allow_map(test_binder_provider_no_im_t, device_t, chr_file) +allow test_binder_provider_no_im_t test_binder_mgr_t:fd use; +allow test_binder_provider_no_im_t device_t:chr_file getattr; +fs_getattr_tmpfs(test_binder_provider_no_im_t) +allow test_binder_provider_no_im_t tmpfs_t:file { read write open }; +allow_map(test_binder_provider_no_im_t, tmpfs_t, file) +fs_manage_tmpfs_dirs(test_binder_provider_no_im_t) +fs_manage_tmpfs_files(test_binder_provider_no_im_t) + +# +############ 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..494b761 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -30,6 +30,10 @@ ifeq ($(shell grep -q getrlimit $(POLDEV)/include/support/all_perms.spt && echo SUBDIRS += prlimit endif +ifeq ($(shell grep -q binder $(POLDEV)/include/support/all_perms.spt && echo true),true) +SUBDIRS += binder +endif + ifeq ($(shell grep "^SELINUX_INFINIBAND_ENDPORT_TEST=" infiniband_endport/ibendport_test.conf | cut -d'=' -f 2),1) SUBDIRS += infiniband_endport endif diff --git a/tests/binder/Makefile b/tests/binder/Makefile new file mode 100644 index 0000000..0d76723 --- /dev/null +++ b/tests/binder/Makefile @@ -0,0 +1,7 @@ +TARGETS = check_binder test_binder + +LDLIBS += -lselinux -lrt + +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..7b81a3d --- /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 = 2; + 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..86fab52 --- /dev/null +++ b/tests/binder/test @@ -0,0 +1,89 @@ +#!/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)"; + } + } + else { + $v = " "; + } + + # check if binder driver available and kernel/userspace versions. + $result = system("$basedir/check_binder 2> /dev/null"); + + if ( $result >> 8 eq 0 ) { + plan tests => 6; + } + elsif ( $result >> 8 eq 1 ) { + plan skip_all => "Binder not supported by kernel"; + } + elsif ( $result >> 8 eq 2 ) { + plan skip_all => "Binder kernel/userspace versions differ"; + } + else { + plan skip_all => "Error checking Binder driver"; + } +} + +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. + +# 1 Verify that authorized provider can transact with the manager. +$result = + system + "runcon -t test_binder_provider_t $basedir/test_binder $v -r 1 provider"; +ok( $result eq 0 ); + +# 2 Verify that provider cannot call manager (no call perm). +$result = system +"runcon -t test_binder_provider_no_call_t $basedir/test_binder $v -r 2 provider 2>&1"; +ok( $result >> 8 eq 8 ); + +# 3 Verify that provider cannot communicate with manager (no impersonate perm). +$result = system +"runcon -t test_binder_provider_no_im_t $basedir/test_binder $v -r 1 provider 2>&1"; +ok( $result >> 8 eq 103 ); + +# 4 Verify that provider cannot communicate with manager (no transfer perm). +$result = system +"runcon -t test_binder_provider_no_transfer_t $basedir/test_binder $v -r 1 provider 2>&1"; +ok( $result >> 8 eq 8 ); + +# Kill the manager. +kill TERM, $pid; + +# 5 Verify that provider cannot become a manager (no set_context_mgr perm). +$result = + system + "runcon -t test_binder_provider_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. + +# 6 Verify that authorized provider 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_provider_t $basedir/test_binder $v provider -r 1 2>&1"; +ok( $result >> 8 eq 8 ); + +# 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..270668a --- /dev/null +++ b/tests/binder/test_binder.c @@ -0,0 +1,684 @@ +/* + * This is a simple binder Service Manager/Service Provider that only uses + * the raw ioctl commands to test the SELinux binder permissions: + * set_context_mgr, call, transfer, impersonate. + * + * 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 + +/* These are the Binder txn->code values used by the Service Provider and + * Manager to request/retrieve a binder handle. + */ +#define ADD_TEST_SERVICE 100 /* Sent by Service Provider */ +#define GET_TEST_SERVICE 101 /* Sent by Client */ + +#define TEST_SERVICE_MANAGER_HANDLE 0 + +static int binder_parse(int fd, uintptr_t ptr, size_t size, bool manager); + +static bool verbose; +uint32_t sp_handle; +static unsigned char *shm_base; +static int shm_fd; +static int shm_size = 32; + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [-r replies] [-v] manager | provider\n" + "Where:\n\t" + "-r Number of replies to expect from test - default 0.\n\t" + "-v Print context and command information.\n\t" + "manager Act as Service Manager.\n\t" + "service Act as Service Provider.\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); +} + +/* Create a small piece of shared memory between the Manager and Service + * Provider to share a handle as explained in the do_service_manager() + * function. + */ +static void create_shm(bool manager) +{ + char *name = "sp_handle"; + + if (manager) + shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); + else + shm_fd = shm_open(name, O_RDONLY, 0666); + if (shm_fd < 0) { + fprintf(stderr, "%s shm_open: %s\n", __func__, strerror(errno)); + exit(-1); + } + + ftruncate(shm_fd, shm_size); + + if (manager) + shm_base = mmap(0, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, 0); + else + shm_base = mmap(0, shm_size, PROT_READ, MAP_SHARED, shm_fd, 0); + if (shm_base == MAP_FAILED) { + fprintf(stderr, "%s mmap: %s\n", __func__, strerror(errno)); + close(shm_fd); + 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"; + } +} + +static void print_trans_data(struct binder_transaction_data *txn_in) +{ + struct flat_binder_object *obj; + binder_size_t *offs = (binder_size_t *) + (uintptr_t)txn_in->data.ptr.offsets; + size_t count = txn_in->offsets_size / sizeof(binder_size_t); + + printf("\thandle: %ld\n", (unsigned long)txn_in->target.handle); + printf("\tcookie: %lld\n", txn_in->cookie); + printf("\tcode: %d\n", txn_in->code); + switch (txn_in->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: %x\n", txn_in->flags); + return; + } + printf("\tsender pid: %u\n", txn_in->sender_pid); + printf("\tsender euid: %u\n", txn_in->sender_euid); + printf("\tdata_size: %llu\n", txn_in->data_size); + printf("\toffsets_size: %llu\n", txn_in->offsets_size); + + while (count--) { + obj = (struct flat_binder_object *) + (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs++); + + switch (obj->hdr.type) { + case BINDER_TYPE_BINDER: + printf("\thdr: BINDER_TYPE_BINDER\n"); + printf("\tbinder: %llx\n", obj->binder); + break; + case BINDER_TYPE_HANDLE: + printf("\thdr: BINDER_TYPE_HANDLE\n"); + printf("\thandle: %x\n", obj->handle); + break; + case BINDER_TYPE_FD: + printf("\thdr: BINDER_TYPE_FD\n"); + printf("\tfd: %x\n", obj->handle); + break; + default: + printf("Unknown header: %u\n", obj->hdr.type); + return; + } + printf("\tflags: priority: 0x%x accept FDS: %s\n", + obj->flags & FLAT_BINDER_FLAG_PRIORITY_MASK, + obj->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS ? "YES" : "NO"); + printf("\tcookie: %llx\n", obj->cookie); + } +} + +/* If add a service provider, then obtain a handle for it and store in + * shared memory. The handle will then be used by the service provider + * process to contact the Manager for its file descriptor, thus triggering + * the 'impersonate' permission (as current_sid() != task_sid(from)) + * It is done this way as being a cheapskate it saved adding code to the + * GET_TEST_SERVICE process plus running a Client as well. This achieves + * the same objective. + */ +static void do_service_manager(int fd, struct binder_transaction_data *txn_in) +{ + int result; + struct flat_binder_object *obj; + struct binder_write_read bwr; + uint32_t acmd[2]; + binder_size_t *offs; + + switch (txn_in->code) { + case ADD_TEST_SERVICE: + offs = (binder_size_t *)(uintptr_t)txn_in->data.ptr.offsets; + + /* Get fbo that contains the Managers binder file descriptor. */ + obj = (struct flat_binder_object *) + (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs); + + if (obj->hdr.type == BINDER_TYPE_HANDLE) { + sp_handle = obj->handle; + memcpy(shm_base, &sp_handle, sizeof(sp_handle)); + if (verbose) + printf("Manager has BINDER_TYPE_HANDLE obj->handle: %d\n", + sp_handle); + } else { + fprintf(stderr, "Failed to obtain a handle\n"); + exit(-1); + } + + acmd[0] = BC_ACQUIRE; + acmd[1] = obj->handle; + + memset(&bwr, 0, sizeof(bwr)); + bwr.write_buffer = (uintptr_t)&acmd; + bwr.write_size = sizeof(acmd); + + result = ioctl(fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "ServiceProvider ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + exit(-1); + } + + if (verbose) + printf("Manager acquired handle: %d for Service Provider\n", + sp_handle); + break; + + case GET_TEST_SERVICE: + if (verbose) + printf("GET_TEST_SERVICE not supported\n"); + break; + default: + fprintf(stderr, "Unknown txn->code: %d\n", txn_in->code); + exit(-1); + } +} + +static void request_manager_fd(int fd, struct binder_transaction_data *txn_in) +{ + int result; + unsigned int writebuf[1024]; + struct binder_fd_object obj; + struct binder_write_read bwr; + struct binder_transaction_data *txn; + + if (txn_in->flags == TF_ONE_WAY) { + if (verbose) + printf("Manager no reply to BC_TRANSACTION as flags = TF_ONE_WAY\n"); + return; + } + + if (verbose) + printf("Manager sending BC_REPLY to obtain its FD\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 binder_fd_object)); + obj.hdr.type = BINDER_TYPE_FD; + obj.pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; + obj.cookie = txn->cookie; + /* The binder fd is used for testing as it allows policy to set + * whether the Service and Manager can be allowed access (fd use) + * or not. For example test_binder_mgr_t has: + * allow test_binder_service_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 Service Provider will use this (the Managers fd) to + * send a transaction. + */ + obj.fd = fd; + + if (verbose) + printf("Manager handle: %d and its FD: %d\n", + txn->target.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 = (uintptr_t)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)); + exit(-1); + } +} + +/* 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, + bool manager) +{ + int result; + uint32_t cmd; + struct stat sb; + struct binder_write_read bwr; + struct binder_fd_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 bfdo that contains the Managers binder file descriptor. */ + obj = (struct binder_fd_object *) + (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs); + + if (obj->hdr.type != BINDER_TYPE_FD) { + fprintf(stderr, "Header not BINDER_TYPE_FD: %d\n", + obj->hdr.type); + exit(100); + } + + /* fstat this just to see if a valid fd */ + result = fstat(obj->fd, &sb); + if (result < 0) { + fprintf(stderr, "Not a valid fd: %s\n", strerror(errno)); + exit(101); + } + + if (verbose) + printf("Service Provider retrieved Managers fd: %d st_dev: %ld\n", + obj->fd, 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)); + /* Copy handle from the Manager */ + memcpy(&txn->target.handle, shm_base, sizeof(uint32_t)); + + 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 = (uintptr_t)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->fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "Service Provider ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + exit(102); + } + + if (verbose) + printf("Service Provider read_consumed: %lld\n", + bwr.read_consumed); + + cmd = binder_parse(obj->fd, (uintptr_t)readbuf, + bwr.read_consumed, manager); + + if (verbose) + printf("Service Provider using Managers FD\n"); + + if (cmd == BR_FAILED_REPLY || + cmd == BR_DEAD_REPLY || + cmd == BR_DEAD_BINDER) { + fprintf(stderr, + "Failed response from Service Provider using Managers FD\n"); + exit(103); + } +} + +/* Parse response, reply as required and then return last CMD */ +static int binder_parse(int fd, uintptr_t ptr, size_t size, bool manager) +{ + 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", + manager ? "Manager" : "Service Provider", + 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("%s BR_TRANSACTION data:\n", + manager ? "Manager" : "Service Provider"); + print_trans_data(txn); + } + + if (manager) { + do_service_manager(fd, txn); + request_manager_fd(fd, txn); + } + + ptr += sizeof(*txn); + break; + } + case BR_REPLY: { + struct binder_transaction_data *txn = + (struct binder_transaction_data *)ptr; + + if (verbose) { + printf("%s BR_REPLY data:\n", + manager ? "Manager" : "Service Provider"); + print_trans_data(txn); + } + + /* Service Provider extracts the Manager fd, and responds */ + if (!manager) + extract_fd_and_respond(txn, manager); + + 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", + manager ? "Manager" : "Service Provider", + cmd); + exit(-1); + } + } + + return cmd; +} + +int main(int argc, char **argv) +{ + int opt, result, binder_fd, provider_replies = 0; + uint32_t cmd; + bool manager; + pid_t pid; + char *driver = "/dev/binder"; + char *context; + void *map_base; + size_t map_size = 2048; + struct binder_write_read bwr; + struct flat_binder_object obj; + struct binder_transaction_data *txn; + unsigned int readbuf[32]; + unsigned int writebuf[1024]; + + verbose = false; + + while ((opt = getopt(argc, argv, "vr:")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + case 'r': + provider_replies = atoi(optarg); + break; + default: + usage(argv[0]); + } + } + + if ((argc - optind) != 1) + usage(argv[0]); + + if (!strcmp(argv[optind], "manager")) + manager = true; + else if (!strcmp(argv[optind], "provider")) + manager = false; + else + usage(argv[0]); + + binder_fd = open(driver, O_RDWR | O_CLOEXEC); + if (binder_fd < 0) { + fprintf(stderr, "Cannot open %s error: %s\n", driver, + strerror(errno)); + exit(1); + } + + map_base = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, binder_fd, 0); + if (map_base == MAP_FAILED) { + fprintf(stderr, "mmap error: %s\n", strerror(errno)); + close(binder_fd); + exit(2); + } + + /* Create the appropriate shared memory for passing the Service + * Providers handle from the Manager to the Service Provider for + * use in the impersonate tests. This saves adding a Client to + * do this job. + */ + create_shm(manager); + + /* 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(); + + if (manager) { /* Service Manager */ + if (verbose) { + printf("Manager PID: %d Process context:\n\t%s\n", + pid, context); + } + + result = ioctl(binder_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(binder_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(binder_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(binder_fd, (uintptr_t)readbuf, + bwr.read_consumed, manager); + } + } else { /* Service Provider */ + if (verbose) { + printf("Service Provider 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 = TEST_SERVICE_MANAGER_HANDLE; + txn->cookie = 0; + txn->code = ADD_TEST_SERVICE; + txn->flags = TF_ACCEPT_FDS; + + memset(&obj, 0, sizeof(struct flat_binder_object)); + obj.hdr.type = BINDER_TYPE_BINDER; + obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; + obj.binder = (uintptr_t)NULL; + 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 = (uintptr_t)writebuf; + bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn); + + if (verbose) + printf("Service Provider sending transaction to Manager - ADD_TEST_SERVICE\n"); + + /* Each test will expect a different number of replies */ + while (provider_replies) { + bwr.read_size = sizeof(readbuf); + bwr.read_consumed = 0; + bwr.read_buffer = (uintptr_t)readbuf; + + result = ioctl(binder_fd, BINDER_WRITE_READ, &bwr); + if (result < 0) { + fprintf(stderr, + "Service Provider ioctl BINDER_WRITE_READ: %s\n", + strerror(errno)); + result = 7; + goto brexit; + } + + if (verbose) + printf("Service Provider read_consumed: %lld\n", + bwr.read_consumed); + + cmd = binder_parse(binder_fd, (uintptr_t)readbuf, + bwr.read_consumed, manager); + + if (cmd == BR_FAILED_REPLY || + cmd == BR_DEAD_REPLY || + cmd == BR_DEAD_BINDER) { + result = 8; + goto brexit; + } + provider_replies--; + } + } + +brexit: + free(context); + munmap(shm_base, shm_size); + close(shm_fd); + munmap(map_base, map_size); + close(binder_fd); + + return result; +}