Home | History | Annotate | Download | only in servicemanager
      1 /* Copyright 2008 The Android Open Source Project
      2  */
      3 
      4 #include <errno.h>
      5 #include <fcntl.h>
      6 #include <inttypes.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 
     11 #include <private/android_filesystem_config.h>
     12 
     13 #include <selinux/android.h>
     14 #include <selinux/avc.h>
     15 
     16 #include "binder.h"
     17 
     18 #if 0
     19 #define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
     20 #define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
     21 #else
     22 #define LOG_TAG "ServiceManager"
     23 #include <cutils/log.h>
     24 #endif
     25 
     26 const char *str8(const uint16_t *x, size_t x_len)
     27 {
     28     static char buf[128];
     29     size_t max = 127;
     30     char *p = buf;
     31 
     32     if (x_len < max) {
     33         max = x_len;
     34     }
     35 
     36     if (x) {
     37         while ((max > 0) && (*x != '\0')) {
     38             *p++ = *x++;
     39             max--;
     40         }
     41     }
     42     *p++ = 0;
     43     return buf;
     44 }
     45 
     46 int str16eq(const uint16_t *a, const char *b)
     47 {
     48     while (*a && *b)
     49         if (*a++ != *b++) return 0;
     50     if (*a || *b)
     51         return 0;
     52     return 1;
     53 }
     54 
     55 static int selinux_enabled;
     56 static char *service_manager_context;
     57 static struct selabel_handle* sehandle;
     58 
     59 static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name)
     60 {
     61     char *sctx = NULL;
     62     const char *class = "service_manager";
     63     bool allowed;
     64 
     65     if (getpidcon(spid, &sctx) < 0) {
     66         ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
     67         return false;
     68     }
     69 
     70     int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
     71     allowed = (result == 0);
     72 
     73     freecon(sctx);
     74     return allowed;
     75 }
     76 
     77 static bool check_mac_perms_from_getcon(pid_t spid, const char *perm)
     78 {
     79     if (selinux_enabled <= 0) {
     80         return true;
     81     }
     82 
     83     return check_mac_perms(spid, service_manager_context, perm, NULL);
     84 }
     85 
     86 static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name)
     87 {
     88     bool allowed;
     89     char *tctx = NULL;
     90 
     91     if (selinux_enabled <= 0) {
     92         return true;
     93     }
     94 
     95     if (!sehandle) {
     96         ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
     97         abort();
     98     }
     99 
    100     if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
    101         ALOGE("SELinux: No match for %s in service_contexts.\n", name);
    102         return false;
    103     }
    104 
    105     allowed = check_mac_perms(spid, tctx, perm, name);
    106     freecon(tctx);
    107     return allowed;
    108 }
    109 
    110 static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
    111 {
    112     const char *perm = "add";
    113     return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
    114 }
    115 
    116 static int svc_can_list(pid_t spid)
    117 {
    118     const char *perm = "list";
    119     return check_mac_perms_from_getcon(spid, perm) ? 1 : 0;
    120 }
    121 
    122 static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid)
    123 {
    124     const char *perm = "find";
    125     return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
    126 }
    127 
    128 struct svcinfo
    129 {
    130     struct svcinfo *next;
    131     uint32_t handle;
    132     struct binder_death death;
    133     int allow_isolated;
    134     size_t len;
    135     uint16_t name[0];
    136 };
    137 
    138 struct svcinfo *svclist = NULL;
    139 
    140 struct svcinfo *find_svc(const uint16_t *s16, size_t len)
    141 {
    142     struct svcinfo *si;
    143 
    144     for (si = svclist; si; si = si->next) {
    145         if ((len == si->len) &&
    146             !memcmp(s16, si->name, len * sizeof(uint16_t))) {
    147             return si;
    148         }
    149     }
    150     return NULL;
    151 }
    152 
    153 void svcinfo_death(struct binder_state *bs, void *ptr)
    154 {
    155     struct svcinfo *si = (struct svcinfo* ) ptr;
    156 
    157     ALOGI("service '%s' died\n", str8(si->name, si->len));
    158     if (si->handle) {
    159         binder_release(bs, si->handle);
    160         si->handle = 0;
    161     }
    162 }
    163 
    164 uint16_t svcmgr_id[] = {
    165     'a','n','d','r','o','i','d','.','o','s','.',
    166     'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
    167 };
    168 
    169 
    170 uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
    171 {
    172     struct svcinfo *si = find_svc(s, len);
    173 
    174     if (!si || !si->handle) {
    175         return 0;
    176     }
    177 
    178     if (!si->allow_isolated) {
    179         // If this service doesn't allow access from isolated processes,
    180         // then check the uid to see if it is isolated.
    181         uid_t appid = uid % AID_USER;
    182         if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
    183             return 0;
    184         }
    185     }
    186 
    187     if (!svc_can_find(s, len, spid)) {
    188         return 0;
    189     }
    190 
    191     return si->handle;
    192 }
    193 
    194 int do_add_service(struct binder_state *bs,
    195                    const uint16_t *s, size_t len,
    196                    uint32_t handle, uid_t uid, int allow_isolated,
    197                    pid_t spid)
    198 {
    199     struct svcinfo *si;
    200 
    201     //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
    202     //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
    203 
    204     if (!handle || (len == 0) || (len > 127))
    205         return -1;
    206 
    207     if (!svc_can_register(s, len, spid)) {
    208         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
    209              str8(s, len), handle, uid);
    210         return -1;
    211     }
    212 
    213     si = find_svc(s, len);
    214     if (si) {
    215         if (si->handle) {
    216             ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
    217                  str8(s, len), handle, uid);
    218             svcinfo_death(bs, si);
    219         }
    220         si->handle = handle;
    221     } else {
    222         si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
    223         if (!si) {
    224             ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
    225                  str8(s, len), handle, uid);
    226             return -1;
    227         }
    228         si->handle = handle;
    229         si->len = len;
    230         memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
    231         si->name[len] = '\0';
    232         si->death.func = (void*) svcinfo_death;
    233         si->death.ptr = si;
    234         si->allow_isolated = allow_isolated;
    235         si->next = svclist;
    236         svclist = si;
    237     }
    238 
    239     binder_acquire(bs, handle);
    240     binder_link_to_death(bs, handle, &si->death);
    241     return 0;
    242 }
    243 
    244 int svcmgr_handler(struct binder_state *bs,
    245                    struct binder_transaction_data *txn,
    246                    struct binder_io *msg,
    247                    struct binder_io *reply)
    248 {
    249     struct svcinfo *si;
    250     uint16_t *s;
    251     size_t len;
    252     uint32_t handle;
    253     uint32_t strict_policy;
    254     int allow_isolated;
    255 
    256     //ALOGI("target=%p code=%d pid=%d uid=%d\n",
    257     //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
    258 
    259     if (txn->target.ptr != BINDER_SERVICE_MANAGER)
    260         return -1;
    261 
    262     if (txn->code == PING_TRANSACTION)
    263         return 0;
    264 
    265     // Equivalent to Parcel::enforceInterface(), reading the RPC
    266     // header with the strict mode policy mask and the interface name.
    267     // Note that we ignore the strict_policy and don't propagate it
    268     // further (since we do no outbound RPCs anyway).
    269     strict_policy = bio_get_uint32(msg);
    270     s = bio_get_string16(msg, &len);
    271     if (s == NULL) {
    272         return -1;
    273     }
    274 
    275     if ((len != (sizeof(svcmgr_id) / 2)) ||
    276         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
    277         fprintf(stderr,"invalid id %s\n", str8(s, len));
    278         return -1;
    279     }
    280 
    281     if (sehandle && selinux_status_updated() > 0) {
    282         struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
    283         if (tmp_sehandle) {
    284             selabel_close(sehandle);
    285             sehandle = tmp_sehandle;
    286         }
    287     }
    288 
    289     switch(txn->code) {
    290     case SVC_MGR_GET_SERVICE:
    291     case SVC_MGR_CHECK_SERVICE:
    292         s = bio_get_string16(msg, &len);
    293         if (s == NULL) {
    294             return -1;
    295         }
    296         handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
    297         if (!handle)
    298             break;
    299         bio_put_ref(reply, handle);
    300         return 0;
    301 
    302     case SVC_MGR_ADD_SERVICE:
    303         s = bio_get_string16(msg, &len);
    304         if (s == NULL) {
    305             return -1;
    306         }
    307         handle = bio_get_ref(msg);
    308         allow_isolated = bio_get_uint32(msg) ? 1 : 0;
    309         if (do_add_service(bs, s, len, handle, txn->sender_euid,
    310             allow_isolated, txn->sender_pid))
    311             return -1;
    312         break;
    313 
    314     case SVC_MGR_LIST_SERVICES: {
    315         uint32_t n = bio_get_uint32(msg);
    316 
    317         if (!svc_can_list(txn->sender_pid)) {
    318             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
    319                     txn->sender_euid);
    320             return -1;
    321         }
    322         si = svclist;
    323         while ((n-- > 0) && si)
    324             si = si->next;
    325         if (si) {
    326             bio_put_string16(reply, si->name);
    327             return 0;
    328         }
    329         return -1;
    330     }
    331     default:
    332         ALOGE("unknown code %d\n", txn->code);
    333         return -1;
    334     }
    335 
    336     bio_put_uint32(reply, 0);
    337     return 0;
    338 }
    339 
    340 
    341 static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
    342 {
    343     snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
    344     return 0;
    345 }
    346 
    347 int main(int argc, char **argv)
    348 {
    349     struct binder_state *bs;
    350 
    351     bs = binder_open(128*1024);
    352     if (!bs) {
    353         ALOGE("failed to open binder driver\n");
    354         return -1;
    355     }
    356 
    357     if (binder_become_context_manager(bs)) {
    358         ALOGE("cannot become context manager (%s)\n", strerror(errno));
    359         return -1;
    360     }
    361 
    362     selinux_enabled = is_selinux_enabled();
    363     sehandle = selinux_android_service_context_handle();
    364     selinux_status_open(true);
    365 
    366     if (selinux_enabled > 0) {
    367         if (sehandle == NULL) {
    368             ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
    369             abort();
    370         }
    371 
    372         if (getcon(&service_manager_context) != 0) {
    373             ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
    374             abort();
    375         }
    376     }
    377 
    378     union selinux_callback cb;
    379     cb.func_audit = audit_callback;
    380     selinux_set_callback(SELINUX_CB_AUDIT, cb);
    381     cb.func_log = selinux_log_callback;
    382     selinux_set_callback(SELINUX_CB_LOG, cb);
    383 
    384     binder_loop(bs, svcmgr_handler);
    385 
    386     return 0;
    387 }
    388