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        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
291        if (tmp_sehandle) {
292            selabel_close(sehandle);
293            sehandle = tmp_sehandle;
294        }
295    }
296
297    switch(txn->code) {
298    case SVC_MGR_GET_SERVICE:
299    case SVC_MGR_CHECK_SERVICE:
300        s = bio_get_string16(msg, &len);
301        if (s == NULL) {
302            return -1;
303        }
304        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
305        if (!handle)
306            break;
307        bio_put_ref(reply, handle);
308        return 0;
309
310    case SVC_MGR_ADD_SERVICE:
311        s = bio_get_string16(msg, &len);
312        if (s == NULL) {
313            return -1;
314        }
315        handle = bio_get_ref(msg);
316        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
317        if (do_add_service(bs, s, len, handle, txn->sender_euid,
318            allow_isolated, txn->sender_pid))
319            return -1;
320        break;
321
322    case SVC_MGR_LIST_SERVICES: {
323        uint32_t n = bio_get_uint32(msg);
324
325        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
326            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
327                    txn->sender_euid);
328            return -1;
329        }
330        si = svclist;
331        while ((n-- > 0) && si)
332            si = si->next;
333        if (si) {
334            bio_put_string16(reply, si->name);
335            return 0;
336        }
337        return -1;
338    }
339    default:
340        ALOGE("unknown code %d\n", txn->code);
341        return -1;
342    }
343
344    bio_put_uint32(reply, 0);
345    return 0;
346}
347
348
349static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
350{
351    struct audit_data *ad = (struct audit_data *)data;
352
353    if (!ad || !ad->name) {
354        ALOGE("No service manager audit data");
355        return 0;
356    }
357
358    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
359    return 0;
360}
361
362int main(int argc, char** argv)
363{
364    struct binder_state *bs;
365    union selinux_callback cb;
366    char *driver;
367
368    if (argc > 1) {
369        driver = argv[1];
370    } else {
371        driver = "/dev/binder";
372    }
373
374    bs = binder_open(driver, 128*1024);
375    if (!bs) {
376#ifdef VENDORSERVICEMANAGER
377        ALOGW("failed to open binder driver %s\n", driver);
378        while (true) {
379            sleep(UINT_MAX);
380        }
381#else
382        ALOGE("failed to open binder driver %s\n", driver);
383#endif
384        return -1;
385    }
386
387    if (binder_become_context_manager(bs)) {
388        ALOGE("cannot become context manager (%s)\n", strerror(errno));
389        return -1;
390    }
391
392    cb.func_audit = audit_callback;
393    selinux_set_callback(SELINUX_CB_AUDIT, cb);
394    cb.func_log = selinux_log_callback;
395    selinux_set_callback(SELINUX_CB_LOG, cb);
396
397#ifdef VENDORSERVICEMANAGER
398    sehandle = selinux_android_vendor_service_context_handle();
399#else
400    sehandle = selinux_android_service_context_handle();
401#endif
402    selinux_status_open(true);
403
404    if (sehandle == NULL) {
405        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
406        abort();
407    }
408
409    if (getcon(&service_manager_context) != 0) {
410        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
411        abort();
412    }
413
414
415    binder_loop(bs, svcmgr_handler);
416
417    return 0;
418}
419