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 <selinux/android.h>
     12 #include <selinux/avc.h>
     13 
     14 #include "binder.h"
     15 
     16 #if 0
     17 #define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
     18 #define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
     19 #else
     20 #define LOG_TAG "ServiceManager"
     21 #include <cutils/log.h>
     22 #endif
     23 
     24 uint32_t svcmgr_handle;
     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;
    173 
    174     if (!svc_can_find(s, len, spid)) {
    175         ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n",
    176              str8(s, len), uid);
    177         return 0;
    178     }
    179     si = find_svc(s, len);
    180     //ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0);
    181     if (si && si->handle) {
    182         if (!si->allow_isolated) {
    183             // If this service doesn't allow access from isolated processes,
    184             // then check the uid to see if it is isolated.
    185             uid_t appid = uid % AID_USER;
    186             if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
    187                 return 0;
    188             }
    189         }
    190         return si->handle;
    191     } else {
    192         return 0;
    193     }
    194 }
    195 
    196 int do_add_service(struct binder_state *bs,
    197                    const uint16_t *s, size_t len,
    198                    uint32_t handle, uid_t uid, int allow_isolated,
    199                    pid_t spid)
    200 {
    201     struct svcinfo *si;
    202 
    203     //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
    204     //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
    205 
    206     if (!handle || (len == 0) || (len > 127))
    207         return -1;
    208 
    209     if (!svc_can_register(s, len, spid)) {
    210         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
    211              str8(s, len), handle, uid);
    212         return -1;
    213     }
    214 
    215     si = find_svc(s, len);
    216     if (si) {
    217         if (si->handle) {
    218             ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
    219                  str8(s, len), handle, uid);
    220             svcinfo_death(bs, si);
    221         }
    222         si->handle = handle;
    223     } else {
    224         si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
    225         if (!si) {
    226             ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
    227                  str8(s, len), handle, uid);
    228             return -1;
    229         }
    230         si->handle = handle;
    231         si->len = len;
    232         memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
    233         si->name[len] = '\0';
    234         si->death.func = (void*) svcinfo_death;
    235         si->death.ptr = si;
    236         si->allow_isolated = allow_isolated;
    237         si->next = svclist;
    238         svclist = si;
    239     }
    240 
    241     binder_acquire(bs, handle);
    242     binder_link_to_death(bs, handle, &si->death);
    243     return 0;
    244 }
    245 
    246 int svcmgr_handler(struct binder_state *bs,
    247                    struct binder_transaction_data *txn,
    248                    struct binder_io *msg,
    249                    struct binder_io *reply)
    250 {
    251     struct svcinfo *si;
    252     uint16_t *s;
    253     size_t len;
    254     uint32_t handle;
    255     uint32_t strict_policy;
    256     int allow_isolated;
    257 
    258     //ALOGI("target=%x code=%d pid=%d uid=%d\n",
    259     //  txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid);
    260 
    261     if (txn->target.handle != svcmgr_handle)
    262         return -1;
    263 
    264     if (txn->code == PING_TRANSACTION)
    265         return 0;
    266 
    267     // Equivalent to Parcel::enforceInterface(), reading the RPC
    268     // header with the strict mode policy mask and the interface name.
    269     // Note that we ignore the strict_policy and don't propagate it
    270     // further (since we do no outbound RPCs anyway).
    271     strict_policy = bio_get_uint32(msg);
    272     s = bio_get_string16(msg, &len);
    273     if (s == NULL) {
    274         return -1;
    275     }
    276 
    277     if ((len != (sizeof(svcmgr_id) / 2)) ||
    278         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
    279         fprintf(stderr,"invalid id %s\n", str8(s, len));
    280         return -1;
    281     }
    282 
    283     if (sehandle && selinux_status_updated() > 0) {
    284         struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
    285         if (tmp_sehandle) {
    286             selabel_close(sehandle);
    287             sehandle = tmp_sehandle;
    288         }
    289     }
    290 
    291     switch(txn->code) {
    292     case SVC_MGR_GET_SERVICE:
    293     case SVC_MGR_CHECK_SERVICE:
    294         s = bio_get_string16(msg, &len);
    295         if (s == NULL) {
    296             return -1;
    297         }
    298         handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
    299         if (!handle)
    300             break;
    301         bio_put_ref(reply, handle);
    302         return 0;
    303 
    304     case SVC_MGR_ADD_SERVICE:
    305         s = bio_get_string16(msg, &len);
    306         if (s == NULL) {
    307             return -1;
    308         }
    309         handle = bio_get_ref(msg);
    310         allow_isolated = bio_get_uint32(msg) ? 1 : 0;
    311         if (do_add_service(bs, s, len, handle, txn->sender_euid,
    312             allow_isolated, txn->sender_pid))
    313             return -1;
    314         break;
    315 
    316     case SVC_MGR_LIST_SERVICES: {
    317         uint32_t n = bio_get_uint32(msg);
    318 
    319         if (!svc_can_list(txn->sender_pid)) {
    320             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
    321                     txn->sender_euid);
    322             return -1;
    323         }
    324         si = svclist;
    325         while ((n-- > 0) && si)
    326             si = si->next;
    327         if (si) {
    328             bio_put_string16(reply, si->name);
    329             return 0;
    330         }
    331         return -1;
    332     }
    333     default:
    334         ALOGE("unknown code %d\n", txn->code);
    335         return -1;
    336     }
    337 
    338     bio_put_uint32(reply, 0);
    339     return 0;
    340 }
    341 
    342 
    343 static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
    344 {
    345     snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
    346     return 0;
    347 }
    348 
    349 int main(int argc, char **argv)
    350 {
    351     struct binder_state *bs;
    352 
    353     bs = binder_open(128*1024);
    354     if (!bs) {
    355         ALOGE("failed to open binder driver\n");
    356         return -1;
    357     }
    358 
    359     if (binder_become_context_manager(bs)) {
    360         ALOGE("cannot become context manager (%s)\n", strerror(errno));
    361         return -1;
    362     }
    363 
    364     selinux_enabled = is_selinux_enabled();
    365     sehandle = selinux_android_service_context_handle();
    366 
    367     if (selinux_enabled > 0) {
    368         if (sehandle == NULL) {
    369             ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
    370             abort();
    371         }
    372 
    373         if (getcon(&service_manager_context) != 0) {
    374             ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
    375             abort();
    376         }
    377     }
    378 
    379     union selinux_callback cb;
    380     cb.func_audit = audit_callback;
    381     selinux_set_callback(SELINUX_CB_AUDIT, cb);
    382     cb.func_log = selinux_log_callback;
    383     selinux_set_callback(SELINUX_CB_LOG, cb);
    384 
    385     svcmgr_handle = BINDER_SERVICE_MANAGER;
    386     binder_loop(bs, svcmgr_handler);
    387 
    388     return 0;
    389 }
    390