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