• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
str8(const uint16_t * x,size_t x_len)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 
str16eq(const uint16_t * a,const char * b)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 
check_mac_perms(pid_t spid,const char * sid,uid_t uid,const char * tctx,const char * perm,const char * name)64 static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
65 {
66     char *lookup_sid = NULL;
67     const char *class = "service_manager";
68     bool allowed;
69     struct audit_data ad;
70 
71     if (sid == NULL && getpidcon(spid, &lookup_sid) < 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     if (sid == NULL) {
81         android_errorWriteLog(0x534e4554, "121035042");
82     }
83 
84     int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
85     allowed = (result == 0);
86 
87     freecon(lookup_sid);
88     return allowed;
89 }
90 
check_mac_perms_from_getcon(pid_t spid,const char * sid,uid_t uid,const char * perm)91 static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
92 {
93     return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
94 }
95 
check_mac_perms_from_lookup(pid_t spid,const char * sid,uid_t uid,const char * perm,const char * name)96 static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
97 {
98     bool allowed;
99     char *tctx = NULL;
100 
101     if (!sehandle) {
102         ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
103         abort();
104     }
105 
106     if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
107         ALOGE("SELinux: No match for %s in service_contexts.\n", name);
108         return false;
109     }
110 
111     allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
112     freecon(tctx);
113     return allowed;
114 }
115 
svc_can_register(const uint16_t * name,size_t name_len,pid_t spid,const char * sid,uid_t uid)116 static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
117 {
118     const char *perm = "add";
119 
120     if (multiuser_get_app_id(uid) >= AID_APP) {
121         return 0; /* Don't allow apps to register services */
122     }
123 
124     return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
125 }
126 
svc_can_list(pid_t spid,const char * sid,uid_t uid)127 static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
128 {
129     const char *perm = "list";
130     return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
131 }
132 
svc_can_find(const uint16_t * name,size_t name_len,pid_t spid,const char * sid,uid_t uid)133 static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
134 {
135     const char *perm = "find";
136     return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
137 }
138 
139 struct svcinfo
140 {
141     struct svcinfo *next;
142     uint32_t handle;
143     struct binder_death death;
144     int allow_isolated;
145     uint32_t dumpsys_priority;
146     size_t len;
147     uint16_t name[0];
148 };
149 
150 struct svcinfo *svclist = NULL;
151 
find_svc(const uint16_t * s16,size_t len)152 struct svcinfo *find_svc(const uint16_t *s16, size_t len)
153 {
154     struct svcinfo *si;
155 
156     for (si = svclist; si; si = si->next) {
157         if ((len == si->len) &&
158             !memcmp(s16, si->name, len * sizeof(uint16_t))) {
159             return si;
160         }
161     }
162     return NULL;
163 }
164 
svcinfo_death(struct binder_state * bs,void * ptr)165 void svcinfo_death(struct binder_state *bs, void *ptr)
166 {
167     struct svcinfo *si = (struct svcinfo* ) ptr;
168 
169     ALOGI("service '%s' died\n", str8(si->name, si->len));
170     if (si->handle) {
171         binder_release(bs, si->handle);
172         si->handle = 0;
173     }
174 }
175 
176 uint16_t svcmgr_id[] = {
177     'a','n','d','r','o','i','d','.','o','s','.',
178     'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
179 };
180 
181 
do_find_service(const uint16_t * s,size_t len,uid_t uid,pid_t spid,const char * sid)182 uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
183 {
184     struct svcinfo *si = find_svc(s, len);
185 
186     if (!si || !si->handle) {
187         return 0;
188     }
189 
190     if (!si->allow_isolated) {
191         // If this service doesn't allow access from isolated processes,
192         // then check the uid to see if it is isolated.
193         uid_t appid = uid % AID_USER;
194         if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
195             return 0;
196         }
197     }
198 
199     if (!svc_can_find(s, len, spid, sid, uid)) {
200         return 0;
201     }
202 
203     return si->handle;
204 }
205 
do_add_service(struct binder_state * bs,const uint16_t * s,size_t len,uint32_t handle,uid_t uid,int allow_isolated,uint32_t dumpsys_priority,pid_t spid,const char * sid)206 int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
207                    uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
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, sid, 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->dumpsys_priority = dumpsys_priority;
245         si->next = svclist;
246         svclist = si;
247     }
248 
249     binder_acquire(bs, handle);
250     binder_link_to_death(bs, handle, &si->death);
251     return 0;
252 }
253 
svcmgr_handler(struct binder_state * bs,struct binder_transaction_data_secctx * txn_secctx,struct binder_io * msg,struct binder_io * reply)254 int svcmgr_handler(struct binder_state *bs,
255                    struct binder_transaction_data_secctx *txn_secctx,
256                    struct binder_io *msg,
257                    struct binder_io *reply)
258 {
259     struct svcinfo *si;
260     uint16_t *s;
261     size_t len;
262     uint32_t handle;
263     uint32_t strict_policy;
264     int allow_isolated;
265     uint32_t dumpsys_priority;
266 
267     struct binder_transaction_data *txn = &txn_secctx->transaction_data;
268 
269     //ALOGI("target=%p code=%d pid=%d uid=%d\n",
270     //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
271 
272     if (txn->target.ptr != BINDER_SERVICE_MANAGER)
273         return -1;
274 
275     if (txn->code == PING_TRANSACTION)
276         return 0;
277 
278     // Equivalent to Parcel::enforceInterface(), reading the RPC
279     // header with the strict mode policy mask and the interface name.
280     // Note that we ignore the strict_policy and don't propagate it
281     // further (since we do no outbound RPCs anyway).
282     strict_policy = bio_get_uint32(msg);
283     bio_get_uint32(msg);  // Ignore worksource header.
284     s = bio_get_string16(msg, &len);
285     if (s == NULL) {
286         return -1;
287     }
288 
289     if ((len != (sizeof(svcmgr_id) / 2)) ||
290         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
291         fprintf(stderr,"invalid id %s\n", str8(s, len));
292         return -1;
293     }
294 
295     if (sehandle && selinux_status_updated() > 0) {
296 #ifdef VENDORSERVICEMANAGER
297         struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
298 #else
299         struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
300 #endif
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                                  (const char*) txn_secctx->secctx);
316         if (!handle)
317             break;
318         bio_put_ref(reply, handle);
319         return 0;
320 
321     case SVC_MGR_ADD_SERVICE:
322         s = bio_get_string16(msg, &len);
323         if (s == NULL) {
324             return -1;
325         }
326         handle = bio_get_ref(msg);
327         allow_isolated = bio_get_uint32(msg) ? 1 : 0;
328         dumpsys_priority = bio_get_uint32(msg);
329         if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
330                            txn->sender_pid, (const char*) txn_secctx->secctx))
331             return -1;
332         break;
333 
334     case SVC_MGR_LIST_SERVICES: {
335         uint32_t n = bio_get_uint32(msg);
336         uint32_t req_dumpsys_priority = bio_get_uint32(msg);
337 
338         if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
339             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
340                     txn->sender_euid);
341             return -1;
342         }
343         si = svclist;
344         // walk through the list of services n times skipping services that
345         // do not support the requested priority
346         while (si) {
347             if (si->dumpsys_priority & req_dumpsys_priority) {
348                 if (n == 0) break;
349                 n--;
350             }
351             si = si->next;
352         }
353         if (si) {
354             bio_put_string16(reply, si->name);
355             return 0;
356         }
357         return -1;
358     }
359     default:
360         ALOGE("unknown code %d\n", txn->code);
361         return -1;
362     }
363 
364     bio_put_uint32(reply, 0);
365     return 0;
366 }
367 
368 
audit_callback(void * data,__unused security_class_t cls,char * buf,size_t len)369 static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
370 {
371     struct audit_data *ad = (struct audit_data *)data;
372 
373     if (!ad || !ad->name) {
374         ALOGE("No service manager audit data");
375         return 0;
376     }
377 
378     snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
379     return 0;
380 }
381 
main(int argc,char ** argv)382 int main(int argc, char** argv)
383 {
384     struct binder_state *bs;
385     union selinux_callback cb;
386     char *driver;
387 
388     if (argc > 1) {
389         driver = argv[1];
390     } else {
391         driver = "/dev/binder";
392     }
393 
394     bs = binder_open(driver, 128*1024);
395     if (!bs) {
396 #ifdef VENDORSERVICEMANAGER
397         ALOGW("failed to open binder driver %s\n", driver);
398         while (true) {
399             sleep(UINT_MAX);
400         }
401 #else
402         ALOGE("failed to open binder driver %s\n", driver);
403 #endif
404         return -1;
405     }
406 
407     if (binder_become_context_manager(bs)) {
408         ALOGE("cannot become context manager (%s)\n", strerror(errno));
409         return -1;
410     }
411 
412     cb.func_audit = audit_callback;
413     selinux_set_callback(SELINUX_CB_AUDIT, cb);
414 #ifdef VENDORSERVICEMANAGER
415     cb.func_log = selinux_vendor_log_callback;
416 #else
417     cb.func_log = selinux_log_callback;
418 #endif
419     selinux_set_callback(SELINUX_CB_LOG, cb);
420 
421 #ifdef VENDORSERVICEMANAGER
422     sehandle = selinux_android_vendor_service_context_handle();
423 #else
424     sehandle = selinux_android_service_context_handle();
425 #endif
426     selinux_status_open(true);
427 
428     if (sehandle == NULL) {
429         ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
430         abort();
431     }
432 
433     if (getcon(&service_manager_context) != 0) {
434         ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
435         abort();
436     }
437 
438 
439     binder_loop(bs, svcmgr_handler);
440 
441     return 0;
442 }
443