From patchwork Tue May 22 11:37:52 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: 10418199 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 1C196600CC for ; Tue, 22 May 2018 11:39:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 063A220952 for ; Tue, 22 May 2018 11:39:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EC9E727F2B; Tue, 22 May 2018 11:39:37 +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 ucol19pa09.eemsg.mail.mil (ucol19pa09.eemsg.mail.mil [214.24.24.82]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B571728C5E for ; Tue, 22 May 2018 11:39:13 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.49,430,1520899200"; d="scan'208";a="701962068" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.2]) by ucol19pa09.eemsg.mail.mil with ESMTP; 22 May 2018 11:39:12 +0000 X-IronPort-AV: E=Sophos;i="5.49,430,1520899200"; d="scan'208";a="12032482" IronPort-PHdr: =?us-ascii?q?9a23=3AkmeLxhdximget4GjyMLdy+vVlGMj4u6mDksu8p?= =?us-ascii?q?Mizoh2WeGdxcq6bBSN2/xhgRfzUJnB7Loc0qyK6/umATRIyK3CmUhKSIZLWR?= =?us-ascii?q?4BhJdetC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBx?= =?us-ascii?q?rwKxd+KPjrFY7OlcS30P2594HObwlSizexfb1/IA+qoQnNq8IbnZZsJqEtxx?= =?us-ascii?q?XTv3BGYf5WxWRmJVKSmxbz+MK994N9/ipTpvws6ddOXb31cKokQ7NYCi8mM3?= =?us-ascii?q?0u683wqRbDVwqP6WACXWgQjxFFHhLK7BD+Xpf2ryv6qu9w0zSUMMHqUbw5Xy?= =?us-ascii?q?mp4KlxSB/slSwJKTg3/m/KgcB0la5XvQ6tqxl5zoXJYo+aKeB+c7vdc90EWG?= =?us-ascii?q?RPUMVfWStaD4+gc4cCFfYNMPxEo4XhoVYFsBuwBROrBOPq0jJGmn720rE60+?= =?us-ascii?q?s7CwHJwRErEdAUv3TVqtX6KrwSWv2rzKnJ1zrIcu5Y1in56IjJdBAhvP6NVq?= =?us-ascii?q?93fMrK10YvEwLFjlONqY3qJD6VyuQMvHSb7+pnT+6vjXUnpBtrrjigwccslJ?= =?us-ascii?q?DEi4QIwV7K8iV5xZw6Jdy+SENjfd6lH51QuzuHOIRsXsMtWWdlszs5xL0eoZ?= =?us-ascii?q?O3YScHxZs9yxPfdvCLaZaE7x39WOqLPDt0nHFodbOlixqv/0WtxffwW8m63V?= =?us-ascii?q?pQsyZIltrBu3YQ3BLJ8MeHUOFy/kK51DaK0ADc9/9LLFgvlareN54h2rkwlo?= =?us-ascii?q?cPsUjbHi/5hkH2jKiOe0U44Oeo8eXnYqj9ppOGK491ih3xMqQpmsClB+Q3Lh?= =?us-ascii?q?MOUHSB9eS51b3j+VX1QLRMjvIojqnUqI3WKMsUq6KjAwJZz5wv5wiwAju4yt?= =?us-ascii?q?gUgGELLFdfdxKGi4jpNUvOIPf9DfqnmFSjjjNrx/HAPr38DZTBN2PMkLD8fb?= =?us-ascii?q?Z790FT1hEzwMtD55NUFr4BIPXzVlX3tNzDFBA1KQO0w+H5CNllzIMRRXqPAr?= =?us-ascii?q?OFMKPVqVKI5OUvI++Wa48JuDbyMf4l6uXsjX8+n18deLOm3YALaH+mBPRmOF?= =?us-ascii?q?+VYX32gtcOCW0KpBYxTPT2iF2eVj5ef3SyX6Am6T4nC4KmFoDDRoasgLyfxy?= =?us-ascii?q?q7EJlWZn1JC1+XDHfocZmEW+oWZCKVOM9hnSQOVaK9RI85yRGuqAj6xqJpL+?= =?us-ascii?q?rV/i0YsIzs1MJu6u3dix496Dt0D96H3GGVVWF0mWEISCEq06Bju0B9zU2D0a?= =?us-ascii?q?dgifxCCdNT/+9JUhs9NZPE0uN1F9XyWgXHfteVVVqrWcumDi8rTtIwwt4OZE?= =?us-ascii?q?B9F8+kjh/dwyqgG6UVmKCTBJwo7qLc2GD8KNthy3nczqkslEUpQsxKNWK6nK?= =?us-ascii?q?F/7BTTC5TPk0qHi6agbb4c0zLV9Gef0WqOu1lVXxBoUarfR3AfZ1DWoM/h5k?= =?us-ascii?q?zYVb+uCK8nMhNFycGYNqRFdMfljVJcRPfsIN7eeX6+m3+sBRaUwbOBdITqe3?= =?us-ascii?q?8H0yXbFEcEkhsT8G2DNQgmByetunneDTJ1FV71ZEPs6+Z+omuhTkAo1wGKc1?= =?us-ascii?q?Fh172t9x4Wn/OcSPQT3q8ftScisTp0H1G938/MB9qHvQphc71WYckh71dfyW?= =?us-ascii?q?LZqwt9M4S6IK9/nF4echp4v1n12hptFopAlNImrHQwzAp9MaiYyk9OdyuE3Z?= =?us-ascii?q?DsPb3aMnPy8w2yZKPN1VHe1dmX9r0J6Psmt1XppBupGVY683V7z9lV1GOR5o?= =?us-ascii?q?7EDAoIVpLxSVo3+gNhp7HcZSk86YbU2mdqMaWutD/Nxc4pDvM/yhm8Z9dfLL?= =?us-ascii?q?+EFAjqHswUHceuLPAqlEazbhIfJ+1S6rA7P9m9ePub3a6nJuFgnCipjW5f+o?= =?us-ascii?q?ByzlqM9zZgSu7Px5sFxfCY3g+DVzjil1esqdr4lp5eZTEVBGa/zjLkBIFJbK?= =?us-ascii?q?1oYYkLEXuuI9GwxthmmZ7tWmJX9EKkB1McwsOmZRqSb1v73Q1fzkkXpX2nmS?= =?us-ascii?q?2iwDxulDEltK2f3DbBw+76bhoIJnZLRHV+jVfrOYW0i9EaXFO0bwQwjxuq+0?= =?us-ascii?q?L6x6ldpKRiIGjeWlxIfzD3L2FkU6u/qqGCb9RJ6Jw2rSVdSP68bkyCSr7hvx?= =?us-ascii?q?sa1DvuH3FZxDA/czGlpI/5kAB9iGOTN3tzt2fZdt1rxRvF49zcX/FR1CIcRC?= =?us-ascii?q?ZkkTnXGkS8P96x8NWXiZjDtPu+WnmiVpJNdynr1oWAuzWn5WFwBh2/hf+zkM?= =?us-ascii?q?X9EQcmyS/7y8VqVSLQoRbkeIbryqC6Pvx/fkZyAl/899R1Gptln4stn5Efx2?= =?us-ascii?q?Iaho6P8XoclmfzLM9b1r7gY3oDQj4L2dHV7xb/1E1lMH2J25rzVm+Bzct5e9?= =?us-ascii?q?m6fmQW1zoj78BMFaiZ96JEnS1orVq4tw7RZ+ZynisFw/s09HEam/0JuBYqzi?= =?us-ascii?q?iFGrAdB1RYPSj3mhuU7tC+sKVWaH+hcbeq0kpyh9ehDKuNogtEQnb2Zo8iHT?= =?us-ascii?q?Ns7sV4KF/M3mf86of4eNnXaNIerROUnAndgOhSMpI+jOIKhTBgOWL/o3Iq1/?= =?us-ascii?q?I7gQZp3ZGgs4iNM39t876hAh5EKj31YNse+jT3gqZamsaZwZyvHol7FToRR5?= =?us-ascii?q?boS+ynEC4Jtfv7LQmOCCMzpm2dGbXBAQ+V8F1moG7XE5C3K3GXI2EUzdt4RB?= =?us-ascii?q?aDOUNfmxobXDMmnp4+DQCn39buf1t85jwL4V74sBRMwPpyNxbjSmffuBuoaj?= =?us-ascii?q?AsRZiZNhpZ9BlC51/OPMyQ7+JzBTpY/oGvrAyMLGyUfQJIAn0IWkOeA1DvJL?= =?us-ascii?q?6u5cPP8+KAHOqxM+POYamSqexZT/qI3Yyg3ZB48DaKN8WPIn5iAuY62kVdQ3?= =?us-ascii?q?92Bd7VmzIVSywYjyjNddKUpA+g+i1rqcCy6O/kVxno6YuLCrtSKslv+wusja?= =?us-ascii?q?eYKeGfmDx1KS1G2ZMIxH/IzqUf3VEJhi5ydzitC6kAtTXXQKPegKBXEwUbay?= =?us-ascii?q?R1NMdS6KI8xAZNM9bBitzpzr54kuI1C1BdWFP6m8GpassKI2emOVzaGkmEL7?= =?us-ascii?q?WGKifNw83tZqO8U7JQhv1OtxKsoTabD1PjPjObmjbzWBCgK/9Mgz+AMRxZoI?= =?us-ascii?q?GybBBtCW35Q9Lnbh20K9h3jDIszb0znHPKOnYWMSJgfENVsr2Q8SRYj+1jG2?= =?us-ascii?q?xG63ppN/OEmyGY7ubGLJYZquFrAiNqmOJZ+3k117xV7CRYS/NvgyvSssRio1?= =?us-ascii?q?e4nemT0jBnSgZBqi5XhIKXukVvIafZ9plAWHbc+xIN6WSQCwgUqNZ+D93vur?= =?us-ascii?q?xQysLRm67pLzdC6d3U99MGB8fIMMKHLGYhMR3xFT7XDAoFSSCkOHrah0xanv?= =?us-ascii?q?GS+GOaroQmqpjsn5oOT6FUWEYzFvwEFkRvBMYCL4tvXjM4jb6bi9YF5Xygox?= =?us-ascii?q?bLQMVXpZPHVvWJAfXzMjmZi6JEZxgJwb/iK4QcKJH70VR4alZmhITKB1bQXd?= =?us-ascii?q?dVry17cAA0u1tC/2JkTmIv20LocRii4H4JFfGpmR42hBN+Yf4z+zbs+Vs3IE?= =?us-ascii?q?TFpDcomkkrhdrlmSyRcCL2LKqoQI5WDCz0t04sPZzlRwZ1bBa/klZ6OzfeQL?= =?us-ascii?q?JdlbxgdXpkiAXEo5tABeZcTbFYYB8X3fyYeu8n0Updqiq63k9K/vHKCYF4lA?= =?us-ascii?q?stf5+stGxP1B5+bN4vJKzQOKpIwkJWhq2Qoi+izvoxzxMGJ0YR7GOSfzYFuE?= =?us-ascii?q?gPNrk8OSWo+O1t6QuZljtMfmgMSuAmovVw9kMyI+6A1T7v06ZfKkCtMOySN7?= =?us-ascii?q?iZtHbElc6JRFMwy0wJmlJZ8rhx1Mcsb1CbV1szzLeLERQGK9bCIxlPb8VO7H?= =?us-ascii?q?jTYTqOseLVzJJpPoW9E+foTfOOtKcUmU+rAQcpHoQW4csaBJWs1l/XLdv/Jr?= =?us-ascii?q?4f1Rot/BjrJEmCDPlRYh2LlDYHrN2hw5Bv2IlcJjcdAWJ7MSqt/bvYvQ4qj+?= =?us-ascii?q?CFXNsvbHcaQ5EINnQoV82mgyRZpWhPDCGr0uIFzwiP9yTzqTrWDDTnddVsee?= =?us-ascii?q?mUag12CNGt4zo/6ai3hUTQ8pXEKGHwLc5itcPX6eMGu5aHDOtZTbZgs0fdn4?= =?us-ascii?q?lYQ2KlU2vUHNGoOZf/cIgsYsbyCnqgVVy/kT01Rd/rPNmxNqiInR3oRYFMvY?= =?us-ascii?q?mB2jAjNNOyFjEZGxd0vOEN/LtyaxAZbZcnZhDlrBgxN6u6IAiEyNquWHqtJS?= =?us-ascii?q?FQT/ZB0eWwf6ZXwDY0bu+m1HsgSYk3z/Ot/k4XQ5EFlQrTxeq5Z4ZETyj8BH?= =?us-ascii?q?hdewTJpSo2k2hhN+kywucjwBPGq1YcKTWLePZvaGNao9E2HUmSLmluCmokW1?= =?us-ascii?q?+cipLO4wC2078O/ytdntNU0exfv3j9pZLfYSyjV7K1ppnPtCogd9cmqbVrMY?= =?us-ascii?q?P/OsuGqI/enjvHQZnVqAKFSi26GORGmthRJiJYT+JFmG8/NswApYVB7U0xVt?= =?us-ascii?q?ojKLxUEqUsoK6laSZ8By4I0SAZT5+A3CAFguqkwbTajAqQcJI4PBwHq5hCg9?= =?us-ascii?q?odUy9qYiwFvqOjUZvZl3OcQGgRPAgT9RhM5B4HloJof+Dl5pbIQ4FIyzFIpv?= =?us-ascii?q?J7TDfLFoNo9lbgTWGWmUb3SPOkk+Oz3AJSyOnj0t4UWRJlDkhd3elWnFMyKL?= =?us-ascii?q?5rM6kQopLKsjiQeEPmu2LtzfCrJEVNxc3RbFL0FozFunTgUicE430bWZdPyG?= =?us-ascii?q?3DFZQViwd5aLwkpE9WL4CiZ0nz/CEryJpxH7mgS8+rw0gqrWwcSyetCdpBBP?= =?us-ascii?q?lssEjLVz19f5CrtJLlNo1QQm9X5pKQsEpWn1t2MyGn05pcN99C7SMWUDhJvz?= =?us-ascii?q?qdoMO4SNdf1s9uE58MPtB/tm/hGKxZJZeRomc5urj0x3DF/DA8tUu1yy+oG6?= =?us-ascii?q?+kVe5Z+XMRGhkxLWSEtkYvF/cs8nvV8l3VqV908ftUCqSNgElsrjtwBYxBBj?= =?us-ascii?q?FM1X+5NVtzV2VGv/9cKKvLb8xWW+MyagO3OxwiCf4m2FSE/VtqknjkYyx9rB?= =?us-ascii?q?da9jvZXwkzSykanKnhliEZqs66JzAWUZRIYis9by3dMQKUhThXvApDa0FtQ5?= =?us-ascii?q?0ZGs1F+60B0oRJ4srPUl2sKSYYXBx4Kg03z/xflVJZsEqCfSDRFw2odezAsh?= =?us-ascii?q?dvZ8eesNapLOjl/AdAko7nrPo4+LsdSHK7ggCtXNTer5PmttKQqEuOdaD4M+?= =?us-ascii?q?mibn/dVjTMigqwhbg8BZnQ4yfTKBZbK4V9yXc8Y5juE3TLPRNdJ6IfPUVbS7?= =?us-ascii?q?t3adBbouBee89keboG+a53CRKBXRPjAouvrONJLlzLXzTRMz2B8vCjoYLU9b?= =?us-ascii?q?HdS/LvZsqCx3bdRKJ4I4l15CLnG7jw149e4U321u1r9kxkVVjMKzqBo8j5Jg?= =?us-ascii?q?MX+MmicVPvvpstHT7NAZdwln/tyltBd8oRTS2q6o4XyIhF6HbqVOJ3zlTzsP?= =?us-ascii?q?BI97Z684U35KppycisL6fINftaqVNnAgSTBghy8JUtAXRwR2dVYuALM/fdZ6?= =?us-ascii?q?UZjcfpq+DsDKwa8xiV9uNWaNfdIEHBgMa/ACmGSRNYhAcBtSIaLgyE2vGZga?= =?us-ascii?q?B0TdiqpfPl2kMt5FizNQUGw6xs5Yia/KqIuO7XYAHLwbgCRKfqWtv5rq4wtE?= =?us-ascii?q?OK+f0kiLkOd3RxYw28FegQVtUQxmn+wq83yiIsCdnMH6r6+P5EVXI2gC7vm4?= =?us-ascii?q?xnE1URAPMUEqKB/Z5CkWcgh+zZKtoWf7hAmmaOEB6pCboCxmCr6iSJOmllgx?= =?us-ascii?q?fO0x7qTWO18lD2sTdyQTHQwNf7jkpVSr63CF9TXyuoI0B3qi+AMRHztNXppa?= =?us-ascii?q?Q68l05PnbjtNKXm2urIKlXENHnJNyAPSk0o0oag4YwRty014EUA9i9INYN8H?= =?us-ascii?q?FmdPTe9mernjRdrKdAmoXR/Nua+ujNHXmnla2Vsa+BxDdCyng3pVs/8MyvNu?= =?us-ascii?q?nS592WRPSlz34RQD1juwTdXx60pLvbr0oXOUCSy0fEhogKPtBf3Xkl2UDr//?= =?us-ascii?q?AjT8gv9ApCFobBafQCpSrwODfuwlaQfcg3Vi+A3DtTBF71FkN4GKck0mLqoM?= =?us-ascii?q?3JjWvQ+0EvRoRoeEzonwZ3AJskKUIt81UXxisDERQTZhCbFr6oGF/lIZECVU?= =?us-ascii?q?cddRSNxKK6dbsv3U1v3rOv4/febeNiCKoLKvZdiQmOkF9AGp0Ita0eQbR8e0?= =?us-ascii?q?JS9aPMogjtFZLnXvj8mnYqM/26XNxa+9gDt3Q++ga/Wwag6ZBb4rkHipCHbL?= =?us-ascii?q?JLbIPQs8B760dn4T8PeTJXgBhjkRy2TeAcqPrk4tjBv5qi8vyuW7o1R+UL6x?= =?us-ascii?q?g0AHxzj573gFAlvdHX2PlTR5bQiYT+6g9NJWCFuJrU0hl7M+oOKJmrcKxm93?= =?us-ascii?q?oZOygUP2gOMsaOa/kg/y9tNy3e51NeDcMXftMUJdfDlw9ShE3oXrFT68XaF0?= =?us-ascii?q?SXC4d2bc8o6XT4xCoy8ZsmXebq8CW2KozH71FRI/NDiz1hlNDFpOgVx/reEj?= =?us-ascii?q?QY4Xmdaxho3yyDypiNC/Dr/eWPydHZTE0GHi8oU4hHIDqN5A2nSvCzlJr3Tg?= =?us-ascii?q?Oe8tXzj44mdEKMWnyxm7wIsqdSEeFajCX2xTxeFp3oiPKUtNqs83FbtlpdEI?= =?us-ascii?q?Z89RfFArlQPo1nORTkkcmmXkp8CTXxeMHachojo+SXyf0K4+pgK0vyf4kbLQ?= =?us-ascii?q?wYy7ji83paUhNuSKLqvlaeRe8Ra99mSPTKr39L7YJgL7QCPEOapJzsrzdHtE?= =?us-ascii?q?o6AAk3Z78stjZabFXBnBVJW6bov74Nkg4cUd96uU9PHmK9I2A+6CDEVaRSiq?= =?us-ascii?q?meFvoV/i+VTqMQT0ViKjl+TA+t2JVyZ7upmuhKvXhYkSN7vPgnyCdmRB+7uS?= =?us-ascii?q?3wu6INxywv96yiuDUGo3xFQf2Ukz3UBlVb0PQKkaAcBm766Vy7ZHkMdpHy4b?= =?us-ascii?q?dgJcTk+4ks+HE/YRIkfy0dQ+uvFzvwj6STAoyUsdJcghGNtN/Jbb+pIigYLq?= =?us-ascii?q?49xg77R3hhzgjemw5l8GUVTTWk7d8kPJuyNN0kxyqpHGjbcUgD4rlNsMTvr1?= =?us-ascii?q?ILS/E2aVx5ymV5zseHXjENRNDIG2stgAkkcX9EcJNf5hAEDKQohzeIvrVc/g?= =?us-ascii?q?4KejvUFZ6l+obIl8fSxXY9Vctqxn7RpqCdgZMq1GNqlshs7i6KonsSbPDYU8?= =?us-ascii?q?5wDXjvzIdQ1/Lxa++rsu8ZVIts0K6hX+MaMsm/5Wu2341nWkukxrQYAlq4P/?= =?us-ascii?q?YPxrPaUye+VW2YQv+Gc2mWkDY/NU7+/x6oLkc4aM1StU8yLvPChoJAlw3mSb?= =?us-ascii?q?50Qz+fqkPbzGwiN+MacBk7uJmmewwMUuERY+mcJe4zwPwxElcMaGXJHSRuAe?= =?us-ascii?q?+srVGthJR7O2ln4UjiY+Ti6APmMNyJFRQfDI7aqIJx+fy9RmKcNn9gzAFyMF?= =?us-ascii?q?Ny9+jBC1Q7rvVcfIqJndjMm9R71vYId/VoMS06oN4TgINj6ZKP3ceMax7Ry4?= =?us-ascii?q?j9JdDPrvifGf3fwFwgentGXboBfQP1+4I6M8YiW73dGLtWoRURCKshTZw/KW?= =?us-ascii?q?jx7qB0LQJ0cg7Xfri0hNflpv6TaptUuXDW6lUwIT/Yux0E1vO7Vwh7b5Cth3?= =?us-ascii?q?XpPJA8XDZBr9pxBRR8GItABsQArw+9DJ6VnqG3k96x+0VktO8Wqaf9CfHH2M?= =?us-ascii?q?6k04h/UJVW/0yGMTjLCKV2hklojfy+gvLa3ZnwDcPid8kEVO9+QmPdbbLGBI?= =?us-ascii?q?S/JS6OOs3mYU5J7qaT365hXRWRfi/5XqyGuzO/NPh/+ko71o14fOzPzDMz9b?= =?us-ascii?q?Hb3sX9Z31Bqii/qn6JMYJS4ETQBePCRxJUVeaF8GF9EKAQd4v09fsBMdw4z9?= =?us-ascii?q?iG/gZ89ChN39OFI6e7r0/M3Fx0dYnAIUTyxyY5WI8KIAihPks2h2/WtGjdDW?= =?us-ascii?q?5AIcijLMlgmc6ZDgbx6ElphWEtemlBF3LvSNeKJGcbwNmzZBGK9Q1XD9YDmP?= =?us-ascii?q?S7eUgjtqKoU+VoNZJFmfuzubkfi9ZmNznPRNRGPyHXNLJ7OSFRAfvLpFgpZB?= =?us-ascii?q?4Errc0V5wpZZmOPEwHMECAxTn0zQvZy0L4bdOs1KGXICsP9HhM0qzI0TxRpw?= =?us-ascii?q?mipfaWnNfjXq3YbJD3QvHfKDYpBXmmQmEpHEKo/0q0k+YVt/qfZ2EEqxYbZT?= =?us-ascii?q?zWQBUfvYhzvNPQCSnVguQlc5oU18qXQyThdCotrqs5Bi9RuQisSvsFGBKeO2?= =?us-ascii?q?Xgi2pVogCVLchM9HPjYqawzLZUXfAbGI1BbruSRN6OKt5EIDJ9rDQSOO+mc5?= =?us-ascii?q?X8prc/30mAU2oQW5LF8FyYUV7eFueRwzPtQJU9o5k/ui1u/MnZ2CBwDfKbbP?= =?us-ascii?q?6kuzey/9vg326jsurEWzxoOhQ4?= X-IPAS-Result: =?us-ascii?q?A2CoAAB+AARb/wHyM5BdGQEBAQEBAQEBAQEBAQcBAQEBA?= =?us-ascii?q?YMYK2J9FROLeV+MGGSCChqTNhQLgVYmAxABhmIhNBgBAgEBAQEBAQIBaxwMg?= =?us-ascii?q?jUkglcCFwEMVQMJAkgIAwFaCQkFgl1AAiiBPwEBARUDAaomM4N0VoN7gg+IN?= =?us-ascii?q?Q6CBYEPgliDBIINAYVqAocrCoRsgSKLDAmFaohigUI+hg+EepIfHDiBUisIA?= =?us-ascii?q?hgIIQ+Baxp5CYIXF3oBB4ZLhktueQEBASiKdiuCGQEB?= Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 22 May 2018 11:39:11 +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 w4MBd8wq024234; Tue, 22 May 2018 07:39:09 -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 w4MBcANg035267 for ; Tue, 22 May 2018 07:38:10 -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 w4MBcDSE024176; Tue, 22 May 2018 07:38:13 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1BGAABVAARblywWGNZdGgEBAQEBAgEBA?= =?us-ascii?q?QEIAQEBAYMYKGV9KIt5X4wYgm4akzYUgWQmEYRAgiIhNBgBAgEBAQEBAQIUAQE?= =?us-ascii?q?BAQEIFgZLhVUBDBkBOAEVgSkJCYMiAiiBPgEDFQMBqiYzgnAFf2SDZgeCAwQIh?= =?us-ascii?q?zl8ghOBD4JYgwSCDQEihUgChysKhGyBIosMCQWFZYhigUI+hg+EepIfHIIKMxo?= =?us-ascii?q?jgxMJggsMDgl6AQeCQ4QIhktueSuKdiuCGQEB?= X-IPAS-Result: =?us-ascii?q?A1BGAABVAARblywWGNZdGgEBAQEBAgEBAQEIAQEBAYMYKGV?= =?us-ascii?q?9KIt5X4wYgm4akzYUgWQmEYRAgiIhNBgBAgEBAQEBAQIUAQEBAQEIFgZLhVUBD?= =?us-ascii?q?BkBOAEVgSkJCYMiAiiBPgEDFQMBqiYzgnAFf2SDZgeCAwQIhzl8ghOBD4JYgwS?= =?us-ascii?q?CDQEihUgChysKhGyBIosMCQWFZYhigUI+hg+EepIfHIIKMxojgxMJggsMDgl6A?= =?us-ascii?q?QeCQ4QIhktueSuKdiuCGQEB?= X-IronPort-AV: E=Sophos;i="5.49,430,1520913600"; d="scan'208";a="282292" Received: from emsm-gh1-uea10.ncsc.mil ([214.29.60.34]) by goalie.tycho.ncsc.mil with ESMTP; 22 May 2018 07:38:12 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3ASENw9x/jKKjbE/9uRHKM819IXTAuvvDOBiVQ1K?= =?us-ascii?q?B+0eITIJqq85mqBkHD//Il1AaPAd2Araocw8Pt8InYEVQa5piAtH1QOLdtbD?= =?us-ascii?q?Qizfssogo7HcSeAlf6JvO5JwYzHcBFSUM3tyrjaRsdF8nxfUDdrWOv5jAOBB?= =?us-ascii?q?r/KRB1JuPoEYLOksi7ze+/94HdbglSmDaxfa55IQmrownWqsQYm5ZpJLwryh?= =?us-ascii?q?vOrHtIeuBWyn1tKFmOgRvy5dq+8YB6/ShItP0v68BPUaPhf6QlVrNYFygpM3?= =?us-ascii?q?o05MLwqxbOSxaE62YGXWUXlhpIBBXF7A3/U5zsvCb2qvZx1S+HNsDwULs6Wy?= =?us-ascii?q?mt771zRRHolikJKjA3/mLQhMFrkK5XvAisqwBlzoLIfI2YMud1cKPHfdMdQG?= =?us-ascii?q?pMRtpfVy1dDYO8dYQPFfcONvtaoYbnplsOqwWxBRKxD+7o0D9Ih2P53a0g3O?= =?us-ascii?q?Q7DA7JxBAvEMoOsHvOrdX1MrkdUfuuwabT0TXDbvVW2Svj54jSdBAuv+2MUa?= =?us-ascii?q?hsfsrWzEkiDgXIhUiep4ziOjOazOUNs26D4up8WuOvjXQrpBxrrTiz3MghjJ?= =?us-ascii?q?TCiIENyl3c6yl13Yk4KcemREN0e9KoDoVcuzuVOoZ5Ws8vQGBltDwnxrAItp?= =?us-ascii?q?O3ZigHxZo9yxLCb/GKcI6F6Q/5WumLOzd3nndldaq/hxms9UigzfXxWcep3l?= =?us-ascii?q?tWsCRInMfBuGoR2hDP68WLUOVy8Vmk2TaU2ADf8ORELlo1larfMZIhx78wlp?= =?us-ascii?q?4LvUTCGC/5hln2gbeIekk59eWk8frrb7r8qpOCKYN4kA7zP6s2lsy6G+s4Mw?= =?us-ascii?q?wOX2aB+eS70b3u5Vf5QLRWgf02iKbZqo3VKtwHqaGhAw9ayIcj6xChADe9y9?= =?us-ascii?q?kXhmUHLFNDeBKbkYfpIVfOL+7kDfuln1uslzJry+jcPrL9GpXNMmTDkLD5cL?= =?us-ascii?q?Zm9kFc0xE+zcxf5p1ICrEBJ+j/WknqtNPCFBM5PAu0w/j/AtVnyoweQX6PAr?= =?us-ascii?q?OeMK7Kql+H+OYvI+iKZI8ItzfwMOQl5v7ygn85nl8RZ6+p3YANZ3yiEfRmJF?= =?us-ascii?q?uZbWLsgtgfFWcKuRIzTOjtiFKeSzFTY3ayX6Un5jEnEo6mCYDDSZy3j7yFwS?= =?us-ascii?q?i7GZhWaXpHClCKCXvodoOEVOkQaC+KIcJskyYIWaWvRoIuzx2jtAH3x6B6Iu?= =?us-ascii?q?fQ+SAUrZfj28J05+3XmxEy7zt0D8GF3myKVWF0n38HRz8s06BlvENy0kuM3r?= =?us-ascii?q?B4g/NCFNxT4e1GUhwhOJHH0+x6CtbyWh7fcdeTTlapXMmmDSstQdI2xt8Del?= =?us-ascii?q?5xG8++gRDbwyqqH7gVmqSMCZwu86LTw3jxKNxny3nbzKYuk0EpQstVOm2ngK?= =?us-ascii?q?5w6RPTCpXSnEWFlqaqc7gc0zDX9GeF02WOoFtUXxJ3UaXARH0TflHWosjh5k?= =?us-ascii?q?PeU7+uDqwqPwxaycGfMatHccHpjFVaS/fjP9TSeWSxm3yqChqSybOMa5Tqdn?= =?us-ascii?q?wF0CXHFEcEixwT/WqBNQUmASqhuHzRDDhvFVLpfkPt/vJzqG+7T0AozwGKaF?= =?us-ascii?q?dt17yu+hEPn/CcRPQT3qwdtSontj55AlK938/NC9qcuQVhZrhSYdI84VhZzW?= =?us-ascii?q?/Vq181Apv1NK1mh1gDYyxrrkju0FNxEYwGns806DsxwBFaNbOT0FQHcSiRm5?= =?us-ascii?q?/3JO75MG73qSquYK7fwF2W8N+X/KoUoKAiql7jtRulIUEV83xm1dRO+3GA55?= =?us-ascii?q?PWARAUXI63WUEyoUsp74rGazUwstuHnUZnNrO552eYgYAgGfclxxC8ftxWLK?= =?us-ascii?q?KDEkroHtYHA9S1eLZ4pniISkkvBMkLreg5Msa9eL2D0a+veuNhmGHugWdG5d?= =?us-ascii?q?Vl31iJ+jBmTfSAn5UI0rmE2QzPTDL1iFPg+sD6kIxJf3cTS0K11SniGINLYK?= =?us-ascii?q?BuO40MDGo=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0BGAAB+AARblywWGNZdGgEBAQEBAgE?= =?us-ascii?q?BAQEIAQEBAYMYKGV9KIt5X4wYgm4akzYUgWQmEYRAgiIhNBgBAgEBAQEBAQI?= =?us-ascii?q?BEwEBAQEBCBYGSwyCNSKCcgEMGQE4ARWBKQkJgyICKIE+AQMVAwGqJjOCcAV?= =?us-ascii?q?/ZINmB4IDBAiHOXyCE4EPgliDBIINASKFSAKHKwqEbIEiiwwJBYVliGKBQj6?= =?us-ascii?q?GD4R6kh8cggozGiODEwmCCwwOCXoBB4JDhAiGS255K4p2K4IZAQE?= X-IPAS-Result: =?us-ascii?q?A0BGAAB+AARblywWGNZdGgEBAQEBAgEBAQEIAQEBAYMYK?= =?us-ascii?q?GV9KIt5X4wYgm4akzYUgWQmEYRAgiIhNBgBAgEBAQEBAQIBEwEBAQEBCBYGS?= =?us-ascii?q?wyCNSKCcgEMGQE4ARWBKQkJgyICKIE+AQMVAwGqJjOCcAV/ZINmB4IDBAiHO?= =?us-ascii?q?XyCE4EPgliDBIINASKFSAKHKwqEbIEiiwwJBYVliGKBQj6GD4R6kh8cggozG?= =?us-ascii?q?iODEwmCCwwOCXoBB4JDhAiGS255K4p2K4IZAQE?= X-IronPort-AV: E=Sophos;i="5.49,430,1520899200"; d="scan'208";a="12032448" X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown Received: from usat3cpa06.eemsg.mail.mil ([214.24.22.44]) by EMSM-GH1-UEA10.NCSC.MIL with ESMTP; 22 May 2018 11:38:10 +0000 X-EEMSG-check-005: 0 X-EEMSG-check-006: 000-001;644e8c28-08dc-4a41-98bb-8c61e33fedb9 X-EEMSG-check-008: 34265312|UHIL3CPA11_EEMSG_MP27.csd.disa.mil X-EEMSG-SBRS: 3.5 X-EEMSG-ORIG-IP: 65.20.0.122 X-EEMSG-check-002: true X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0ApAAAg/wNbh3oAFEFdGQEBAQEBAQEBAQEBAQcBAQEBAYMYgQ19KIt5X48GGpM2FIFkEBYRhECCQzQYAQIBAQEBAQECFAEBAQoLCQgoIwyFSQEMGQE4ARWBKQkJgyICKIE+AQMVBKomM4JwBX9kg2YHggMECIc5gw+BD4JYgwSCDQEihUgChysKhGyBIosMCQWFZYhigUI+hg+EepIfHIIKMxojgxMJggsMDgl6AQeCQ4QIhktueSuKdiuCGQEB X-IPAS-Result: A0ApAAAg/wNbh3oAFEFdGQEBAQEBAQEBAQEBAQcBAQEBAYMYgQ19KIt5X48GGpM2FIFkEBYRhECCQzQYAQIBAQEBAQECFAEBAQoLCQgoIwyFSQEMGQE4ARWBKQkJgyICKIE+AQMVBKomM4JwBX9kg2YHggMECIc5gw+BD4JYgwSCDQEihUgChysKhGyBIosMCQWFZYhigUI+hg+EepIfHIIKMxojgxMJggsMDgl6AQeCQ4QIhktueSuKdiuCGQEB Received: from rgout0102.bt.lon5.cpcloud.co.uk (HELO rgout01.bt.lon5.cpcloud.co.uk) ([65.20.0.122]) by UHIL3CPA11.eemsg.mail.mil with ESMTP; 22 May 2018 11:38:00 +0000 X-OWM-Source-IP: 86.134.53.198 (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: gggruggvucftvghtrhhoucdtuddrgedthedrgedugdegfecutefuodetggdotefrodftvfcurfhrohhfihhlvgemuceutffkvffkuffjvffgnffgvefqofdpqfgfvfenuceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofestddtredtredttdenucfhrhhomheptfhitghhrghrugcujfgrihhnvghsuceorhhitghhrghruggptggphhgrihhnvghssegsthhinhhtvghrnhgvthdrtghomheqnecuffhomhgrihhnpehtgihnrdgurghtrgenucfkphepkeeirddufeegrdehfedrudelkeenucfrrghrrghmpehhvghloheplhhotggrlhhhohhsthdrlhhotggrlhguohhmrghinhdpihhnvghtpeekiedrudefgedrheefrdduleekpdhmrghilhhfrhhomhepoehrihgthhgrrhgupggtpghhrghinhgvshessghtihhnthgvrhhnvghtrdgtohhmqedprhgtphhtthhopeeorhhitghhrghruggptggphhgrihhnvghssegsthhinhhtvghrnhgvthdrtghomheqpdhrtghpthhtohepoehsughssehthigthhhordhnshgrrdhgohhvqedprhgtphhtthhopeeoshgvlhhinhhugiesthihtghhohdrnhhsrgdrghhovheqnecuvehluhhsthgvrhfuihiivgeptd Received: from localhost.localdomain (86.134.53.198) by rgout01.bt.lon5.cpcloud.co.uk (9.0.019.26-1) (authenticated as richard_c_haines@btinternet.com) id 5AFAEA6F009A6131; Tue, 22 May 2018 12:37:58 +0100 X-EEMSG-check-009: 444-444 To: selinux@tycho.nsa.gov, sds@tycho.nsa.gov Date: Tue, 22 May 2018 12:37:52 +0100 Message-Id: <20180522113752.11936-1-richard_c_haines@btinternet.com> X-Mailer: git-send-email 2.17.0 Subject: [RFC V4 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 Acked-by: Stephen Smalley --- README.md | 8 + defconfig | 7 + policy/Makefile | 4 + policy/test_binder.te | 120 +++++++ tests/Makefile | 5 + tests/binder/Makefile | 7 + tests/binder/check_binder.c | 80 +++++ tests/binder/test | 89 +++++ tests/binder/test_binder.c | 684 ++++++++++++++++++++++++++++++++++++ 9 files changed, 1004 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..7082661 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,3 +1,4 @@ +INCLUDEDIR ?= /usr/include POLDEV ?= /usr/share/selinux/devel export CFLAGS+=-g -O0 -Wall -D_GNU_SOURCE @@ -30,6 +31,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 && test -e $(INCLUDEDIR)/linux/android/binder.h && 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..9e6c2bd --- /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 2 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 2 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..0d10a58 --- /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 { + uint32_t cmd; + struct binder_transaction_data txn; + } __attribute__((packed)) writebuf; + unsigned int readbuf[32]; + + 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.cmd = BC_TRANSACTION; + memcpy(&writebuf.txn.target.handle, shm_base, sizeof(uint32_t)); + + writebuf.txn.cookie = 0; + writebuf.txn.code = 0; + writebuf.txn.flags = TF_ONE_WAY; + + writebuf.txn.data_size = 0; + writebuf.txn.data.ptr.buffer = (uintptr_t)NULL; + writebuf.txn.data.ptr.offsets = (uintptr_t)NULL; + writebuf.txn.offsets_size = 0; + + memset(&bwr, 0, sizeof(bwr)); + bwr.write_size = sizeof(writebuf); + bwr.write_consumed = 0; + bwr.write_buffer = (uintptr_t)&writebuf; + 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 = 1024 * 8; + struct binder_write_read bwr; + struct flat_binder_object obj; + struct { + uint32_t cmd; + struct binder_transaction_data txn; + } __attribute__((packed)) writebuf; + unsigned int readbuf[32]; + + 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.cmd = BC_TRANSACTION; + writebuf.txn.target.handle = TEST_SERVICE_MANAGER_HANDLE; + writebuf.txn.cookie = 0; + writebuf.txn.code = ADD_TEST_SERVICE; + writebuf.txn.flags = TF_ACCEPT_FDS; + + obj.hdr.type = BINDER_TYPE_BINDER; + obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; + obj.binder = (uintptr_t)NULL; + obj.cookie = 0; + + writebuf.txn.data_size = sizeof(struct flat_binder_object); + writebuf.txn.offsets_size = sizeof(binder_size_t); + + writebuf.txn.data.ptr.buffer = (uintptr_t)&obj; + writebuf.txn.data.ptr.offsets = (uintptr_t)&obj + + sizeof(struct flat_binder_object); + + bwr.write_buffer = (uintptr_t)&writebuf; + bwr.write_size = sizeof(writebuf); + bwr.write_consumed = 0; + + 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, + "xxService 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; +}