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