service_manager.c revision 2a0e40945b5f7adf2055b2f439b3ba4c6389ddc3
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>
12652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich#include <selinux/avc.h>
1369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "binder.h"
1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#if 0
1794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#else
2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define LOG_TAG "ServiceManager"
2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <cutils/log.h>
2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#endif
2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
245fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescuuint32_t svcmgr_handle;
2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
26652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevichconst char *str8(const uint16_t *x, size_t x_len)
2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    static char buf[128];
29652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    size_t max = 127;
3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *p = buf;
3194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    if (x_len < max) {
33652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        max = x_len;
34652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    }
35652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich
3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (x) {
37652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        while ((max > 0) && (*x != '\0')) {
3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            *p++ = *x++;
39652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich            max--;
4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *p++ = 0;
4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return buf;
4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
469b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuint str16eq(const uint16_t *a, const char *b)
4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (*a && *b)
4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (*a++ != *b++) return 0;
5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (*a || *b)
5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 1;
5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
552a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic int selinux_enabled;
562a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic char *service_manager_context;
5769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic struct selabel_handle* sehandle;
5869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
592a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name)
6069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn{
6169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    char *sctx = NULL;
622a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    const char *class = "service_manager";
632a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    bool allowed;
6469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
652a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (getpidcon(spid, &sctx) < 0) {
662a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
6769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
6869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
6969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
702a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
712a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    allowed = (result == 0);
722a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
732a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    freecon(sctx);
742a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    return allowed;
752a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn}
762a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
772a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic bool check_mac_perms_from_getcon(pid_t spid, const char *perm)
782a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn{
792a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (selinux_enabled <= 0) {
802a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        return true;
8169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
8269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
832a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    return check_mac_perms(spid, service_manager_context, perm, NULL);
842a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn}
852a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
862a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name)
872a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn{
882a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    bool allowed;
892a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    char *tctx = NULL;
902a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
912a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (selinux_enabled <= 0) {
922a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        return true;
9369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
9469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
952a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (!sehandle) {
962a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
972a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        abort();
9869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
9969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1002a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
1012a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
10269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        return false;
10369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
10469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1052a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    allowed = check_mac_perms(spid, tctx, perm, name);
10669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    freecon(tctx);
10769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    return allowed;
10869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn}
10969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
1102a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
1112a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn{
1122a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    const char *perm = "add";
1132a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
1142a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn}
1152a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
1162a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic int svc_can_list(pid_t spid)
11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
1182a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    const char *perm = "list";
1192a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    return check_mac_perms_from_getcon(spid, perm) ? 1 : 0;
1202a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn}
1212a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
1222a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnstatic int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid)
1232a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn{
1242a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    const char *perm = "find";
1252a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1289b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo
12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *next;
1315fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    uint32_t handle;
13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_death death;
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int allow_isolated;
1349b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t len;
13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t name[0];
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1389b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo *svclist = NULL;
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1409b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescustruct svcinfo *find_svc(const uint16_t *s16, size_t len)
14194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
14294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (si = svclist; si; si = si->next) {
14594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((len == si->len) &&
14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return si;
14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
1509b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    return NULL;
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid svcinfo_death(struct binder_state *bs, void *ptr)
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
1559b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    struct svcinfo *si = (struct svcinfo* ) ptr;
1569b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
157652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    ALOGI("service '%s' died\n", str8(si->name, si->len));
1585fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (si->handle) {
1595fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        binder_release(bs, si->handle);
1605fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = 0;
1619b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    }
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1649b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescuuint16_t svcmgr_id[] = {
16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    'a','n','d','r','o','i','d','.','o','s','.',
1669b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1699b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
1702a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahnuint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1742a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (!svc_can_find(s, len, spid)) {
1752a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n",
1762a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn             str8(s, len), uid);
1772a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        return 0;
1782a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    }
1793a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu    si = find_svc(s, len);
180652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    //ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0);
1815fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (si && si->handle) {
18294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (!si->allow_isolated) {
18394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            // If this service doesn't allow access from isolated processes,
18494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            // then check the uid to see if it is isolated.
1859b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu            uid_t appid = uid % AID_USER;
18694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
18794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                return 0;
18894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
18994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
1905fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        return si->handle;
19194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
19294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
19394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
19494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
19594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
19694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint do_add_service(struct binder_state *bs,
1979b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu                   const uint16_t *s, size_t len,
19869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn                   uint32_t handle, uid_t uid, int allow_isolated,
19969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn                   pid_t spid)
20094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
20194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
2023a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu
203652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
20494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
20594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2065fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    if (!handle || (len == 0) || (len > 127))
20794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
20894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2092a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (!svc_can_register(s, len, spid)) {
2105fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
211652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich             str8(s, len), handle, uid);
21294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
21394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
21494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
21594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    si = find_svc(s, len);
21694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (si) {
2175fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        if (si->handle) {
2185fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
219652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich                 str8(s, len), handle, uid);
22094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            svcinfo_death(bs, si);
22194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2225fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = handle;
22394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
22494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
22594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (!si) {
2265fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
227652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich                 str8(s, len), handle, uid);
22894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
22994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
2305fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        si->handle = handle;
23194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->len = len;
23294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
23394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->name[len] = '\0';
2349b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu        si->death.func = (void*) svcinfo_death;
23594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->death.ptr = si;
23694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->allow_isolated = allow_isolated;
23794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si->next = svclist;
23894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        svclist = si;
23994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
24094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2415fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    binder_acquire(bs, handle);
2425fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    binder_link_to_death(bs, handle, &si->death);
24394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
24494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
24594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
24694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint svcmgr_handler(struct binder_state *bs,
247bcf38880c65297da58194eb0c0ce8d6e2bab7d94Serban Constantinescu                   struct binder_transaction_data *txn,
24894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                   struct binder_io *msg,
24994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                   struct binder_io *reply)
25094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
25194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct svcinfo *si;
25294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint16_t *s;
2539b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    size_t len;
2545fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu    uint32_t handle;
25594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    uint32_t strict_policy;
25694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int allow_isolated;
25794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2583a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu    //ALOGI("target=%x code=%d pid=%d uid=%d\n",
2593a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu    //  txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid);
26094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
261bcf38880c65297da58194eb0c0ce8d6e2bab7d94Serban Constantinescu    if (txn->target.handle != svcmgr_handle)
26294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
26394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
264e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg    if (txn->code == PING_TRANSACTION)
265e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg        return 0;
266e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg
26794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Equivalent to Parcel::enforceInterface(), reading the RPC
26894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // header with the strict mode policy mask and the interface name.
26994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Note that we ignore the strict_policy and don't propagate it
27094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // further (since we do no outbound RPCs anyway).
27194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    strict_policy = bio_get_uint32(msg);
27294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    s = bio_get_string16(msg, &len);
273652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    if (s == NULL) {
274652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        return -1;
275652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich    }
276652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich
27794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((len != (sizeof(svcmgr_id) / 2)) ||
27894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
279652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        fprintf(stderr,"invalid id %s\n", str8(s, len));
28094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
28194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
28294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
28369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    if (sehandle && selinux_status_updated() > 0) {
28469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
28569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        if (tmp_sehandle) {
28669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            selabel_close(sehandle);
28769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            sehandle = tmp_sehandle;
28869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        }
28969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    }
29069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
29194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    switch(txn->code) {
29294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_GET_SERVICE:
29394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_CHECK_SERVICE:
29494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        s = bio_get_string16(msg, &len);
295652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        if (s == NULL) {
296652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich            return -1;
297652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        }
2982a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
2995fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        if (!handle)
30094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
3015fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        bio_put_ref(reply, handle);
30294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
30394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
30494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_ADD_SERVICE:
30594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        s = bio_get_string16(msg, &len);
306652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        if (s == NULL) {
307652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich            return -1;
308652c485467598240ecbb3a60516ad1140eddfab1Nick Kralevich        }
3095fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu        handle = bio_get_ref(msg);
31094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
31169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn        if (do_add_service(bs, s, len, handle, txn->sender_euid,
31269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn            allow_isolated, txn->sender_pid))
31394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
31494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        break;
31594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    case SVC_MGR_LIST_SERVICES: {
3173a345f0df5f62d77e875a289e9aee89f0d1b526eSerban Constantinescu        uint32_t n = bio_get_uint32(msg);
31894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
3192a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        if (!svc_can_list(txn->sender_pid)) {
3202a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
3212a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn                    txn->sender_euid);
3222a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn            return -1;
3232a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        }
32494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        si = svclist;
32594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        while ((n-- > 0) && si)
32694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            si = si->next;
32794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (si) {
32894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bio_put_string16(reply, si->name);
32994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return 0;
33094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
33194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
33294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
33394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    default:
33494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("unknown code %d\n", txn->code);
33594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
33694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
33794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
33894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bio_put_uint32(reply, 0);
33994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
34094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
34194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
34269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
34369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahnstatic int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
34469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn{
34569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
34669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    return 0;
34769154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn}
34869154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
34994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint main(int argc, char **argv)
35094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct binder_state *bs;
35294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    bs = binder_open(128*1024);
354a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu    if (!bs) {
355a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu        ALOGE("failed to open binder driver\n");
356a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu        return -1;
357a44542ca74b7da5b44ba30c205c3244805bb0600Serban Constantinescu    }
35894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (binder_become_context_manager(bs)) {
36094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot become context manager (%s)\n", strerror(errno));
36194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
36294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
36394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
3642a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    selinux_enabled = is_selinux_enabled();
36569154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    sehandle = selinux_android_service_context_handle();
36669154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
3672a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    if (selinux_enabled > 0) {
3682a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        if (sehandle == NULL) {
3692a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn            ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
3702a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn            abort();
3712a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        }
3722a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
3732a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        if (getcon(&service_manager_context) != 0) {
3742a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn            ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
3752a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn            abort();
3762a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn        }
3772a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn    }
3782a0e40945b5f7adf2055b2f439b3ba4c6389ddc3Riley Spahn
37969154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    union selinux_callback cb;
38069154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    cb.func_audit = audit_callback;
38169154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    selinux_set_callback(SELINUX_CB_AUDIT, cb);
38269154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    cb.func_log = selinux_log_callback;
38369154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn    selinux_set_callback(SELINUX_CB_LOG, cb);
38469154df9efd3ffb7580b72a0138f58a2f5443db6Riley Spahn
3859b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu    svcmgr_handle = BINDER_SERVICE_MANAGER;
38694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    binder_loop(bs, svcmgr_handler);
3879b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu
38894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
38994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
390