blob: f142093da5e343393de93ea90cb887f21fdf91ba [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/* Copyright 2008 The Android Open Source Project
2 */
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <errno.h>
7#include <fcntl.h>
8
9#include <private/android_filesystem_config.h>
10
Riley Spahn69154df2014-06-05 11:07:18 -070011#include <selinux/android.h>
12
Mike Lockwood94afecf2012-10-24 10:45:23 -070013#include "binder.h"
14
15#if 0
16#define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
17#define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
18#else
19#define LOG_TAG "ServiceManager"
20#include <cutils/log.h>
21#endif
22
Serban Constantinescu5fb1b882014-01-30 14:07:34 +000023uint32_t svcmgr_handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -070024
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000025const char *str8(const uint16_t *x)
Mike Lockwood94afecf2012-10-24 10:45:23 -070026{
27 static char buf[128];
28 unsigned max = 127;
29 char *p = buf;
30
31 if (x) {
32 while (*x && max--) {
33 *p++ = *x++;
34 }
35 }
36 *p++ = 0;
37 return buf;
38}
39
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000040int str16eq(const uint16_t *a, const char *b)
Mike Lockwood94afecf2012-10-24 10:45:23 -070041{
42 while (*a && *b)
43 if (*a++ != *b++) return 0;
44 if (*a || *b)
45 return 0;
46 return 1;
47}
48
Riley Spahn69154df2014-06-05 11:07:18 -070049static struct selabel_handle* sehandle;
50
51static bool check_mac_perms(const char *name, pid_t spid)
52{
53 if (is_selinux_enabled() <= 0) {
54 return true;
55 }
56
57 bool allowed = false;
58
59 const char *class = "service_manager";
60 const char *perm = "add";
61
62 char *tctx = NULL;
63 char *sctx = NULL;
64
65 if (!sehandle) {
66 ALOGE("SELinux: Failed to find sehandle %s.\n", name);
67 return false;
68 }
69
70 if (getpidcon(spid, &sctx) < 0) {
71 ALOGE("SELinux: getpidcon failed to retrieve pid context.\n");
72 return false;
73 }
74
75 if (!sctx) {
76 ALOGE("SELinux: Failed to find sctx for %s.\n", name);
77 return false;
78 }
79
80 if (selabel_lookup(sehandle, &tctx, name, 1) != 0) {
81 ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name);
82 freecon(sctx);
83 return false;
84 }
85
86 if (!tctx) {
87 ALOGE("SELinux: Failed to find tctx for %s.\n", name);
88 freecon(sctx);
89 return false;
90 }
91
92 int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
93 allowed = (result == 0);
94
95 freecon(sctx);
96 freecon(tctx);
97 return allowed;
98}
99
100static int svc_can_register(uid_t uid, const uint16_t *name, pid_t spid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700101{
Riley Spahn1244edc2014-06-25 15:15:21 -0700102 return check_mac_perms(str8(name), spid) ? 1 : 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700103}
104
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000105struct svcinfo
Mike Lockwood94afecf2012-10-24 10:45:23 -0700106{
107 struct svcinfo *next;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000108 uint32_t handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700109 struct binder_death death;
110 int allow_isolated;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000111 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700112 uint16_t name[0];
113};
114
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000115struct svcinfo *svclist = NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700116
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000117struct svcinfo *find_svc(const uint16_t *s16, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700118{
119 struct svcinfo *si;
120
121 for (si = svclist; si; si = si->next) {
122 if ((len == si->len) &&
123 !memcmp(s16, si->name, len * sizeof(uint16_t))) {
124 return si;
125 }
126 }
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000127 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700128}
129
130void svcinfo_death(struct binder_state *bs, void *ptr)
131{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000132 struct svcinfo *si = (struct svcinfo* ) ptr;
133
Mike Lockwood94afecf2012-10-24 10:45:23 -0700134 ALOGI("service '%s' died\n", str8(si->name));
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000135 if (si->handle) {
136 binder_release(bs, si->handle);
137 si->handle = 0;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000138 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700139}
140
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000141uint16_t svcmgr_id[] = {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700142 'a','n','d','r','o','i','d','.','o','s','.',
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000143 'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
Mike Lockwood94afecf2012-10-24 10:45:23 -0700144};
Mike Lockwood94afecf2012-10-24 10:45:23 -0700145
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000146
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000147uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700148{
149 struct svcinfo *si;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700150
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000151 si = find_svc(s, len);
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000152 //ALOGI("check_service('%s') handle = %x\n", str8(s), si ? si->handle : 0);
153 if (si && si->handle) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700154 if (!si->allow_isolated) {
155 // If this service doesn't allow access from isolated processes,
156 // then check the uid to see if it is isolated.
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000157 uid_t appid = uid % AID_USER;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700158 if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
159 return 0;
160 }
161 }
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000162 return si->handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700163 } else {
164 return 0;
165 }
166}
167
168int do_add_service(struct binder_state *bs,
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000169 const uint16_t *s, size_t len,
Riley Spahn69154df2014-06-05 11:07:18 -0700170 uint32_t handle, uid_t uid, int allow_isolated,
171 pid_t spid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700172{
173 struct svcinfo *si;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000174
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000175 //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s), handle,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700176 // allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
177
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000178 if (!handle || (len == 0) || (len > 127))
Mike Lockwood94afecf2012-10-24 10:45:23 -0700179 return -1;
180
Riley Spahn69154df2014-06-05 11:07:18 -0700181 if (!svc_can_register(uid, s, spid)) {
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000182 ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
183 str8(s), handle, uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700184 return -1;
185 }
186
187 si = find_svc(s, len);
188 if (si) {
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000189 if (si->handle) {
190 ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
191 str8(s), handle, uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700192 svcinfo_death(bs, si);
193 }
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000194 si->handle = handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700195 } else {
196 si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
197 if (!si) {
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000198 ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
199 str8(s), handle, uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700200 return -1;
201 }
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000202 si->handle = handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700203 si->len = len;
204 memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
205 si->name[len] = '\0';
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000206 si->death.func = (void*) svcinfo_death;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700207 si->death.ptr = si;
208 si->allow_isolated = allow_isolated;
209 si->next = svclist;
210 svclist = si;
211 }
212
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000213 binder_acquire(bs, handle);
214 binder_link_to_death(bs, handle, &si->death);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700215 return 0;
216}
217
218int svcmgr_handler(struct binder_state *bs,
Serban Constantinescubcf38882014-01-10 13:56:27 +0000219 struct binder_transaction_data *txn,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700220 struct binder_io *msg,
221 struct binder_io *reply)
222{
223 struct svcinfo *si;
224 uint16_t *s;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000225 size_t len;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000226 uint32_t handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700227 uint32_t strict_policy;
228 int allow_isolated;
229
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000230 //ALOGI("target=%x code=%d pid=%d uid=%d\n",
231 // txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700232
Serban Constantinescubcf38882014-01-10 13:56:27 +0000233 if (txn->target.handle != svcmgr_handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700234 return -1;
235
Arve Hjønnevåge5245cb2014-01-28 21:35:03 -0800236 if (txn->code == PING_TRANSACTION)
237 return 0;
238
Mike Lockwood94afecf2012-10-24 10:45:23 -0700239 // Equivalent to Parcel::enforceInterface(), reading the RPC
240 // header with the strict mode policy mask and the interface name.
241 // Note that we ignore the strict_policy and don't propagate it
242 // further (since we do no outbound RPCs anyway).
243 strict_policy = bio_get_uint32(msg);
244 s = bio_get_string16(msg, &len);
245 if ((len != (sizeof(svcmgr_id) / 2)) ||
246 memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
247 fprintf(stderr,"invalid id %s\n", str8(s));
248 return -1;
249 }
250
Riley Spahn69154df2014-06-05 11:07:18 -0700251 if (sehandle && selinux_status_updated() > 0) {
252 struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
253 if (tmp_sehandle) {
254 selabel_close(sehandle);
255 sehandle = tmp_sehandle;
256 }
257 }
258
Mike Lockwood94afecf2012-10-24 10:45:23 -0700259 switch(txn->code) {
260 case SVC_MGR_GET_SERVICE:
261 case SVC_MGR_CHECK_SERVICE:
262 s = bio_get_string16(msg, &len);
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000263 handle = do_find_service(bs, s, len, txn->sender_euid);
264 if (!handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700265 break;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000266 bio_put_ref(reply, handle);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700267 return 0;
268
269 case SVC_MGR_ADD_SERVICE:
270 s = bio_get_string16(msg, &len);
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000271 handle = bio_get_ref(msg);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700272 allow_isolated = bio_get_uint32(msg) ? 1 : 0;
Riley Spahn69154df2014-06-05 11:07:18 -0700273 if (do_add_service(bs, s, len, handle, txn->sender_euid,
274 allow_isolated, txn->sender_pid))
Mike Lockwood94afecf2012-10-24 10:45:23 -0700275 return -1;
276 break;
277
278 case SVC_MGR_LIST_SERVICES: {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000279 uint32_t n = bio_get_uint32(msg);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700280
281 si = svclist;
282 while ((n-- > 0) && si)
283 si = si->next;
284 if (si) {
285 bio_put_string16(reply, si->name);
286 return 0;
287 }
288 return -1;
289 }
290 default:
291 ALOGE("unknown code %d\n", txn->code);
292 return -1;
293 }
294
295 bio_put_uint32(reply, 0);
296 return 0;
297}
298
Riley Spahn69154df2014-06-05 11:07:18 -0700299
300static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
301{
302 snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
303 return 0;
304}
305
Mike Lockwood94afecf2012-10-24 10:45:23 -0700306int main(int argc, char **argv)
307{
308 struct binder_state *bs;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700309
310 bs = binder_open(128*1024);
Serban Constantinescua44542c2014-01-30 15:16:45 +0000311 if (!bs) {
312 ALOGE("failed to open binder driver\n");
313 return -1;
314 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700315
316 if (binder_become_context_manager(bs)) {
317 ALOGE("cannot become context manager (%s)\n", strerror(errno));
318 return -1;
319 }
320
Riley Spahn69154df2014-06-05 11:07:18 -0700321 sehandle = selinux_android_service_context_handle();
322
323 union selinux_callback cb;
324 cb.func_audit = audit_callback;
325 selinux_set_callback(SELINUX_CB_AUDIT, cb);
326 cb.func_log = selinux_log_callback;
327 selinux_set_callback(SELINUX_CB_LOG, cb);
328
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000329 svcmgr_handle = BINDER_SERVICE_MANAGER;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700330 binder_loop(bs, svcmgr_handler);
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000331
Mike Lockwood94afecf2012-10-24 10:45:23 -0700332 return 0;
333}