service_manager.c revision 69154df9efd3ffb7580b72a0138f58a2f5443db6
1/* 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 11#include <selinux/android.h> 12 13#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 23/* TODO: 24 * These should come from a config file or perhaps be 25 * based on some namespace rules of some sort (media 26 * uid can register media.*, etc) 27 */ 28static struct { 29 uid_t uid; 30 const char *name; 31} allowed[] = { 32 { AID_MEDIA, "media.audio_flinger" }, 33 { AID_MEDIA, "media.log" }, 34 { AID_MEDIA, "media.player" }, 35 { AID_MEDIA, "media.camera" }, 36 { AID_MEDIA, "media.audio_policy" }, 37 { AID_DRM, "drm.drmManager" }, 38 { AID_NFC, "nfc" }, 39 { AID_BLUETOOTH, "bluetooth" }, 40 { AID_RADIO, "radio.phone" }, 41 { AID_RADIO, "radio.sms" }, 42 { AID_RADIO, "radio.phonesubinfo" }, 43 { AID_RADIO, "radio.simphonebook" }, 44/* TODO: remove after phone services are updated: */ 45 { AID_RADIO, "phone" }, 46 { AID_RADIO, "sip" }, 47 { AID_RADIO, "isms" }, 48 { AID_RADIO, "iphonesubinfo" }, 49 { AID_RADIO, "simphonebook" }, 50 { AID_MEDIA, "common_time.clock" }, 51 { AID_MEDIA, "common_time.config" }, 52 { AID_KEYSTORE, "android.security.keystore" }, 53}; 54 55uint32_t svcmgr_handle; 56 57const char *str8(const uint16_t *x) 58{ 59 static char buf[128]; 60 unsigned max = 127; 61 char *p = buf; 62 63 if (x) { 64 while (*x && max--) { 65 *p++ = *x++; 66 } 67 } 68 *p++ = 0; 69 return buf; 70} 71 72int str16eq(const uint16_t *a, const char *b) 73{ 74 while (*a && *b) 75 if (*a++ != *b++) return 0; 76 if (*a || *b) 77 return 0; 78 return 1; 79} 80 81static struct selabel_handle* sehandle; 82 83static bool check_mac_perms(const char *name, pid_t spid) 84{ 85 if (is_selinux_enabled() <= 0) { 86 return true; 87 } 88 89 bool allowed = false; 90 91 const char *class = "service_manager"; 92 const char *perm = "add"; 93 94 char *tctx = NULL; 95 char *sctx = NULL; 96 97 if (!sehandle) { 98 ALOGE("SELinux: Failed to find sehandle %s.\n", name); 99 return false; 100 } 101 102 if (getpidcon(spid, &sctx) < 0) { 103 ALOGE("SELinux: getpidcon failed to retrieve pid context.\n"); 104 return false; 105 } 106 107 if (!sctx) { 108 ALOGE("SELinux: Failed to find sctx for %s.\n", name); 109 return false; 110 } 111 112 if (selabel_lookup(sehandle, &tctx, name, 1) != 0) { 113 ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name); 114 freecon(sctx); 115 return false; 116 } 117 118 if (!tctx) { 119 ALOGE("SELinux: Failed to find tctx for %s.\n", name); 120 freecon(sctx); 121 return false; 122 } 123 124 int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); 125 allowed = (result == 0); 126 127 freecon(sctx); 128 freecon(tctx); 129 return allowed; 130} 131 132static int svc_can_register(uid_t uid, const uint16_t *name, pid_t spid) 133{ 134 size_t n; 135 136 if ((uid == 0) || (uid == AID_SYSTEM)) 137 return check_mac_perms(str8(name), spid) ? 1 : 0; 138 139 for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++) 140 if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name)) 141 return check_mac_perms(str8(name), spid) ? 1 : 0; 142 143 return 0; 144} 145 146struct 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 156struct svcinfo *svclist = NULL; 157 158struct 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 171void 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)); 176 if (si->handle) { 177 binder_release(bs, si->handle); 178 si->handle = 0; 179 } 180} 181 182uint16_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 188uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid) 189{ 190 struct svcinfo *si; 191 192 si = find_svc(s, len); 193 //ALOGI("check_service('%s') handle = %x\n", str8(s), si ? si->handle : 0); 194 if (si && si->handle) { 195 if (!si->allow_isolated) { 196 // If this service doesn't allow access from isolated processes, 197 // then check the uid to see if it is isolated. 198 uid_t appid = uid % AID_USER; 199 if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { 200 return 0; 201 } 202 } 203 return si->handle; 204 } else { 205 return 0; 206 } 207} 208 209int do_add_service(struct binder_state *bs, 210 const uint16_t *s, size_t len, 211 uint32_t handle, uid_t uid, int allow_isolated, 212 pid_t spid) 213{ 214 struct svcinfo *si; 215 216 //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s), handle, 217 // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); 218 219 if (!handle || (len == 0) || (len > 127)) 220 return -1; 221 222 if (!svc_can_register(uid, s, spid)) { 223 ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", 224 str8(s), handle, uid); 225 return -1; 226 } 227 228 si = find_svc(s, len); 229 if (si) { 230 if (si->handle) { 231 ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", 232 str8(s), handle, uid); 233 svcinfo_death(bs, si); 234 } 235 si->handle = handle; 236 } else { 237 si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); 238 if (!si) { 239 ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", 240 str8(s), handle, uid); 241 return -1; 242 } 243 si->handle = handle; 244 si->len = len; 245 memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); 246 si->name[len] = '\0'; 247 si->death.func = (void*) svcinfo_death; 248 si->death.ptr = si; 249 si->allow_isolated = allow_isolated; 250 si->next = svclist; 251 svclist = si; 252 } 253 254 binder_acquire(bs, handle); 255 binder_link_to_death(bs, handle, &si->death); 256 return 0; 257} 258 259int svcmgr_handler(struct binder_state *bs, 260 struct binder_transaction_data *txn, 261 struct binder_io *msg, 262 struct binder_io *reply) 263{ 264 struct svcinfo *si; 265 uint16_t *s; 266 size_t len; 267 uint32_t handle; 268 uint32_t strict_policy; 269 int allow_isolated; 270 271 //ALOGI("target=%x code=%d pid=%d uid=%d\n", 272 // txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid); 273 274 if (txn->target.handle != svcmgr_handle) 275 return -1; 276 277 if (txn->code == PING_TRANSACTION) 278 return 0; 279 280 // Equivalent to Parcel::enforceInterface(), reading the RPC 281 // header with the strict mode policy mask and the interface name. 282 // Note that we ignore the strict_policy and don't propagate it 283 // further (since we do no outbound RPCs anyway). 284 strict_policy = bio_get_uint32(msg); 285 s = bio_get_string16(msg, &len); 286 if ((len != (sizeof(svcmgr_id) / 2)) || 287 memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { 288 fprintf(stderr,"invalid id %s\n", str8(s)); 289 return -1; 290 } 291 292 if (sehandle && selinux_status_updated() > 0) { 293 struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); 294 if (tmp_sehandle) { 295 selabel_close(sehandle); 296 sehandle = tmp_sehandle; 297 } 298 } 299 300 switch(txn->code) { 301 case SVC_MGR_GET_SERVICE: 302 case SVC_MGR_CHECK_SERVICE: 303 s = bio_get_string16(msg, &len); 304 handle = do_find_service(bs, s, len, txn->sender_euid); 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 handle = bio_get_ref(msg); 313 allow_isolated = bio_get_uint32(msg) ? 1 : 0; 314 if (do_add_service(bs, s, len, handle, txn->sender_euid, 315 allow_isolated, txn->sender_pid)) 316 return -1; 317 break; 318 319 case SVC_MGR_LIST_SERVICES: { 320 uint32_t n = bio_get_uint32(msg); 321 322 si = svclist; 323 while ((n-- > 0) && si) 324 si = si->next; 325 if (si) { 326 bio_put_string16(reply, si->name); 327 return 0; 328 } 329 return -1; 330 } 331 default: 332 ALOGE("unknown code %d\n", txn->code); 333 return -1; 334 } 335 336 bio_put_uint32(reply, 0); 337 return 0; 338} 339 340 341static int audit_callback(void *data, security_class_t cls, char *buf, size_t len) 342{ 343 snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data); 344 return 0; 345} 346 347int main(int argc, char **argv) 348{ 349 struct binder_state *bs; 350 351 bs = binder_open(128*1024); 352 if (!bs) { 353 ALOGE("failed to open binder driver\n"); 354 return -1; 355 } 356 357 if (binder_become_context_manager(bs)) { 358 ALOGE("cannot become context manager (%s)\n", strerror(errno)); 359 return -1; 360 } 361 362 sehandle = selinux_android_service_context_handle(); 363 364 union selinux_callback cb; 365 cb.func_audit = audit_callback; 366 selinux_set_callback(SELINUX_CB_AUDIT, cb); 367 cb.func_log = selinux_log_callback; 368 selinux_set_callback(SELINUX_CB_LOG, cb); 369 370 svcmgr_handle = BINDER_SERVICE_MANAGER; 371 binder_loop(bs, svcmgr_handler); 372 373 return 0; 374} 375