├── Android.mk ├── bctest.c ├── binder.h ├── fuzz.c ├── service_manager.c └── binder.c /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | svc_c_flags = \ 4 | -Wall -Wextra \ 5 | 6 | ifneq ($(TARGET_USES_64_BIT_BINDER),true) 7 | ifneq ($(TARGET_IS_64_BIT),true) 8 | svc_c_flags += -DBINDER_IPC_32BIT=1 9 | endif 10 | endif 11 | 12 | include $(CLEAR_VARS) 13 | LOCAL_SHARED_LIBRARIES := liblog 14 | LOCAL_SRC_FILES := bctest.c binder.c fuzz.c 15 | LOCAL_CFLAGS += $(svc_c_flags) 16 | LOCAL_MODULE := bctest 17 | LOCAL_MODULE_TAGS := optional 18 | include $(BUILD_EXECUTABLE) 19 | 20 | include $(CLEAR_VARS) 21 | LOCAL_SHARED_LIBRARIES := liblog 22 | LOCAL_SRC_FILES := service_manager.c binder.c 23 | LOCAL_CFLAGS += $(svc_c_flags) 24 | LOCAL_MODULE := servicemanager 25 | LOCAL_INIT_RC := servicemanager.rc 26 | include $(BUILD_EXECUTABLE) 27 | -------------------------------------------------------------------------------- /bctest.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2008 The Android Open Source Project 2 | */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "binder.h" 10 | 11 | uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name) 12 | { 13 | uint32_t handle; 14 | unsigned iodata[512/4]; 15 | struct binder_io msg, reply; 16 | 17 | bio_init(&msg, iodata, sizeof(iodata), 4); 18 | bio_put_uint32(&msg, 0); // strict mode header 19 | bio_put_string16_x(&msg, SVC_MGR_NAME); 20 | bio_put_string16_x(&msg, name); 21 | 22 | if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE)) 23 | return 0; 24 | 25 | handle = bio_get_ref(&reply); 26 | 27 | if (handle) 28 | binder_acquire(bs, handle); 29 | 30 | binder_done(bs, &msg, &reply); 31 | 32 | return handle; 33 | } 34 | 35 | int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr) 36 | { 37 | int status; 38 | unsigned iodata[512/4]; 39 | struct binder_io msg, reply; 40 | 41 | bio_init(&msg, iodata, sizeof(iodata), 4); 42 | bio_put_uint32(&msg, 0); // strict mode header 43 | bio_put_string16_x(&msg, SVC_MGR_NAME); 44 | bio_put_string16_x(&msg, name); 45 | bio_put_obj(&msg, ptr); 46 | 47 | if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE)) 48 | return -1; 49 | 50 | status = bio_get_uint32(&reply); 51 | 52 | binder_done(bs, &msg, &reply); 53 | 54 | return status; 55 | } 56 | 57 | unsigned token; 58 | 59 | int main(int argc, char **argv) 60 | { 61 | int fd; 62 | struct binder_state *bs; 63 | uint32_t svcmgr = BINDER_SERVICE_MANAGER; 64 | uint32_t handle; 65 | 66 | bs = binder_open(128*1024); 67 | if (!bs) { 68 | fprintf(stderr, "failed to open binder driver\n"); 69 | return -1; 70 | } 71 | 72 | argc--; 73 | argv++; 74 | while (argc > 0) { 75 | if (!strcmp(argv[0],"alt")) { 76 | handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr"); 77 | if (!handle) { 78 | fprintf(stderr,"cannot find alt_svc_mgr\n"); 79 | return -1; 80 | } 81 | svcmgr = handle; 82 | fprintf(stderr,"svcmgr is via %x\n", handle); 83 | } else if (!strcmp(argv[0],"lookup")) { 84 | if (argc < 2) { 85 | fprintf(stderr,"argument required\n"); 86 | return -1; 87 | } 88 | handle = svcmgr_lookup(bs, svcmgr, argv[1]); 89 | fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle); 90 | argc--; 91 | argv++; 92 | } else if (!strcmp(argv[0],"publish")) { 93 | if (argc < 2) { 94 | fprintf(stderr,"argument required\n"); 95 | return -1; 96 | } 97 | svcmgr_publish(bs, svcmgr, argv[1], &token); 98 | argc--; 99 | argv++; 100 | } else { 101 | fprintf(stderr,"unknown command %s\n", argv[0]); 102 | return -1; 103 | } 104 | argc--; 105 | argv++; 106 | } 107 | return 0; 108 | } 109 | -------------------------------------------------------------------------------- /binder.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2008 The Android Open Source Project 2 | */ 3 | 4 | #ifndef _BINDER_H_ 5 | #define _BINDER_H_ 6 | 7 | #include 8 | #include 9 | 10 | struct binder_state; 11 | 12 | struct binder_io 13 | { 14 | char *data; /* pointer to read/write from */ 15 | binder_size_t *offs; /* array of offsets */ 16 | size_t data_avail; /* bytes available in data buffer */ 17 | size_t offs_avail; /* entries available in offsets array */ 18 | 19 | char *data0; /* start of data buffer */ 20 | binder_size_t *offs0; /* start of offsets buffer */ 21 | uint32_t flags; 22 | uint32_t unused; 23 | }; 24 | 25 | struct binder_death { 26 | void (*func)(struct binder_state *bs, void *ptr); 27 | void *ptr; 28 | }; 29 | 30 | struct binder_handle { 31 | uint32_t handle; 32 | uint16_t *str; 33 | } 34 | 35 | 36 | /* the one magic handle */ 37 | #define BINDER_SERVICE_MANAGER 0U 38 | 39 | #define SVC_MGR_NAME "android.os.IServiceManager" 40 | 41 | enum { 42 | /* Must match definitions in IBinder.h and IServiceManager.h */ 43 | PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'), 44 | SVC_MGR_GET_SERVICE = 1, 45 | SVC_MGR_CHECK_SERVICE, 46 | SVC_MGR_ADD_SERVICE, 47 | SVC_MGR_LIST_SERVICES, 48 | }; 49 | 50 | enum transaction_flags { 51 | TF_ONE_WAY = 0x01, 52 | TF_ROOT_OBJECT = 0x04, 53 | TF_STATUS_CODE = 0x08, 54 | TF_ACCEPT_FDS = 0x10, 55 | }; 56 | 57 | 58 | typedef int (*binder_handler)(struct binder_state *bs, 59 | struct binder_transaction_data *txn, 60 | struct binder_io *msg, 61 | struct binder_io *reply); 62 | 63 | struct binder_state *binder_open(size_t mapsize); 64 | void binder_close(struct binder_state *bs); 65 | 66 | /* initiate a blocking binder call 67 | * - returns zero on success 68 | */ 69 | int binder_call(struct binder_state *bs, 70 | struct binder_io *msg, struct binder_io *reply, 71 | uint32_t target, uint32_t code); 72 | 73 | /* release any state associate with the binder_io 74 | * - call once any necessary data has been extracted from the 75 | * binder_io after binder_call() returns 76 | * - can safely be called even if binder_call() fails 77 | */ 78 | void binder_done(struct binder_state *bs, 79 | struct binder_io *msg, struct binder_io *reply); 80 | 81 | /* manipulate strong references */ 82 | void binder_acquire(struct binder_state *bs, uint32_t target); 83 | void binder_release(struct binder_state *bs, uint32_t target); 84 | 85 | void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death); 86 | 87 | void binder_loop(struct binder_state *bs, binder_handler func); 88 | 89 | int binder_become_context_manager(struct binder_state *bs); 90 | 91 | /* allocate a binder_io, providing a stack-allocated working 92 | * buffer, size of the working buffer, and how many object 93 | * offset entries to reserve from the buffer 94 | */ 95 | void bio_init(struct binder_io *bio, void *data, 96 | size_t maxdata, size_t maxobjects); 97 | 98 | void bio_put_obj(struct binder_io *bio, void *ptr); 99 | void bio_put_ref(struct binder_io *bio, uint32_t handle); 100 | void bio_put_uint32(struct binder_io *bio, uint32_t n); 101 | void bio_put_string16(struct binder_io *bio, const uint16_t *str); 102 | void bio_put_string16_x(struct binder_io *bio, const char *_str); 103 | 104 | uint32_t bio_get_uint32(struct binder_io *bio); 105 | uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz); 106 | uint32_t bio_get_ref(struct binder_io *bio); 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /fuzz.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static const uint16_t NO_HANDLE[] = {'n','o','h','a','n','d','l','e','\0'}; 6 | 7 | typedef binder_driver_command_protocol binder_command_type 8 | 9 | /* Hand crafted organic artisan integers created after years of R&D 10 | * to wreak havoc on naive code. 11 | */ 12 | 13 | static int havoc_ints[] = 14 | { 15 | 0x00000000, 0x00000001, 0x00000002, 16 | 0x0000003, //add more ints on this line, its killing my ocd just having one 17 | 0x80000000, 0x80000001, 0xFFFFFFFF, 18 | 0xFFFFFFFE, 0x7FFFFFFF, 0x7FFFFFFE 19 | }; 20 | 21 | 22 | /* Length in bytes */ 23 | static void bit_flip(void *buffer, unsigned int length) { 24 | 25 | } 26 | 27 | /* Length in bytes */ 28 | static void byte_flip(void *buffer, unsigned int length) { 29 | 30 | } 31 | 32 | /* Length in bytes */ 33 | static void byte_shift(void *buffer, unsigned int length) { 34 | 35 | } 36 | 37 | static uint32_t get_handle(struct binder_handle *ptr) { 38 | if (rand() % 2) { 39 | get_random_handle(ptr); 40 | return ptr->handle; 41 | } 42 | 43 | ptr->handle = (uint32_t) rand(); 44 | ptr->str = NO_HANDLE; 45 | return ptr->handle; 46 | } 47 | 48 | static uint32_t get_cookie(void) { 49 | /* TODO pick from our hand crafted ints */ 50 | return (uint32_t) rand(); 51 | } 52 | 53 | static int get_transaction_flags(void) { 54 | static int flag_perms[] = { 55 | TF_ONE_WAY, 56 | TF_ONE_WAY | TF_ROOT_OBJECT, 57 | TF_ONE_WAY | TF_ROOT_OBJECT | TF_STATUS_CODE, 58 | TF_ONE_WAY | TF_ROOT_OBJECT | TF_STATUS_CODE | TF_ACCEPT_FDS, 59 | TF_ONE_WAY | TF_ROOT_OBJECT | TF_ACCEPT_FDS, 60 | TF_ONE_WAY | TF_STATUS_CODE, 61 | TF_ONE_WAY | TF_STATUS_CODE | TF_ACCEPT_FDS, 62 | TF_ONE_WAY | TF_ACCEPT_FDS, 63 | TF_ROOT_OBJECT, 64 | TF_ROOT_OBJECT | TF_STATUS_CODE, 65 | TF_ROOT_OBJECT | TF_STATUS_CODE | TF_ACCEPT_FDS, 66 | TF_ROOT_OBJECT | TF_ACCEPT_FDS, 67 | TF_STATUS_CODE, 68 | TF_STATUS_CODE | TF_ACCEPT_FDS, 69 | TF_ACCEPT_FDS 70 | }; 71 | return flag_perms[rand % 16]; 72 | } 73 | 74 | 75 | static void *gen_transaction(void) { 76 | struct binder_transaction_data *data; 77 | data = malloc(sizeof(*data)); 78 | if (!data) { 79 | fprintf(stderr, "couldn't generate trans, malloc failed\n"); 80 | return NULL; 81 | } 82 | struct binder_handle temp; 83 | data->target.ptr = get_handle(&temp); 84 | data->cookie = get_cookie(); 85 | data->code = get_transaction_flags(); 86 | /* maybe a havoc int? */ 87 | data->data_size = get_transaction_data_size(); 88 | data->offsets_size = get_offsets_size(); 89 | data->data.ptr.buffer = 90 | get_transaction_data(data->data_size, data->offsets_size); 91 | data->data.ptr.offsets = 92 | get_transaction_offsets(data->data_size, data->offsets_size, 93 | data->data.ptr.buffer); 94 | 95 | 96 | /* TODO send to bit/byte flippers shifters */ 97 | /* TODO figure out how to free all this memory im mallocing */ 98 | return data; 99 | 100 | } 101 | 102 | 103 | void *generate_data_for(binder_command_type type) { 104 | 105 | switch(type) { 106 | case BC_TRANSACTION: 107 | return gen_transaction(); 108 | case BC_ACQUIRE_RESULT: 109 | case BC_FREE_BUFFER: 110 | case BC_INCREFS: 111 | case BC_ACQUIRE: 112 | case BC_RELEASE: 113 | case BC_DECREFS: 114 | case BC_INCREFS_DONE: 115 | case BC_ACQUIRE_DONE: 116 | case BC_ATTEMPT_ACQUIRE: 117 | case BC_REGISTER_LOOPER: 118 | case BC_ENTER_LOOPER: 119 | case BC_EXIT_LOOPER: 120 | case BC_REQUEST_DEATH_NOTIFICATION: 121 | case BC_CLEAR_DEATH_NOTIFICATION: 122 | case BC_DEAD_BINDER_DONE: 123 | default: 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /service_manager.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2008 The Android Open Source Project 2 | */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 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 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 | a{ 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 | if (!svc_can_list(txn->sender_pid)) { 317 | ALOGE("list_service() uid=%d - PERMISSION DENIED\n", 318 | txn->sender_euid); 319 | return -1; 320 | } 321 | si = svclist; 322 | while ((n-- > 0) && si) 323 | si = si->next; 324 | if (si) { 325 | bio_put_string16(reply, si->name); 326 | return 0; 327 | } 328 | return -1; 329 | } 330 | default: 331 | ALOGE("unknown code %d\n", txn->code); 332 | return -1; 333 | } 334 | 335 | bio_put_uint32(reply, 0); 336 | return 0; 337 | } 338 | 339 | 340 | static int audit_callback(void *data, security_class_t cls, char *buf, size_t len) 341 | { 342 | snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data); 343 | return 0; 344 | } 345 | 346 | int main(int argc, char **argv) 347 | { 348 | struct binder_state *bs; 349 | 350 | bs = binder_open(128*1024); 351 | if (!bs) { 352 | ALOGE("failed to open binder driver\n"); 353 | return -1; 354 | } 355 | 356 | if (binder_become_context_manager(bs)) { 357 | ALOGE("cannot become context manager (%s)\n", strerror(errno)); 358 | return -1; 359 | } 360 | 361 | selinux_enabled = is_selinux_enabled(); 362 | sehandle = selinux_android_service_context_handle(); 363 | selinux_status_open(true); 364 | 365 | if (selinux_enabled > 0) { 366 | if (sehandle == NULL) { 367 | ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); 368 | abort(); 369 | } 370 | 371 | if (getcon(&service_manager_context) != 0) { 372 | ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); 373 | abort(); 374 | } 375 | } 376 | 377 | union selinux_callback cb; 378 | cb.func_audit = audit_callback; 379 | selinux_set_callback(SELINUX_CB_AUDIT, cb); 380 | cb.func_log = selinux_log_callback; 381 | selinux_set_callback(SELINUX_CB_LOG, cb); 382 | 383 | binder_loop(bs, svcmgr_handler); 384 | 385 | return 0; 386 | } 387 | -------------------------------------------------------------------------------- /binder.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2008 The Android Open Source Project 2 | */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "binder.h" 14 | 15 | #define MAX_BIO_SIZE (1 << 30) 16 | 17 | #define TRACE 0 18 | 19 | #define LOG_TAG "Binder" 20 | #include 21 | 22 | const int verbose = 0; 23 | 24 | #define MAX_SERVICES 400 25 | static uint16_t *services[400]; 26 | static uint32_t handles[400]; 27 | static uint32_t num_handles_set; 28 | 29 | 30 | void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn); 31 | 32 | #if TRACE 33 | void hexdump(void *_data, size_t len) 34 | { 35 | unsigned char *data = _data; 36 | size_t count; 37 | 38 | for (count = 0; count < len; count++) { 39 | if ((count & 15) == 0) 40 | fprintf(stderr,"%04zu:", count); 41 | fprintf(stderr," %02x %c", *data, 42 | (*data < 32) || (*data > 126) ? '.' : *data); 43 | data++; 44 | if ((count & 15) == 15) 45 | fprintf(stderr,"\n"); 46 | } 47 | if ((count & 15) != 0) 48 | fprintf(stderr,"\n"); 49 | } 50 | 51 | void binder_dump_txn(struct binder_transaction_data *txn) 52 | { 53 | struct flat_binder_object *obj; 54 | binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets; 55 | size_t count = txn->offsets_size / sizeof(binder_size_t); 56 | 57 | fprintf(stderr," target %016"PRIx64" cookie %016"PRIx64" code %08x flags %08x\n", 58 | (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags); 59 | fprintf(stderr," pid %8d uid %8d data %"PRIu64" offs %"PRIu64"\n", 60 | txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size); 61 | hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size); 62 | while (count--) { 63 | obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++); 64 | fprintf(stderr," - type %08x flags %08x ptr %016"PRIx64" cookie %016"PRIx64"\n", 65 | obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie); 66 | } 67 | } 68 | 69 | #define NAME(n) case n: return #n 70 | const char *cmd_name(uint32_t cmd) 71 | { 72 | switch(cmd) { 73 | NAME(BR_NOOP); 74 | NAME(BR_TRANSACTION_COMPLETE); 75 | NAME(BR_INCREFS); 76 | NAME(BR_ACQUIRE); 77 | NAME(BR_RELEASE); 78 | NAME(BR_DECREFS); 79 | NAME(BR_TRANSACTION); 80 | NAME(BR_REPLY); 81 | NAME(BR_FAILED_REPLY); 82 | NAME(BR_DEAD_REPLY); 83 | NAME(BR_DEAD_BINDER); 84 | default: return "???"; 85 | } 86 | } 87 | #else 88 | #define hexdump(a,b) do{} while (0) 89 | #define binder_dump_txn(txn) do{} while (0) 90 | #endif 91 | 92 | #define BIO_F_SHARED 0x01 /* needs to be buffer freed */ 93 | #define BIO_F_OVERFLOW 0x02 /* ran out of space */ 94 | #define BIO_F_IOERROR 0x04 95 | #define BIO_F_MALLOCED 0x08 /* needs to be free()'d */ 96 | 97 | struct binder_state 98 | { 99 | int fd; 100 | void *mapped; 101 | size_t mapsize; 102 | }; 103 | 104 | struct binder_state *binder_open(size_t mapsize) 105 | { 106 | struct binder_state *bs; 107 | struct binder_version vers; 108 | 109 | bs = malloc(sizeof(*bs)); 110 | if (!bs) { 111 | errno = ENOMEM; 112 | return NULL; 113 | } 114 | 115 | bs->fd = open("/dev/binder", O_RDWR); 116 | if (bs->fd < 0) { 117 | fprintf(stderr,"binder: cannot open device (%s)\n", 118 | strerror(errno)); 119 | goto fail_open; 120 | } 121 | 122 | if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || 123 | (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { 124 | fprintf(stderr, 125 | "binder: kernel driver version (%d) differs from user space version (%d)\n", 126 | vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); 127 | goto fail_open; 128 | } 129 | 130 | bs->mapsize = mapsize; 131 | bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 132 | if (bs->mapped == MAP_FAILED) { 133 | fprintf(stderr,"binder: cannot map device (%s)\n", 134 | strerror(errno)); 135 | goto fail_map; 136 | } 137 | 138 | return bs; 139 | 140 | fail_map: 141 | close(bs->fd); 142 | fail_open: 143 | free(bs); 144 | return NULL; 145 | } 146 | 147 | void binder_close(struct binder_state *bs) 148 | { 149 | munmap(bs->mapped, bs->mapsize); 150 | close(bs->fd); 151 | free(bs); 152 | } 153 | 154 | 155 | int binder_write(struct binder_state *bs, void *data, size_t len) 156 | { 157 | struct binder_write_read bwr; 158 | int res; 159 | 160 | bwr.write_size = len; 161 | bwr.write_consumed = 0; 162 | bwr.write_buffer = (uintptr_t) data; 163 | bwr.read_size = 0; 164 | bwr.read_consumed = 0; 165 | bwr.read_buffer = 0; 166 | res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 167 | if (res < 0) { 168 | fprintf(stderr,"binder_write: ioctl failed (%s)\n", 169 | strerror(errno)); 170 | } 171 | return res; 172 | } 173 | 174 | void binder_send_reply(struct binder_state *bs, 175 | struct binder_io *reply, 176 | binder_uintptr_t buffer_to_free, 177 | int status) 178 | { 179 | struct { 180 | uint32_t cmd_free; 181 | binder_uintptr_t buffer; 182 | uint32_t cmd_reply; 183 | struct binder_transaction_data txn; 184 | } __attribute__((packed)) data; 185 | 186 | data.cmd_free = BC_FREE_BUFFER; 187 | data.buffer = buffer_to_free; 188 | data.cmd_reply = BC_REPLY; 189 | data.txn.target.ptr = 0; 190 | data.txn.cookie = 0; 191 | data.txn.code = 0; 192 | if (status) { 193 | data.txn.flags = TF_STATUS_CODE; 194 | data.txn.data_size = sizeof(int); 195 | data.txn.offsets_size = 0; 196 | data.txn.data.ptr.buffer = (uintptr_t)&status; 197 | data.txn.data.ptr.offsets = 0; 198 | } else { 199 | data.txn.flags = 0; 200 | data.txn.data_size = reply->data - reply->data0; 201 | data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0); 202 | data.txn.data.ptr.buffer = (uintptr_t)reply->data0; 203 | data.txn.data.ptr.offsets = (uintptr_t)reply->offs0; 204 | } 205 | binder_write(bs, &data, sizeof(data)); 206 | } 207 | 208 | int binder_parse(struct binder_state *bs, struct binder_io *bio, 209 | uintptr_t ptr, size_t size, binder_handler func) 210 | { 211 | int r = 1; 212 | uintptr_t end = ptr + (uintptr_t) size; 213 | 214 | while (ptr < end) { 215 | uint32_t cmd = *(uint32_t *) ptr; 216 | ptr += sizeof(uint32_t); 217 | #if TRACE 218 | fprintf(stderr,"%s:\n", cmd_name(cmd)); 219 | #endif 220 | switch(cmd) { 221 | case BR_NOOP: 222 | break; 223 | case BR_TRANSACTION_COMPLETE: 224 | break; 225 | case BR_INCREFS: 226 | case BR_ACQUIRE: 227 | case BR_RELEASE: 228 | case BR_DECREFS: 229 | #if TRACE 230 | fprintf(stderr," %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *))); 231 | #endif 232 | ptr += sizeof(struct binder_ptr_cookie); 233 | break; 234 | case BR_TRANSACTION: { 235 | struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; 236 | if ((end - ptr) < sizeof(*txn)) { 237 | ALOGE("parse: txn too small!\n"); 238 | return -1; 239 | } 240 | binder_dump_txn(txn); 241 | if (func) { 242 | unsigned rdata[256/4]; 243 | struct binder_io msg; 244 | struct binder_io reply; 245 | int res; 246 | 247 | bio_init(&reply, rdata, sizeof(rdata), 4); 248 | bio_init_from_txn(&msg, txn); 249 | res = func(bs, txn, &msg, &reply); 250 | binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); 251 | } 252 | ptr += sizeof(*txn); 253 | break; 254 | } 255 | case BR_REPLY: { 256 | struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; 257 | if ((end - ptr) < sizeof(*txn)) { 258 | ALOGE("parse: reply too small!\n"); 259 | return -1; 260 | } 261 | binder_dump_txn(txn); 262 | if (bio) { 263 | bio_init_from_txn(bio, txn); 264 | bio = 0; 265 | } else { 266 | /* todo FREE BUFFER */ 267 | } 268 | ptr += sizeof(*txn); 269 | r = 0; 270 | break; 271 | } 272 | case BR_DEAD_BINDER: { 273 | struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr; 274 | ptr += sizeof(binder_uintptr_t); 275 | death->func(bs, death->ptr); 276 | break; 277 | } 278 | case BR_FAILED_REPLY: 279 | r = -1; 280 | break; 281 | case BR_DEAD_REPLY: 282 | r = -1; 283 | break; 284 | default: 285 | ALOGE("parse: OOPS %d\n", cmd); 286 | return -1; 287 | } 288 | } 289 | 290 | return r; 291 | } 292 | 293 | void binder_acquire(struct binder_state *bs, uint32_t target) 294 | { 295 | uint32_t cmd[2]; 296 | cmd[0] = BC_ACQUIRE; 297 | cmd[1] = target; 298 | binder_write(bs, cmd, sizeof(cmd)); 299 | } 300 | 301 | void binder_release(struct binder_state *bs, uint32_t target) 302 | { 303 | uint32_t cmd[2]; 304 | cmd[0] = BC_RELEASE; 305 | cmd[1] = target; 306 | binder_write(bs, cmd, sizeof(cmd)); 307 | } 308 | 309 | void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death) 310 | { 311 | struct { 312 | uint32_t cmd; 313 | struct binder_handle_cookie payload; 314 | } __attribute__((packed)) data; 315 | 316 | data.cmd = BC_REQUEST_DEATH_NOTIFICATION; 317 | data.payload.handle = target; 318 | data.payload.cookie = (uintptr_t) death; 319 | binder_write(bs, &data, sizeof(data)); 320 | } 321 | 322 | int binder_call(struct binder_state *bs, 323 | struct binder_io *msg, struct binder_io *reply, 324 | uint32_t target, uint32_t code) 325 | { 326 | int res; 327 | struct binder_write_read bwr; 328 | struct { 329 | uint32_t cmd; 330 | struct binder_transaction_data txn; 331 | } __attribute__((packed)) writebuf; 332 | unsigned readbuf[32]; 333 | 334 | if (msg->flags & BIO_F_OVERFLOW) { 335 | fprintf(stderr,"binder: txn buffer overflow\n"); 336 | goto fail; 337 | } 338 | 339 | writebuf.cmd = BC_TRANSACTION; 340 | writebuf.txn.target.handle = target; 341 | writebuf.txn.code = code; 342 | writebuf.txn.flags = 0; 343 | writebuf.txn.data_size = msg->data - msg->data0; 344 | writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0); 345 | writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0; 346 | writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0; 347 | 348 | bwr.write_size = sizeof(writebuf); 349 | bwr.write_consumed = 0; 350 | bwr.write_buffer = (uintptr_t) &writebuf; 351 | 352 | hexdump(msg->data0, msg->data - msg->data0); 353 | for (;;) { 354 | bwr.read_size = sizeof(readbuf); 355 | bwr.read_consumed = 0; 356 | bwr.read_buffer = (uintptr_t) readbuf; 357 | 358 | res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 359 | 360 | if (res < 0) { 361 | fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno)); 362 | goto fail; 363 | } 364 | 365 | res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0); 366 | if (res == 0) return 0; 367 | if (res < 0) goto fail; 368 | } 369 | 370 | fail: 371 | memset(reply, 0, sizeof(*reply)); 372 | reply->flags |= BIO_F_IOERROR; 373 | return -1; 374 | } 375 | 376 | void binder_loop(struct binder_state *bs, binder_handler func) 377 | { 378 | int res; 379 | struct binder_write_read bwr; 380 | uint32_t readbuf[32]; 381 | 382 | bwr.write_size = 0; 383 | bwr.write_consumed = 0; 384 | bwr.write_buffer = 0; 385 | 386 | readbuf[0] = BC_ENTER_LOOPER; 387 | binder_write(bs, readbuf, sizeof(uint32_t)); 388 | 389 | for (;;) { 390 | bwr.read_size = sizeof(readbuf); 391 | bwr.read_consumed = 0; 392 | bwr.read_buffer = (uintptr_t) readbuf; 393 | 394 | res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 395 | 396 | if (res < 0) { 397 | ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); 398 | break; 399 | } 400 | 401 | res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); 402 | if (res == 0) { 403 | ALOGE("binder_loop: unexpected reply?!\n"); 404 | break; 405 | } 406 | if (res < 0) { 407 | ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); 408 | break; 409 | } 410 | } 411 | } 412 | 413 | void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn) 414 | { 415 | bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer; 416 | bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets; 417 | bio->data_avail = txn->data_size; 418 | bio->offs_avail = txn->offsets_size / sizeof(size_t); 419 | bio->flags = BIO_F_SHARED; 420 | } 421 | 422 | void bio_init(struct binder_io *bio, void *data, 423 | size_t maxdata, size_t maxoffs) 424 | { 425 | size_t n = maxoffs * sizeof(size_t); 426 | 427 | if (n > maxdata) { 428 | bio->flags = BIO_F_OVERFLOW; 429 | bio->data_avail = 0; 430 | bio->offs_avail = 0; 431 | return; 432 | } 433 | 434 | bio->data = bio->data0 = (char *) data + n; 435 | bio->offs = bio->offs0 = data; 436 | bio->data_avail = maxdata - n; 437 | bio->offs_avail = maxoffs; 438 | bio->flags = 0; 439 | } 440 | 441 | static void *bio_alloc(struct binder_io *bio, size_t size) 442 | { 443 | size = (size + 3) & (~3); 444 | if (size > bio->data_avail) { 445 | bio->flags |= BIO_F_OVERFLOW; 446 | return NULL; 447 | } else { 448 | void *ptr = bio->data; 449 | bio->data += size; 450 | bio->data_avail -= size; 451 | return ptr; 452 | } 453 | } 454 | 455 | void binder_done(struct binder_state *bs, 456 | struct binder_io *msg, 457 | struct binder_io *reply) 458 | { 459 | struct { 460 | uint32_t cmd; 461 | uintptr_t buffer; 462 | } __attribute__((packed)) data; 463 | 464 | if (reply->flags & BIO_F_SHARED) { 465 | data.cmd = BC_FREE_BUFFER; 466 | data.buffer = (uintptr_t) reply->data0; 467 | binder_write(bs, &data, sizeof(data)); 468 | reply->flags = 0; 469 | } 470 | } 471 | 472 | static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio) 473 | { 474 | struct flat_binder_object *obj; 475 | 476 | obj = bio_alloc(bio, sizeof(*obj)); 477 | 478 | if (obj && bio->offs_avail) { 479 | bio->offs_avail--; 480 | *bio->offs++ = ((char*) obj) - ((char*) bio->data0); 481 | return obj; 482 | } 483 | 484 | bio->flags |= BIO_F_OVERFLOW; 485 | return NULL; 486 | } 487 | 488 | void bio_put_uint32(struct binder_io *bio, uint32_t n) 489 | { 490 | uint32_t *ptr = bio_alloc(bio, sizeof(n)); 491 | if (ptr) 492 | *ptr = n; 493 | } 494 | 495 | void bio_put_obj(struct binder_io *bio, void *ptr) 496 | { 497 | struct flat_binder_object *obj; 498 | 499 | obj = bio_alloc_obj(bio); 500 | if (!obj) 501 | return; 502 | 503 | obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; 504 | obj->type = BINDER_TYPE_BINDER; 505 | obj->binder = (uintptr_t)ptr; 506 | obj->cookie = 0; 507 | } 508 | 509 | void bio_put_ref(struct binder_io *bio, uint32_t handle) 510 | { 511 | struct flat_binder_object *obj; 512 | 513 | if (handle) 514 | obj = bio_alloc_obj(bio); 515 | else 516 | obj = bio_alloc(bio, sizeof(*obj)); 517 | 518 | if (!obj) 519 | return; 520 | 521 | obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; 522 | obj->type = BINDER_TYPE_HANDLE; 523 | obj->handle = handle; 524 | obj->cookie = 0; 525 | } 526 | 527 | void bio_put_string16(struct binder_io *bio, const uint16_t *str) 528 | { 529 | size_t len; 530 | uint16_t *ptr; 531 | 532 | if (!str) { 533 | bio_put_uint32(bio, 0xffffffff); 534 | return; 535 | } 536 | 537 | len = 0; 538 | while (str[len]) len++; 539 | 540 | if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { 541 | bio_put_uint32(bio, 0xffffffff); 542 | return; 543 | } 544 | 545 | /* Note: The payload will carry 32bit size instead of size_t */ 546 | bio_put_uint32(bio, (uint32_t) len); 547 | len = (len + 1) * sizeof(uint16_t); 548 | ptr = bio_alloc(bio, len); 549 | if (ptr) 550 | memcpy(ptr, str, len); 551 | } 552 | 553 | void bio_put_string16_x(struct binder_io *bio, const char *_str) 554 | { 555 | unsigned char *str = (unsigned char*) _str; 556 | size_t len; 557 | uint16_t *ptr; 558 | 559 | if (!str) { 560 | bio_put_uint32(bio, 0xffffffff); 561 | return; 562 | } 563 | 564 | len = strlen(_str); 565 | 566 | if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { 567 | bio_put_uint32(bio, 0xffffffff); 568 | return; 569 | } 570 | 571 | /* Note: The payload will carry 32bit size instead of size_t */ 572 | bio_put_uint32(bio, len); 573 | ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t)); 574 | if (!ptr) 575 | return; 576 | 577 | while (*str) 578 | *ptr++ = *str++; 579 | *ptr++ = 0; 580 | } 581 | 582 | static void *bio_get(struct binder_io *bio, size_t size) 583 | { 584 | size = (size + 3) & (~3); 585 | 586 | if (bio->data_avail < size){ 587 | bio->data_avail = 0; 588 | bio->flags |= BIO_F_OVERFLOW; 589 | return NULL; 590 | } else { 591 | void *ptr = bio->data; 592 | bio->data += size; 593 | bio->data_avail -= size; 594 | return ptr; 595 | } 596 | } 597 | 598 | uint32_t bio_get_uint32(struct binder_io *bio) 599 | { 600 | uint32_t *ptr = bio_get(bio, sizeof(*ptr)); 601 | return ptr ? *ptr : 0; 602 | } 603 | 604 | uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz) 605 | { 606 | size_t len; 607 | 608 | /* Note: The payload will carry 32bit size instead of size_t */ 609 | len = (size_t) bio_get_uint32(bio); 610 | if (sz) 611 | *sz = len; 612 | return bio_get(bio, (len + 1) * sizeof(uint16_t)); 613 | } 614 | 615 | static struct flat_binder_object *_bio_get_obj(struct binder_io *bio) 616 | { 617 | size_t n; 618 | size_t off = bio->data - bio->data0; 619 | 620 | /* TODO: be smarter about this? */ 621 | for (n = 0; n < bio->offs_avail; n++) { 622 | if (bio->offs[n] == off) 623 | return bio_get(bio, sizeof(struct flat_binder_object)); 624 | } 625 | 626 | bio->data_avail = 0; 627 | bio->flags |= BIO_F_OVERFLOW; 628 | return NULL; 629 | } 630 | 631 | uint32_t bio_get_ref(struct binder_io *bio) 632 | { 633 | struct flat_binder_object *obj; 634 | 635 | obj = _bio_get_obj(bio); 636 | if (!obj) 637 | return 0; 638 | 639 | if (obj->type == BINDER_TYPE_HANDLE) 640 | return obj->handle; 641 | 642 | return 0; 643 | } 644 | 645 | 646 | static uint32_t get_handle_from_svcmgr(const uint16_t *str, binder_state *bs){ 647 | struct binder_io msg; 648 | struct binder_io reply; 649 | unsigned rdata[256]; 650 | int res; 651 | uint32_t ref; 652 | 653 | bio_init(&msg, rdata, sizeof(rdata), 0); 654 | bio_put_string16(&msg, svcmgr_id); 655 | bio_put_string16(&msg, str); 656 | 657 | res = binder_call(bs, &msg, &reply, 0, 658 | BINDER_SERVICE_MANAGER, SVC_MGR_GET_SERVICE); 659 | 660 | if (res == -1) 661 | return res; 662 | 663 | ref = bio_get_ref(&reply); 664 | if (ref == 0) 665 | return -1; 666 | 667 | return ref; 668 | } 669 | 670 | void get_all_handles(struct binder_state *bs) { 671 | struct binder_io msg; 672 | struct binder_io reply; 673 | unsigned rdata[256]; 674 | uint16_t *str; 675 | int res; 676 | size_t sz; 677 | unsigned service_count = 0; 678 | uint32_t handle; 679 | do { 680 | bio_init(&msg, rdata, sizeof(rdata), 0); 681 | bio_put_string16(&msg, svcmgr_id); 682 | /* put the cmd */ 683 | bio_put_uint32(&msg, service_count); 684 | res = binder_call(bs, &msg, &reply, 685 | BINDER_SERVICE_MANAGER, SVC_MGR_LIST_SERVICES); 686 | if (res) { 687 | str = bio_get_string16(&reply, &sz); 688 | si = malloc((sz + 1) * sizeof(uint16_t)); 689 | if (!si) { 690 | fprintf(stderr, "malloc failed\n"); 691 | res = -1; 692 | break; 693 | } 694 | si[sz] = '/0'; 695 | services[service_count] = si; 696 | handle = get_handle_from_svcmgr(str, sz); 697 | if (handle == -1) { 698 | free(si); 699 | break; 700 | } 701 | handles[service_count] = handle; 702 | service_count++; 703 | } 704 | } while(res != -1 && service_count < MAX_SERVICES); 705 | num_handles_set = service_count; 706 | } 707 | 708 | 709 | void get_random_handle(struct binder_handle *ptr) { 710 | int r = rand() % num_handles_set; 711 | ptr->str = services[r]; 712 | ptr->handle = handles[r]; 713 | printf_v("get_random_handle selected %s, and handle %u\n", 714 | ptr->str, ptr->handle); 715 | } 716 | --------------------------------------------------------------------------------