Android: Add support for 32-bit Binder calls in a 64-bit kernel
authorBintian Wang <bintian.wang@linaro.org>
Wed, 9 Oct 2013 10:52:57 +0000 (18:52 +0800)
committerMark Brown <broonie@linaro.org>
Wed, 22 Jan 2014 15:36:17 +0000 (15:36 +0000)
Android's IPC, Binder, does not support calls from a 32-bit userspace
in a 64 bit kernel. This patch adds support for syscalls coming from a
32-bit userspace in a 64-bit kernel.

Most of the changes were applied to types that change sizes between
32 and 64 bit world. This will also fix some of the issues around
checking the size of an incoming transaction package in the ioctl
switch. Since  the transaction's ioctl number are generated using
_IOC(dir,type,nr,size), a different userspace size will generate
a different ioctl number, thus switching by _IOC_NR is a better
solution.

The patch has been successfully tested on ARMv8 AEM and Versatile
Express V2P-CA9.

[Fixed up several conflicts with upstream -- broonie]

Signed-off-by: Serban Constantinescu <serban.constantinescu@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
drivers/staging/android/binder.c
drivers/staging/android/binder.h

index f8d5b03f54441d5b703b00bc7f23dc45ea139ada..87f1e1ca8dc5e6068eedf1a4a1ac2c0282bbe2f5 100644 (file)
@@ -229,8 +229,8 @@ struct binder_node {
        int internal_strong_refs;
        int local_weak_refs;
        int local_strong_refs;
-       void __user *ptr;
-       void __user *cookie;
+       userptr32_t ptr;
+       userptr32_t cookie;
        unsigned has_strong_ref:1;
        unsigned pending_strong_ref:1;
        unsigned has_weak_ref:1;
@@ -243,7 +243,7 @@ struct binder_node {
 
 struct binder_ref_death {
        struct binder_work work;
-       void __user *cookie;
+       userptr32_t cookie;
 };
 
 struct binder_ref {
@@ -318,7 +318,7 @@ struct binder_proc {
        int requested_threads;
        int requested_threads_started;
        int ready_threads;
-       long default_priority;
+       int default_priority;
        struct dentry *debugfs_entry;
 };
 
@@ -360,8 +360,8 @@ struct binder_transaction {
        struct binder_buffer *buffer;
        unsigned int    code;
        unsigned int    flags;
-       long    priority;
-       long    saved_priority;
+       int     priority;
+       int     saved_priority;
        kuid_t  sender_euid;
 };
 
@@ -430,16 +430,16 @@ static inline void binder_unlock(const char *tag)
        mutex_unlock(&binder_main_lock);
 }
 
-static void binder_set_nice(long nice)
+static void binder_set_nice(int nice)
 {
-       long min_nice;
+       int min_nice;
        if (can_nice(current, nice)) {
                set_user_nice(current, nice);
                return;
        }
        min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur;
        binder_debug(BINDER_DEBUG_PRIORITY_CAP,
-                    "%d: nice value %ld not allowed use %ld instead\n",
+                    "%d: nice value %d not allowed use %d instead\n",
                      current->pid, nice, min_nice);
        set_user_nice(current, min_nice);
        if (min_nice < 20)
@@ -516,13 +516,13 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc,
 }
 
 static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
-                                                 void __user *user_ptr)
+                                                 userptr32_t user_ptr)
 {
        struct rb_node *n = proc->allocated_buffers.rb_node;
        struct binder_buffer *buffer;
        struct binder_buffer *kern_ptr;
 
-       kern_ptr = user_ptr - proc->user_buffer_offset
+       kern_ptr = (void *)(unsigned long)user_ptr - proc->user_buffer_offset
                - offsetof(struct binder_buffer, data);
 
        while (n) {
@@ -660,8 +660,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
                return NULL;
        }
 
-       size = ALIGN(data_size, sizeof(void *)) +
-               ALIGN(offsets_size, sizeof(void *));
+       size = ALIGN(data_size, sizeof(userptr32_t)) +
+               ALIGN(offsets_size, sizeof(userptr32_t));
 
        if (size < data_size || size < offsets_size) {
                binder_user_error("%d: got transaction with invalid size %zd-%zd\n",
@@ -809,8 +809,8 @@ static void binder_free_buf(struct binder_proc *proc,
 
        buffer_size = binder_buffer_size(proc, buffer);
 
-       size = ALIGN(buffer->data_size, sizeof(void *)) +
-               ALIGN(buffer->offsets_size, sizeof(void *));
+       size = ALIGN(buffer->data_size, sizeof(userptr32_t)) +
+               ALIGN(buffer->offsets_size, sizeof(userptr32_t));
 
        binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
                     "%d: binder_free_buf %p size %zd buffer_size %zd\n",
@@ -857,7 +857,7 @@ static void binder_free_buf(struct binder_proc *proc,
 }
 
 static struct binder_node *binder_get_node(struct binder_proc *proc,
-                                          void __user *ptr)
+                                          userptr32_t ptr)
 {
        struct rb_node *n = proc->nodes.rb_node;
        struct binder_node *node;
@@ -876,8 +876,8 @@ static struct binder_node *binder_get_node(struct binder_proc *proc,
 }
 
 static struct binder_node *binder_new_node(struct binder_proc *proc,
-                                          void __user *ptr,
-                                          void __user *cookie)
+                                          userptr32_t ptr,
+                                          userptr32_t cookie)
 {
        struct rb_node **p = &proc->nodes.rb_node;
        struct rb_node *parent = NULL;
@@ -909,7 +909,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
        INIT_LIST_HEAD(&node->work.entry);
        INIT_LIST_HEAD(&node->async_todo);
        binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-                    "%d:%d node %d u%p c%p created\n",
+                    "%d:%d node %d u%x c%x created\n",
                     proc->pid, current->pid, node->debug_id,
                     node->ptr, node->cookie);
        return node;
@@ -1227,9 +1227,9 @@ static void binder_send_failed_reply(struct binder_transaction *t,
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
                                              struct binder_buffer *buffer,
-                                             size_t *failed_at)
+                                             uint32_t *failed_at)
 {
-       size_t *offp, *off_end;
+       uint32_t *offp, *off_end;
        int debug_id = buffer->debug_id;
 
        binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1240,17 +1240,18 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
        if (buffer->target_node)
                binder_dec_node(buffer->target_node, 1, 0);
 
-       offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+       offp = (uint32_t *)(buffer->data +
+                           ALIGN(buffer->data_size, sizeof(userptr32_t)));
        if (failed_at)
                off_end = failed_at;
        else
-               off_end = (void *)offp + buffer->offsets_size;
+               off_end = (uint32_t *)offp + (buffer->offsets_size/4);
        for (; offp < off_end; offp++) {
                struct flat_binder_object *fp;
                if (*offp > buffer->data_size - sizeof(*fp) ||
                    buffer->data_size < sizeof(*fp) ||
-                   !IS_ALIGNED(*offp, sizeof(void *))) {
-                       pr_err("transaction release %d bad offset %zd, size %zd\n",
+                   !IS_ALIGNED(*offp, sizeof(userptr32_t))) {
+                       pr_err("transaction release %d bad offset %x, size %zd\n",
                         debug_id, *offp, buffer->data_size);
                        continue;
                }
@@ -1260,12 +1261,11 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
                case BINDER_TYPE_WEAK_BINDER: {
                        struct binder_node *node = binder_get_node(proc, fp->binder);
                        if (node == NULL) {
-                               pr_err("transaction release %d bad node %p\n",
-                                       debug_id, fp->binder);
+                               pr_err("transaction release %d bad node %x\n", debug_id, fp->binder);
                                break;
                        }
                        binder_debug(BINDER_DEBUG_TRANSACTION,
-                                    "        node %d u%p\n",
+                                    "        node %d u%x\n",
                                     node->debug_id, node->ptr);
                        binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
                } break;
@@ -1304,7 +1304,7 @@ static void binder_transaction(struct binder_proc *proc,
 {
        struct binder_transaction *t;
        struct binder_work *tcomplete;
-       size_t *offp, *off_end;
+       uint32_t *offp, *off_end;
        struct binder_proc *target_proc;
        struct binder_thread *target_thread = NULL;
        struct binder_node *target_node = NULL;
@@ -1437,14 +1437,14 @@ static void binder_transaction(struct binder_proc *proc,
 
        if (reply)
                binder_debug(BINDER_DEBUG_TRANSACTION,
-                            "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n",
+                            "%d:%d BC_REPLY %d -> %d:%d, data %x-%x size %d-%d\n",
                             proc->pid, thread->pid, t->debug_id,
                             target_proc->pid, target_thread->pid,
                             tr->data.ptr.buffer, tr->data.ptr.offsets,
                             tr->data_size, tr->offsets_size);
        else
                binder_debug(BINDER_DEBUG_TRANSACTION,
-                            "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n",
+                            "%d:%d BC_TRANSACTION %d -> %d - node %d, data %x-%x size %d-%d\n",
                             proc->pid, thread->pid, t->debug_id,
                             target_proc->pid, target_node->debug_id,
                             tr->data.ptr.buffer, tr->data.ptr.offsets,
@@ -1477,33 +1477,34 @@ static void binder_transaction(struct binder_proc *proc,
        if (target_node)
                binder_inc_node(target_node, 1, 0, NULL);
 
-       offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+       offp = (uint32_t *)(t->buffer->data +
+                           ALIGN(tr->data_size, sizeof(userptr32_t)));
 
-       if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+       if (copy_from_user(t->buffer->data, (void *)(unsigned long)(tr->data.ptr.buffer),  tr->data_size)) {
                binder_user_error("%d:%d got transaction with invalid data ptr\n",
                                proc->pid, thread->pid);
                return_error = BR_FAILED_REPLY;
                goto err_copy_data_failed;
        }
-       if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+       if (copy_from_user(offp, (void *)(unsigned long)(tr->data.ptr.offsets), tr->offsets_size)) {
                binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
                                proc->pid, thread->pid);
                return_error = BR_FAILED_REPLY;
                goto err_copy_data_failed;
        }
-       if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
-               binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n",
+       if (!IS_ALIGNED(tr->offsets_size, sizeof(uint32_t))) {
+               binder_user_error("%d:%d got transaction with invalid offsets size, %d\n",
                                proc->pid, thread->pid, tr->offsets_size);
                return_error = BR_FAILED_REPLY;
                goto err_bad_offset;
        }
-       off_end = (void *)offp + tr->offsets_size;
+       off_end = (uint32_t *)offp + (tr->offsets_size/4);
        for (; offp < off_end; offp++) {
                struct flat_binder_object *fp;
                if (*offp > t->buffer->data_size - sizeof(*fp) ||
                    t->buffer->data_size < sizeof(*fp) ||
-                   !IS_ALIGNED(*offp, sizeof(void *))) {
-                       binder_user_error("%d:%d got transaction with invalid offset, %zd\n",
+                   !IS_ALIGNED(*offp, sizeof(userptr32_t))) {
+                       binder_user_error("%d:%d got transaction with invalid offset, %x\n",
                                        proc->pid, thread->pid, *offp);
                        return_error = BR_FAILED_REPLY;
                        goto err_bad_offset;
@@ -1524,7 +1525,7 @@ static void binder_transaction(struct binder_proc *proc,
                                node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
                        }
                        if (fp->cookie != node->cookie) {
-                               binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n",
+                               binder_user_error("%d:%d sending u%x node %d, cookie mismatch %x != %x\n",
                                        proc->pid, thread->pid,
                                        fp->binder, node->debug_id,
                                        fp->cookie, node->cookie);
@@ -1549,7 +1550,7 @@ static void binder_transaction(struct binder_proc *proc,
 
                        trace_binder_transaction_node_to_ref(t, node, ref);
                        binder_debug(BINDER_DEBUG_TRANSACTION,
-                                    "        node %d u%p -> ref %d desc %d\n",
+                                    "        node %d u%x -> ref %d desc %d\n",
                                     node->debug_id, node->ptr, ref->debug_id,
                                     ref->desc);
                } break;
@@ -1577,7 +1578,7 @@ static void binder_transaction(struct binder_proc *proc,
                                binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
                                trace_binder_transaction_ref_to_node(t, ref);
                                binder_debug(BINDER_DEBUG_TRANSACTION,
-                                            "        ref %d desc %d -> node %d u%p\n",
+                                            "        ref %d desc %d -> node %d u%x\n",
                                             ref->debug_id, ref->desc, ref->node->debug_id,
                                             ref->node->ptr);
                        } else {
@@ -1700,7 +1701,7 @@ err_dead_binder:
 err_invalid_target_handle:
 err_no_context_mgr_node:
        binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-                    "%d:%d transaction failed %d, size %zd-%zd\n",
+                    "%d:%d transaction failed %d, size %d-%d\n",
                     proc->pid, thread->pid, return_error,
                     tr->data_size, tr->offsets_size);
 
@@ -1719,7 +1720,7 @@ err_no_context_mgr_node:
 }
 
 int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
-                       void __user *buffer, int size, signed long *consumed)
+                       void __user *buffer, int size, int *consumed)
 {
        uint32_t cmd;
        void __user *ptr = buffer + *consumed;
@@ -1735,11 +1736,16 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                        proc->stats.bc[_IOC_NR(cmd)]++;
                        thread->stats.bc[_IOC_NR(cmd)]++;
                }
-               switch (cmd) {
-               case BC_INCREFS:
-               case BC_ACQUIRE:
-               case BC_RELEASE:
-               case BC_DECREFS: {
+               /*
+                * since  the transaction's IOCTL number are generated using
+                * _IOC(dir,type,nr,size), a different userspace size will not
+                * fall through
+                */
+               switch (_IOC_NR(cmd)) {
+               case _IOC_NR(BC_INCREFS):
+               case _IOC_NR(BC_ACQUIRE):
+               case _IOC_NR(BC_RELEASE):
+               case _IOC_NR(BC_DECREFS): {
                        uint32_t target;
                        struct binder_ref *ref;
                        const char *debug_string;
@@ -1763,20 +1769,20 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                        proc->pid, thread->pid, target);
                                break;
                        }
-                       switch (cmd) {
-                       case BC_INCREFS:
+                       switch (_IOC_NR(cmd)) {
+                       case _IOC_NR(BC_INCREFS):
                                debug_string = "IncRefs";
                                binder_inc_ref(ref, 0, NULL);
                                break;
-                       case BC_ACQUIRE:
+                       case _IOC_NR(BC_ACQUIRE):
                                debug_string = "Acquire";
                                binder_inc_ref(ref, 1, NULL);
                                break;
-                       case BC_RELEASE:
+                       case _IOC_NR(BC_RELEASE):
                                debug_string = "Release";
                                binder_dec_ref(ref, 1);
                                break;
-                       case BC_DECREFS:
+                       case _IOC_NR(BC_DECREFS):
                        default:
                                debug_string = "DecRefs";
                                binder_dec_ref(ref, 0);
@@ -1788,21 +1794,25 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
                        break;
                }
-               case BC_INCREFS_DONE:
-               case BC_ACQUIRE_DONE: {
-                       void __user *node_ptr;
-                       void *cookie;
+               case _IOC_NR(BC_INCREFS_DONE):
+               case _IOC_NR(BC_ACQUIRE_DONE): {
+                       userptr32_t node_ptr;
+                       userptr32_t cookie;
                        struct binder_node *node;
 
-                       if (get_user(node_ptr, (void * __user *)ptr))
+                       if (_IOC_SIZE(cmd) != sizeof(struct binder_ptr_cookie)) {
+                               pr_err("binder: tranzaction structure size differs\n");
                                return -EFAULT;
-                       ptr += sizeof(void *);
-                       if (get_user(cookie, (void * __user *)ptr))
+                       }
+                       if (get_user(node_ptr, (userptr32_t __user *)ptr))
+                               return -EFAULT;
+                       ptr += sizeof(userptr32_t);
+                       if (get_user(cookie, (userptr32_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(userptr32_t);
                        node = binder_get_node(proc, node_ptr);
                        if (node == NULL) {
-                               binder_user_error("%d:%d %s u%p no match\n",
+                               binder_user_error("%d:%d %s u%x no match\n",
                                        proc->pid, thread->pid,
                                        cmd == BC_INCREFS_DONE ?
                                        "BC_INCREFS_DONE" :
@@ -1811,7 +1821,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                break;
                        }
                        if (cookie != node->cookie) {
-                               binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n",
+                               binder_user_error("%d:%d %s u%x node %d cookie mismatch %x != %x\n",
                                        proc->pid, thread->pid,
                                        cmd == BC_INCREFS_DONE ?
                                        "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
@@ -1844,34 +1854,34 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                     node->debug_id, node->local_strong_refs, node->local_weak_refs);
                        break;
                }
-               case BC_ATTEMPT_ACQUIRE:
+               case _IOC_NR(BC_ATTEMPT_ACQUIRE):
                        pr_err("BC_ATTEMPT_ACQUIRE not supported\n");
                        return -EINVAL;
-               case BC_ACQUIRE_RESULT:
+               case _IOC_NR(BC_ACQUIRE_RESULT):
                        pr_err("BC_ACQUIRE_RESULT not supported\n");
                        return -EINVAL;
 
-               case BC_FREE_BUFFER: {
-                       void __user *data_ptr;
+               case _IOC_NR(BC_FREE_BUFFER): {
+                       userptr32_t data_ptr;
                        struct binder_buffer *buffer;
 
-                       if (get_user(data_ptr, (void * __user *)ptr))
+                       if (get_user(data_ptr, (userptr32_t  __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(userptr32_t);
 
                        buffer = binder_buffer_lookup(proc, data_ptr);
                        if (buffer == NULL) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n",
+                               binder_user_error("%d:%d BC_FREE_BUFFER u%x no match\n",
                                        proc->pid, thread->pid, data_ptr);
                                break;
                        }
                        if (!buffer->allow_user_free) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n",
+                               binder_user_error("%d:%d BC_FREE_BUFFER u%x matched unreturned buffer\n",
                                        proc->pid, thread->pid, data_ptr);
                                break;
                        }
                        binder_debug(BINDER_DEBUG_FREE_BUFFER,
-                                    "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
+                                    "%d:%d BC_FREE_BUFFER u%x found buffer %d for %s transaction\n",
                                     proc->pid, thread->pid, data_ptr, buffer->debug_id,
                                     buffer->transaction ? "active" : "finished");
 
@@ -1892,10 +1902,14 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                        break;
                }
 
-               case BC_TRANSACTION:
-               case BC_REPLY: {
+               case _IOC_NR(BC_TRANSACTION):
+               case _IOC_NR(BC_REPLY): {
                        struct binder_transaction_data tr;
 
+                       if (_IOC_SIZE(cmd) != sizeof(tr)) {
+                               pr_err("binder: tranzaction structure size differs\n");
+                               return -EFAULT;
+                       }
                        if (copy_from_user(&tr, ptr, sizeof(tr)))
                                return -EFAULT;
                        ptr += sizeof(tr);
@@ -1903,7 +1917,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                        break;
                }
 
-               case BC_REGISTER_LOOPER:
+               case _IOC_NR(BC_REGISTER_LOOPER):
                        binder_debug(BINDER_DEBUG_THREADS,
                                     "%d:%d BC_REGISTER_LOOPER\n",
                                     proc->pid, thread->pid);
@@ -1921,7 +1935,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                        }
                        thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
                        break;
-               case BC_ENTER_LOOPER:
+               case _IOC_NR(BC_ENTER_LOOPER):
                        binder_debug(BINDER_DEBUG_THREADS,
                                     "%d:%d BC_ENTER_LOOPER\n",
                                     proc->pid, thread->pid);
@@ -1932,26 +1946,26 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                        }
                        thread->looper |= BINDER_LOOPER_STATE_ENTERED;
                        break;
-               case BC_EXIT_LOOPER:
+               case _IOC_NR(BC_EXIT_LOOPER):
                        binder_debug(BINDER_DEBUG_THREADS,
                                     "%d:%d BC_EXIT_LOOPER\n",
                                     proc->pid, thread->pid);
                        thread->looper |= BINDER_LOOPER_STATE_EXITED;
                        break;
 
-               case BC_REQUEST_DEATH_NOTIFICATION:
-               case BC_CLEAR_DEATH_NOTIFICATION: {
+               case _IOC_NR(BC_REQUEST_DEATH_NOTIFICATION):
+               case _IOC_NR(BC_CLEAR_DEATH_NOTIFICATION): {
                        uint32_t target;
-                       void __user *cookie;
+                       userptr32_t cookie;
                        struct binder_ref *ref;
                        struct binder_ref_death *death;
 
                        if (get_user(target, (uint32_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(uint32_t);
-                       if (get_user(cookie, (void __user * __user *)ptr))
+                       if (get_user(cookie, (userptr32_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(userptr32_t);
                        ref = binder_get_ref(proc, target);
                        if (ref == NULL) {
                                binder_user_error("%d:%d %s invalid ref %d\n",
@@ -1964,7 +1978,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                        }
 
                        binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-                                    "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+                                    "%d:%d %s %x ref %d desc %d s %d w %d for node %d\n",
                                     proc->pid, thread->pid,
                                     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
                                     "BC_REQUEST_DEATH_NOTIFICATION" :
@@ -2007,7 +2021,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                }
                                death = ref->death;
                                if (death->cookie != cookie) {
-                                       binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
+                                       binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %x != %x\n",
                                                proc->pid, thread->pid,
                                                death->cookie, cookie);
                                        break;
@@ -2027,14 +2041,13 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                }
                        }
                } break;
-               case BC_DEAD_BINDER_DONE: {
+               case _IOC_NR(BC_DEAD_BINDER_DONE): {
                        struct binder_work *w;
-                       void __user *cookie;
+                       userptr32_t cookie;
                        struct binder_ref_death *death = NULL;
-                       if (get_user(cookie, (void __user * __user *)ptr))
+                       if (get_user(cookie, (userptr32_t __user *)ptr))
                                return -EFAULT;
-
-                       ptr += sizeof(void *);
+                       ptr += sizeof(userptr32_t);
                        list_for_each_entry(w, &proc->delivered_death, entry) {
                                struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
                                if (tmp_death->cookie == cookie) {
@@ -2043,10 +2056,10 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
                                }
                        }
                        binder_debug(BINDER_DEBUG_DEAD_BINDER,
-                                    "%d:%d BC_DEAD_BINDER_DONE %p found %p\n",
+                                    "%d:%d BC_DEAD_BINDER_DONE %x found %p\n",
                                     proc->pid, thread->pid, cookie, death);
                        if (death == NULL) {
-                               binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
+                               binder_user_error("%d:%d BC_DEAD_BINDER_DONE %x not found\n",
                                        proc->pid, thread->pid, cookie);
                                break;
                        }
@@ -2100,7 +2113,7 @@ static int binder_has_thread_work(struct binder_thread *thread)
 static int binder_thread_read(struct binder_proc *proc,
                              struct binder_thread *thread,
                              void  __user *buffer, int size,
-                             signed long *consumed, int non_block)
+                             int *consumed, int non_block)
 {
        void __user *ptr = buffer + *consumed;
        void __user *end = buffer + size;
@@ -2246,22 +2259,22 @@ retry:
                                if (put_user(cmd, (uint32_t __user *)ptr))
                                        return -EFAULT;
                                ptr += sizeof(uint32_t);
-                               if (put_user(node->ptr, (void * __user *)ptr))
+                               if (put_user((unsigned long)node->ptr, (userptr32_t __user *)ptr))
                                        return -EFAULT;
-                               ptr += sizeof(void *);
-                               if (put_user(node->cookie, (void * __user *)ptr))
+                               ptr += sizeof(userptr32_t);
+                               if (put_user((unsigned long)node->cookie, (userptr32_t __user *)ptr))
                                        return -EFAULT;
-                               ptr += sizeof(void *);
+                               ptr += sizeof(userptr32_t);
 
                                binder_stat_br(proc, thread, cmd);
                                binder_debug(BINDER_DEBUG_USER_REFS,
-                                            "%d:%d %s %d u%p c%p\n",
+                                            "%d:%d %s %d u%x c%x\n",
                                             proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
                        } else {
                                list_del_init(&w->entry);
                                if (!weak && !strong) {
                                        binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-                                                    "%d:%d node %d u%p c%p deleted\n",
+                                                    "%d:%d node %d u%x c%x deleted\n",
                                                     proc->pid, thread->pid, node->debug_id,
                                                     node->ptr, node->cookie);
                                        rb_erase(&node->rb_node, &proc->nodes);
@@ -2269,7 +2282,7 @@ retry:
                                        binder_stats_deleted(BINDER_STAT_NODE);
                                } else {
                                        binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-                                                    "%d:%d node %d u%p c%p state unchanged\n",
+                                                    "%d:%d node %d u%x c%x state unchanged\n",
                                                     proc->pid, thread->pid, node->debug_id, node->ptr,
                                                     node->cookie);
                                }
@@ -2289,12 +2302,12 @@ retry:
                        if (put_user(cmd, (uint32_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(uint32_t);
-                       if (put_user(death->cookie, (void * __user *)ptr))
+                       if (put_user((unsigned long)death->cookie, (userptr32_t __user *)ptr))
                                return -EFAULT;
-                       ptr += sizeof(void *);
+                       ptr += sizeof(userptr32_t);
                        binder_stat_br(proc, thread, cmd);
                        binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-                                    "%d:%d %s %p\n",
+                                    "%d:%d %s %x\n",
                                      proc->pid, thread->pid,
                                      cmd == BR_DEAD_BINDER ?
                                      "BR_DEAD_BINDER" :
@@ -2329,8 +2342,8 @@ retry:
                                binder_set_nice(target_node->min_priority);
                        cmd = BR_TRANSACTION;
                } else {
-                       tr.target.ptr = NULL;
-                       tr.cookie = NULL;
+                       tr.target.ptr = 0;
+                       tr.cookie = 0;
                        cmd = BR_REPLY;
                }
                tr.code = t->code;
@@ -2345,13 +2358,14 @@ retry:
                        tr.sender_pid = 0;
                }
 
-               tr.data_size = t->buffer->data_size;
-               tr.offsets_size = t->buffer->offsets_size;
-               tr.data.ptr.buffer = (void *)t->buffer->data +
-                                       proc->user_buffer_offset;
-               tr.data.ptr.offsets = tr.data.ptr.buffer +
+               tr.data_size = (userptr32_t)t->buffer->data_size;
+               tr.offsets_size = (userptr32_t)t->buffer->offsets_size;
+               tr.data.ptr.buffer = (unsigned long)((void *)t->buffer->data +
+                                       proc->user_buffer_offset);
+
+               tr.data.ptr.offsets = (userptr32_t)(tr.data.ptr.buffer +
                                        ALIGN(t->buffer->data_size,
-                                           sizeof(void *));
+                                           sizeof(userptr32_t)));
 
                if (put_user(cmd, (uint32_t __user *)ptr))
                        return -EFAULT;
@@ -2363,7 +2377,7 @@ retry:
                trace_binder_transaction_received(t);
                binder_stat_br(proc, thread, cmd);
                binder_debug(BINDER_DEBUG_TRANSACTION,
-                            "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n",
+                            "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %x-%x\n",
                             proc->pid, thread->pid,
                             (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
                             "BR_REPLY",
@@ -2585,10 +2599,16 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                goto err;
        }
 
-       switch (cmd) {
-       case BINDER_WRITE_READ: {
+       /*
+        * since  the transaction's IOCTL number are generated using
+        * _IOC(dir,type,nr,size), a different userspace size will not
+        * fall through
+        */
+       switch (_IOC_NR(cmd)) {
+       case _IOC_NR(BINDER_WRITE_READ): {
                struct binder_write_read bwr;
                if (size != sizeof(struct binder_write_read)) {
+                       pr_err("binder: BINDER_WRITE_READ transaction size differs\n");
                        ret = -EINVAL;
                        goto err;
                }
@@ -2597,12 +2617,12 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        goto err;
                }
                binder_debug(BINDER_DEBUG_READ_WRITE,
-                            "%d:%d write %ld at %08lx, read %ld at %08lx\n",
+                            "%d:%d write %d at %08x, read %d at %08x\n",
                             proc->pid, thread->pid, bwr.write_size,
                             bwr.write_buffer, bwr.read_size, bwr.read_buffer);
 
                if (bwr.write_size > 0) {
-                       ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+                       ret = binder_thread_write(proc, thread, (void __user *)(unsigned long)(bwr.write_buffer), bwr.write_size, &bwr.write_consumed);
                        trace_binder_write_done(ret);
                        if (ret < 0) {
                                bwr.read_consumed = 0;
@@ -2612,7 +2632,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
                }
                if (bwr.read_size > 0) {
-                       ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+                       ret = binder_thread_read(proc, thread, (void __user *)(unsigned long)(bwr.read_buffer), bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
                        trace_binder_read_done(ret);
                        if (!list_empty(&proc->todo))
                                wake_up_interruptible(&proc->wait);
@@ -2623,7 +2643,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
                }
                binder_debug(BINDER_DEBUG_READ_WRITE,
-                            "%d:%d wrote %ld of %ld, read return %ld of %ld\n",
+                            "%d:%d wrote %d of %d, read return %d of %d\n",
                             proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
                             bwr.read_consumed, bwr.read_size);
                if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
@@ -2632,13 +2652,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                }
                break;
        }
-       case BINDER_SET_MAX_THREADS:
+       case _IOC_NR(BINDER_SET_MAX_THREADS):
                if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
                        ret = -EINVAL;
                        goto err;
                }
                break;
-       case BINDER_SET_CONTEXT_MGR:
+       case _IOC_NR(BINDER_SET_CONTEXT_MGR):
                if (binder_context_mgr_node != NULL) {
                        pr_err("BINDER_SET_CONTEXT_MGR already set\n");
                        ret = -EBUSY;
@@ -2657,7 +2677,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
                } else
                        binder_context_mgr_uid = current->cred->euid;
-               binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
+               binder_context_mgr_node = binder_new_node(proc, 0, 0);
                if (binder_context_mgr_node == NULL) {
                        ret = -ENOMEM;
                        goto err;
@@ -2667,14 +2687,15 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                binder_context_mgr_node->has_strong_ref = 1;
                binder_context_mgr_node->has_weak_ref = 1;
                break;
-       case BINDER_THREAD_EXIT:
+       case _IOC_NR(BINDER_THREAD_EXIT):
                binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
                             proc->pid, thread->pid);
                binder_free_thread(proc, thread);
                thread = NULL;
                break;
-       case BINDER_VERSION:
+       case _IOC_NR(BINDER_VERSION):
                if (size != sizeof(struct binder_version)) {
+                       pr_err("binder: BINDER_VERSION size differs\n");
                        ret = -EINVAL;
                        goto err;
                }
@@ -2684,6 +2705,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                }
                break;
        default:
+               pr_err("binder: IOCTL No. not found\n");
                ret = -EINVAL;
                goto err;
        }
@@ -3108,7 +3130,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix,
                                     struct binder_transaction *t)
 {
        seq_printf(m,
-                  "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+                  "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %d r%d",
                   prefix, t->debug_id, t,
                   t->from ? t->from->proc->pid : 0,
                   t->from ? t->from->pid : 0,
@@ -3153,7 +3175,7 @@ static void print_binder_work(struct seq_file *m, const char *prefix,
                break;
        case BINDER_WORK_NODE:
                node = container_of(w, struct binder_node, work);
-               seq_printf(m, "%snode work %d: u%p c%p\n",
+               seq_printf(m, "%snode work %d: u%x c%x\n",
                           prefix, node->debug_id, node->ptr, node->cookie);
                break;
        case BINDER_WORK_DEAD_BINDER:
@@ -3214,7 +3236,7 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
        hlist_for_each_entry(ref, &node->refs, node_entry)
                count++;
 
-       seq_printf(m, "  node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
+       seq_printf(m, "  node %d: u%x c%x hs %d hw %d ls %d lw %d is %d iw %d",
                   node->debug_id, node->ptr, node->cookie,
                   node->has_strong_ref, node->has_weak_ref,
                   node->local_strong_refs, node->local_weak_refs,
@@ -3517,6 +3539,7 @@ static const struct file_operations binder_fops = {
        .owner = THIS_MODULE,
        .poll = binder_poll,
        .unlocked_ioctl = binder_ioctl,
+       .compat_ioctl = binder_ioctl,   /* handler for 32-bit compat layer */
        .mmap = binder_mmap,
        .open = binder_open,
        .flush = binder_flush,
index d4101a671718ef2c8428c18074dec6fd13f94c65..f514f30db1a672ab07a88f804c8e5312fce18562 100644 (file)
 #ifndef _LINUX_BINDER_H
 #define _LINUX_BINDER_H
 
-#include "uapi/binder.h"
+#include <linux/ioctl.h>
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+       ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+#define B_TYPE_LARGE 0x85
+
+typedef uint32_t userptr32_t;
+
+enum {
+       BINDER_TYPE_BINDER      = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
+       BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
+       BINDER_TYPE_HANDLE      = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
+       BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
+       BINDER_TYPE_FD          = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
+};
+
+enum {
+       FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+       FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+};
+
+/*
+ * This is the flattened representation of a Binder object for transfer
+ * between processes.  The 'offsets' supplied as part of a binder transaction
+ * contains offsets into the data where these structures occur.  The Binder
+ * driver takes care of re-writing the structure type and data as it moves
+ * between processes.
+ */
+struct flat_binder_object {
+       /* 8 bytes for large_flat_header. */
+       uint32_t                type;
+       uint32_t                flags;
+
+       /* 8 bytes of data. */
+       union {
+               userptr32_t     binder;         /* local object */
+               int32_t         handle;         /* remote object */
+       };
+
+       /* extra data associated with local object */
+       userptr32_t             cookie;
+};
+
+/*
+ * On 64-bit platforms where user code may run in 32-bits the driver must
+ * translate the buffer (and local binder) addresses appropriately.
+ */
+
+struct binder_write_read {
+       int32_t         write_size;     /* bytes to write */
+       int32_t         write_consumed; /* bytes consumed by driver */
+       uint32_t        write_buffer;
+       int32_t         read_size;      /* bytes to read */
+       int32_t         read_consumed;  /* bytes consumed by driver */
+       uint32_t        read_buffer;
+};
+
+/* Use with BINDER_VERSION, driver fills in fields. */
+struct binder_version {
+       /* driver protocol version -- increment with incompatible change */
+       int32_t         protocol_version;
+};
+
+/* This is the current protocol version. */
+#define BINDER_CURRENT_PROTOCOL_VERSION 7
+
+#define BINDER_WRITE_READ              _IOWR('b', 1, struct binder_write_read)
+#define        BINDER_SET_IDLE_TIMEOUT         _IOW('b', 3, __s64)
+#define        BINDER_SET_MAX_THREADS          _IOW('b', 5, uint32_t)
+#define        BINDER_SET_IDLE_PRIORITY        _IOW('b', 6, __s32)
+#define        BINDER_SET_CONTEXT_MGR          _IOW('b', 7, __s32)
+#define        BINDER_THREAD_EXIT              _IOW('b', 8, __s32)
+#define BINDER_VERSION                 _IOWR('b', 9, struct binder_version)
+
+/*
+ * NOTE: Two special error codes you should check for when calling
+ * in to the driver are:
+ *
+ * EINTR -- The operation has been interupted.  This should be
+ * handled by retrying the ioctl() until a different error code
+ * is returned.
+ *
+ * ECONNREFUSED -- The driver is no longer accepting operations
+ * from your process.  That is, the process is being destroyed.
+ * You should handle this by exiting from your process.  Note
+ * that once this error code is returned, all further calls to
+ * the driver from any thread will return this same code.
+ */
+
+enum transaction_flags {
+       TF_ONE_WAY      = 0x01, /* this is a one-way call: async, no return */
+       TF_ROOT_OBJECT  = 0x04, /* contents are the component's root object */
+       TF_STATUS_CODE  = 0x08, /* contents are a 32-bit status code */
+       TF_ACCEPT_FDS   = 0x10, /* allow replies with file descriptors */
+};
+
+struct binder_transaction_data {
+       /* The first two are only used for bcTRANSACTION and brTRANSACTION,
+        * identifying the target and contents of the transaction.
+        */
+       union {
+               uint32_t        handle; /* target descriptor of command transaction */
+               userptr32_t     ptr;    /* target descriptor of return transaction */
+       } target;
+       userptr32_t     cookie; /* target object cookie */
+       unsigned int    code;           /* transaction command */
+
+       /* General information about the transaction. */
+       __u32           flags;
+       pid_t           sender_pid;
+       uid_t           sender_euid;
+       uint32_t        data_size;      /* number of bytes of data */
+       uint32_t        offsets_size;   /* number of bytes of offsets */
+
+       /* If this transaction is inline, the data immediately
+        * follows here; otherwise, it ends with a pointer to
+        * the data buffer.
+        */
+       union {
+               struct {
+                       /* transaction data */
+                       userptr32_t     buffer;
+                       /* offsets from buffer to flat_binder_object structs */
+                       userptr32_t     offsets;
+               } ptr;
+               __u8    buf[8];
+       } data;
+};
+
+struct binder_ptr_cookie {
+       userptr32_t tr;
+       userptr32_t cookie;
+};
+
+struct binder_pri_desc {
+       __s32 priority;
+       __u32 desc;
+};
+
+struct binder_pri_ptr_cookie {
+       int priority;
+       userptr32_t ptr;
+       userptr32_t cookie;
+};
+
+enum binder_driver_return_protocol {
+       BR_ERROR = _IOR('r', 0, __s32),
+       /*
+        * int: error code
+        */
+
+       BR_OK = _IO('r', 1),
+       /* No parameters! */
+
+       BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
+       BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
+       /*
+        * binder_transaction_data: the received command.
+        */
+
+       BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
+       /*
+        * not currently supported
+        * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
+        * Else the remote object has acquired a primary reference.
+        */
+
+       BR_DEAD_REPLY = _IO('r', 5),
+       /*
+        * The target of the last transaction (either a bcTRANSACTION or
+        * a bcATTEMPT_ACQUIRE) is no longer with us.  No parameters.
+        */
+
+       BR_TRANSACTION_COMPLETE = _IO('r', 6),
+       /*
+        * No parameters... always refers to the last transaction requested
+        * (including replies).  Note that this will be sent even for
+        * asynchronous transactions.
+        */
+
+       BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
+       BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
+       BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
+       BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
+       /*
+        * void *:      ptr to binder
+        * void *: cookie for binder
+        */
+
+       BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
+       /*
+        * not currently supported
+        * int: priority
+        * void *: ptr to binder
+        * void *: cookie for binder
+        */
+
+       BR_NOOP = _IO('r', 12),
+       /*
+        * No parameters.  Do nothing and examine the next command.  It exists
+        * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
+        */
+
+       BR_SPAWN_LOOPER = _IO('r', 13),
+       /*
+        * No parameters.  The driver has determined that a process has no
+        * threads waiting to service incoming transactions.  When a process
+        * receives this command, it must spawn a new service thread and
+        * register it via bcENTER_LOOPER.
+        */
+
+       BR_FINISHED = _IO('r', 14),
+       /*
+        * not currently supported
+        * stop threadpool thread
+        */
+
+       BR_DEAD_BINDER = _IOR('r', 15, userptr32_t),
+       /*
+        * void *: cookie
+        */
+       BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, userptr32_t),
+       /*
+        * void *: cookie
+        */
+
+       BR_FAILED_REPLY = _IO('r', 17),
+       /*
+        * The the last transaction (either a bcTRANSACTION or
+        * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory).  No parameters.
+        */
+};
+
+enum binder_driver_command_protocol {
+       BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
+       BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
+       /*
+        * binder_transaction_data: the sent command.
+        */
+
+       BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
+       /*
+        * not currently supported
+        * int:  0 if the last BR_ATTEMPT_ACQUIRE was not successful.
+        * Else you have acquired a primary reference on the object.
+        */
+
+       BC_FREE_BUFFER = _IOW('c', 3, void *),
+       /*
+        * void *: ptr to transaction data received on a read
+        */
+
+       BC_INCREFS = _IOW('c', 4, __u32),
+       BC_ACQUIRE = _IOW('c', 5, __u32),
+       BC_RELEASE = _IOW('c', 6, __u32),
+       BC_DECREFS = _IOW('c', 7, __u32),
+       /*
+        * int: descriptor
+        */
+
+       BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
+       BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
+       /*
+        * void *: ptr to binder
+        * void *: cookie for binder
+        */
+
+       BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
+       /*
+        * not currently supported
+        * int: priority
+        * int: descriptor
+        */
+
+       BC_REGISTER_LOOPER = _IO('c', 11),
+       /*
+        * No parameters.
+        * Register a spawned looper thread with the device.
+        */
+
+       BC_ENTER_LOOPER = _IO('c', 12),
+       BC_EXIT_LOOPER = _IO('c', 13),
+       /*
+        * No parameters.
+        * These two commands are sent as an application-level thread
+        * enters and exits the binder loop, respectively.  They are
+        * used so the binder can have an accurate count of the number
+        * of looping threads it has available.
+        */
+
+       BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
+       /*
+        * void *: ptr to binder
+        * void *: cookie
+        */
+
+       BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
+       /*
+        * void *: ptr to binder
+        * void *: cookie
+        */
+
+       BC_DEAD_BINDER_DONE = _IOW('c', 16, userptr32_t),
+       /*
+        * void *: cookie
+        */
+};
 
 #endif /* _LINUX_BINDER_H */