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