1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* Copyright 2008 The Android Open Source Project
2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */
3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <errno.h>
5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <fcntl.h>
6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <inttypes.h>
7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <stdio.h>
8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <stdlib.h>
9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <string.h>
10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <cutils/multiuser.h>
12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <private/android_filesystem_config.h>
14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <selinux/android.h>
16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <selinux/avc.h>
17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "binder.h"
19d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#ifdef VENDORSERVICEMANAGER
21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#define LOG_TAG "VendorServiceManager"
22766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu#else
23afc221499d943386256feb9db46c119ff834bf79Yuqian Li#define LOG_TAG "ServiceManager"
24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#endif
25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <log/log.h>
26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikstruct audit_data {
28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    pid_t pid;
29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    uid_t uid;
30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    const char *name;
316f485569fa3d6047dcffd068aebf361e3598783cDerek Sollenberger};
32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikconst char *str8(const uint16_t *x, size_t x_len)
34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik{
35003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    static char buf[128];
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    size_t max = 127;
37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    char *p = buf;
38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
39c0e7a90f1f5f98e85dbeda021fac0dff79725933Stan Iliev    if (x_len < max) {
40003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        max = x_len;
41b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
42003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik
43b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (x) {
44e4db79de127cfe961195f52907af8451026eaa20Chris Craik        while ((max > 0) && (*x != '\0')) {
45b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *p++ = *x++;
46161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik            max--;
47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
48b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
49003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    *p++ = 0;
50b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    return buf;
51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
52b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
53b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint str16eq(const uint16_t *a, const char *b)
54003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik{
55003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    while (*a && *b)
56b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (*a++ != *b++) return 0;
57003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    if (*a || *b)
58b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return 0;
59b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return 1;
60d645640180c25c2711e99aa82ec629155f8e91baChris Craik}
61d645640180c25c2711e99aa82ec629155f8e91baChris Craik
62d645640180c25c2711e99aa82ec629155f8e91baChris Craikstatic char *service_manager_context;
63d645640180c25c2711e99aa82ec629155f8e91baChris Craikstatic struct selabel_handle* sehandle;
64d645640180c25c2711e99aa82ec629155f8e91baChris Craik
65d645640180c25c2711e99aa82ec629155f8e91baChris Craikstatic bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
66d645640180c25c2711e99aa82ec629155f8e91baChris Craik{
67d645640180c25c2711e99aa82ec629155f8e91baChris Craik    char *sctx = NULL;
68d645640180c25c2711e99aa82ec629155f8e91baChris Craik    const char *class = "service_manager";
69d645640180c25c2711e99aa82ec629155f8e91baChris Craik    bool allowed;
70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    struct audit_data ad;
71003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik
72b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (getpidcon(spid, &sctx) < 0) {
73b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
74b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return false;
75b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
76b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
77b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ad.pid = spid;
78b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ad.uid = uid;
79b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ad.name = name;
80b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
81b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
82b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    allowed = (result == 0);
83b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
84b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    freecon(sctx);
85b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return allowed;
86b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
87b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikstatic bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik{
906fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
936fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikstatic bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik{
956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    bool allowed;
967df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    char *tctx = NULL;
97b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
987df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    if (!sehandle) {
996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
1006fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        abort();
1016fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return false;
106eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    }
107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    allowed = check_mac_perms(spid, uid, tctx, perm, name);
109b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    freecon(tctx);
110b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return allowed;
111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
112b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
113b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikstatic int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
114b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik{
115b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    const char *perm = "add";
116b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
117b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (multiuser_get_app_id(uid) >= AID_APP) {
118b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return 0; /* Don't allow apps to register services */
119eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    }
1206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
121eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
122eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita}
1236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikstatic int svc_can_list(pid_t spid, uid_t uid)
1256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik{
1266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    const char *perm = "list";
1276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
1286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
1296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
130e4f6d968f51ba3bb867e8e124dca97b7e9c3fea5Chris Craikstatic int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
131e4f6d968f51ba3bb867e8e124dca97b7e9c3fea5Chris Craik{
1326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    const char *perm = "find";
1336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
134b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikstruct svcinfo
137b87eadda1818034ce03d85f30388384d1ac65916Chris Craik{
138b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    struct svcinfo *next;
139b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    uint32_t handle;
140b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    struct binder_death death;
141b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    int allow_isolated;
142b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    size_t len;
143eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    uint16_t name[0];
144b87eadda1818034ce03d85f30388384d1ac65916Chris Craik};
1456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikstruct svcinfo *svclist = NULL;
1476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
148b87eadda1818034ce03d85f30388384d1ac65916Chris Craikstruct svcinfo *find_svc(const uint16_t *s16, size_t len)
1496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik{
1506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    struct svcinfo *si;
1516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1523c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    for (si = svclist; si; si = si->next) {
1533c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        if ((len == si->len) &&
1543c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
1553c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik            return si;
1563c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        }
1573c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    }
1583c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    return NULL;
1596fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
1606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid svcinfo_death(struct binder_state *bs, void *ptr)
1626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik{
163b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    struct svcinfo *si = (struct svcinfo* ) ptr;
1643c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
165b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    ALOGI("service '%s' died\n", str8(si->name, si->len));
1663c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    if (si->handle) {
1673c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        binder_release(bs, si->handle);
1683c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        si->handle = 0;
1693c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    }
1703c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik}
1713c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
1723c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craikuint16_t svcmgr_id[] = {
1733c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    'a','n','d','r','o','i','d','.','o','s','.',
1743c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
1753c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik};
1763c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
1773c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
1783c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craikuint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
1793c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik{
1803c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    struct svcinfo *si = find_svc(s, len);
1813c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
1823c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    if (!si || !si->handle) {
1833c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        return 0;
1843c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    }
1853c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
1863c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    if (!si->allow_isolated) {
1873c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        // If this service doesn't allow access from isolated processes,
1883c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        // then check the uid to see if it is isolated.
1893c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        uid_t appid = uid % AID_USER;
1903c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
191b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            return 0;
1926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
1936fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1943c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik
195b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    if (!svc_can_find(s, len, spid, uid)) {
1963c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik        return 0;
1973c53ec51efd4bbc3f06cc63dd8efe186e3fb168fChris Craik    }
198b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
1996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    return si->handle;
200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint do_add_service(struct binder_state *bs,
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   const uint16_t *s, size_t len,
204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   uint32_t handle, uid_t uid, int allow_isolated,
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   pid_t spid)
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik{
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    struct svcinfo *si;
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!handle || (len == 0) || (len > 127))
213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return -1;
214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!svc_can_register(s, len, spid, uid)) {
216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik             str8(s, len), handle, uid);
218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return -1;
219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    si = find_svc(s, len);
222b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (si) {
223b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (si->handle) {
224b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
225b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                 str8(s, len), handle, uid);
226b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            svcinfo_death(bs, si);
227e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik        }
228b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si->handle = handle;
229b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
230b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
231b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (!si) {
232b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
233b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                 str8(s, len), handle, uid);
234b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return -1;
235b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si->handle = handle;
2376e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed        si->len = len;
238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si->name[len] = '\0';
2406e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed        si->death.func = (void*) svcinfo_death;
241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si->death.ptr = si;
242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si->allow_isolated = allow_isolated;
2436e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed        si->next = svclist;
244b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        svclist = si;
245b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
246b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
247b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    binder_acquire(bs, handle);
248b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    binder_link_to_death(bs, handle, &si->death);
249b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return 0;
250260ab726486317496bc12a57d599ea96dcde3284Mike Reed}
251a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
252a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craikint svcmgr_handler(struct binder_state *bs,
253a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik                   struct binder_transaction_data *txn,
254a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik                   struct binder_io *msg,
255b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   struct binder_io *reply)
256b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik{
257b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    struct svcinfo *si;
2584c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik    uint16_t *s;
2594c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik    size_t len;
2604c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik    uint32_t handle;
2614c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik    uint32_t strict_policy;
262b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int allow_isolated;
263b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
264386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
265386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
266386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik
267386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
268386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        return -1;
269386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik
270386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    if (txn->code == PING_TRANSACTION)
271386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        return 0;
272b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
273386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    // Equivalent to Parcel::enforceInterface(), reading the RPC
274814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    // header with the strict mode policy mask and the interface name.
275386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    // Note that we ignore the strict_policy and don't propagate it
276386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    // further (since we do no outbound RPCs anyway).
2777df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    strict_policy = bio_get_uint32(msg);
278386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    s = bio_get_string16(msg, &len);
279386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    if (s == NULL) {
280e4db79de127cfe961195f52907af8451026eaa20Chris Craik        return -1;
281386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    }
282b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
283a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    if ((len != (sizeof(svcmgr_id) / 2)) ||
284a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
285814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik        fprintf(stderr,"invalid id %s\n", str8(s, len));
286a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        return -1;
287a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    }
2887df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck
289386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    if (sehandle && selinux_status_updated() > 0) {
290a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
291e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (tmp_sehandle) {
292a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            selabel_close(sehandle);
293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            sehandle = tmp_sehandle;
294a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
295b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
296814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik
297814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    switch(txn->code) {
2987df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    case SVC_MGR_GET_SERVICE:
299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    case SVC_MGR_CHECK_SERVICE:
300b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        s = bio_get_string16(msg, &len);
301e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (s == NULL) {
302b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return -1;
303b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
304b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
305b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (!handle)
306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            break;
307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bio_put_ref(reply, handle);
3087a89600bac7ab889a5ba8a994c57d677de0e45d5Chris Craik        return 0;
309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    case SVC_MGR_ADD_SERVICE:
311b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        s = bio_get_string16(msg, &len);
312b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (s == NULL) {
313b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return -1;
314b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
315b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        handle = bio_get_ref(msg);
316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (do_add_service(bs, s, len, handle, txn->sender_euid,
318b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            allow_isolated, txn->sender_pid))
319b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return -1;
320b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        break;
321b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
322b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    case SVC_MGR_LIST_SERVICES: {
323b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        uint32_t n = bio_get_uint32(msg);
324b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
325b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
326b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
327b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    txn->sender_euid);
328b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return -1;
329b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
330b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        si = svclist;
3317df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck        while ((n-- > 0) && si)
332b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            si = si->next;
333b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (si) {
334e4db79de127cfe961195f52907af8451026eaa20Chris Craik            bio_put_string16(reply, si->name);
335b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return 0;
336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return -1;
338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
339814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    default:
340814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik        ALOGE("unknown code %d\n", txn->code);
341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return -1;
342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    bio_put_uint32(reply, 0);
345b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return 0;
346b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
348b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
349b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikstatic int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
350b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik{
351b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    struct audit_data *ad = (struct audit_data *)data;
352b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
353b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!ad || !ad->name) {
354b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        ALOGE("No service manager audit data");
355b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return 0;
356b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
357b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
358b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
359b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return 0;
360b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
361b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
362b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint main(int argc, char** argv)
363b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik{
364b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    struct binder_state *bs;
365814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    union selinux_callback cb;
366b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    char *driver;
367b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
368814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    if (argc > 1) {
369814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik        driver = argv[1];
3702dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    } else {
3712dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        driver = "/dev/binder";
3722dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    }
3732dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik
3742dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    bs = binder_open(driver, 128*1024);
3752dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik    if (!bs) {
3762dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik#ifdef VENDORSERVICEMANAGER
3772dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        ALOGW("failed to open binder driver %s\n", driver);
3782dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        while (true) {
379b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            sleep(UINT_MAX);
380386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
381268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik#else
382268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        ALOGE("failed to open binder driver %s\n", driver);
383268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik#endif
384268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        return -1;
385268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    }
386268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
387268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    if (binder_become_context_manager(bs)) {
388268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        ALOGE("cannot become context manager (%s)\n", strerror(errno));
389268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        return -1;
390268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    }
391268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
392268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    cb.func_audit = audit_callback;
393268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    selinux_set_callback(SELINUX_CB_AUDIT, cb);
3947df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    cb.func_log = selinux_log_callback;
395268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    selinux_set_callback(SELINUX_CB_LOG, cb);
396e4db79de127cfe961195f52907af8451026eaa20Chris Craik
397268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik#ifdef VENDORSERVICEMANAGER
398268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    sehandle = selinux_android_vendor_service_context_handle();
399268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik#else
400268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    sehandle = selinux_android_service_context_handle();
401268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik#endif
402b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    selinux_status_open(true);
403268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
404814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    if (sehandle == NULL) {
405814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
406386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        abort();
407b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
408386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik
409268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    if (getcon(&service_manager_context) != 0) {
410268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
411268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        abort();
412268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    }
413268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
414268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
415268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    binder_loop(bs, svcmgr_handler);
416268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
4177df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    return 0;
418268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik}
419e4db79de127cfe961195f52907af8451026eaa20Chris Craik