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
str8(const uint16_t * x,size_t x_len)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
str16eq(const uint16_t * a,const char * b)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
check_mac_perms(pid_t spid,uid_t uid,const char * tctx,const char * perm,const char * name)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
check_mac_perms_from_getcon(pid_t spid,uid_t uid,const char * perm)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
check_mac_perms_from_lookup(pid_t spid,uid_t uid,const char * perm,const char * name)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
svc_can_register(const uint16_t * name,size_t name_len,pid_t spid,uid_t uid)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
svc_can_list(pid_t spid,uid_t uid)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
svc_can_find(const uint16_t * name,size_t name_len,pid_t spid,uid_t uid)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
find_svc(const uint16_t * s16,size_t len)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
svcinfo_death(struct binder_state * bs,void * ptr)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
do_find_service(const uint16_t * s,size_t len,uid_t uid,pid_t spid)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
do_add_service(struct binder_state * bs,const uint16_t * s,size_t len,uint32_t handle,uid_t uid,int allow_isolated,pid_t spid)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
svcmgr_handler(struct binder_state * bs,struct binder_transaction_data * txn,struct binder_io * msg,struct binder_io * reply)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
audit_callback(void * data,__unused security_class_t cls,char * buf,size_t len)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
main()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