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