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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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