service_manager.c revision 69154df9efd3ffb7580b72a0138f58a2f5443db6
194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Copyright 2008 The Android Open Source Project
294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <stdio.h>
594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <stdlib.h>
694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <errno.h>
794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <fcntl.h>
894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <private/android_filesystem_config.h>
1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn#include <selinux/android.h>
1269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "binder.h"
1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#if 0
1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
1794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#else
1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define LOG_TAG "ServiceManager"
2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <cutils/log.h>
2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#endif
2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* TODO:
2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * These should come from a config file or perhaps be
2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * based on some namespace rules of some sort (media
2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * uid can register media.*, etc)
2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic struct {
299b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    uid_t uid;
3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    const char *name;
3194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} allowed[] = {
3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_MEDIA, "media.audio_flinger" },
3364c8be07878a6a110e5386c5f789fa9db51c5746Glenn Kasten    { AID_MEDIA, "media.log" },
3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_MEDIA, "media.player" },
3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_MEDIA, "media.camera" },
3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_MEDIA, "media.audio_policy" },
3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_DRM,   "drm.drmManager" },
3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_NFC,   "nfc" },
3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_BLUETOOTH, "bluetooth" },
4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "radio.phone" },
4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "radio.sms" },
4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "radio.phonesubinfo" },
4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "radio.simphonebook" },
4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* TODO: remove after phone services are updated: */
4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "phone" },
4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "sip" },
4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "isms" },
4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "iphonesubinfo" },
4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_RADIO, "simphonebook" },
5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_MEDIA, "common_time.clock" },
5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { AID_MEDIA, "common_time.config" },
52244408786cf1f374eeacbf6d16dd5a6f7b5e3c59Kenny Root    { AID_KEYSTORE, "android.security.keystore" },
5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
555fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescuuint32_t svcmgr_handle;
5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
579b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuconst char *str8(const uint16_t *x)
5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    static char buf[128];
6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned max = 127;
6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *p = buf;
6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (x) {
6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        while (*x && max--) {
6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            *p++ = *x++;
6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *p++ = 0;
6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return buf;
7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
729b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuint str16eq(const uint16_t *a, const char *b)
7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (*a && *b)
7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (*a++ != *b++) return 0;
7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (*a || *b)
7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 1;
7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
8169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic struct selabel_handle* sehandle;
8269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
8369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic bool check_mac_perms(const char *name, pid_t spid)
8469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn{
8569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (is_selinux_enabled() <= 0) {
8669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return true;
8769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
8869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
8969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    bool allowed = false;
9069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
9169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    const char *class = "service_manager";
9269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    const char *perm = "add";
9369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
9469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    char *tctx = NULL;
9569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    char *sctx = NULL;
9669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
9769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (!sehandle) {
9869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        ALOGE("SELinux: Failed to find sehandle %s.\n", name);
9969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
10069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
10169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
10269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (getpidcon(spid, &sctx) < 0) {
10369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        ALOGE("SELinux: getpidcon failed to retrieve pid context.\n");
10469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
10569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
10669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
10769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (!sctx) {
10869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        ALOGE("SELinux: Failed to find sctx for %s.\n", name);
10969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
11069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
11169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
11269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (selabel_lookup(sehandle, &tctx, name, 1) != 0) {
11369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name);
11469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        freecon(sctx);
11569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
11669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
11769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
11869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (!tctx) {
11969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        ALOGE("SELinux: Failed to find tctx for %s.\n", name);
12069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        freecon(sctx);
12169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
12269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
12369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
12469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
12569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    allowed = (result == 0);
12669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
12769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    freecon(sctx);
12869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    freecon(tctx);
12969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    return allowed;
13069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn}
13169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
13269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic int svc_can_register(uid_t uid, const uint16_t *name, pid_t spid)
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
1349b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t n;
1359b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((uid == 0) || (uid == AID_SYSTEM))
13769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return check_mac_perms(str8(name), spid) ? 1 : 0;
13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
14169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            return check_mac_perms(str8(name), spid) ? 1 : 0;
14294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
14594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1469b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo
14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *next;
1495fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    uint32_t handle;
15094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_death death;
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int allow_isolated;
1529b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t len;
15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t name[0];
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1569b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo *svclist = NULL;
15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1589b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo *find_svc(const uint16_t *s16, size_t len)
15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (si = svclist; si; si = si->next) {
16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((len == si->len) &&
16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return si;
16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
1689b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    return NULL;
16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid svcinfo_death(struct binder_state *bs, void *ptr)
17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
1739b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    struct svcinfo *si = (struct svcinfo* ) ptr;
1749b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ALOGI("service '%s' died\n", str8(si->name));
1765fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (si->handle) {
1775fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        binder_release(bs, si->handle);
1785fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = 0;
1799b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    }
18094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
18194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1829b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuuint16_t svcmgr_id[] = {
18394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    'a','n','d','r','o','i','d','.','o','s','.',
1849b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
18594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
18694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1879b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
1885fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescuuint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid)
18994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
19094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
19194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1923a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu    si = find_svc(s, len);
1935fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    //ALOGI("check_service('%s') handle = %x\n", str8(s), si ? si->handle : 0);
1945fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (si && si->handle) {
19594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (!si->allow_isolated) {
19694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            // If this service doesn't allow access from isolated processes,
19794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            // then check the uid to see if it is isolated.
1989b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu            uid_t appid = uid % AID_USER;
19994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
20094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                return 0;
20194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
20294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2035fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        return si->handle;
20494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
20594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
20694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
20794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
20894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
20994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint do_add_service(struct binder_state *bs,
2109b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu                   const uint16_t *s, size_t len,
21169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn                   uint32_t handle, uid_t uid, int allow_isolated,
21269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn                   pid_t spid)
21394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
21494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
2153a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu
2165fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s), handle,
21794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
21894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2195fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (!handle || (len == 0) || (len > 127))
22094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
22194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
22269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (!svc_can_register(uid, s, spid)) {
2235fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
2245fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu             str8(s), handle, uid);
22594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
22694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
22794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
22894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    si = find_svc(s, len);
22994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (si) {
2305fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        if (si->handle) {
2315fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
2325fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu                 str8(s), handle, uid);
23394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            svcinfo_death(bs, si);
23494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2355fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = handle;
23694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
23794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
23894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (!si) {
2395fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
2405fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu                 str8(s), handle, uid);
24194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
24294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2435fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = handle;
24494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->len = len;
24594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
24694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->name[len] = '\0';
2479b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu        si->death.func = (void*) svcinfo_death;
24894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->death.ptr = si;
24994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->allow_isolated = allow_isolated;
25094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->next = svclist;
25194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        svclist = si;
25294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
25394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2545fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    binder_acquire(bs, handle);
2555fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    binder_link_to_death(bs, handle, &si->death);
25694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
25794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
25894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
25994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint svcmgr_handler(struct binder_state *bs,
260bcf38880c65297da58194eb0c0ce8d6e2bab7d94Serban Constantinescu                   struct binder_transaction_data *txn,
26194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                   struct binder_io *msg,
26294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                   struct binder_io *reply)
26394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
26494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
26594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t *s;
2669b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t len;
2675fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    uint32_t handle;
26894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t strict_policy;
26994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int allow_isolated;
27094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2713a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu    //ALOGI("target=%x code=%d pid=%d uid=%d\n",
2723a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu    //  txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid);
27394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
274bcf38880c65297da58194eb0c0ce8d6e2bab7d94Serban Constantinescu    if (txn->target.handle != svcmgr_handle)
27594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
27694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
277e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg    if (txn->code == PING_TRANSACTION)
278e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg        return 0;
279e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg
28094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Equivalent to Parcel::enforceInterface(), reading the RPC
28194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // header with the strict mode policy mask and the interface name.
28294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Note that we ignore the strict_policy and don't propagate it
28394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // further (since we do no outbound RPCs anyway).
28494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    strict_policy = bio_get_uint32(msg);
28594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    s = bio_get_string16(msg, &len);
28694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((len != (sizeof(svcmgr_id) / 2)) ||
28794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
28894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fprintf(stderr,"invalid id %s\n", str8(s));
28994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
29094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
29194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
29269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (sehandle && selinux_status_updated() > 0) {
29369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
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);
3045fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        handle = do_find_service(bs, s, len, txn->sender_euid);
3055fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        if (!handle)
30694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
3075fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        bio_put_ref(reply, handle);
30894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
30994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_ADD_SERVICE:
31194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        s = bio_get_string16(msg, &len);
3125fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        handle = bio_get_ref(msg);
31394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
31469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        if (do_add_service(bs, s, len, handle, txn->sender_euid,
31569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            allow_isolated, txn->sender_pid))
31694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
31794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        break;
31894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_LIST_SERVICES: {
3203a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu        uint32_t n = bio_get_uint32(msg);
32194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si = svclist;
32394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        while ((n-- > 0) && si)
32494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            si = si->next;
32594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (si) {
32694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bio_put_string16(reply, si->name);
32794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return 0;
32894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
32994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
33094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
33194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    default:
33294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("unknown code %d\n", txn->code);
33394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
33494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
33594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
33694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio_put_uint32(reply, 0);
33794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
33894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
33994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
34069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
34169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
34269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn{
34369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
34469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    return 0;
34569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn}
34669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
34794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint main(int argc, char **argv)
34894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
34994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_state *bs;
35094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bs = binder_open(128*1024);
352a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu    if (!bs) {
353a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu        ALOGE("failed to open binder driver\n");
354a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu        return -1;
355a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu    }
35694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (binder_become_context_manager(bs)) {
35894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot become context manager (%s)\n", strerror(errno));
35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
36094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
36194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
36269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    sehandle = selinux_android_service_context_handle();
36369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
36469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    union selinux_callback cb;
36569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    cb.func_audit = audit_callback;
36669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    selinux_set_callback(SELINUX_CB_AUDIT, cb);
36769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    cb.func_log = selinux_log_callback;
36869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    selinux_set_callback(SELINUX_CB_LOG, cb);
36969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
3709b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    svcmgr_handle = BINDER_SERVICE_MANAGER;
37194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_loop(bs, svcmgr_handler);
3729b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
37394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
37494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
375