From patchwork Sun May 20 18:25:06 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: 10413581 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 C3317601F9 for ; Sun, 20 May 2018 18:27:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AED822873E for ; Sun, 20 May 2018 18:27:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A360B28742; Sun, 20 May 2018 18:27:03 +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 UCOL19PA11.eemsg.mail.mil (ucol19pa11.eemsg.mail.mil [214.24.24.84]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0056E2873E for ; Sun, 20 May 2018 18:27:00 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.49,423,1520899200"; d="scan'208";a="517034837" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.2]) by UCOL19PA11.eemsg.mail.mil with ESMTP; 20 May 2018 18:26:59 +0000 X-IronPort-AV: E=Sophos;i="5.49,423,1520899200"; d="scan'208";a="11979982" IronPort-PHdr: =?us-ascii?q?9a23=3A+Y9LjRY+IAUpgWXEFAM4lhD/LSx+4OfEezUN45?= =?us-ascii?q?9isYplN5qZoc26Zh7h7PlgxGXEQZ/co6odzbaO6Oa4ASQp2tWoiDg6aptCVh?= =?us-ascii?q?sI2409vjcLJ4q7M3D9N+PgdCcgHc5PBxdP9nC/NlVJSo6lPwWB6nK94iQPFR?= =?us-ascii?q?rhKAF7Ovr6GpLIj8Swyuu+54Dfbx9HiTahb75+Ngm6oRnMvcQKnIVuLbo8xA?= =?us-ascii?q?HUqXVSYeRWwm1oJVOXnxni48q74YBu/SdNtf8/7sBMSar1cbg2QrxeFzQmLn?= =?us-ascii?q?s65Nb3uhnZTAuA/WUTX2MLmRdVGQfF7RX6XpDssivms+d2xSeXMdHqQb0yRD?= =?us-ascii?q?+t4b1rSBv1gykZMTA3/nzchshpgK5GvB6tohpyyJPWbo6ILvpzZqPTc80HS2?= =?us-ascii?q?RPXchfUDdMDp+gY4YVE+YMJ/pUo5X7qlATrRW+Hw6sBOb3xzFUh3/5wa063P?= =?us-ascii?q?47EQ7bwQcuHcgBsHXSrNrrL6cZTP61zKjSwj7ecv1ZxzP96InOchA8rvCHQL?= =?us-ascii?q?V9cdHPxkkrFgPFiEiQqIP+MjOJ1uUCr2ib7+16WeKpkG4osRt9ojeoxscyk4?= =?us-ascii?q?TEgJ8exFPc9Shh3Yo4KtK1RFR7bNK5CpdcqS6XO5VsTs8/W21luzs2xqcbtZ?= =?us-ascii?q?O1YiQG0psqyhzFZ/CZc4WF5A/oWvyLLjdinn1lfaqyhxO18Ue91OLxTtK00F?= =?us-ascii?q?NWripdldnMq2wN2wTT6seZTvt9+V+s2SqV2ADJ6+FEPFs0mbDHK58h3rEwlp?= =?us-ascii?q?0TvV7FHiDqg0X5kLWadkAl+uis8+jnY7PmqYGAN4Jslw3zPasjlta/DOglKA?= =?us-ascii?q?QCQWeW9fqm2LH+5UH5Ra9FjvwykqnXqpDaIsEbq7aiAwBL1oYj6hC/Dyqp0d?= =?us-ascii?q?gBhnYHK09FeBSbgIf3IFHDO+z4DPejjFSslzdn3fbGPqb7DZnXIXjDl6nhca?= =?us-ascii?q?5n60FA0Aoz0cxf55VMB7EDJ/LzXFX+tMDYDhAjNQy52OTnCNJ71oMbQ22PGb?= =?us-ascii?q?OZP73IsV+T/O4vJPOMZIANsjbnN/cl/+LujWM+mVIFf6mp34EYZ2y7HvR9JE?= =?us-ascii?q?WZZ3vsgskaHGcEugo+UePrh0afUT5Ve3ayQrgw5jYhCIKpFY3DXJyigKSd3C?= =?us-ascii?q?enGZ1bfnhGBU6XHnj2cYWEWusMaCWJL89gjDMLS6auR5Um1RG0uw/w06BnIf?= =?us-ascii?q?bM+i0EqZLj08B46PDUlRE08zx7EtqS02WMT2xvhGwHWSU23KdlrUx60FeD3r?= =?us-ascii?q?Byg+ZEGtxL+/NJTgA6OIbBwOxmEd/yQBnMccuOSFajXtqpGyoxTs4rz98IfU?= =?us-ascii?q?l9B82ojgrf0CqyH78Vi7uLCYQq/aLExXfxPcd9y23d2ak5lVYmWMpPNXa+hq?= =?us-ascii?q?577QfcG5DGn1+el6aweqQWxDTN+3ubzWqSoEFYVxZ9UaTDXXADeETWqcr25k?= =?us-ascii?q?bcQL+yE7QmMhBMycmaKqRUbN3piE9JRPbnONvFZGKwlH28BRGSxrODdIDqYX?= =?us-ascii?q?kS3D3BCEgYlAAe5XaHNAk5BienuG/eCThuGUvuY0Pq6+V+rmm0TlU3zwGLcU?= =?us-ascii?q?1uyaC5+hgLivyAU/kTxK4LuD89qzVoG1awx9zXC9uEpwpkYqpce8gw4FlZ2m?= =?us-ascii?q?3EsAx9JIavL7h4hl4ZcQR4oV/h1wltBoVHi8gqo2sgzBBuJqKAzFNBazSY0I?= =?us-ascii?q?j+Or3NMGby+gyga6/N2lzF1daW4qYP5O0jq1TtpwGlDE0i829o09NNyXuT+o?= =?us-ascii?q?3KDBYOUZL2Sks39AJ1p7LdYikg/I7U1mdjMaqzsj/fwd4pA/Elyhm4dddFLK?= =?us-ascii?q?yEDBPyE9EdB8W2MuMlhkKpbhMaM+BI76M7Jd+pd/6c1K6sJuZgkyqsjX5b74?= =?us-ascii?q?BlzkKM6y18R/bU0Jkfx/GXwBCHVyv8jVemqc33gpxLZTAMEWq51SjkBZRear?= =?us-ascii?q?d0fYkVFWekO9e3yclmh57xR35Y80auB0kb18C0YheSYFn93AJK2UQRv3OnhT?= =?us-ascii?q?OyzyZonDExsqqfwCvOzvz5dBoJIG5LQ3JijUv3LIividAaW0apbw0zmxuj/0?= =?us-ascii?q?r6wbZUpLhnJWnJXUhIZzT2L31lUqaouLuNecpP6I82viVNS+Sxek6aRaDnox?= =?us-ascii?q?QBziPjGnFSxDchdzGlop/5hQB1iHqBLHZvq3rUYd9wxRbD69zAQv5RxCAKSz?= =?us-ascii?q?V4iTnQAFi8MMKk/dGVl5fFqO++TWWhWodUcSnxwoOKrDG76nFyAR2jg/Cznc?= =?us-ascii?q?XqEQw70S/gy9lmTD7Iowj4Yonq0aS6LO1mc1JzBF/k6sp6HIB+nZcrhJ0K33?= =?us-ascii?q?gVmImV92IdkWjvKdVbxb7+bH0VSD4RxN7V5Azl11N5Ln2VwIL4WG6QwtB8Z9?= =?us-ascii?q?ameWMawCU979pFCK2M9rxLgTN1okakrQLWefV9nSkSyf016HMBgOEGpgwtzj?= =?us-ascii?q?6bAr8MAUlUJyvslw6H79qmtqVYeH6vcaSs1Ep5hd2hFKuNohxYWHnnYpctBy?= =?us-ascii?q?lw7tlhP1LWy3Dz95rkd8fKbdIIrBGUiBDAj/VPKJ0tiPUKiy1nOXjyvXI70e?= =?us-ascii?q?I7iwJh3Y2itoidN2pt5L65AgJfNjDtecMT/CzigL1AnsaQwo+vHo9tGjMVU5?= =?us-ascii?q?v0VfioCi4dtez7NwaSFz0xsm+bFqDCHQ+b80pps3PPE4yrNn2OKnkW19NiSA?= =?us-ascii?q?OaJExFjwAeRC86kYIhFgC22Mzhd1905jMR5178tBRB0edoNx7xUmfRugiodi?= =?us-ascii?q?s0SJiYLBpT8A5O/UHVPtKC7uhrBSFX4oWhrBCRKmycfwlIA3sGWkqYB1DkO7?= =?us-ascii?q?mj/tfA/PaFCeq5NfvBe62OqfZZV/eK252gzpdm8yyLNsWVMXloF+c71VZbXX?= =?us-ascii?q?BlB8TZnC0CRDELmCLIaM6bogu89jBso8Ch7vvrQgPv5IqIC7tUK9lv/Q65gb?= =?us-ascii?q?ubPe6KmCl5MSpY1o8LxXLQxrgfxkAdhDx1dza3F7QAqSnNTLnLl6BNExEbbj?= =?us-ascii?q?l/NMxS76IzxgNNI9LUisvp1r5kif44E1FFVUb7lcGxfcwHOG+9NFLdBEaQKL?= =?us-ascii?q?SGKzzLw8ftbqO6VbJQjf9btxmqtTacCU/jMSyJlyP1WBC3LeFMkCabMQRFt4?= =?us-ascii?q?6mdRptDWnjTMn6ah2gKtN3liM5zqEuinPRK2EcNTl8c0VQrryf9i5XnvV+G3?= =?us-ascii?q?Zc7np+N+WFlTyW7/XDKpYRt/tnGCN0l/hV4H4i0bta8DlEROBpmCvVttNupV?= =?us-ascii?q?Cmku2LyjV5SxpDsSxEi5yRvUVlI6nZ8YNAWXnc9hIX8WqQEwgKp8diCtD3oK?= =?us-ascii?q?9Qy9fPlKX1KDpZ7t3b49ATB8nOJ8KBKnYhNgDpGDHMBgsfUTGrLX3fh1BakP?= =?us-ascii?q?yK7HKVoYI1qobyl5cVTb9bTEI6FvUfCkt/HdwCJIx4XjQrkLKBi84I/3W+pg?= =?us-ascii?q?HLRMpGppDHSu6SAfL3JTaFirlEYgEEwan/LYUSKIL73VdtakN9nIvUGErdRs?= =?us-ascii?q?xCoipkbgAoukpN62R+Qnc12037dgOn+GUTGuKsnh4qlgt+Zvwg9DXs41Y3Pl?= =?us-ascii?q?rKoy8wkEgtmdr7mj2RdT/xLLuqXY5IESb0sFIxMpzjSQZvcQKyhVBkNCvDR7?= =?us-ascii?q?9Jibtva3pkiAvHtJtMHv5cVrFEbwUWxfGMZPUo0E5QqiO5yk9b/eHFE4dtlB?= =?us-ascii?q?M2cZ6wqHJNwxhjY8AuJaPOPqVJ1ERfhqKVsyCz1+Ax2hIRJ0ED8GOKYi4Hpk?= =?us-ascii?q?wJOqMgJyW24uxm8RaClCdbeGgQS/oqpepn+V4nNOSeziLvzqVDJ1urOOyFNa?= =?us-ascii?q?OZvGbBldWWTVwsy0MIjUhF/aR20Ms5dUqbSVwvxqOLFxsVLcrCNR1Vb81K+X?= =?us-ascii?q?jXeiaOq/vCwZR0PoW6De3oQumOtLsOjkKjBgYpEJwG7t4dEZm0zEHYMcDnIa?= =?us-ascii?q?YeyRoz4ATrJVOFDOlGeR+QjDgHpMS/w4Nt0olGOjERG2N9Pjur5rzPvA8lnO?= =?us-ascii?q?KDXMsqYncdRoYEKnM2WMi9my5Fv3RBDCK63f8YyAmC9TDzvT7cDD/iYNp/fP?= =?us-ascii?q?2Ufw9jCMmq+TUj9Ki7kUTY8pHfJ27mK9ttotrP6OMcp5aADfNbV6JwvFzdm4?= =?us-ascii?q?ZCQXymSmDPEcOvK5j2dYYsccT+CmymXVynlzI1U8DxMc62IaeWhwHlXpxbv5?= =?us-ascii?q?SF3D89L8+9DSsRGw1wpu0Z46J8fwIDaYIhYRH0rwQ+K7C/IACA39W0RWatKC?= =?us-ascii?q?dZT/lYzeW+fLxZ1zMiYPKgxnY8SZ831PW48UkIRJ4WlB7e3uqja5NYUSftBn?= =?us-ascii?q?xXYx/PqjYhl2h9KuYyxf8yzw/KsVYGLz+Gb/BmaGtAv9E4BFOdP292CnYmSF?= =?us-ascii?q?CAjYrP+Ams36od/yFFhdZbzfVFsGTivp/YeD+sQrakqY/SsyU7dtUmv7dxPp?= =?us-ascii?q?b9IsSYsJPenzrfTJbUsg2EXy66F+ZamtZKLyJCRflEg2clNtIauYBZ80o+St?= =?us-ascii?q?8+J6BTCKkrvr2rZyBoAjISzS8YUoOA3SYNguSn1rvbiBifbootPAYDsJVYjd?= =?us-ascii?q?sXSzR2bT8GpK+/S4XWkHeJSm0RLwcJ7gRD+h4Alo52fuDq+4fJQoVDyzhKrP?= =?us-ascii?q?JwVSvLC4Rn90DhRmGQn1f4VO2rk/a10gJK0PLszt4bVQZnCUhaw+ZZjFEoKb?= =?us-ascii?q?9wK6kUsI7HqTqIdUT9vGL21uSpOENRycrPd13jDYrFs2X8Xjcb+X0OSo9F0G?= =?us-ascii?q?vfGogKkwpldKYro01BL5q8ekbj4Two3YdpEqK5VcCqxlYlsW0JSz2sE9VfF+?= =?us-ascii?q?FsqEjXVyF9Y5C3tJXlPI1fQnNX+J2YsFpZjFlhMyuixpZGLcFC/CIMViBVoT?= =?us-ascii?q?qBpNuyVNFD2chuAp8MONh/oW3yGKdZN5WKvnI5pKTvymfH9DA4rli63i+/G6?= =?us-ascii?q?iiT+JW52ceABkmJ3yCqkkzCOsh6mXS8lfTvV1v4uhUGKOPgltroDZhAJ9BGy?= =?us-ascii?q?xF1Xa7IFRvVHNGqflVKLzJc8xARPk/fQOvNAEjGv4nxUOJ+Vp5kmv+Yyx3qg?= =?us-ascii?q?RV4TvdXxUuWSkTnLjthSUUqtu7Nj8CV5JIcTIhYj/eJAKVhS9boBRSZ1xkVp?= =?us-ascii?q?0CHtlF/LQb0pdO8crZVUagMycFUwJ+Ngggy/pQiVZDsFmEeSDaFQeob+jAvQ?= =?us-ascii?q?B3fciLsM6kN/D5/ABZioz5ruw366IDSGC4lgG3R9DRsZP8vMWQtkSSbKf4L/?= =?us-ascii?q?G8YXjZQTjUlhCwma0rAITW/yXIKwpbLIR6yWA4bpf/D27LIQ5GKLgfJ0ZBUq?= =?us-ascii?q?B6c9pGqPhAZ8B4YKYJ5bNtBhWfSxPzAoygsudJIUvISDTDKyWB7va/rpjN7b?= =?us-ascii?q?zcTujgYtKDx2rdT6JwJJd65iHxG6323o9G5kr2xvBt+1t/SVfcNyCBqMruJh?= =?us-ascii?q?8X5Ma4bETvpZspEi3KAJdrjHXi3FlAeNQNTy2s7psY1ItT6GzsRuJgzkjzrO?= =?us-ascii?q?pS+qFm6YYt+bBpzty0JaPIJvREqkJnBwWUBgF29pUsHGd/RnpeYukKKPvLeq?= =?us-ascii?q?QZl8/uofjtF6ML8B2V5/BZadzfKkHDgMa/DD+cSQZDnAgctzEXNRec2OSDm6?= =?us-ascii?q?9vTsapv+751Vwx41KmNB4J0Kht5ZuY+qqPvOLXYAbRzbkAWqjuWMzzq68htF?= =?us-ascii?q?6M6vI/lb4BYGp1bxegEOgHWc4X3n3gwrwyzSIwD8PDGKrt+PxCV3I8hT/gno?= =?us-ascii?q?5yHlUIFfMOHLqL+4tekn0+m+PHKt0carpClXqXFR64Dr8Czmam6y2TIGR+gx?= =?us-ascii?q?HO1RTwTXmy7F/woy94WzHDz8z/kkpPS7m4GVtSXzezOUBmqj+POxDotNXvs6?= =?us-ascii?q?Qv8E42KnDktM6KlGa5PbNXGMv/JMCTISYqv18XiZwxScap2Y8FBdq8LtAR8G?= =?us-ascii?q?t9bvvF8W+rlTFOo7tfjYrE/s6V4unXHWWnj6CCr7WN3zVYx3gjsFEx9N+vK/?= =?us-ascii?q?bO58eQTPSwzWYRSCV/tBXdUB6psLDbqEoUOUOT2kfRhIMKJs1Z3WU/1kz+5e?= =?us-ascii?q?giQcg8+x9CGYvbfPMNuyzzNyXozlqFZNI3TCae2SNNHl3pCVl4BLQ82GXosc?= =?us-ascii?q?3SlHfQ4FMpSZNyd0zmmRx3F583KV8p6FUM3iUDFhUCZg6BA7G1H0TlKpEEWl?= =?us-ascii?q?IZZRSAxri6db893VdvzbO3+O/Tcet8CrIVNvlHkg6BgFhbG5wRsa0EQ7JwYk?= =?us-ascii?q?Rd+7DTpgjjDYjnQvfnmGEoNfKvXsBV7cAZtnUl4galRBqs85RD4KgBiJCOaK?= =?us-ascii?q?FEZYLAvMdm70do/TQPbDBCgABjjxOlVuARvO/j7cLBsJW29uauVL0gR+EW9x?= =?us-ascii?q?goGWt+j4H/gE04od3N0edTVJHVg5zl8A9RO36KpJra0x5kJOoBNY2reqpg93?= =?us-ascii?q?IAJyQZPHIBI96Wa/g64y9wPzTe/FhCDd0WZdIYJsXBgwZUhVP1WLtL7MrUBk?= =?us-ascii?q?eYC5tvd8Av92f3zjE1/oc7Uubk8jC2PorT71BKP/NElyVsj8nPpO0azPvdEi?= =?us-ascii?q?QX5mOZaxdtyCOY15aNE+rw/fmLyNzMWFMJAjU2U5xEKDSf9gKpQOu1lJP0Ug?= =?us-ascii?q?Kb8cLzj5c+e1iWRnOvhqgFtbxMEeFYgCXhwjdeDpz1h+6Ss9e06mtXsV1HEI?= =?us-ascii?q?Bp4RLZGKVfOoh7Ngn5l8mqQEh8HSj/eMDPexowueqW2P0D4+FjOEv/f4MbJA?= =?us-ascii?q?wLy67i43pPUgRuUKL2vkqeXe8JZdtmVunLrnZO5IJkNq8AIVmdpJvxrjtSr1?= =?us-ascii?q?A2GgApYqcqrjNGbknOgBFVW6Hstb4ClAQcX9B5uUtXFGO+Im0+4STIVbhPgK?= =?us-ascii?q?mXFvMV7i2ZTrYSXEVwLiN+XxS11Y1he7utmvBGvH1Jnid5oPUxyDxmQx28uS?= =?us-ascii?q?zwqK4X3zIv5q24vi0buXNZVuWejzvICVJbwfQPjKccCHXi6VunbXkBdoTy47?= =?us-ascii?q?5nJcL++okn+Xg/ZwssfzEeV+S6Fy7wl7+IApCIsN9EnxGCpsPObaOoICgJMr?= =?us-ascii?q?Q9zg7jR2Rj0gfAgRlk6mwLQi+v7NU8PoWyJd4lxja0GWjcbFsM7L1GsM/wtV?= =?us-ascii?q?4TUuQ7clJgwGRm0siCWCINXsjPFHgvgggjc2VEf4pJ6QUGGKkwnjaIoq5G8x?= =?us-ascii?q?kaYTfMCISl+5XfktnT1Hk4TNdq2njWqbOfipMtyn1llMt+7jSSt3QKa+zYT8?= =?us-ascii?q?hsD2D01odb1+PzfO2tsuQdR4t91LShUeMNMtW5+WSoxppmQEmlyaoCH1ChKu?= =?us-ascii?q?8M2q/bUzu5SW2fQemLd2mMnzAkMk/9/BWoKlw3aNxWr08mKebCh4RTlwvmUb?= =?us-ascii?q?9uQSWQv1DbxnQ5MewGbwI2pJunewsSQe4UfeeTOeguwPw4CFsLdHLJAyp2C+?= =?us-ascii?q?movl6pnYh7PWhg4ErgbeTq6ADmP8OYGgMYHo7Csp5x5fu6S3qDOXB6zx1yO1?= =?us-ascii?q?J7+vzCF1Q3qu9cc5GRncXfh9R7ze4JbfFtPjMhutQLgIJs9ZGU0NuWcRHW1p?= =?us-ascii?q?vyJ9TVov+CA/3FzkQqYXpXUrwDbgPw+Yo6P8Q1W7rJHbtWpR4cH7Q1QIQ9N2?= =?us-ascii?q?ft86F5NBhzcgDUZLuog8TnpfmGZoVKqH/M71IxLSDcuxsZxvyyUwN7c4imh3?= =?us-ascii?q?XsL5A0QTJMt9ltChx6E4RVH8MArw2nA4WImK2hj9+x/F91tPUOsaXtDfDK0c?= =?us-ascii?q?6234R3X5RC5EyLOijeBLVzj0lmk+i+mOrM35fvBc/4dt4JVvJ3TnDFZ7PeG4?= =?us-ascii?q?WwMDOOOsbye05c9L6c1ap0XxKLZCD4Q6WGtDerNO957koj1oN3ZOrTwyYs77?= =?us-ascii?q?HdxtTyfHpWqTy/rX6IMptf8ELFBfbYXx1KVfqJ6npqHaoSbYbt7OsOK8AtwM?= =?us-ascii?q?CA4wlv6zRPyMyII7KgrkDQ2kJ0b4jbI1bx1CklQYYKIA6wMUoqgWDHsXTQGm?= =?us-ascii?q?9TLtSlKclrnNaaEAbt509vlmExfGJOBm3oRdKINGQDwcKxeBWK9B5XD9YEh+?= =?us-ascii?q?O6flU4ubCpSeRzJpVEmfmltLUAkdpzLSHPX9JVMzvfLL9xIDpcF/3DpEI0bR?= =?us-ascii?q?4cr7g1RoA1aICJLUMcLkiAzSLyzQ3f0Uz7bNGsyKaILzoW8nVA1b7F1yNMqB?= =?us-ascii?q?OjtfaWhc3jTqnUYZfrV/PMNColSyqaRSgsHkaz5FmkuvsFs+SALGsD8RgoZX?= =?us-ascii?q?eJBQoSoL1/hcTBBW/U3+t4ddsFg+7eEzv8UwVkhaEyAWBNrknKTP0dRjPbd3?= =?us-ascii?q?vwvG0Jgg2pJvZW8TrFZryey7EdD/YXCYtFaPGuSOzYcPFYKiwAnCkYPvqxZd?= =?us-ascii?q?vRs/Ay1VeeHkUDFKydzlyVTEeMTrS8zjPtUJ5doYk98hEl/tPWgz8/R7/FO7?= =?us-ascii?q?eZui6G7p+zjCHev/bXEGYqfRpm06o5HGCdzUwYeyk/ANYPtRSoG/aN?= X-IPAS-Result: =?us-ascii?q?A2DgAABOvQFb/wHyM5BaGQEBAQEBAQEBAQEBAQcBAQEBA?= =?us-ascii?q?YMYK2F9FROLeF+MGWSCChqTNhQLgVYmAxABhlMhNBgBAgEBAQEBAQIBaxwMg?= =?us-ascii?q?jUkglcCFw1VAwkCSAgDAVoJCQWCXUACKIE/AQEBFQMBpnAzg3RWg3OCD4g1D?= =?us-ascii?q?oIFgQ+CV4MEgg0BhWoChyoKhGyBIosKCYVqiGKBQj6GDoR6khwcOIFSKwgCG?= =?us-ascii?q?AghD4FrGnkJghcXh02GS255AQEBKIwBK4IZAQE?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 20 May 2018 18:26:58 +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 w4KIQt1u026619; Sun, 20 May 2018 14:26:56 -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 w4KIPLOg038599 for ; Sun, 20 May 2018 14:25:21 -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 w4KIPONK026565; Sun, 20 May 2018 14:25:24 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1BVAADcvAFbly0WGNZaGQEBAQEBAQEBA?= =?us-ascii?q?QEBAQcBAQEBAYMYKGR9KIt4X4wZgm4akzYUgWQmEYRAghMhNBgBAgEBAQEBAQI?= =?us-ascii?q?UAQEBAQEIFgZLhVUNGQE4ARWBKQkJgyICKIE+AQMVAwGmcDOCcAV/ZINeB4IDB?= =?us-ascii?q?AiHOXyCE4EPgleDBIINASKFSAKHKgqEbIEiiwoJBYVliGKBQj6GDoR6khwcggo?= =?us-ascii?q?zGiODEwmCCwwOCYNFhAiGS255K4wBK4IZAQE?= X-IPAS-Result: =?us-ascii?q?A1BVAADcvAFbly0WGNZaGQEBAQEBAQEBAQEBAQcBAQEBAYM?= =?us-ascii?q?YKGR9KIt4X4wZgm4akzYUgWQmEYRAghMhNBgBAgEBAQEBAQIUAQEBAQEIFgZLh?= =?us-ascii?q?VUNGQE4ARWBKQkJgyICKIE+AQMVAwGmcDOCcAV/ZINeB4IDBAiHOXyCE4EPgle?= =?us-ascii?q?DBIINASKFSAKHKgqEbIEiiwoJBYVliGKBQj6GDoR6khwcggozGiODEwmCCwwOC?= =?us-ascii?q?YNFhAiGS255K4wBK4IZAQE?= X-IronPort-AV: E=Sophos;i="5.49,423,1520913600"; d="scan'208";a="281265" Received: from emsm-gh1-uea11.ncsc.mil ([214.29.60.35]) by goalie.tycho.ncsc.mil with ESMTP; 20 May 2018 14:25:21 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3A6FmNtxE6rsgQ0qTCb9xtxZ1GYnF86YWxBRYc79?= =?us-ascii?q?8ds5kLTJ76pci9bnLW6fgltlLVR4KTs6sC17KN9fi4EUU7or+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/b9bRxVMzGAPCi1WdsIroNC6W2OQVq2WX8fdsWO21h2I5pAx9uCajytk2ho?= =?us-ascii?q?TGho8Z0lPJ+ThjzIooK9C0VlR3bNGmHZdKqS2XN417Sd44TW5yoiY10LgGtI?= =?us-ascii?q?a7fCcUzJQnwAbSZPKafYWU/BzuWvicLy1kiX55er+znQi9/lalyu3nWcm4yl?= =?us-ascii?q?NKoTBEktnIrHwN0h3T6syfRvt8+EeuxyqP2hjN5u1ZLk04j7TXJpE7zrIuiJ?= =?us-ascii?q?Yfq0vOEy/ulEXzlqCWd0Ek+uay6+TgZ7XrvoWcN45ohQH+KKsugNGwDvwkPQ?= =?us-ascii?q?cWX2iU4+W81Lv98k3iW7hFleE2kqjfsJDGO8sbvKi5DBFJ0oo59xm/CDKm3M?= =?us-ascii?q?wCnXYbNFJFZA6Hj4/xNlHVPf/4Fuyyg0iskTh3x/DGOaftApPWLnfZirvhcr?= =?us-ascii?q?F961BEwgop0d9f/45UCq0GIP/rQU/+qtjYDh4/MwypzOfqE8l914MCVmKPBa?= =?us-ascii?q?+VKqXSsUSS6e41LOmMY5EVtC79K/c74/7uimc0mVsafaa1x5QXbHC4HvN9I0?= =?us-ascii?q?WFe3bshtABHnsQsQo6UePqj1iCXiRSZ3a0R6485zc7B5y6DYrbRY2hnaaN0D?= =?us-ascii?q?q1E5FIfGxLBVKBHW32e4iEQ/sMbTidIs5lkjwKT7ihTIoh2AmpuQ/gyrpoMu?= =?us-ascii?q?rU9TcCtZ3+zNd6+/XclREo+jx1CcSSzXqNQnpvkWMURj822rx/rlJnyleFz6?= =?us-ascii?q?d4n+ZUGsBU5/NMSwo2LYTcwPBiC9DuRgLBec+ERVG8QtWnHT4xTsg+w8UTbE?= =?us-ascii?q?llB9qtlhDD0DCrA78TibOLH4c5/bnA33jwIcZ912jJ1LMnj1Y4XstDL3Gphq?= =?us-ascii?q?l69wXKH4LJiVmWl762daQA2y7A7GCOzXGTs0FDSwNwTaXEUmwfZkvRt9j54F?= =?us-ascii?q?jCQKW0BbQoNQtB19ePJrNQatL1lVVGWOvjONPGbm+2gGe/GxKIxrKKbIr3dG?= =?us-ascii?q?QQxzndCUgYnAAT+naKLw4+Bjy7rG7EAzxuEkzvblrq/OJjtn67SlI0zxqWb0?= =?us-ascii?q?J/zbq75x8VhP2CRP4Lwr5X8Bsm/i55GFe7wsL+F8uLpw0ner5VJ9w6/hMPzm?= =?us-ascii?q?7CnxBsNZynaaZ5jxgRdBokkVnp0kBNC45AmNIm5FMjzQx/MurMylJKdzqC0a?= =?us-ascii?q?f7Db3eK2//5zild6/QxlzE1tuKvKwI7aJr+B3YoAi1Gx96oD1c2N5P3i7EvM?= =?us-ascii?q?+YBRcOUZ/3Tkc8/gR7oLefeCQm+ofIzi02Y5SPmwOZ8OoAXLJjxxulZNgZNa?= =?us-ascii?q?qFEEn3EslJT8StKel/g1Wzax8eJudIvO43MtLua/yBkLWuNeJk3XqmgG1L7Z?= =?us-ascii?q?o70xek/TZ9TPLFxZAI37eT2Q6K?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0BwAADcvAFbly0WGNZaGgEBAQEBAgE?= =?us-ascii?q?BAQEIAQEBAYMYKGR9KIt4X4wZgm4akzYUgWQmEYRAghMhNBgBAgEBAQEBAQI?= =?us-ascii?q?BEwEBAQEBCBYGSwyCNSKCcg0ZATgBFYEpCQmDIgIogT4BAxUDAaZwM4JwBX9?= =?us-ascii?q?kg14HggMECIc5fIITgQ+CV4MEgg0BIoVIAocqCoRsgSKLCgkFhWWIYoFCPoY?= =?us-ascii?q?OhHqSHByCCjMaI4MTCYILDA4Jg0WECIZLbnkrjAErghkBAQ?= X-IPAS-Result: =?us-ascii?q?A0BwAADcvAFbly0WGNZaGgEBAQEBAgEBAQEIAQEBAYMYK?= =?us-ascii?q?GR9KIt4X4wZgm4akzYUgWQmEYRAghMhNBgBAgEBAQEBAQIBEwEBAQEBCBYGS?= =?us-ascii?q?wyCNSKCcg0ZATgBFYEpCQmDIgIogT4BAxUDAaZwM4JwBX9kg14HggMECIc5f?= =?us-ascii?q?IITgQ+CV4MEgg0BIoVIAocqCoRsgSKLCgkFhWWIYoFCPoYOhHqSHByCCjMaI?= =?us-ascii?q?4MTCYILDA4Jg0WECIZLbnkrjAErghkBAQ?= X-IronPort-AV: E=Sophos;i="5.49,423,1520899200"; d="scan'208";a="13535095" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from usat3cpa07.eemsg.mail.mil ([214.24.22.45]) by emsm-gh1-uea11.NCSC.MIL with ESMTP; 20 May 2018 18:25:19 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;c8ada15d-5331-4e6d-81b7-e53a8e8f2357 X-EEMSG-check-008: 230390937|USAT3CPA01_EEMSG_MP17.csd.disa.mil X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.216 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0A+AADouwFbh9gAFEFaGQEBAQEBAQEBAQEBAQcBAQEBAYMYgQx9KIt4X48HGpM2FIFkEBYRhECCNDQYAQIBAQEBAQECFAEBAQoLCQgoIwyFSQ0ZATgBFYEpCQmDIgIogT4BAxUEpnEzgnAFf2SDXgeCAwQIhzmDD4EPgleDBIINASKFSAKHKgqEbIEiiwoJBYVliGKBQj6GDoR6khwcggozGiODEwmCCwwOCYNFhAiGS255K4wBK4IZAQE X-IPAS-Result: A0A+AADouwFbh9gAFEFaGQEBAQEBAQEBAQEBAQcBAQEBAYMYgQx9KIt4X48HGpM2FIFkEBYRhECCNDQYAQIBAQEBAQECFAEBAQoLCQgoIwyFSQ0ZATgBFYEpCQmDIgIogT4BAxUEpnEzgnAFf2SDXgeCAwQIhzmDD4EPgleDBIINASKFSAKHKgqEbIEiiwoJBYVliGKBQj6GDoR6khwcggozGiODEwmCCwwOCYNFhAiGS255K4wBK4IZAQE Received: from rgout0403.bt.lon5.cpcloud.co.uk (HELO rgout04.bt.lon5.cpcloud.co.uk) ([65.20.0.216]) by USAT3CPA01.eemsg.mail.mil with ESMTP; 20 May 2018 18:25:16 +0000 X-OWM-Source-IP: 81.132.47.25 (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: gggruggvucftvghtrhhoucdtuddrgedthedrfeejgdduvdekucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuueftkffvkffujffvgffngfevqffopdfqfgfvnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffosedttdertdertddtnecuhfhrohhmpeftihgthhgrrhguucfjrghinhgvshcuoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqeenucfkphepkedurddufedvrdegjedrvdehnecurfgrrhgrmhephhgvlhhopehlohgtrghlhhhoshhtrdhlohgtrghlughomhgrihhnpdhinhgvthepkedurddufedvrdegjedrvdehpdhmrghilhhfrhhomhepoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqedprhgtphhtthhopeeorhhitghhrghruggptggphhgrihhnvghssegsthhinhhtvghrnhgvthdrtghomheqpdhrtghpthhtohepoehsughssehthigthhhordhnshgrrdhgohhvqedprhgtphhtthhopeeoshgvlhhinhhugiesthihtghhohdrnhhsrgdrghhovheqnecuvehluhhsthgvrhfuihiivgeptd Received: from localhost.localdomain (81.132.47.25) by rgout04.bt.lon5.cpcloud.co.uk (9.0.019.26-1) (authenticated as richard_c_haines@btinternet.com) id 5AF327EC010416E7; Sun, 20 May 2018 19:25:13 +0100 X-EEMSG-check-009: 444-444 To: selinux@tycho.nsa.gov, sds@tycho.nsa.gov Date: Sun, 20 May 2018 19:25:06 +0100 Message-Id: <20180520182506.19665-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.17.0 Subject: [RFC V2 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 | 96 +++++ tests/Makefile | 4 + tests/binder/Makefile | 7 + tests/binder/check_binder.c | 80 +++++ tests/binder/test | 89 +++++ tests/binder/test_binder.c | 685 ++++++++++++++++++++++++++++++++++++ 9 files changed, 980 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..3fd4dd5 --- /dev/null +++ b/policy/test_binder.te @@ -0,0 +1,96 @@ + +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 map }; +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 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 test_binder_provider_t:binder { call }; +allow test_binder_mgr_no_fd_t device_t:chr_file { ioctl open read write map }; +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 map }; + +# +########################## 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 map }; +# 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 map }; + +# +#################### 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 map }; +fs_getattr_tmpfs(test_binder_provider_no_call_t) +allow test_binder_provider_no_call_t tmpfs_t:file { read write open map }; + +# +#################### 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 map }; +fs_getattr_tmpfs(test_binder_provider_no_transfer_t) +allow test_binder_provider_no_transfer_t tmpfs_t:file { read write open map }; + +# +#################### 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 map }; +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 map }; + +# +############ 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..919e568 --- /dev/null +++ b/tests/binder/test_binder.c @@ -0,0 +1,685 @@ +/* + * 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; +}