binder.c revision d57d9b900da83b1b5431d90e250f86c0047c618a
1/* Copyright 2008 The Android Open Source Project
2 */
3
4#include <inttypes.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <errno.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <sys/mman.h>
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 <cutils/log.h>
21
22void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
23
24#if TRACE
25void hexdump(void *_data, size_t len)
26{
27    unsigned char *data = _data;
28    size_t count;
29
30    for (count = 0; count < len; count++) {
31        if ((count & 15) == 0)
32            fprintf(stderr,"%04zu:", count);
33        fprintf(stderr," %02x %c", *data,
34                (*data < 32) || (*data > 126) ? '.' : *data);
35        data++;
36        if ((count & 15) == 15)
37            fprintf(stderr,"\n");
38    }
39    if ((count & 15) != 0)
40        fprintf(stderr,"\n");
41}
42
43void binder_dump_txn(struct binder_transaction_data *txn)
44{
45    struct flat_binder_object *obj;
46    binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets;
47    size_t count = txn->offsets_size / sizeof(binder_size_t);
48
49    fprintf(stderr,"  target %016"PRIx64"  cookie %016"PRIx64"  code %08x  flags %08x\n",
50            (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags);
51    fprintf(stderr,"  pid %8d  uid %8d  data %"PRIu64"  offs %"PRIu64"\n",
52            txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size);
53    hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size);
54    while (count--) {
55        obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++);
56        fprintf(stderr,"  - type %08x  flags %08x  ptr %016"PRIx64"  cookie %016"PRIx64"\n",
57                obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie);
58    }
59}
60
61#define NAME(n) case n: return #n
62const char *cmd_name(uint32_t cmd)
63{
64    switch(cmd) {
65        NAME(BR_NOOP);
66        NAME(BR_TRANSACTION_COMPLETE);
67        NAME(BR_INCREFS);
68        NAME(BR_ACQUIRE);
69        NAME(BR_RELEASE);
70        NAME(BR_DECREFS);
71        NAME(BR_TRANSACTION);
72        NAME(BR_REPLY);
73        NAME(BR_FAILED_REPLY);
74        NAME(BR_DEAD_REPLY);
75        NAME(BR_DEAD_BINDER);
76    default: return "???";
77    }
78}
79#else
80#define hexdump(a,b) do{} while (0)
81#define binder_dump_txn(txn)  do{} while (0)
82#endif
83
84#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
85#define BIO_F_OVERFLOW  0x02  /* ran out of space */
86#define BIO_F_IOERROR   0x04
87#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
88
89struct binder_state
90{
91    int fd;
92    void *mapped;
93    size_t mapsize;
94};
95
96struct binder_state *binder_open(size_t mapsize)
97{
98    struct binder_state *bs;
99    struct binder_version vers;
100
101    bs = malloc(sizeof(*bs));
102    if (!bs) {
103        errno = ENOMEM;
104        return NULL;
105    }
106
107    bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
108    if (bs->fd < 0) {
109        fprintf(stderr,"binder: cannot open device (%s)\n",
110                strerror(errno));
111        goto fail_open;
112    }
113
114    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
115        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
116        fprintf(stderr,
117                "binder: kernel driver version (%d) differs from user space version (%d)\n",
118                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
119        goto fail_open;
120    }
121
122    bs->mapsize = mapsize;
123    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
124    if (bs->mapped == MAP_FAILED) {
125        fprintf(stderr,"binder: cannot map device (%s)\n",
126                strerror(errno));
127        goto fail_map;
128    }
129
130    return bs;
131
132fail_map:
133    close(bs->fd);
134fail_open:
135    free(bs);
136    return NULL;
137}
138
139void binder_close(struct binder_state *bs)
140{
141    munmap(bs->mapped, bs->mapsize);
142    close(bs->fd);
143    free(bs);
144}
145
146int binder_become_context_manager(struct binder_state *bs)
147{
148    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
149}
150
151int binder_write(struct binder_state *bs, void *data, size_t len)
152{
153    struct binder_write_read bwr;
154    int res;
155
156    bwr.write_size = len;
157    bwr.write_consumed = 0;
158    bwr.write_buffer = (uintptr_t) data;
159    bwr.read_size = 0;
160    bwr.read_consumed = 0;
161    bwr.read_buffer = 0;
162    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
163    if (res < 0) {
164        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
165                strerror(errno));
166    }
167    return res;
168}
169
170void binder_send_reply(struct binder_state *bs,
171                       struct binder_io *reply,
172                       binder_uintptr_t buffer_to_free,
173                       int status)
174{
175    struct {
176        uint32_t cmd_free;
177        binder_uintptr_t buffer;
178        uint32_t cmd_reply;
179        struct binder_transaction_data txn;
180    } __attribute__((packed)) data;
181
182    data.cmd_free = BC_FREE_BUFFER;
183    data.buffer = buffer_to_free;
184    data.cmd_reply = BC_REPLY;
185    data.txn.target.ptr = 0;
186    data.txn.cookie = 0;
187    data.txn.code = 0;
188    if (status) {
189        data.txn.flags = TF_STATUS_CODE;
190        data.txn.data_size = sizeof(int);
191        data.txn.offsets_size = 0;
192        data.txn.data.ptr.buffer = (uintptr_t)&status;
193        data.txn.data.ptr.offsets = 0;
194    } else {
195        data.txn.flags = 0;
196        data.txn.data_size = reply->data - reply->data0;
197        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
198        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
199        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
200    }
201    binder_write(bs, &data, sizeof(data));
202}
203
204int binder_parse(struct binder_state *bs, struct binder_io *bio,
205                 uintptr_t ptr, size_t size, binder_handler func)
206{
207    int r = 1;
208    uintptr_t end = ptr + (uintptr_t) size;
209
210    while (ptr < end) {
211        uint32_t cmd = *(uint32_t *) ptr;
212        ptr += sizeof(uint32_t);
213#if TRACE
214        fprintf(stderr,"%s:\n", cmd_name(cmd));
215#endif
216        switch(cmd) {
217        case BR_NOOP:
218            break;
219        case BR_TRANSACTION_COMPLETE:
220            break;
221        case BR_INCREFS:
222        case BR_ACQUIRE:
223        case BR_RELEASE:
224        case BR_DECREFS:
225#if TRACE
226            fprintf(stderr,"  %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
227#endif
228            ptr += sizeof(struct binder_ptr_cookie);
229            break;
230        case BR_TRANSACTION: {
231            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
232            if ((end - ptr) < sizeof(*txn)) {
233                ALOGE("parse: txn too small!\n");
234                return -1;
235            }
236            binder_dump_txn(txn);
237            if (func) {
238                unsigned rdata[256/4];
239                struct binder_io msg;
240                struct binder_io reply;
241                int res;
242
243                bio_init(&reply, rdata, sizeof(rdata), 4);
244                bio_init_from_txn(&msg, txn);
245                res = func(bs, txn, &msg, &reply);
246                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
247            }
248            ptr += sizeof(*txn);
249            break;
250        }
251        case BR_REPLY: {
252            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
253            if ((end - ptr) < sizeof(*txn)) {
254                ALOGE("parse: reply too small!\n");
255                return -1;
256            }
257            binder_dump_txn(txn);
258            if (bio) {
259                bio_init_from_txn(bio, txn);
260                bio = 0;
261            } else {
262                /* todo FREE BUFFER */
263            }
264            ptr += sizeof(*txn);
265            r = 0;
266            break;
267        }
268        case BR_DEAD_BINDER: {
269            struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
270            ptr += sizeof(binder_uintptr_t);
271            death->func(bs, death->ptr);
272            break;
273        }
274        case BR_FAILED_REPLY:
275            r = -1;
276            break;
277        case BR_DEAD_REPLY:
278            r = -1;
279            break;
280        default:
281            ALOGE("parse: OOPS %d\n", cmd);
282            return -1;
283        }
284    }
285
286    return r;
287}
288
289void binder_acquire(struct binder_state *bs, uint32_t target)
290{
291    uint32_t cmd[2];
292    cmd[0] = BC_ACQUIRE;
293    cmd[1] = target;
294    binder_write(bs, cmd, sizeof(cmd));
295}
296
297void binder_release(struct binder_state *bs, uint32_t target)
298{
299    uint32_t cmd[2];
300    cmd[0] = BC_RELEASE;
301    cmd[1] = target;
302    binder_write(bs, cmd, sizeof(cmd));
303}
304
305void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
306{
307    struct {
308        uint32_t cmd;
309        struct binder_handle_cookie payload;
310    } __attribute__((packed)) data;
311
312    data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
313    data.payload.handle = target;
314    data.payload.cookie = (uintptr_t) death;
315    binder_write(bs, &data, sizeof(data));
316}
317
318int binder_call(struct binder_state *bs,
319                struct binder_io *msg, struct binder_io *reply,
320                uint32_t target, uint32_t code)
321{
322    int res;
323    struct binder_write_read bwr;
324    struct {
325        uint32_t cmd;
326        struct binder_transaction_data txn;
327    } __attribute__((packed)) writebuf;
328    unsigned readbuf[32];
329
330    if (msg->flags & BIO_F_OVERFLOW) {
331        fprintf(stderr,"binder: txn buffer overflow\n");
332        goto fail;
333    }
334
335    writebuf.cmd = BC_TRANSACTION;
336    writebuf.txn.target.handle = target;
337    writebuf.txn.code = code;
338    writebuf.txn.flags = 0;
339    writebuf.txn.data_size = msg->data - msg->data0;
340    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
341    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
342    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
343
344    bwr.write_size = sizeof(writebuf);
345    bwr.write_consumed = 0;
346    bwr.write_buffer = (uintptr_t) &writebuf;
347
348    hexdump(msg->data0, msg->data - msg->data0);
349    for (;;) {
350        bwr.read_size = sizeof(readbuf);
351        bwr.read_consumed = 0;
352        bwr.read_buffer = (uintptr_t) readbuf;
353
354        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
355
356        if (res < 0) {
357            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
358            goto fail;
359        }
360
361        res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
362        if (res == 0) return 0;
363        if (res < 0) goto fail;
364    }
365
366fail:
367    memset(reply, 0, sizeof(*reply));
368    reply->flags |= BIO_F_IOERROR;
369    return -1;
370}
371
372void binder_loop(struct binder_state *bs, binder_handler func)
373{
374    int res;
375    struct binder_write_read bwr;
376    uint32_t readbuf[32];
377
378    bwr.write_size = 0;
379    bwr.write_consumed = 0;
380    bwr.write_buffer = 0;
381
382    readbuf[0] = BC_ENTER_LOOPER;
383    binder_write(bs, readbuf, sizeof(uint32_t));
384
385    for (;;) {
386        bwr.read_size = sizeof(readbuf);
387        bwr.read_consumed = 0;
388        bwr.read_buffer = (uintptr_t) readbuf;
389
390        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
391
392        if (res < 0) {
393            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
394            break;
395        }
396
397        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
398        if (res == 0) {
399            ALOGE("binder_loop: unexpected reply?!\n");
400            break;
401        }
402        if (res < 0) {
403            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
404            break;
405        }
406    }
407}
408
409void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
410{
411    bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
412    bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
413    bio->data_avail = txn->data_size;
414    bio->offs_avail = txn->offsets_size / sizeof(size_t);
415    bio->flags = BIO_F_SHARED;
416}
417
418void bio_init(struct binder_io *bio, void *data,
419              size_t maxdata, size_t maxoffs)
420{
421    size_t n = maxoffs * sizeof(size_t);
422
423    if (n > maxdata) {
424        bio->flags = BIO_F_OVERFLOW;
425        bio->data_avail = 0;
426        bio->offs_avail = 0;
427        return;
428    }
429
430    bio->data = bio->data0 = (char *) data + n;
431    bio->offs = bio->offs0 = data;
432    bio->data_avail = maxdata - n;
433    bio->offs_avail = maxoffs;
434    bio->flags = 0;
435}
436
437static void *bio_alloc(struct binder_io *bio, size_t size)
438{
439    size = (size + 3) & (~3);
440    if (size > bio->data_avail) {
441        bio->flags |= BIO_F_OVERFLOW;
442        return NULL;
443    } else {
444        void *ptr = bio->data;
445        bio->data += size;
446        bio->data_avail -= size;
447        return ptr;
448    }
449}
450
451void binder_done(struct binder_state *bs,
452                 __unused struct binder_io *msg,
453                 struct binder_io *reply)
454{
455    struct {
456        uint32_t cmd;
457        uintptr_t buffer;
458    } __attribute__((packed)) data;
459
460    if (reply->flags & BIO_F_SHARED) {
461        data.cmd = BC_FREE_BUFFER;
462        data.buffer = (uintptr_t) reply->data0;
463        binder_write(bs, &data, sizeof(data));
464        reply->flags = 0;
465    }
466}
467
468static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
469{
470    struct flat_binder_object *obj;
471
472    obj = bio_alloc(bio, sizeof(*obj));
473
474    if (obj && bio->offs_avail) {
475        bio->offs_avail--;
476        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
477        return obj;
478    }
479
480    bio->flags |= BIO_F_OVERFLOW;
481    return NULL;
482}
483
484void bio_put_uint32(struct binder_io *bio, uint32_t n)
485{
486    uint32_t *ptr = bio_alloc(bio, sizeof(n));
487    if (ptr)
488        *ptr = n;
489}
490
491void bio_put_obj(struct binder_io *bio, void *ptr)
492{
493    struct flat_binder_object *obj;
494
495    obj = bio_alloc_obj(bio);
496    if (!obj)
497        return;
498
499    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
500    obj->type = BINDER_TYPE_BINDER;
501    obj->binder = (uintptr_t)ptr;
502    obj->cookie = 0;
503}
504
505void bio_put_ref(struct binder_io *bio, uint32_t handle)
506{
507    struct flat_binder_object *obj;
508
509    if (handle)
510        obj = bio_alloc_obj(bio);
511    else
512        obj = bio_alloc(bio, sizeof(*obj));
513
514    if (!obj)
515        return;
516
517    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
518    obj->type = BINDER_TYPE_HANDLE;
519    obj->handle = handle;
520    obj->cookie = 0;
521}
522
523void bio_put_string16(struct binder_io *bio, const uint16_t *str)
524{
525    size_t len;
526    uint16_t *ptr;
527
528    if (!str) {
529        bio_put_uint32(bio, 0xffffffff);
530        return;
531    }
532
533    len = 0;
534    while (str[len]) len++;
535
536    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
537        bio_put_uint32(bio, 0xffffffff);
538        return;
539    }
540
541    /* Note: The payload will carry 32bit size instead of size_t */
542    bio_put_uint32(bio, (uint32_t) len);
543    len = (len + 1) * sizeof(uint16_t);
544    ptr = bio_alloc(bio, len);
545    if (ptr)
546        memcpy(ptr, str, len);
547}
548
549void bio_put_string16_x(struct binder_io *bio, const char *_str)
550{
551    unsigned char *str = (unsigned char*) _str;
552    size_t len;
553    uint16_t *ptr;
554
555    if (!str) {
556        bio_put_uint32(bio, 0xffffffff);
557        return;
558    }
559
560    len = strlen(_str);
561
562    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
563        bio_put_uint32(bio, 0xffffffff);
564        return;
565    }
566
567    /* Note: The payload will carry 32bit size instead of size_t */
568    bio_put_uint32(bio, len);
569    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
570    if (!ptr)
571        return;
572
573    while (*str)
574        *ptr++ = *str++;
575    *ptr++ = 0;
576}
577
578static void *bio_get(struct binder_io *bio, size_t size)
579{
580    size = (size + 3) & (~3);
581
582    if (bio->data_avail < size){
583        bio->data_avail = 0;
584        bio->flags |= BIO_F_OVERFLOW;
585        return NULL;
586    }  else {
587        void *ptr = bio->data;
588        bio->data += size;
589        bio->data_avail -= size;
590        return ptr;
591    }
592}
593
594uint32_t bio_get_uint32(struct binder_io *bio)
595{
596    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
597    return ptr ? *ptr : 0;
598}
599
600uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
601{
602    size_t len;
603
604    /* Note: The payload will carry 32bit size instead of size_t */
605    len = (size_t) bio_get_uint32(bio);
606    if (sz)
607        *sz = len;
608    return bio_get(bio, (len + 1) * sizeof(uint16_t));
609}
610
611static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
612{
613    size_t n;
614    size_t off = bio->data - bio->data0;
615
616    /* TODO: be smarter about this? */
617    for (n = 0; n < bio->offs_avail; n++) {
618        if (bio->offs[n] == off)
619            return bio_get(bio, sizeof(struct flat_binder_object));
620    }
621
622    bio->data_avail = 0;
623    bio->flags |= BIO_F_OVERFLOW;
624    return NULL;
625}
626
627uint32_t bio_get_ref(struct binder_io *bio)
628{
629    struct flat_binder_object *obj;
630
631    obj = _bio_get_obj(bio);
632    if (!obj)
633        return 0;
634
635    if (obj->type == BINDER_TYPE_HANDLE)
636        return obj->handle;
637
638    return 0;
639}
640