Home | History | Annotate | Download | only in servicemanager
      1 /* Copyright 2008 The Android Open Source Project
      2  */
      3 
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <errno.h>
      7 #include <fcntl.h>
      8 
      9 #include <private/android_filesystem_config.h>
     10 
     11 #include "binder.h"
     12 
     13 #if 0
     14 #define LOGI(x...) fprintf(stderr, "svcmgr: " x)
     15 #define LOGE(x...) fprintf(stderr, "svcmgr: " x)
     16 #else
     17 #define LOG_TAG "ServiceManager"
     18 #include <cutils/log.h>
     19 #endif
     20 
     21 /* TODO:
     22  * These should come from a config file or perhaps be
     23  * based on some namespace rules of some sort (media
     24  * uid can register media.*, etc)
     25  */
     26 static struct {
     27     unsigned uid;
     28     const char *name;
     29 } allowed[] = {
     30 #ifdef LVMX
     31     { AID_MEDIA, "com.lifevibes.mx.ipc" },
     32 #endif
     33     { AID_MEDIA, "media.audio_flinger" },
     34     { AID_MEDIA, "media.player" },
     35     { AID_MEDIA, "media.camera" },
     36     { AID_MEDIA, "media.audio_policy" },
     37     { AID_NFC,   "nfc" },
     38     { AID_RADIO, "radio.phone" },
     39     { AID_RADIO, "radio.sms" },
     40     { AID_RADIO, "radio.phonesubinfo" },
     41     { AID_RADIO, "radio.simphonebook" },
     42 /* TODO: remove after phone services are updated: */
     43     { AID_RADIO, "phone" },
     44     { AID_RADIO, "sip" },
     45     { AID_RADIO, "isms" },
     46     { AID_RADIO, "iphonesubinfo" },
     47     { AID_RADIO, "simphonebook" },
     48 };
     49 
     50 void *svcmgr_handle;
     51 
     52 const char *str8(uint16_t *x)
     53 {
     54     static char buf[128];
     55     unsigned max = 127;
     56     char *p = buf;
     57 
     58     if (x) {
     59         while (*x && max--) {
     60             *p++ = *x++;
     61         }
     62     }
     63     *p++ = 0;
     64     return buf;
     65 }
     66 
     67 int str16eq(uint16_t *a, const char *b)
     68 {
     69     while (*a && *b)
     70         if (*a++ != *b++) return 0;
     71     if (*a || *b)
     72         return 0;
     73     return 1;
     74 }
     75 
     76 int svc_can_register(unsigned uid, uint16_t *name)
     77 {
     78     unsigned n;
     79 
     80     if ((uid == 0) || (uid == AID_SYSTEM))
     81         return 1;
     82 
     83     for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
     84         if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
     85             return 1;
     86 
     87     return 0;
     88 }
     89 
     90 struct svcinfo
     91 {
     92     struct svcinfo *next;
     93     void *ptr;
     94     struct binder_death death;
     95     unsigned len;
     96     uint16_t name[0];
     97 };
     98 
     99 struct svcinfo *svclist = 0;
    100 
    101 struct svcinfo *find_svc(uint16_t *s16, unsigned len)
    102 {
    103     struct svcinfo *si;
    104 
    105     for (si = svclist; si; si = si->next) {
    106         if ((len == si->len) &&
    107             !memcmp(s16, si->name, len * sizeof(uint16_t))) {
    108             return si;
    109         }
    110     }
    111     return 0;
    112 }
    113 
    114 void svcinfo_death(struct binder_state *bs, void *ptr)
    115 {
    116     struct svcinfo *si = ptr;
    117     LOGI("service '%s' died\n", str8(si->name));
    118     if (si->ptr) {
    119         binder_release(bs, si->ptr);
    120         si->ptr = 0;
    121     }
    122 }
    123 
    124 uint16_t svcmgr_id[] = {
    125     'a','n','d','r','o','i','d','.','o','s','.',
    126     'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
    127 };
    128 
    129 
    130 void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)
    131 {
    132     struct svcinfo *si;
    133     si = find_svc(s, len);
    134 
    135 //    LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
    136     if (si && si->ptr) {
    137         return si->ptr;
    138     } else {
    139         return 0;
    140     }
    141 }
    142 
    143 int do_add_service(struct binder_state *bs,
    144                    uint16_t *s, unsigned len,
    145                    void *ptr, unsigned uid)
    146 {
    147     struct svcinfo *si;
    148 //    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
    149 
    150     if (!ptr || (len == 0) || (len > 127))
    151         return -1;
    152 
    153     if (!svc_can_register(uid, s)) {
    154         LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
    155              str8(s), ptr, uid);
    156         return -1;
    157     }
    158 
    159     si = find_svc(s, len);
    160     if (si) {
    161         if (si->ptr) {
    162             LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
    163                  str8(s), ptr, uid);
    164             return -1;
    165         }
    166         si->ptr = ptr;
    167     } else {
    168         si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
    169         if (!si) {
    170             LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
    171                  str8(s), ptr, uid);
    172             return -1;
    173         }
    174         si->ptr = ptr;
    175         si->len = len;
    176         memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
    177         si->name[len] = '\0';
    178         si->death.func = svcinfo_death;
    179         si->death.ptr = si;
    180         si->next = svclist;
    181         svclist = si;
    182     }
    183 
    184     binder_acquire(bs, ptr);
    185     binder_link_to_death(bs, ptr, &si->death);
    186     return 0;
    187 }
    188 
    189 int svcmgr_handler(struct binder_state *bs,
    190                    struct binder_txn *txn,
    191                    struct binder_io *msg,
    192                    struct binder_io *reply)
    193 {
    194     struct svcinfo *si;
    195     uint16_t *s;
    196     unsigned len;
    197     void *ptr;
    198     uint32_t strict_policy;
    199 
    200 //    LOGI("target=%p code=%d pid=%d uid=%d\n",
    201 //         txn->target, txn->code, txn->sender_pid, txn->sender_euid);
    202 
    203     if (txn->target != svcmgr_handle)
    204         return -1;
    205 
    206     // Equivalent to Parcel::enforceInterface(), reading the RPC
    207     // header with the strict mode policy mask and the interface name.
    208     // Note that we ignore the strict_policy and don't propagate it
    209     // further (since we do no outbound RPCs anyway).
    210     strict_policy = bio_get_uint32(msg);
    211     s = bio_get_string16(msg, &len);
    212     if ((len != (sizeof(svcmgr_id) / 2)) ||
    213         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
    214         fprintf(stderr,"invalid id %s\n", str8(s));
    215         return -1;
    216     }
    217 
    218     switch(txn->code) {
    219     case SVC_MGR_GET_SERVICE:
    220     case SVC_MGR_CHECK_SERVICE:
    221         s = bio_get_string16(msg, &len);
    222         ptr = do_find_service(bs, s, len);
    223         if (!ptr)
    224             break;
    225         bio_put_ref(reply, ptr);
    226         return 0;
    227 
    228     case SVC_MGR_ADD_SERVICE:
    229         s = bio_get_string16(msg, &len);
    230         ptr = bio_get_ref(msg);
    231         if (do_add_service(bs, s, len, ptr, txn->sender_euid))
    232             return -1;
    233         break;
    234 
    235     case SVC_MGR_LIST_SERVICES: {
    236         unsigned n = bio_get_uint32(msg);
    237 
    238         si = svclist;
    239         while ((n-- > 0) && si)
    240             si = si->next;
    241         if (si) {
    242             bio_put_string16(reply, si->name);
    243             return 0;
    244         }
    245         return -1;
    246     }
    247     default:
    248         LOGE("unknown code %d\n", txn->code);
    249         return -1;
    250     }
    251 
    252     bio_put_uint32(reply, 0);
    253     return 0;
    254 }
    255 
    256 int main(int argc, char **argv)
    257 {
    258     struct binder_state *bs;
    259     void *svcmgr = BINDER_SERVICE_MANAGER;
    260 
    261     bs = binder_open(128*1024);
    262 
    263     if (binder_become_context_manager(bs)) {
    264         LOGE("cannot become context manager (%s)\n", strerror(errno));
    265         return -1;
    266     }
    267 
    268     svcmgr_handle = svcmgr;
    269     binder_loop(bs, svcmgr_handler);
    270     return 0;
    271 }
    272