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 <private/android_filesystem_config.h> 12 13 #include <selinux/android.h> 14 #include <selinux/avc.h> 15 16 #include "binder.h" 17 18 #if 0 19 #define ALOGI(x...) fprintf(stderr, "svcmgr: " x) 20 #define ALOGE(x...) fprintf(stderr, "svcmgr: " x) 21 #else 22 #define LOG_TAG "ServiceManager" 23 #include <cutils/log.h> 24 #endif 25 26 const char *str8(const uint16_t *x, size_t x_len) 27 { 28 static char buf[128]; 29 size_t max = 127; 30 char *p = buf; 31 32 if (x_len < max) { 33 max = x_len; 34 } 35 36 if (x) { 37 while ((max > 0) && (*x != '\0')) { 38 *p++ = *x++; 39 max--; 40 } 41 } 42 *p++ = 0; 43 return buf; 44 } 45 46 int str16eq(const uint16_t *a, const char *b) 47 { 48 while (*a && *b) 49 if (*a++ != *b++) return 0; 50 if (*a || *b) 51 return 0; 52 return 1; 53 } 54 55 static int selinux_enabled; 56 static char *service_manager_context; 57 static struct selabel_handle* sehandle; 58 59 static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name) 60 { 61 char *sctx = NULL; 62 const char *class = "service_manager"; 63 bool allowed; 64 65 if (getpidcon(spid, &sctx) < 0) { 66 ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); 67 return false; 68 } 69 70 int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); 71 allowed = (result == 0); 72 73 freecon(sctx); 74 return allowed; 75 } 76 77 static bool check_mac_perms_from_getcon(pid_t spid, const char *perm) 78 { 79 if (selinux_enabled <= 0) { 80 return true; 81 } 82 83 return check_mac_perms(spid, service_manager_context, perm, NULL); 84 } 85 86 static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name) 87 { 88 bool allowed; 89 char *tctx = NULL; 90 91 if (selinux_enabled <= 0) { 92 return true; 93 } 94 95 if (!sehandle) { 96 ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n"); 97 abort(); 98 } 99 100 if (selabel_lookup(sehandle, &tctx, name, 0) != 0) { 101 ALOGE("SELinux: No match for %s in service_contexts.\n", name); 102 return false; 103 } 104 105 allowed = check_mac_perms(spid, tctx, perm, name); 106 freecon(tctx); 107 return allowed; 108 } 109 110 static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid) 111 { 112 const char *perm = "add"; 113 return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; 114 } 115 116 static int svc_can_list(pid_t spid) 117 { 118 const char *perm = "list"; 119 return check_mac_perms_from_getcon(spid, perm) ? 1 : 0; 120 } 121 122 static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid) 123 { 124 const char *perm = "find"; 125 return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; 126 } 127 128 struct svcinfo 129 { 130 struct svcinfo *next; 131 uint32_t handle; 132 struct binder_death death; 133 int allow_isolated; 134 size_t len; 135 uint16_t name[0]; 136 }; 137 138 struct svcinfo *svclist = NULL; 139 140 struct svcinfo *find_svc(const uint16_t *s16, size_t len) 141 { 142 struct svcinfo *si; 143 144 for (si = svclist; si; si = si->next) { 145 if ((len == si->len) && 146 !memcmp(s16, si->name, len * sizeof(uint16_t))) { 147 return si; 148 } 149 } 150 return NULL; 151 } 152 153 void svcinfo_death(struct binder_state *bs, void *ptr) 154 { 155 struct svcinfo *si = (struct svcinfo* ) ptr; 156 157 ALOGI("service '%s' died\n", str8(si->name, si->len)); 158 if (si->handle) { 159 binder_release(bs, si->handle); 160 si->handle = 0; 161 } 162 } 163 164 uint16_t svcmgr_id[] = { 165 'a','n','d','r','o','i','d','.','o','s','.', 166 'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r' 167 }; 168 169 170 uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid) 171 { 172 struct svcinfo *si = find_svc(s, len); 173 174 if (!si || !si->handle) { 175 return 0; 176 } 177 178 if (!si->allow_isolated) { 179 // If this service doesn't allow access from isolated processes, 180 // then check the uid to see if it is isolated. 181 uid_t appid = uid % AID_USER; 182 if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { 183 return 0; 184 } 185 } 186 187 if (!svc_can_find(s, len, spid)) { 188 return 0; 189 } 190 191 return si->handle; 192 } 193 194 int do_add_service(struct binder_state *bs, 195 const uint16_t *s, size_t len, 196 uint32_t handle, uid_t uid, int allow_isolated, 197 pid_t spid) 198 { 199 struct svcinfo *si; 200 201 //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle, 202 // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); 203 204 if (!handle || (len == 0) || (len > 127)) 205 return -1; 206 207 if (!svc_can_register(s, len, spid)) { 208 ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", 209 str8(s, len), handle, uid); 210 return -1; 211 } 212 213 si = find_svc(s, len); 214 if (si) { 215 if (si->handle) { 216 ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", 217 str8(s, len), handle, uid); 218 svcinfo_death(bs, si); 219 } 220 si->handle = handle; 221 } else { 222 si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); 223 if (!si) { 224 ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", 225 str8(s, len), handle, uid); 226 return -1; 227 } 228 si->handle = handle; 229 si->len = len; 230 memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); 231 si->name[len] = '\0'; 232 si->death.func = (void*) svcinfo_death; 233 si->death.ptr = si; 234 si->allow_isolated = allow_isolated; 235 si->next = svclist; 236 svclist = si; 237 } 238 239 binder_acquire(bs, handle); 240 binder_link_to_death(bs, handle, &si->death); 241 return 0; 242 } 243 244 int svcmgr_handler(struct binder_state *bs, 245 struct binder_transaction_data *txn, 246 struct binder_io *msg, 247 struct binder_io *reply) 248 { 249 struct svcinfo *si; 250 uint16_t *s; 251 size_t len; 252 uint32_t handle; 253 uint32_t strict_policy; 254 int allow_isolated; 255 256 //ALOGI("target=%p code=%d pid=%d uid=%d\n", 257 // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); 258 259 if (txn->target.ptr != BINDER_SERVICE_MANAGER) 260 return -1; 261 262 if (txn->code == PING_TRANSACTION) 263 return 0; 264 265 // Equivalent to Parcel::enforceInterface(), reading the RPC 266 // header with the strict mode policy mask and the interface name. 267 // Note that we ignore the strict_policy and don't propagate it 268 // further (since we do no outbound RPCs anyway). 269 strict_policy = bio_get_uint32(msg); 270 s = bio_get_string16(msg, &len); 271 if (s == NULL) { 272 return -1; 273 } 274 275 if ((len != (sizeof(svcmgr_id) / 2)) || 276 memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { 277 fprintf(stderr,"invalid id %s\n", str8(s, len)); 278 return -1; 279 } 280 281 if (sehandle && selinux_status_updated() > 0) { 282 struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); 283 if (tmp_sehandle) { 284 selabel_close(sehandle); 285 sehandle = tmp_sehandle; 286 } 287 } 288 289 switch(txn->code) { 290 case SVC_MGR_GET_SERVICE: 291 case SVC_MGR_CHECK_SERVICE: 292 s = bio_get_string16(msg, &len); 293 if (s == NULL) { 294 return -1; 295 } 296 handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); 297 if (!handle) 298 break; 299 bio_put_ref(reply, handle); 300 return 0; 301 302 case SVC_MGR_ADD_SERVICE: 303 s = bio_get_string16(msg, &len); 304 if (s == NULL) { 305 return -1; 306 } 307 handle = bio_get_ref(msg); 308 allow_isolated = bio_get_uint32(msg) ? 1 : 0; 309 if (do_add_service(bs, s, len, handle, txn->sender_euid, 310 allow_isolated, txn->sender_pid)) 311 return -1; 312 break; 313 314 case SVC_MGR_LIST_SERVICES: { 315 uint32_t n = bio_get_uint32(msg); 316 317 if (!svc_can_list(txn->sender_pid)) { 318 ALOGE("list_service() uid=%d - PERMISSION DENIED\n", 319 txn->sender_euid); 320 return -1; 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 341 static 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 347 int 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 selinux_enabled = is_selinux_enabled(); 363 sehandle = selinux_android_service_context_handle(); 364 selinux_status_open(true); 365 366 if (selinux_enabled > 0) { 367 if (sehandle == NULL) { 368 ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); 369 abort(); 370 } 371 372 if (getcon(&service_manager_context) != 0) { 373 ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); 374 abort(); 375 } 376 } 377 378 union selinux_callback cb; 379 cb.func_audit = audit_callback; 380 selinux_set_callback(SELINUX_CB_AUDIT, cb); 381 cb.func_log = selinux_log_callback; 382 selinux_set_callback(SELINUX_CB_LOG, cb); 383 384 binder_loop(bs, svcmgr_handler); 385 386 return 0; 387 } 388