194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Copyright 2008 The Android Open Source Project
294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <errno.h>
594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <fcntl.h>
60b41ad5d6ec86cd2d481969dcff7e88f2805324fElliott Hughes#include <inttypes.h>
713df5f5f8fbc5a3fdfdd5d1ba5dc853cf3f017f0Mark Salyzyn#include <stdio.h>
813df5f5f8fbc5a3fdfdd5d1ba5dc853cf3f017f0Mark Salyzyn#include <stdlib.h>
913df5f5f8fbc5a3fdfdd5d1ba5dc853cf3f017f0Mark Salyzyn#include <string.h>
1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11212c88143ebdeabbab364fca7680d8cd2caff256Yifan Hong#include <cutils/android_filesystem_config.h>
126b9c6d23f69a64f76fc26cda6989183042b0621cArve Hjønnevåg#include <cutils/multiuser.h>
136b9c6d23f69a64f76fc26cda6989183042b0621cArve Hjønnevåg
1469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn#include <selinux/android.h>
157d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich#include <selinux/avc.h>
1669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "binder.h"
1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1931361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#ifdef VENDORSERVICEMANAGER
2031361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#define LOG_TAG "VendorServiceManager"
2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#else
2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define LOG_TAG "ServiceManager"
2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#endif
2431361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#include <log/log.h>
2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
268fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstruct audit_data {
278fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    pid_t pid;
288fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    uid_t uid;
298fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    const char *name;
308fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts};
318fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts
327d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevichconst char *str8(const uint16_t *x, size_t x_len)
3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    static char buf[128];
357d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    size_t max = 127;
3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *p = buf;
3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
387d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    if (x_len < max) {
397d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        max = x_len;
407d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    }
417d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich
4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (x) {
437d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        while ((max > 0) && (*x != '\0')) {
4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            *p++ = *x++;
457d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich            max--;
4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *p++ = 0;
4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return buf;
5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
529b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuint str16eq(const uint16_t *a, const char *b)
5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (*a && *b)
5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (*a++ != *b++) return 0;
5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (*a || *b)
5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 1;
5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
61c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahnstatic char *service_manager_context;
6269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic struct selabel_handle* sehandle;
6369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
648fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstatic bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
6569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn{
6669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    char *sctx = NULL;
67c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    const char *class = "service_manager";
68c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    bool allowed;
698fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    struct audit_data ad;
7069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
71c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    if (getpidcon(spid, &sctx) < 0) {
72c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
7369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
7469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
7569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
768fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    ad.pid = spid;
778fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    ad.uid = uid;
788fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    ad.name = name;
798fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts
808fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
81c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    allowed = (result == 0);
82c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
83c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    freecon(sctx);
84c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    return allowed;
85c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn}
86c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
878fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstatic bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
88c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn{
898fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
90c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn}
91c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
928fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstatic bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
93c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn{
94c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    bool allowed;
95c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    char *tctx = NULL;
96c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
97c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    if (!sehandle) {
98c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
99c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn        abort();
10069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
10169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
102c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
103c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
10469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
10569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
10669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1078fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    allowed = check_mac_perms(spid, uid, tctx, perm, name);
10869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    freecon(tctx);
10969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    return allowed;
11069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn}
11169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1128fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstatic int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
113c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn{
114c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    const char *perm = "add";
1155fa90a063f77054fc6068f45f6a21f43d64364b6Arve Hjønnevåg
1166b9c6d23f69a64f76fc26cda6989183042b0621cArve Hjønnevåg    if (multiuser_get_app_id(uid) >= AID_APP) {
1175fa90a063f77054fc6068f45f6a21f43d64364b6Arve Hjønnevåg        return 0; /* Don't allow apps to register services */
1185fa90a063f77054fc6068f45f6a21f43d64364b6Arve Hjønnevåg    }
1195fa90a063f77054fc6068f45f6a21f43d64364b6Arve Hjønnevåg
1208fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
121c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn}
122c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
1238fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstatic int svc_can_list(pid_t spid, uid_t uid)
12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
125c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    const char *perm = "list";
1268fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
127c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn}
128c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
1298fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Robertsstatic int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
130c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn{
131c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    const char *perm = "find";
1328fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1359b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *next;
1385fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    uint32_t handle;
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_death death;
14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int allow_isolated;
141f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair    uint32_t dumpsys_priority;
1429b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t len;
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t name[0];
14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
14594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1469b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo *svclist = NULL;
14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1489b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo *find_svc(const uint16_t *s16, size_t len)
14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
15094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (si = svclist; si; si = si->next) {
15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((len == si->len) &&
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return si;
15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
1589b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    return NULL;
15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid svcinfo_death(struct binder_state *bs, void *ptr)
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
1639b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    struct svcinfo *si = (struct svcinfo* ) ptr;
1649b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
1657d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    ALOGI("service '%s' died\n", str8(si->name, si->len));
1665fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (si->handle) {
1675fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        binder_release(bs, si->handle);
1685fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = 0;
1699b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    }
17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1729b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuuint16_t svcmgr_id[] = {
17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    'a','n','d','r','o','i','d','.','o','s','.',
1749b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1779b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
178d57d9b900da83b1b5431d90e250f86c0047c618aIan Pedowitzuint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
17994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
180b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich    struct svcinfo *si = find_svc(s, len);
18194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
182b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich    if (!si || !si->handle) {
183c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn        return 0;
184c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    }
185b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich
186b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich    if (!si->allow_isolated) {
187b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich        // If this service doesn't allow access from isolated processes,
188b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich        // then check the uid to see if it is isolated.
189b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich        uid_t appid = uid % AID_USER;
190b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
191b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich            return 0;
19294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
193b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich    }
194b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich
1958fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    if (!svc_can_find(s, len, spid, uid)) {
19694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
19794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
198b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich
199b27bbd18bb65b3744ae066fcd6826285dec8b469Nick Kralevich    return si->handle;
20094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
20194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
202f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nairint do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
203f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
20494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
2053a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu
2067d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
20794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
20894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2095fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (!handle || (len == 0) || (len > 127))
21094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
21194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2128fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    if (!svc_can_register(s, len, spid, uid)) {
2135fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
2147d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich             str8(s, len), handle, uid);
21594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
21694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
21794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
21894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    si = find_svc(s, len);
21994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (si) {
2205fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        if (si->handle) {
2215fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
2227d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich                 str8(s, len), handle, uid);
22394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            svcinfo_death(bs, si);
22494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2255fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = handle;
22694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
22794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
22894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (!si) {
2295fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
2307d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich                 str8(s, len), handle, uid);
23194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
23294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2335fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = handle;
23494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->len = len;
23594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
23694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->name[len] = '\0';
2379b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu        si->death.func = (void*) svcinfo_death;
23894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->death.ptr = si;
23994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->allow_isolated = allow_isolated;
240f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        si->dumpsys_priority = dumpsys_priority;
24194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->next = svclist;
24294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        svclist = si;
24394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
24494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2455fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    binder_acquire(bs, handle);
2465fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    binder_link_to_death(bs, handle, &si->death);
24794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
24894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
24994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
25094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint svcmgr_handler(struct binder_state *bs,
251bcf38880c65297da58194eb0c0ce8d6e2bab7d94Serban Constantinescu                   struct binder_transaction_data *txn,
25294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                   struct binder_io *msg,
25394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                   struct binder_io *reply)
25494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
25594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
25694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t *s;
2579b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t len;
2585fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    uint32_t handle;
25994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t strict_policy;
26094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int allow_isolated;
261f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair    uint32_t dumpsys_priority;
26294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2630b41ad5d6ec86cd2d481969dcff7e88f2805324fElliott Hughes    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
2640b41ad5d6ec86cd2d481969dcff7e88f2805324fElliott Hughes    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
26594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2660b41ad5d6ec86cd2d481969dcff7e88f2805324fElliott Hughes    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
26794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
26894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
269e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg    if (txn->code == PING_TRANSACTION)
270e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg        return 0;
271e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg
27294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Equivalent to Parcel::enforceInterface(), reading the RPC
27394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // header with the strict mode policy mask and the interface name.
27494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Note that we ignore the strict_policy and don't propagate it
27594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // further (since we do no outbound RPCs anyway).
27694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    strict_policy = bio_get_uint32(msg);
27794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    s = bio_get_string16(msg, &len);
2787d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    if (s == NULL) {
2797d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        return -1;
2807d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich    }
2817d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich
28294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((len != (sizeof(svcmgr_id) / 2)) ||
28394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
2847d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        fprintf(stderr,"invalid id %s\n", str8(s, len));
28594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
28694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
28794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
28869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (sehandle && selinux_status_updated() > 0) {
28961f8dfa24b0846ae66328891f8facf9e06237c15Kouji Shiotani#ifdef VENDORSERVICEMANAGER
29061f8dfa24b0846ae66328891f8facf9e06237c15Kouji Shiotani        struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
29161f8dfa24b0846ae66328891f8facf9e06237c15Kouji Shiotani#else
29269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
29361f8dfa24b0846ae66328891f8facf9e06237c15Kouji Shiotani#endif
29469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        if (tmp_sehandle) {
29569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            selabel_close(sehandle);
29669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            sehandle = tmp_sehandle;
29769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        }
29869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
29969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
30094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    switch(txn->code) {
30194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_GET_SERVICE:
30294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_CHECK_SERVICE:
30394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        s = bio_get_string16(msg, &len);
3047d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        if (s == NULL) {
3057d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich            return -1;
3067d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        }
307d57d9b900da83b1b5431d90e250f86c0047c618aIan Pedowitz        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
3085fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        if (!handle)
30994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
3105fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        bio_put_ref(reply, handle);
31194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
31294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_ADD_SERVICE:
31494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        s = bio_get_string16(msg, &len);
3157d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        if (s == NULL) {
3167d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich            return -1;
3177d42a3c31ba78a418f9bdde0e0ab951469f321b5Nick Kralevich        }
3185fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        handle = bio_get_ref(msg);
31994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
320f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        dumpsys_priority = bio_get_uint32(msg);
321f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
322f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair                           txn->sender_pid))
32394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
32494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        break;
32594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_LIST_SERVICES: {
3273a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu        uint32_t n = bio_get_uint32(msg);
328f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        uint32_t req_dumpsys_priority = bio_get_uint32(msg);
32994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
3308fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
331c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
332c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn                    txn->sender_euid);
333c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn            return -1;
334c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn        }
33594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si = svclist;
336f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        // walk through the list of services n times skipping services that
337f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        // do not support the requested priority
338f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        while (si) {
339f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair            if (si->dumpsys_priority & req_dumpsys_priority) {
340f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair                if (n == 0) break;
341f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair                n--;
342f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair            }
34394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            si = si->next;
344f56042d6a496fca2e5cfc1f598251f77a9bc7986Vishnu Nair        }
34594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (si) {
34694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bio_put_string16(reply, si->name);
34794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return 0;
34894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
34994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
35094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    default:
35294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("unknown code %d\n", txn->code);
35394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
35494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
35594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio_put_uint32(reply, 0);
35794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
35894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
36069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
361d57d9b900da83b1b5431d90e250f86c0047c618aIan Pedowitzstatic int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
36269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn{
3638fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    struct audit_data *ad = (struct audit_data *)data;
3648fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts
3658fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    if (!ad || !ad->name) {
3668fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts        ALOGE("No service manager audit data");
3678fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts        return 0;
3688fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    }
3698fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts
3708fb0f92e0fe3c286ebb120bae9e1570ee109fa12William Roberts    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
37169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    return 0;
37269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn}
37369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
37469b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenenint main(int argc, char** argv)
37594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
37694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_state *bs;
37793ba7019cb473158bdea1b8fc73a1db34ea9a129Sandeep Patil    union selinux_callback cb;
37869b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen    char *driver;
37994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
38069b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen    if (argc > 1) {
38169b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen        driver = argv[1];
38269b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen    } else {
38369b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen        driver = "/dev/binder";
38469b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen    }
38569b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen
38669b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen    bs = binder_open(driver, 128*1024);
387a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu    if (!bs) {
38831361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#ifdef VENDORSERVICEMANAGER
38931361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen        ALOGW("failed to open binder driver %s\n", driver);
39031361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen        while (true) {
39131361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen            sleep(UINT_MAX);
39231361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen        }
39331361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#else
39469b0515dcd58a479c41977aca7bd18b865571d09Martijn Coenen        ALOGE("failed to open binder driver %s\n", driver);
39531361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#endif
396a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu        return -1;
397a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu    }
39894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
39994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (binder_become_context_manager(bs)) {
40094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot become context manager (%s)\n", strerror(errno));
40194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
40294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
40394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
40493ba7019cb473158bdea1b8fc73a1db34ea9a129Sandeep Patil    cb.func_audit = audit_callback;
40593ba7019cb473158bdea1b8fc73a1db34ea9a129Sandeep Patil    selinux_set_callback(SELINUX_CB_AUDIT, cb);
40693ba7019cb473158bdea1b8fc73a1db34ea9a129Sandeep Patil    cb.func_log = selinux_log_callback;
40793ba7019cb473158bdea1b8fc73a1db34ea9a129Sandeep Patil    selinux_set_callback(SELINUX_CB_LOG, cb);
40893ba7019cb473158bdea1b8fc73a1db34ea9a129Sandeep Patil
40931361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#ifdef VENDORSERVICEMANAGER
41031361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen    sehandle = selinux_android_vendor_service_context_handle();
41131361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#else
41269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    sehandle = selinux_android_service_context_handle();
41331361232e1e7965d00c638ead2903f08f168f1c9Martijn Coenen#endif
414bea0746b241d15626cf0a56828efc1d4640dbda7Stephen Smalley    selinux_status_open(true);
41569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
416eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich    if (sehandle == NULL) {
417eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
418eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich        abort();
419eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich    }
420c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
421eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich    if (getcon(&service_manager_context) != 0) {
422eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
423eb4d5cbde02b17259e968321ef457b158ce1da4eNick Kralevich        abort();
424c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn    }
425c67e6307cadb1f2cd876907c42d39b8374b93acdRiley Spahn
42669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
42794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_loop(bs, svcmgr_handler);
4289b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
42994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
43094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
431