[PATCH] android: binder: Disable preemption while holding the global binder lock

2016-09-08 Thread Todd Kjos
In Android systems, the display pipeline relies on low
latency binder transactions and is therefore sensitive to
delays caused by contention for the global binder lock.
Jank is siginificantly reduced by disabling preemption
while the global binder lock is held.

Originally-from: Riley Andrews <riandr...@google.com>
Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 194 +++
 1 file changed, 146 insertions(+), 48 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 16288e7..c36e420 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -379,6 +379,7 @@ static int task_get_unused_fd_flags(struct
binder_proc *proc, int flags)
  struct files_struct *files = proc->files;
  unsigned long rlim_cur;
  unsigned long irqs;
+ int ret;

  if (files == NULL)
  return -ESRCH;
@@ -389,7 +390,11 @@ static int task_get_unused_fd_flags(struct
binder_proc *proc, int flags)
  rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
  unlock_task_sighand(proc->tsk, );

- return __alloc_fd(files, 0, rlim_cur, flags);
+ preempt_enable_no_resched();
+ ret = __alloc_fd(files, 0, rlim_cur, flags);
+ preempt_disable();
+
+ return ret;
 }

 /*
@@ -398,8 +403,11 @@ static int task_get_unused_fd_flags(struct
binder_proc *proc, int flags)
 static void task_fd_install(
  struct binder_proc *proc, unsigned int fd, struct file *file)
 {
- if (proc->files)
+ if (proc->files) {
+ preempt_enable_no_resched();
  __fd_install(proc->files, fd, file);
+ preempt_disable();
+ }
 }

 /*
@@ -427,6 +435,7 @@ static inline void binder_lock(const char *tag)
 {
  trace_binder_lock(tag);
  mutex_lock(_main_lock);
+ preempt_disable();
  trace_binder_locked(tag);
 }

@@ -434,8 +443,65 @@ static inline void binder_unlock(const char *tag)
 {
  trace_binder_unlock(tag);
  mutex_unlock(_main_lock);
+ preempt_enable();
+}
+
+static inline void *kzalloc_nopreempt(size_t size)
+{
+ void *ptr;
+
+ ptr = kzalloc(size, GFP_NOWAIT);
+ if (ptr)
+ return ptr;
+
+ preempt_enable_no_resched();
+ ptr = kzalloc(size, GFP_KERNEL);
+ preempt_disable();
+
+ return ptr;
+}
+
+static inline long copy_to_user_nopreempt(void __user *to,
+  const void *from, long n)
+{
+ long ret;
+
+ preempt_enable_no_resched();
+ ret = copy_to_user(to, from, n);
+ preempt_disable();
+ return ret;
+}
+
+static inline long copy_from_user_nopreempt(void *to,
+const void __user *from,
+long n)
+{
+ long ret;
+
+ preempt_enable_no_resched();
+ ret = copy_from_user(to, from, n);
+ preempt_disable();
+ return ret;
 }

+#define get_user_nopreempt(x, ptr) \
+({ \
+ int __ret; \
+ preempt_enable_no_resched(); \
+ __ret = get_user(x, ptr); \
+ preempt_disable(); \
+ __ret; \
+})
+
+#define put_user_nopreempt(x, ptr) \
+({ \
+ int __ret; \
+ preempt_enable_no_resched(); \
+ __ret = put_user(x, ptr); \
+ preempt_disable(); \
+ __ret; \
+})
+
 static void binder_set_nice(long nice)
 {
  long min_nice;
@@ -568,6 +634,8 @@ static int binder_update_page_range(struct
binder_proc *proc, int allocate,
  else
  mm = get_task_mm(proc->tsk);

+ preempt_enable_no_resched();
+
  if (mm) {
  down_write(>mmap_sem);
  vma = proc->vma;
@@ -622,6 +690,9 @@ static int binder_update_page_range(struct
binder_proc *proc, int allocate,
  up_write(>mmap_sem);
  mmput(mm);
  }
+
+ preempt_disable();
+
  return 0;

 free_range:
@@ -644,6 +715,9 @@ err_no_vma:
  up_write(>mmap_sem);
  mmput(mm);
  }
+
+ preempt_disable();
+
  return -ENOMEM;
 }

@@ -903,7 +977,7 @@ static struct binder_node *binder_new_node(struct
binder_proc *proc,
  return NULL;
  }

- node = kzalloc(sizeof(*node), GFP_KERNEL);
+ node = kzalloc_nopreempt(sizeof(*node));
  if (node == NULL)
  return NULL;
  binder_stats_created(BINDER_STAT_NODE);
@@ -1040,7 +1114,7 @@ static struct binder_ref
*binder_get_ref_for_node(struct binder_proc *proc,
  else
  return ref;
  }
- new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ new_ref = kzalloc_nopreempt(sizeof(*ref));
  if (new_ref == NULL)
  return NULL;
  binder_stats_created(BINDER_STAT_REF);
@@ -1438,14 +1512,14 @@ static void binder_transaction(struct binder_proc *proc,
  e->to_proc = target_proc->pid;

  /* TODO: reuse incoming transaction for reply */
- t = kzalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc_nopreempt(sizeof(*t));
  if (t == NULL) {
  return_error = BR_FAILED_REPLY;
  goto err_alloc_t_failed;
  }
  binder_stats_created(BINDER_STAT_TRANSACTION);

- tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
+ tcomplete = kzalloc_nopreempt(sizeof(*tcomplete));
  if (tcomplete == NULL) {
  return_error = BR_FAILED_REPLY;
  goto err_alloc_tcomplete_failed;
@@ -1502,15 +1576,16 @@ static void binder_transaction(struct binder_proc *proc,
  offp = (binder_size_t *)(t->buffer->data +
  ALIGN(tr->data_size, sizeof(void *)));

- if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
-   tr->data.ptr.buffer, tr->data_size)

Re: [PATCH] android: binder: Disable preemption while holding the global binder lock

2016-09-08 Thread Todd Kjos
This was introduced in the 2015 Nexus devices and should have been
submitted to the kernel then since we keep forward porting it to each
new device.

On Thu, Sep 8, 2016 at 9:12 AM, Todd Kjos <tk...@google.com> wrote:
> In Android systems, the display pipeline relies on low
> latency binder transactions and is therefore sensitive to
> delays caused by contention for the global binder lock.
> Jank is siginificantly reduced by disabling preemption
> while the global binder lock is held.
>
> Originally-from: Riley Andrews <riandr...@google.com>
> Signed-off-by: Todd Kjos <tk...@google.com>
> ---
>  drivers/android/binder.c | 194 
> +++
>  1 file changed, 146 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 16288e7..c36e420 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -379,6 +379,7 @@ static int task_get_unused_fd_flags(struct
> binder_proc *proc, int flags)
>   struct files_struct *files = proc->files;
>   unsigned long rlim_cur;
>   unsigned long irqs;
> + int ret;
>
>   if (files == NULL)
>   return -ESRCH;
> @@ -389,7 +390,11 @@ static int task_get_unused_fd_flags(struct
> binder_proc *proc, int flags)
>   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
>   unlock_task_sighand(proc->tsk, );
>
> - return __alloc_fd(files, 0, rlim_cur, flags);
> + preempt_enable_no_resched();
> + ret = __alloc_fd(files, 0, rlim_cur, flags);
> + preempt_disable();
> +
> + return ret;
>  }
>
>  /*
> @@ -398,8 +403,11 @@ static int task_get_unused_fd_flags(struct
> binder_proc *proc, int flags)
>  static void task_fd_install(
>   struct binder_proc *proc, unsigned int fd, struct file *file)
>  {
> - if (proc->files)
> + if (proc->files) {
> + preempt_enable_no_resched();
>   __fd_install(proc->files, fd, file);
> + preempt_disable();
> + }
>  }
>
>  /*
> @@ -427,6 +435,7 @@ static inline void binder_lock(const char *tag)
>  {
>   trace_binder_lock(tag);
>   mutex_lock(_main_lock);
> + preempt_disable();
>   trace_binder_locked(tag);
>  }
>
> @@ -434,8 +443,65 @@ static inline void binder_unlock(const char *tag)
>  {
>   trace_binder_unlock(tag);
>   mutex_unlock(_main_lock);
> + preempt_enable();
> +}
> +
> +static inline void *kzalloc_nopreempt(size_t size)
> +{
> + void *ptr;
> +
> + ptr = kzalloc(size, GFP_NOWAIT);
> + if (ptr)
> + return ptr;
> +
> + preempt_enable_no_resched();
> + ptr = kzalloc(size, GFP_KERNEL);
> + preempt_disable();
> +
> + return ptr;
> +}
> +
> +static inline long copy_to_user_nopreempt(void __user *to,
> +  const void *from, long n)
> +{
> + long ret;
> +
> + preempt_enable_no_resched();
> + ret = copy_to_user(to, from, n);
> + preempt_disable();
> + return ret;
> +}
> +
> +static inline long copy_from_user_nopreempt(void *to,
> +const void __user *from,
> +long n)
> +{
> + long ret;
> +
> + preempt_enable_no_resched();
> + ret = copy_from_user(to, from, n);
> + preempt_disable();
> + return ret;
>  }
>
> +#define get_user_nopreempt(x, ptr) \
> +({ \
> + int __ret; \
> + preempt_enable_no_resched(); \
> + __ret = get_user(x, ptr); \
> + preempt_disable(); \
> + __ret; \
> +})
> +
> +#define put_user_nopreempt(x, ptr) \
> +({ \
> + int __ret; \
> + preempt_enable_no_resched(); \
> + __ret = put_user(x, ptr); \
> + preempt_disable(); \
> + __ret; \
> +})
> +
>  static void binder_set_nice(long nice)
>  {
>   long min_nice;
> @@ -568,6 +634,8 @@ static int binder_update_page_range(struct
> binder_proc *proc, int allocate,
>   else
>   mm = get_task_mm(proc->tsk);
>
> + preempt_enable_no_resched();
> +
>   if (mm) {
>   down_write(>mmap_sem);
>   vma = proc->vma;
> @@ -622,6 +690,9 @@ static int binder_update_page_range(struct
> binder_proc *proc, int allocate,
>   up_write(>mmap_sem);
>   mmput(mm);
>   }
> +
> + preempt_disable();
> +
>   return 0;
>
>  free_range:
> @@ -644,6 +715,9 @@ err_no_vma:
>   up_write(>mmap_sem);
>   mmput(mm);
>   }
> +
> + preempt_disable();
> +
>   return -ENOMEM;
>  }
>
> @@ -903,7 +977,7 @@ static struct binder_node *binder_new_node(struct
> binder_proc *proc,
>   return NULL;
>   }
>
> - node = kzalloc(sizeof(*node), GFP_KERNEL);
> + node = kzalloc_nopreempt(sizeof(*node));
>   if (node == NULL)
>   return NULL;
>   binder_stats_created(BINDER_STAT_NODE);
> @@ -1040,7 +1114,7 @@ static struct binder_ref
> *binder_get_ref_for_node(struct binder_

[PATCH] android: binder: Disable preemption while holding the global binder lock

2016-09-09 Thread Todd Kjos
From: Todd Kjos <tk...@android.com>

In Android systems, the display pipeline relies on low
latency binder transactions and is therefore sensitive to
delays caused by contention for the global binder lock.
Jank is significantly reduced by disabling preemption
while the global binder lock is held.

This patch was originated by Riley Andrews <riandr...@android.com>
with tweaks and forward-porting by me.

Originally-from: Riley Andrews <riandr...@android.com>
Signed-off-by: Todd Kjos <tk...@android.com>
---
 drivers/android/binder.c | 194 +++
 1 file changed, 146 insertions(+), 48 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 16288e7..c36e420 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -379,6 +379,7 @@ static int task_get_unused_fd_flags(struct binder_proc 
*proc, int flags)
struct files_struct *files = proc->files;
unsigned long rlim_cur;
unsigned long irqs;
+   int ret;
 
if (files == NULL)
return -ESRCH;
@@ -389,7 +390,11 @@ static int task_get_unused_fd_flags(struct binder_proc 
*proc, int flags)
rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
unlock_task_sighand(proc->tsk, );
 
-   return __alloc_fd(files, 0, rlim_cur, flags);
+   preempt_enable_no_resched();
+   ret = __alloc_fd(files, 0, rlim_cur, flags);
+   preempt_disable();
+
+   return ret;
 }
 
 /*
@@ -398,8 +403,11 @@ static int task_get_unused_fd_flags(struct binder_proc 
*proc, int flags)
 static void task_fd_install(
struct binder_proc *proc, unsigned int fd, struct file *file)
 {
-   if (proc->files)
+   if (proc->files) {
+   preempt_enable_no_resched();
__fd_install(proc->files, fd, file);
+   preempt_disable();
+   }
 }
 
 /*
@@ -427,6 +435,7 @@ static inline void binder_lock(const char *tag)
 {
trace_binder_lock(tag);
mutex_lock(_main_lock);
+   preempt_disable();
trace_binder_locked(tag);
 }
 
@@ -434,8 +443,65 @@ static inline void binder_unlock(const char *tag)
 {
trace_binder_unlock(tag);
mutex_unlock(_main_lock);
+   preempt_enable();
+}
+
+static inline void *kzalloc_nopreempt(size_t size)
+{
+   void *ptr;
+
+   ptr = kzalloc(size, GFP_NOWAIT);
+   if (ptr)
+   return ptr;
+
+   preempt_enable_no_resched();
+   ptr = kzalloc(size, GFP_KERNEL);
+   preempt_disable();
+
+   return ptr;
+}
+
+static inline long copy_to_user_nopreempt(void __user *to,
+ const void *from, long n)
+{
+   long ret;
+
+   preempt_enable_no_resched();
+   ret = copy_to_user(to, from, n);
+   preempt_disable();
+   return ret;
+}
+
+static inline long copy_from_user_nopreempt(void *to,
+   const void __user *from,
+   long n)
+{
+   long ret;
+
+   preempt_enable_no_resched();
+   ret = copy_from_user(to, from, n);
+   preempt_disable();
+   return ret;
 }
 
+#define get_user_nopreempt(x, ptr) \
+({ \
+   int __ret;  \
+   preempt_enable_no_resched();\
+   __ret = get_user(x, ptr);   \
+   preempt_disable();  \
+   __ret;  \
+})
+
+#define put_user_nopreempt(x, ptr) \
+({ \
+   int __ret;  \
+   preempt_enable_no_resched();\
+   __ret = put_user(x, ptr);   \
+   preempt_disable();  \
+   __ret;  \
+})
+
 static void binder_set_nice(long nice)
 {
long min_nice;
@@ -568,6 +634,8 @@ static int binder_update_page_range(struct binder_proc 
*proc, int allocate,
else
mm = get_task_mm(proc->tsk);
 
+   preempt_enable_no_resched();
+
if (mm) {
down_write(>mmap_sem);
vma = proc->vma;
@@ -622,6 +690,9 @@ static int binder_update_page_range(struct binder_proc 
*proc, int allocate,
up_write(>mmap_sem);
mmput(mm);
}
+
+   preempt_disable();
+
return 0;
 
 free_range:
@@ -644,6 +715,9 @@ err_no_vma:
up_write(>mmap_sem);
mmput(mm);
}
+
+   preempt_disable();
+
return -ENOMEM;
 }
 
@@ -903,7 +977,7 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
return NULL;
}
 
-   node = kzalloc(sizeof(*node), GFP_KERNEL);
+   node = kzalloc_nopreempt(sizeof(*node));
if (node == NULL)
return NULL;
binder_stats_creat

Re: [PATCH] android: binder: Disable preemption while holding the global binder lock

2016-09-09 Thread Todd Kjos
On Fri, Sep 9, 2016 at 8:44 AM, Greg KH <gre...@linuxfoundation.org> wrote:
> On Fri, Sep 09, 2016 at 08:17:44AM -0700, Todd Kjos wrote:
>> From: Todd Kjos <tk...@android.com>
>>
>> In Android systems, the display pipeline relies on low
>> latency binder transactions and is therefore sensitive to
>> delays caused by contention for the global binder lock.
>> Jank is significantly reduced by disabling preemption
>> while the global binder lock is held.
>
> What is the technical definition of "Jank"?  :)

I'll rephrase in the next version to "dropped or delayed frames".

>
>>
>> This patch was originated by Riley Andrews <riandr...@android.com>
>> with tweaks and forward-porting by me.
>>
>> Originally-from: Riley Andrews <riandr...@android.com>
>> Signed-off-by: Todd Kjos <tk...@android.com>
>> ---
>>  drivers/android/binder.c | 194 
>> +++
>>  1 file changed, 146 insertions(+), 48 deletions(-)
>>
>> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
>> index 16288e7..c36e420 100644
>> --- a/drivers/android/binder.c
>> +++ b/drivers/android/binder.c
>> @@ -379,6 +379,7 @@ static int task_get_unused_fd_flags(struct binder_proc 
>> *proc, int flags)
>>   struct files_struct *files = proc->files;
>>   unsigned long rlim_cur;
>>   unsigned long irqs;
>> + int ret;
>>
>>   if (files == NULL)
>>   return -ESRCH;
>> @@ -389,7 +390,11 @@ static int task_get_unused_fd_flags(struct binder_proc 
>> *proc, int flags)
>>   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
>>   unlock_task_sighand(proc->tsk, );
>>
>> - return __alloc_fd(files, 0, rlim_cur, flags);
>> + preempt_enable_no_resched();
>> + ret = __alloc_fd(files, 0, rlim_cur, flags);
>> + preempt_disable();
>> +
>> + return ret;
>>  }
>>
>>  /*
>> @@ -398,8 +403,11 @@ static int task_get_unused_fd_flags(struct binder_proc 
>> *proc, int flags)
>>  static void task_fd_install(
>>   struct binder_proc *proc, unsigned int fd, struct file *file)
>>  {
>> - if (proc->files)
>> + if (proc->files) {
>> + preempt_enable_no_resched();
>>   __fd_install(proc->files, fd, file);
>> + preempt_disable();
>> + }
>>  }
>>
>>  /*
>> @@ -427,6 +435,7 @@ static inline void binder_lock(const char *tag)
>>  {
>>   trace_binder_lock(tag);
>>   mutex_lock(_main_lock);
>> + preempt_disable();
>>   trace_binder_locked(tag);
>>  }
>>
>> @@ -434,8 +443,65 @@ static inline void binder_unlock(const char *tag)
>>  {
>>   trace_binder_unlock(tag);
>>   mutex_unlock(_main_lock);
>> + preempt_enable();
>> +}
>> +
>> +static inline void *kzalloc_nopreempt(size_t size)
>> +{
>> + void *ptr;
>> +
>> + ptr = kzalloc(size, GFP_NOWAIT);
>> + if (ptr)
>> + return ptr;
>> +
>> + preempt_enable_no_resched();
>> + ptr = kzalloc(size, GFP_KERNEL);
>> + preempt_disable();
>
> Doesn't the allocator retry if the first one fails anyway?  Why not
> GFP_NOIO or GFP_ATOMIC?  Have you really hit the second GFP_KERNEL
> usage?

I suspect we have hit the second, since we do get into cases where
direct reclaim is needed. I can't confirm since I haven't instrumented
this case. As you say, if we use GFP_ATOMIC instead, maybe we
wouldn't, but even then I'd be concerned that we could deplete the
memory reserved for atomic. The general idea of trying for a fast,
nowait allocation and then enabling preempt for the rare potentially
blocking allocation seems reasonable, doesn't it?

>> +
>> + return ptr;
>> +}
>> +
>> +static inline long copy_to_user_nopreempt(void __user *to,
>> +   const void *from, long n)
>> +{
>> + long ret;
>> +
>> + preempt_enable_no_resched();
>> + ret = copy_to_user(to, from, n);
>> + preempt_disable();
>> + return ret;
>> +}
>> +
>> +static inline long copy_from_user_nopreempt(void *to,
>> + const void __user *from,
>> + long n)
>> +{
>> + long ret;
>> +
>> + preempt_enable_no_resched();
>> + ret = copy_from_user(to, from, n);
>> + preempt_disable();
>> + retur

Re: [PATCH] android: binder: Disable preemption while holding the global binder lock

2016-09-12 Thread Todd Kjos
Thanks for the reviews. We'll come up with a different solution.

On Sat, Sep 10, 2016 at 10:28 AM, Greg Kroah-Hartman
<gre...@linuxfoundation.org> wrote:
> On Sat, Sep 10, 2016 at 06:37:29PM +0200, Thomas Gleixner wrote:
>> On Sat, 10 Sep 2016, Peter Zijlstra wrote:
>>
>> > On Sat, Sep 10, 2016 at 09:16:59AM -0700, Christoph Hellwig wrote:
>> > > On Thu, Sep 08, 2016 at 09:12:50AM -0700, Todd Kjos wrote:
>> > > > In Android systems, the display pipeline relies on low
>> > > > latency binder transactions and is therefore sensitive to
>> > > > delays caused by contention for the global binder lock.
>> > > > Jank is siginificantly reduced by disabling preemption
>> > > > while the global binder lock is held.
>> > >
>> > > That's now how preempt_disable is supposed to use.  It is for critical
>> >
>> > not, that's supposed to be _not_. Just to be absolutely clear, this is
>> > NOT how you're supposed to use preempt_disable().
>> >
>> > > sections that use per-cpu or similar resources.
>> > >
>> > > >
>> > > > Originally-from: Riley Andrews <riandr...@google.com>
>> > > > Signed-off-by: Todd Kjos <tk...@google.com>
>> >
>> > > > @@ -389,7 +390,11 @@ static int task_get_unused_fd_flags(struct
>> > > > binder_proc *proc, int flags)
>> > > >   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
>> > > >   unlock_task_sighand(proc->tsk, );
>> > > >
>> > > > - return __alloc_fd(files, 0, rlim_cur, flags);
>> > > > + preempt_enable_no_resched();
>> > > > + ret = __alloc_fd(files, 0, rlim_cur, flags);
>> > > > + preempt_disable();
>> >
>> > And the fact that people want to use preempt_enable_no_resched() shows
>> > that they're absolutely clueless.
>> >
>> > This is so broken its not funny.
>> >
>> > NAK NAK NAK
>>
>> Indeed. Sprinkling random preempt_enabe/disable() pairs all over the place
>> documents clearly that this is tinkering and not proper software
>> engineering.
>
> I have pointed out in the other thread for this patch (the one that had
> a patch that could be applied) that the single lock in the binder code
> is the main problem here, it should be solved instead of this messing
> around with priorities.
>
> So don't worry, I'm not taking this change :)
>
> thanks,
>
> greg k-h


Re: [PATCH] android: binder: Disable preemption while holding the global binder lock

2016-09-16 Thread Todd Kjos
Thanks Peter. We'll give that patch a try as part of our refactoring.
Looking at finer-grained locking and we'll try going back to rt_mutex
plus this patch.

On Wed, Sep 14, 2016 at 9:55 AM, Peter Zijlstra  wrote:
> On Wed, Sep 14, 2016 at 06:13:40PM +0200, Peter Zijlstra wrote:
>> On Wed, Sep 14, 2016 at 06:11:03PM +0200, Peter Zijlstra wrote:
>> > On Tue, Sep 13, 2016 at 12:53:27PM -0700, Arve Hjønnevåg wrote:
>> > > On Tue, Sep 13, 2016 at 12:32 AM, Peter Zijlstra  
>> > > wrote:
>> > > > cgroups should be irrelevant, PI is unaware of them.
>> > >
>> > > I don't think cgroups are irrelevant. PI being unaware of them
>> > > explains the problem I described. If the task that holds the lock is
>> > > in a cgroup that has a low cpu.shares value, then boosting the task's
>> > > priority within that group does necessarily make it any more likely to
>> > > run.
>> >
>> > Thing is, for FIFO/DL the important parameters (prio and deadline resp.)
>> > are not cgroup dependent.
>> >
>> > For CFS you're right, and as per usual, cgroups will be a royal pain.
>> > While we can compute the total weight in the block chain, getting that
>> > back to a task which is stuck in a cgroup is just not going to work
>> > well.
>>
>> Not to mention the fact that the weight depends on the current running
>> state. Having those tasks block insta changes the actual weight.
>>
>> > /me curses @ cgroups.. bloody stupid things.
>>
>> More of that.
>
>
> Something a little like so... completely untested, and has a fair number
> of corner cases still left open I think..
>
>
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1691,8 +1691,8 @@ struct task_struct {
> struct seccomp seccomp;
>
>  /* Thread group tracking */
> -   u32 parent_exec_id;
> -   u32 self_exec_id;
> +   u32 parent_exec_id;
> +   u32 self_exec_id;
>  /* Protection of (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed,
>   * mempolicy */
> spinlock_t alloc_lock;
> @@ -1710,6 +1710,11 @@ struct task_struct {
> struct task_struct *pi_top_task;
> /* Deadlock detection and priority inheritance handling */
> struct rt_mutex_waiter *pi_blocked_on;
> +   unsigned long pi_weight;
> +#ifdef CONFIG_CGROUP_SCHED
> +   struct task_group *orig_task_group;
> +   unsigned long normal_weight;
> +#endif
>  #endif
>
>  #ifdef CONFIG_DEBUG_MUTEXES
> @@ -1977,6 +1982,8 @@ static inline int tsk_nr_cpus_allowed(st
> return p->nr_cpus_allowed;
>  }
>
> +extern unsigned long task_pi_weight(struct task_struct *p);
> +
>  #define TNF_MIGRATED   0x01
>  #define TNF_NO_GROUP   0x02
>  #define TNF_SHARED 0x04
> --- a/kernel/locking/rtmutex.c
> +++ b/kernel/locking/rtmutex.c
> @@ -20,6 +20,19 @@
>  #include "rtmutex_common.h"
>
>  /*
> + * !(rt_prio || dl_prio)
> + */
> +static inline bool other_prio(int prio)
> +{
> +   return prio >= MAX_RT_PRIO;
> +}
> +
> +static inline bool other_task(struct task_struct *task)
> +{
> +   return other_prio(task->prio);
> +}
> +
> +/*
>   * lock->owner state tracking:
>   *
>   * lock->owner holds the task_struct pointer of the owner. Bit 0
> @@ -226,6 +239,11 @@ rt_mutex_enqueue(struct rt_mutex *lock,
>
> rb_link_node(>tree_entry, parent, link);
> rb_insert_color(>tree_entry, >waiters);
> +   /*
> +* We want the lock->waiter_weight to reflect the sum of all queued
> +* waiters.
> +*/
> +   lock->waiters_weight += waiter->weight;
>  }
>
>  static void
> @@ -239,6 +257,7 @@ rt_mutex_dequeue(struct rt_mutex *lock,
>
> rb_erase(>tree_entry, >waiters);
> RB_CLEAR_NODE(>tree_entry);
> +   lock->waiters_weight += waiter->weight;
>  }
>
>  static void
> @@ -265,6 +284,18 @@ rt_mutex_enqueue_pi(struct task_struct *
>
> rb_link_node(>pi_tree_entry, parent, link);
> rb_insert_color(>pi_tree_entry, >pi_waiters);
> +
> +   /*
> +* Since a task can own multiple locks, and we have one pi_waiter
> +* for every lock, propagate the lock->waiter_weight, which is the sum
> +* of all weights queued on that lock, into the top waiter, and add
> +* that to the owning task's pi_weight.
> +*
> +* This results in pi_weight being the sum of all blocked waiters
> +* on this task.
> +*/
> +   waiter->top_weight = waiter->lock->waiters_weight;
> +   task->pi_weight += waiter->top_weight;
>  }
>
>  static void
> @@ -278,6 +309,7 @@ rt_mutex_dequeue_pi(struct task_struct *
>
> rb_erase(>pi_tree_entry, >pi_waiters);
> RB_CLEAR_NODE(>pi_tree_entry);
> +   task->pi_weight -= waiter->top_weight;
>  }
>
>  static void rt_mutex_adjust_prio(struct task_struct *p)
> @@ -497,7 +529,7 @@ static int rt_mutex_adjust_prio_chain(st
>  * detection is enabled we continue, but stop the
>  * requeueing in the chain walk.
>  */
> -   

Re: [PATCH 02/37] binder: use group leader instead of open thread

2017-07-07 Thread Todd Kjos
I suspect there won't be a respin. I'll ping you later if you don't
remember it yourself ;)

On Wed, Jul 5, 2017 at 11:47 AM, Greg KH <gre...@linuxfoundation.org> wrote:
> On Wed, Jul 05, 2017 at 09:13:16AM -0700, Todd Kjos wrote:
>> Yes, this one back to 4.4. 01/37 should go to 4.9 (its not in 4.4).
>
> Great, if this gets a respin, can you add it?  If not, I'll try to
> remember it :)
>
> thanks,
>
> greg k-h


[PATCH 07/37] binder: move binder_alloc to separate file

2017-06-29 Thread Todd Kjos
Move the binder allocator functionality to its own file

Continuation of splitting the binder allocator from the binder
driver. Split binder_alloc functions from normal binder functions.

Add kernel doc comments to functions declared extern in
binder_alloc.h

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/Makefile   |   2 +-
 drivers/android/binder.c   | 763 +
 drivers/android/binder_alloc.c | 759 
 drivers/android/binder_alloc.h | 162 +
 4 files changed, 923 insertions(+), 763 deletions(-)
 create mode 100644 drivers/android/binder_alloc.c
 create mode 100644 drivers/android/binder_alloc.h

diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index 3b7e4b072c58..4b7c726bb560 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -1,3 +1,3 @@
 ccflags-y += -I$(src)  # needed for trace events
 
-obj-$(CONFIG_ANDROID_BINDER_IPC)   += binder.o
+obj-$(CONFIG_ANDROID_BINDER_IPC)   += binder.o binder_alloc.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 6c1d0b5b352b..0512971cfc53 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -24,7 +24,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -35,8 +34,6 @@
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 
@@ -45,11 +42,11 @@
 #endif
 
 #include 
+#include "binder_alloc.h"
 #include "binder_trace.h"
 
 static DEFINE_MUTEX(binder_main_lock);
 static DEFINE_MUTEX(binder_deferred_lock);
-static DEFINE_MUTEX(binder_alloc_mmap_lock);
 
 static HLIST_HEAD(binder_devices);
 static HLIST_HEAD(binder_procs);
@@ -157,27 +154,6 @@ module_param_call(stop_on_user_error, 
binder_set_stop_on_user_error,
 #define to_binder_fd_array_object(hdr) \
container_of(hdr, struct binder_fd_array_object, hdr)
 
-/*
- * debug declarations for binder_alloc. To be
- * moved to binder_alloc.c
- */
-enum {
-   BINDER_ALLOC_DEBUG_OPEN_CLOSE = 1U << 1,
-   BINDER_ALLOC_DEBUG_BUFFER_ALLOC   = 1U << 2,
-   BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3,
-};
-static uint32_t binder_alloc_debug_mask;
-
-module_param_named(alloc_debug_mask, binder_alloc_debug_mask,
-  uint, 0644);
-
-#define binder_alloc_debug(mask, x...) \
-   do { \
-   if (binder_alloc_debug_mask & mask) \
-   pr_info(x); \
-   } while (0)
-/* end of binder_alloc debug declarations */
-
 enum binder_stat_types {
BINDER_STAT_PROC,
BINDER_STAT_THREAD,
@@ -314,68 +290,12 @@ struct binder_ref {
struct binder_ref_death *death;
 };
 
-struct binder_buffer {
-   struct list_head entry; /* free and allocated entries by address */
-   struct rb_node rb_node; /* free entry by size or allocated entry */
-   /* by address */
-   unsigned free:1;
-   unsigned allow_user_free:1;
-   unsigned async_transaction:1;
-   unsigned debug_id:29;
-
-   struct binder_transaction *transaction;
-
-   struct binder_node *target_node;
-   size_t data_size;
-   size_t offsets_size;
-   size_t extra_buffers_size;
-   uint8_t data[0];
-};
-
 enum binder_deferred_state {
BINDER_DEFERRED_PUT_FILES= 0x01,
BINDER_DEFERRED_FLUSH= 0x02,
BINDER_DEFERRED_RELEASE  = 0x04,
 };
 
-/**
- * struct binder_alloc - per-binder proc state for binder allocator
- * @vma:   vm_area_struct passed to mmap_handler
- * (invarient after mmap)
- * @vma_vm_mm: copy of vma->vm_mm (invarient after mmap)
- * @buffer:base of per-proc address space mapped via mmap
- * @user_buffer_offset: offset between user and kernel VAs for buffer
- * @buffers:   list of all buffers for this proc
- * @free_buffers:  rb tree of buffers available for allocation
- * sorted by size
- * @allocated_buffers: rb tree of allocated buffers sorted by address
- * @free_async_space:  VA space available for async buffers. This is
- * initialized at mmap time to 1/2 the full VA space
- * @pages: array of physical page addresses for each page of
- * mmap'd space
- * @buffer_size:   size of address space (could be less than requested)
- *
- * Bookkeeping structure for per-proc address space management for binder
- * buffers. It is normally initialized during binder_init() and binder_mmap()
- * calls. The address space is used for both user-visible buffers and for
- * struct binder_buffer objects used to track the user buffers
- */
-struct binder_alloc {
-   struct mutex mutex;
-   struct task_struct *tsk;
-   struct vm_area_struct *vma;
-   struct mm_struct *vma_vm_mm;
-   void *buffer;
-   ptrdiff_t u

[PATCH 36/37] binder: fix death race conditions

2017-06-29 Thread Todd Kjos
From: Martijn Coenen 

A race existed where one thread could register
a death notification for a node, while another
thread was cleaning up that node and sending
out death notifications for its references,
causing simultaneous access to ref->death
because different locks were held.

Signed-off-by: Martijn Coenen 
---
 drivers/android/binder.c | 64 
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 36ef88d10631..1e50b034d49a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -442,6 +442,7 @@ struct binder_ref_data {
  *   ref for deletion in binder_cleanup_ref, a non-NULL
  *   @node indicates the node must be freed
  * @death:   pointer to death notification (ref_death) if requested
+ *   (protected by @node->lock)
  *
  * Structure to track references from procA to target node (on procB). This
  * structure is unsafe to access without holding @proc->outer_lock.
@@ -3337,10 +3338,12 @@ static int binder_thread_write(struct binder_proc *proc,
 ref->data.desc, ref->data.strong,
 ref->data.weak, ref->node->debug_id);
 
+   binder_node_lock(ref->node);
if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
if (ref->death) {
binder_user_error("%d:%d 
BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
proc->pid, thread->pid);
+   binder_node_unlock(ref->node);
binder_proc_unlock(proc);
kfree(death);
break;
@@ -3349,7 +3352,6 @@ static int binder_thread_write(struct binder_proc *proc,
INIT_LIST_HEAD(>work.entry);
death->cookie = cookie;
ref->death = death;
-   binder_node_lock(ref->node);
if (ref->node->proc == NULL) {
ref->death->work.type = 
BINDER_WORK_DEAD_BINDER;
if (thread->looper &
@@ -3368,9 +3370,7 @@ static int binder_thread_write(struct binder_proc *proc,
>wait);
}
}
-   binder_node_unlock(ref->node);
} else {
-   binder_node_lock(ref->node);
if (ref->death == NULL) {
binder_user_error("%d:%d 
BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
proc->pid, thread->pid);
@@ -3410,8 +3410,8 @@ static int binder_thread_write(struct binder_proc *proc,
death->work.type = 
BINDER_WORK_DEAD_BINDER_AND_CLEAR;
}
binder_inner_proc_unlock(proc);
-   binder_node_unlock(ref->node);
}
+   binder_node_unlock(ref->node);
binder_proc_unlock(proc);
} break;
case BC_DEAD_BINDER_DONE: {
@@ -3748,44 +3748,39 @@ static int binder_thread_read(struct binder_proc *proc,
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
struct binder_ref_death *death;
uint32_t cmd;
+   binder_uintptr_t cookie;
 
death = container_of(w, struct binder_ref_death, work);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
else
cmd = BR_DEAD_BINDER;
-   /*
-* TODO: there is a race condition between
-* death notification requests and delivery
-* of the notifications. This will be handled
-* in a later patch.
-*/
-   binder_inner_proc_unlock(proc);
-   if (put_user(cmd, (uint32_t __user *)ptr))
-   return -EFAULT;
-   ptr += sizeof(uint32_t);
-   if (put_user(death->cookie,
-(binder_uintptr_t __user *)ptr))
-   return -EFAULT;
-   ptr += sizeof(binder_uintptr_t);
-  

[PATCH 13/37] binder: refactor queue management in binder_thread_read

2017-06-29 Thread Todd Kjos
In binder_thread_read, the BINDER_WORK_NODE command is used
to communicate the references on the node to userspace. It
can take a couple of iterations in the loop to construct
the list of commands for user space. When locking is added,
the lock would need to be release on each iteration which
means the state could change. The work item is not dequeued
during this process which prevents a simpler queue management
that can just dequeue up front and handle the work item.

Fixed by changing the BINDER_WORK_NODE algorithm in
binder_thread_read to determine which commands to send
to userspace atomically in 1 pass so it stays consistent
with the kernel view.

The work item is now dequeued immediately since only
1 pass is needed.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 151 +--
 1 file changed, 94 insertions(+), 57 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 62ac0c41b8a6..f17d1dfa5b02 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2285,6 +2285,37 @@ static int binder_has_thread_work(struct binder_thread 
*thread)
(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
 }
 
+static int binder_put_node_cmd(struct binder_proc *proc,
+  struct binder_thread *thread,
+  void __user **ptrp,
+  binder_uintptr_t node_ptr,
+  binder_uintptr_t node_cookie,
+  int node_debug_id,
+  uint32_t cmd, const char *cmd_name)
+{
+   void __user *ptr = *ptrp;
+
+   if (put_user(cmd, (uint32_t __user *)ptr))
+   return -EFAULT;
+   ptr += sizeof(uint32_t);
+
+   if (put_user(node_ptr, (binder_uintptr_t __user *)ptr))
+   return -EFAULT;
+   ptr += sizeof(binder_uintptr_t);
+
+   if (put_user(node_cookie, (binder_uintptr_t __user *)ptr))
+   return -EFAULT;
+   ptr += sizeof(binder_uintptr_t);
+
+   binder_stat_br(proc, thread, cmd);
+   binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s %d u%016llx c%016llx\n",
+proc->pid, thread->pid, cmd_name, node_debug_id,
+(u64)node_ptr, (u64)node_cookie);
+
+   *ptrp = ptr;
+   return 0;
+}
+
 static int binder_thread_read(struct binder_proc *proc,
  struct binder_thread *thread,
  binder_uintptr_t binder_buffer, size_t size,
@@ -2410,72 +2441,78 @@ static int binder_thread_read(struct binder_proc *proc,
} break;
case BINDER_WORK_NODE: {
struct binder_node *node = container_of(w, struct 
binder_node, work);
-   uint32_t cmd = BR_NOOP;
-   const char *cmd_name;
-   int strong = node->internal_strong_refs || 
node->local_strong_refs;
-   int weak = !hlist_empty(>refs) || 
node->local_weak_refs || strong;
-
-   if (weak && !node->has_weak_ref) {
-   cmd = BR_INCREFS;
-   cmd_name = "BR_INCREFS";
+   int strong, weak;
+   binder_uintptr_t node_ptr = node->ptr;
+   binder_uintptr_t node_cookie = node->cookie;
+   int node_debug_id = node->debug_id;
+   int has_weak_ref;
+   int has_strong_ref;
+   void __user *orig_ptr = ptr;
+
+   BUG_ON(proc != node->proc);
+   strong = node->internal_strong_refs ||
+   node->local_strong_refs;
+   weak = !hlist_empty(>refs) ||
+   node->local_weak_refs || strong;
+   has_strong_ref = node->has_strong_ref;
+   has_weak_ref = node->has_weak_ref;
+
+   if (weak && !has_weak_ref) {
node->has_weak_ref = 1;
node->pending_weak_ref = 1;
node->local_weak_refs++;
-   } else if (strong && !node->has_strong_ref) {
-   cmd = BR_ACQUIRE;
-   cmd_name = "BR_ACQUIRE";
+   }
+   if (strong && !has_strong_ref) {
node->has_strong_ref = 1;
node->pending_strong_ref = 1;
node->local_strong_refs++;
-   } else if (!strong && node->has_strong_ref) {
-   

[PATCH 10/37] binder: change binder_stats to atomics

2017-06-29 Thread Todd Kjos
From: Badhri Jagan Sridharan <bad...@google.com>

Use atomics for stats to avoid needing to lock for
increments/decrements

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 48 
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index fb484c6acd3e..cd4191d027e1 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -167,22 +167,22 @@ enum binder_stat_types {
 };
 
 struct binder_stats {
-   int br[_IOC_NR(BR_FAILED_REPLY) + 1];
-   int bc[_IOC_NR(BC_REPLY_SG) + 1];
-   int obj_created[BINDER_STAT_COUNT];
-   int obj_deleted[BINDER_STAT_COUNT];
+   atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+   atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+   atomic_t obj_created[BINDER_STAT_COUNT];
+   atomic_t obj_deleted[BINDER_STAT_COUNT];
 };
 
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
 {
-   binder_stats.obj_deleted[type]++;
+   atomic_inc(_stats.obj_deleted[type]);
 }
 
 static inline void binder_stats_created(enum binder_stat_types type)
 {
-   binder_stats.obj_created[type]++;
+   atomic_inc(_stats.obj_created[type]);
 }
 
 struct binder_transaction_log_entry {
@@ -1825,9 +1825,9 @@ static int binder_thread_write(struct binder_proc *proc,
ptr += sizeof(uint32_t);
trace_binder_command(cmd);
if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
-   binder_stats.bc[_IOC_NR(cmd)]++;
-   proc->stats.bc[_IOC_NR(cmd)]++;
-   thread->stats.bc[_IOC_NR(cmd)]++;
+   atomic_inc(_stats.bc[_IOC_NR(cmd)]);
+   atomic_inc(>stats.bc[_IOC_NR(cmd)]);
+   atomic_inc(>stats.bc[_IOC_NR(cmd)]);
}
switch (cmd) {
case BC_INCREFS:
@@ -2201,9 +2201,9 @@ static void binder_stat_br(struct binder_proc *proc,
 {
trace_binder_return(cmd);
if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
-   binder_stats.br[_IOC_NR(cmd)]++;
-   proc->stats.br[_IOC_NR(cmd)]++;
-   thread->stats.br[_IOC_NR(cmd)]++;
+   atomic_inc(_stats.br[_IOC_NR(cmd)]);
+   atomic_inc(>stats.br[_IOC_NR(cmd)]);
+   atomic_inc(>stats.br[_IOC_NR(cmd)]);
}
 }
 
@@ -3453,17 +3453,21 @@ static void print_binder_stats(struct seq_file *m, 
const char *prefix,
BUILD_BUG_ON(ARRAY_SIZE(stats->bc) !=
 ARRAY_SIZE(binder_command_strings));
for (i = 0; i < ARRAY_SIZE(stats->bc); i++) {
-   if (stats->bc[i])
+   int temp = atomic_read(>bc[i]);
+
+   if (temp)
seq_printf(m, "%s%s: %d\n", prefix,
-  binder_command_strings[i], stats->bc[i]);
+  binder_command_strings[i], temp);
}
 
BUILD_BUG_ON(ARRAY_SIZE(stats->br) !=
 ARRAY_SIZE(binder_return_strings));
for (i = 0; i < ARRAY_SIZE(stats->br); i++) {
-   if (stats->br[i])
+   int temp = atomic_read(>br[i]);
+
+   if (temp)
seq_printf(m, "%s%s: %d\n", prefix,
-  binder_return_strings[i], stats->br[i]);
+  binder_return_strings[i], temp);
}
 
BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
@@ -3471,11 +3475,15 @@ static void print_binder_stats(struct seq_file *m, 
const char *prefix,
BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
 ARRAY_SIZE(stats->obj_deleted));
for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
-   if (stats->obj_created[i] || stats->obj_deleted[i])
-   seq_printf(m, "%s%s: active %d total %d\n", prefix,
+   int created = atomic_read(>obj_created[i]);
+   int deleted = atomic_read(>obj_deleted[i]);
+
+   if (created || deleted)
+   seq_printf(m, "%s%s: active %d total %d\n",
+   prefix,
binder_objstat_strings[i],
-   stats->obj_created[i] - stats->obj_deleted[i],
-   stats->obj_created[i]);
+   created - deleted,
+   created);
}
 }
 
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 33/37] binder: use inner lock to protect thread accounting

2017-06-29 Thread Todd Kjos
Use the inner lock to protect thread accounting fields in
proc structure: max_threads, requested_threads,
requested_threads_started and ready_threads.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 28 +++-
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 9d18ca1f7dcc..704540ea3e12 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -498,11 +498,15 @@ enum binder_deferred_state {
  * @delivered_death:  list of delivered death notification
  *(protected by @inner_lock)
  * @max_threads:  cap on number of binder threads
+ *(protected by @inner_lock)
  * @requested_threads:number of binder threads requested but not
  *yet started. In current implementation, can
  *only be 0 or 1.
+ *(protected by @inner_lock)
  * @requested_threads_started: number binder threads started
+ *(protected by @inner_lock)
  * @ready_threads:number of threads waiting for proc work
+ *(protected by @inner_lock)
  * @tmp_ref:  temporary reference to indicate proc is in use
  *(protected by @inner_lock)
  * @default_priority: default scheduler priority
@@ -3234,6 +3238,7 @@ static int binder_thread_write(struct binder_proc *proc,
binder_debug(BINDER_DEBUG_THREADS,
 "%d:%d BC_REGISTER_LOOPER\n",
 proc->pid, thread->pid);
+   binder_inner_proc_lock(proc);
if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: 
BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
@@ -3247,6 +3252,7 @@ static int binder_thread_write(struct binder_proc *proc,
proc->requested_threads_started++;
}
thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
+   binder_inner_proc_unlock(proc);
break;
case BC_ENTER_LOOPER:
binder_debug(BINDER_DEBUG_THREADS,
@@ -3523,11 +3529,11 @@ static int binder_thread_read(struct binder_proc *proc,
binder_inner_proc_lock(proc);
wait_for_proc_work = thread->transaction_stack == NULL &&
binder_worklist_empty_ilocked(>todo);
+   if (wait_for_proc_work)
+   proc->ready_threads++;
binder_inner_proc_unlock(proc);
 
thread->looper |= BINDER_LOOPER_STATE_WAITING;
-   if (wait_for_proc_work)
-   proc->ready_threads++;
 
binder_unlock(__func__);
 
@@ -3558,8 +3564,10 @@ static int binder_thread_read(struct binder_proc *proc,
 
binder_lock(__func__);
 
+   binder_inner_proc_lock(proc);
if (wait_for_proc_work)
proc->ready_threads--;
+   binder_inner_proc_unlock(proc);
thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
 
if (ret)
@@ -3849,19 +3857,22 @@ static int binder_thread_read(struct binder_proc *proc,
 done:
 
*consumed = ptr - buffer;
+   binder_inner_proc_lock(proc);
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
 BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
 /*spawn a new thread if we leave this out */) {
proc->requested_threads++;
+   binder_inner_proc_unlock(proc);
binder_debug(BINDER_DEBUG_THREADS,
 "%d:%d BR_SPAWN_LOOPER\n",
 proc->pid, thread->pid);
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
-   }
+   } else
+   binder_inner_proc_unlock(proc);
return 0;
 }
 
@@ -4241,12 +4252,19 @@ static long binder_ioctl(struct file *filp, unsigned 
int cmd, unsigned long arg)
if (ret)
goto err;
break;
-   case BINDER_SET_MAX_THREADS:
-   if (copy_from_user(>max_threads, ubuf, 
sizeof(proc->max_threads))) {
+   case BINDER_SET_MAX_THREADS: {
+   int max_threads;
+
+   if (copy_from_user(_threads, ubuf,
+  sizeof(max_threads))) {
ret = -EINVAL;
 

[PATCH 35/37] binder: protect against stale pointers in print_binder_transaction

2017-06-29 Thread Todd Kjos
When printing transactions there were several race conditions
that could cause a stale pointer to be deferenced. Fixed by
reading the pointer once and using it if valid (which is
safe). The transaction buffer also needed protection via proc
lock, so it is only printed if we are holding the correct lock.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 60 
 1 file changed, 40 insertions(+), 20 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f07f0d488aa4..36ef88d10631 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -4702,35 +4702,52 @@ binder_defer_work(struct binder_proc *proc, enum 
binder_deferred_state defer)
mutex_unlock(_deferred_lock);
 }
 
-static void print_binder_transaction(struct seq_file *m, const char *prefix,
-struct binder_transaction *t)
+static void print_binder_transaction_ilocked(struct seq_file *m,
+struct binder_proc *proc,
+const char *prefix,
+struct binder_transaction *t)
 {
+   struct binder_proc *to_proc;
+   struct binder_buffer *buffer = t->buffer;
+
+   WARN_ON(!spin_is_locked(>inner_lock));
spin_lock(>lock);
+   to_proc = t->to_proc;
seq_printf(m,
   "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
   prefix, t->debug_id, t,
   t->from ? t->from->proc->pid : 0,
   t->from ? t->from->pid : 0,
-  t->to_proc ? t->to_proc->pid : 0,
+  to_proc ? to_proc->pid : 0,
   t->to_thread ? t->to_thread->pid : 0,
   t->code, t->flags, t->priority, t->need_reply);
spin_unlock(>lock);
 
-   if (t->buffer == NULL) {
+   if (proc != to_proc) {
+   /*
+* Can only safely deref buffer if we are holding the
+* correct proc inner lock for this node
+*/
+   seq_puts(m, "\n");
+   return;
+   }
+
+   if (buffer == NULL) {
seq_puts(m, " buffer free\n");
return;
}
-   if (t->buffer->target_node)
-   seq_printf(m, " node %d",
-  t->buffer->target_node->debug_id);
+   if (buffer->target_node)
+   seq_printf(m, " node %d", buffer->target_node->debug_id);
seq_printf(m, " size %zd:%zd data %p\n",
-  t->buffer->data_size, t->buffer->offsets_size,
-  t->buffer->data);
+  buffer->data_size, buffer->offsets_size,
+  buffer->data);
 }
 
-static void print_binder_work_ilocked(struct seq_file *m, const char *prefix,
- const char *transaction_prefix,
- struct binder_work *w)
+static void print_binder_work_ilocked(struct seq_file *m,
+struct binder_proc *proc,
+const char *prefix,
+const char *transaction_prefix,
+struct binder_work *w)
 {
struct binder_node *node;
struct binder_transaction *t;
@@ -4738,7 +4755,8 @@ static void print_binder_work_ilocked(struct seq_file *m, 
const char *prefix,
switch (w->type) {
case BINDER_WORK_TRANSACTION:
t = container_of(w, struct binder_transaction, work);
-   print_binder_transaction(m, transaction_prefix, t);
+   print_binder_transaction_ilocked(
+   m, proc, transaction_prefix, t);
break;
case BINDER_WORK_RETURN_ERROR: {
struct binder_error *e = container_of(
@@ -4789,20 +4807,21 @@ static void print_binder_thread_ilocked(struct seq_file 
*m,
t = thread->transaction_stack;
while (t) {
if (t->from == thread) {
-   print_binder_transaction(m,
-"outgoing transaction", t);
+   print_binder_transaction_ilocked(m, thread->proc,
+   "outgoing transaction", t);
t = t->from_parent;
} else if (t->to_thread == thread) {
-   print_binder_transaction(m,
+   print_binder_transaction_ilocked(m, thread->proc,
 "incoming transaction", t);
t

[PATCH 34/37] binder: protect binder_ref with outer lock

2017-06-29 Thread Todd Kjos
Use proc->outer_lock to protect the binder_ref structure.
The outer lock allows functions operating on the binder_ref
to do nested acquires of node and inner locks as necessary
to attach refs to nodes atomically.

Binder refs must never be accesssed without holding the
outer lock.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 133 +--
 1 file changed, 83 insertions(+), 50 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 704540ea3e12..f07f0d488aa4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -475,7 +475,9 @@ enum binder_deferred_state {
  *this proc ordered by node->ptr
  *(protected by @inner_lock)
  * @refs_by_desc: rbtree of refs ordered by ref->desc
+ *(protected by @outer_lock)
  * @refs_by_node: rbtree of refs ordered by ref->node
+ *(protected by @outer_lock)
  * @pid   PID of group_leader of process
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
@@ -1269,8 +1271,8 @@ static void binder_put_node(struct binder_node *node)
binder_dec_node_tmpref(node);
 }
 
-static struct binder_ref *binder_get_ref(struct binder_proc *proc,
-u32 desc, bool need_strong_ref)
+static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc,
+u32 desc, bool need_strong_ref)
 {
struct rb_node *n = proc->refs_by_desc.rb_node;
struct binder_ref *ref;
@@ -1293,7 +1295,7 @@ static struct binder_ref *binder_get_ref(struct 
binder_proc *proc,
 }
 
 /**
- * binder_get_ref_for_node() - get the ref associated with given node
+ * binder_get_ref_for_node_olocked() - get the ref associated with given node
  * @proc:  binder_proc that owns the ref
  * @node:  binder_node of target
  * @new_ref:   newly allocated binder_ref to be initialized or %NULL
@@ -1310,9 +1312,10 @@ static struct binder_ref *binder_get_ref(struct 
binder_proc *proc,
  * new_ref. new_ref must be kfree'd by the caller in
  * this case.
  */
-static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
- struct binder_node *node,
- struct binder_ref *new_ref)
+static struct binder_ref *binder_get_ref_for_node_olocked(
+   struct binder_proc *proc,
+   struct binder_node *node,
+   struct binder_ref *new_ref)
 {
struct binder_context *context = proc->context;
struct rb_node **p = >refs_by_node.rb_node;
@@ -1375,7 +1378,7 @@ static struct binder_ref *binder_get_ref_for_node(struct 
binder_proc *proc,
return new_ref;
 }
 
-static void binder_cleanup_ref(struct binder_ref *ref)
+static void binder_cleanup_ref_olocked(struct binder_ref *ref)
 {
bool delete_node = false;
 
@@ -1418,17 +1421,17 @@ static void binder_cleanup_ref(struct binder_ref *ref)
 }
 
 /**
- * binder_inc_ref() - increment the ref for given handle
+ * binder_inc_ref_olocked() - increment the ref for given handle
  * @ref: ref to be incremented
  * @strong:  if true, strong increment, else weak
  * @target_list: list to queue node work on
  *
- * Increment the ref.
+ * Increment the ref. @ref->proc->outer_lock must be held on entry
  *
  * Return: 0, if successful, else errno
  */
-static int binder_inc_ref(struct binder_ref *ref, int strong,
- struct list_head *target_list)
+static int binder_inc_ref_olocked(struct binder_ref *ref, int strong,
+ struct list_head *target_list)
 {
int ret;
 
@@ -1457,12 +1460,9 @@ static int binder_inc_ref(struct binder_ref *ref, int 
strong,
  *
  * Decrement the ref.
  *
- * TODO: kfree is avoided here since an upcoming patch
- * will put this under a lock.
- *
  * Return: true if ref is cleaned up and ready to be freed
  */
-static bool binder_dec_ref(struct binder_ref *ref, int strong)
+static bool binder_dec_ref_olocked(struct binder_ref *ref, int strong)
 {
if (strong) {
if (ref->data.strong == 0) {
@@ -1486,13 +1486,7 @@ static bool binder_dec_ref(struct binder_ref *ref, int 
strong)
ref->data.weak--;
}
if (ref->data.strong == 0 && ref->data.weak == 0) {
-   binder_cleanup_ref(ref);
-   /*
-* TODO: we could kfree(ref) here, but an upcoming
-* patch will call this with a lock held, so we
-* return an indication that the ref should be
-* freed.
-

[PATCH 29/37] binder: add spinlock to protect binder_node

2017-06-29 Thread Todd Kjos
node->node_lock is used to protect elements of node. No
need to acquire for fields that are invariant: debug_id,
ptr, cookie.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 220 +++
 1 file changed, 165 insertions(+), 55 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5a0389767843..5654187555be 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -318,6 +318,7 @@ struct binder_error {
  * @proc: binder_proc that owns this node
  *(invariant after initialized)
  * @refs: list of references on this node
+ *(protected by @lock)
  * @internal_strong_refs: used to take strong references when
  *initiating a transaction
  *(protected by @proc->inner_lock if @proc
@@ -351,6 +352,7 @@ struct binder_error {
  *(protected by @proc->inner_lock if @proc
  *and by @lock)
  * @has_async_transaction: async transaction to node in progress
+ *(protected by @lock)
  * @accept_fds:   file descriptor operations supported for node
  *(invariant after initialized)
  * @min_priority: minimum scheduling priority
@@ -432,6 +434,7 @@ struct binder_ref_data {
  * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
  * @rb_node_node: node for lookup by @node in proc's rb_tree
  * @node_entry:  list entry for node->refs list in target node
+ *   (protected by @node->lock)
  * @proc:binder_proc containing ref
  * @node:binder_node of target node. When cleaning up a
  *   ref for deletion in binder_cleanup_ref, a non-NULL
@@ -707,6 +710,43 @@ _binder_node_unlock(struct binder_node *node, int line)
spin_unlock(>lock);
 }
 
+/**
+ * binder_node_inner_lock() - Acquire node and inner locks
+ * @node: struct binder_node to acquire
+ *
+ * Acquires node->lock. If node->proc also acquires
+ * proc->inner_lock. Used to protect binder_node fields
+ */
+#define binder_node_inner_lock(node) _binder_node_inner_lock(node, __LINE__)
+static void
+_binder_node_inner_lock(struct binder_node *node, int line)
+{
+   binder_debug(BINDER_DEBUG_SPINLOCKS,
+"%s: line=%d\n", __func__, line);
+   spin_lock(>lock);
+   if (node->proc)
+   binder_inner_proc_lock(node->proc);
+}
+
+/**
+ * binder_node_unlock() - Release node and inner locks
+ * @node: struct binder_node to acquire
+ *
+ * Release lock acquired via binder_node_lock()
+ */
+#define binder_node_inner_unlock(node) _binder_node_inner_unlock(node, 
__LINE__)
+static void
+_binder_node_inner_unlock(struct binder_node *node, int line)
+{
+   struct binder_proc *proc = node->proc;
+
+   binder_debug(BINDER_DEBUG_SPINLOCKS,
+"%s: line=%d\n", __func__, line);
+   if (proc)
+   binder_inner_proc_unlock(proc);
+   spin_unlock(>lock);
+}
+
 static bool binder_worklist_empty_ilocked(struct list_head *list)
 {
return list_empty(list);
@@ -925,12 +965,14 @@ static struct binder_node *binder_get_node(struct 
binder_proc *proc,
 }
 
 static struct binder_node *binder_new_node(struct binder_proc *proc,
-  binder_uintptr_t ptr,
-  binder_uintptr_t cookie)
+  struct flat_binder_object *fp)
 {
struct rb_node **p = >nodes.rb_node;
struct rb_node *parent = NULL;
struct binder_node *node;
+   binder_uintptr_t ptr = fp ? fp->binder : 0;
+   binder_uintptr_t cookie = fp ? fp->cookie : 0;
+   __u32 flags = fp ? fp->flags : 0;
 
while (*p) {
parent = *p;
@@ -956,6 +998,8 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
node->ptr = ptr;
node->cookie = cookie;
node->work.type = BINDER_WORK_NODE;
+   node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+   node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
spin_lock_init(>lock);
INIT_LIST_HEAD(>work.entry);
INIT_LIST_HEAD(>async_todo);
@@ -972,12 +1016,15 @@ static void binder_free_node(struct binder_node *node)
binder_stats_deleted(BINDER_STAT_NODE);
 }
 
-static int binder_inc_node_ilocked(struct binder_node *node, int strong,
-  int internal,
-  struct list_head *target_list)
+static int binder_inc_node_nilocked(struct binder_node *node, int strong,
+   int internal,
+   struct list_head *target_list)
 {
-   if (node-

[PATCH 31/37] binder: protect proc->threads with inner_lock

2017-06-29 Thread Todd Kjos
proc->threads will need to be accessed with higher
locks of other processes held so use proc->inner_lock
to protect it. proc->tmp_ref now needs to be protected
by proc->inner_lock.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 87 +++-
 1 file changed, 63 insertions(+), 24 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 4d08b5141b01..5deb9453dee4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -469,6 +469,7 @@ enum binder_deferred_state {
  * struct binder_proc - binder process bookkeeping
  * @proc_node:element for binder_procs list
  * @threads:  rbtree of binder_threads in this proc
+ *(protected by @inner_lock)
  * @nodes:rbtree of binder nodes associated with
  *this proc ordered by node->ptr
  *(protected by @inner_lock)
@@ -486,6 +487,7 @@ enum binder_deferred_state {
  *(protected by binder_deferred_lock)
  * @is_dead:  process is dead and awaiting free
  *when outstanding transactions are cleaned up
+ *(protected by @inner_lock)
  * @todo: list of work for this process
  *(protected by @inner_lock)
  * @wait: wait queue head to wait for proc work
@@ -501,6 +503,7 @@ enum binder_deferred_state {
  * @requested_threads_started: number binder threads started
  * @ready_threads:number of threads waiting for proc work
  * @tmp_ref:  temporary reference to indicate proc is in use
+ *(protected by @inner_lock)
  * @default_priority: default scheduler priority
  *(invariant after initialized)
  * @debugfs_entry:debugfs node
@@ -556,6 +559,7 @@ enum {
  * @proc: binder process for this thread
  *(invariant after initialization)
  * @rb_node:  element for proc->threads rbtree
+ *(protected by @proc->inner_lock)
  * @pid:  PID for this thread
  *(invariant after initialization)
  * @looper:   bitmap of looping state
@@ -576,6 +580,7 @@ enum {
  *always be acquired)
  * @is_dead:  thread is dead and awaiting free
  *when outstanding transactions are cleaned up
+ *(protected by @proc->inner_lock)
  *
  * Bookkeeping structure for binder threads.
  */
@@ -1667,15 +1672,15 @@ static void binder_thread_dec_tmpref(struct 
binder_thread *thread)
/*
 * atomic is used to protect the counter value while
 * it cannot reach zero or thread->is_dead is false
-*
-* TODO: future patch adds locking to ensure that the
-* check of tmp_ref and is_dead is done with a lock held
 */
+   binder_inner_proc_lock(thread->proc);
atomic_dec(>tmp_ref);
if (thread->is_dead && !atomic_read(>tmp_ref)) {
+   binder_inner_proc_unlock(thread->proc);
binder_free_thread(thread);
return;
}
+   binder_inner_proc_unlock(thread->proc);
 }
 
 /**
@@ -1692,12 +1697,15 @@ static void binder_thread_dec_tmpref(struct 
binder_thread *thread)
  */
 static void binder_proc_dec_tmpref(struct binder_proc *proc)
 {
+   binder_inner_proc_lock(proc);
proc->tmp_ref--;
if (proc->is_dead && RB_EMPTY_ROOT(>threads) &&
!proc->tmp_ref) {
+   binder_inner_proc_unlock(proc);
binder_free_proc(proc);
return;
}
+   binder_inner_proc_unlock(proc);
 }
 
 /**
@@ -2480,7 +2488,9 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_dead_binder;
}
+   binder_inner_proc_lock(target_proc);
target_proc->tmp_ref++;
+   binder_inner_proc_unlock(target_proc);
binder_node_unlock(target_node);
if (security_binder_transaction(proc->tsk,
target_proc->tsk) < 0) {
@@ -3854,7 +3864,8 @@ static void binder_release_work(struct binder_proc *proc,
 
 }
 
-static struct binder_thread *binder_get_thread(struct binder_proc *proc)
+static struct binder_thread *binder_get_thread_ilocked(
+   struct binder_proc *proc, struct binder_thread *new_thread)
 {
struct binder_thread *thread = NULL;
struct rb_node *parent = NULL;
@@ -3869,25 +3880,45 @@ static struct binder_thread *binder_get_thread(struct 
binder_proc *proc)
els

[PATCH 32/37] binder: protect transaction_stack with inner lock.

2017-06-29 Thread Todd Kjos
From: Martijn Coenen 

This makes future changes to priority inheritance
easier, since we want to be able to look at a thread's
transaction stack when selecting a thread to inherit
priority for.

It also allows us to take just a single lock in a
few paths, where we used to take two in succession.

Signed-off-by: Martijn Coenen 
---
 drivers/android/binder.c | 96 +++-
 1 file changed, 79 insertions(+), 17 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5deb9453dee4..9d18ca1f7dcc 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -30,7 +30,8 @@
  * 3) proc->inner_lock : protects the thread and node lists
  *(proc->threads, proc->nodes) and all todo lists associated
  *with the binder_proc (proc->todo, thread->todo,
- *proc->delivered_death and node->async_todo).
+ *proc->delivered_death and node->async_todo), as well as
+ *thread->transaction_stack
  *binder_inner_proc_lock() and binder_inner_proc_unlock()
  *are used to acq/rel
  *
@@ -567,11 +568,13 @@ enum {
  * @looper_needs_return:  looping thread needs to exit driver
  *(no lock needed)
  * @transaction_stack:stack of in-progress transactions for this thread
+ *(protected by @proc->inner_lock)
  * @todo: list of work to do for this thread
  *(protected by @proc->inner_lock)
  * @return_error: transaction errors reported by this thread
  *(only accessed by this thread)
  * @reply_error:  transaction errors reported by target thread
+ *(protected by @proc->inner_lock)
  * @wait: wait queue for thread work
  * @stats:per-thread statistics
  *(atomics, no lock needed)
@@ -1644,10 +1647,11 @@ static int binder_inc_ref_for_node(struct binder_proc 
*proc,
return ret;
 }
 
-static void binder_pop_transaction(struct binder_thread *target_thread,
-  struct binder_transaction *t)
+static void binder_pop_transaction_ilocked(struct binder_thread *target_thread,
+  struct binder_transaction *t)
 {
BUG_ON(!target_thread);
+   BUG_ON(!spin_is_locked(_thread->proc->inner_lock));
BUG_ON(target_thread->transaction_stack != t);
BUG_ON(target_thread->transaction_stack->from != target_thread);
target_thread->transaction_stack =
@@ -1731,6 +1735,35 @@ static struct binder_thread *binder_get_txn_from(
return from;
 }
 
+/**
+ * binder_get_txn_from_and_acq_inner() - get t->from and acquire inner lock
+ * @t: binder transaction for t->from
+ *
+ * Same as binder_get_txn_from() except it also acquires the proc->inner_lock
+ * to guarantee that the thread cannot be released while operating on it.
+ * The caller must call binder_inner_proc_unlock() to release the inner lock
+ * as well as call binder_dec_thread_txn() to release the reference.
+ *
+ * Return: the value of t->from
+ */
+static struct binder_thread *binder_get_txn_from_and_acq_inner(
+   struct binder_transaction *t)
+{
+   struct binder_thread *from;
+
+   from = binder_get_txn_from(t);
+   if (!from)
+   return NULL;
+   binder_inner_proc_lock(from->proc);
+   if (t->from) {
+   BUG_ON(from != t->from);
+   return from;
+   }
+   binder_inner_proc_unlock(from->proc);
+   binder_thread_dec_tmpref(from);
+   return NULL;
+}
+
 static void binder_free_transaction(struct binder_transaction *t)
 {
if (t->buffer)
@@ -1747,7 +1780,7 @@ static void binder_send_failed_reply(struct 
binder_transaction *t,
 
BUG_ON(t->flags & TF_ONE_WAY);
while (1) {
-   target_thread = binder_get_txn_from(t);
+   target_thread = binder_get_txn_from_and_acq_inner(t);
if (target_thread) {
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
 "send failed reply for transaction %d to 
%d:%d\n",
@@ -1755,11 +1788,10 @@ static void binder_send_failed_reply(struct 
binder_transaction *t,
  target_thread->proc->pid,
  target_thread->pid);
 
-   binder_pop_transaction(target_thread, t);
+   binder_pop_transaction_ilocked(target_thread, t);
if (target_thread->reply_error.cmd == BR_OK) {
target_thread->reply_error.cmd = error_code;
-   binder_enqueue_work(
-   target_thread->proc,
+   binder_enqueue_work_ilocked(
_thread->reply_error.work,
   

[PATCH 24/37] binder: refactor binder ref inc/dec for thread safety

2017-06-29 Thread Todd Kjos
Once locks are added, binder_ref's will only be accessed
safely with the proc lock held. Refactor the inc/dec paths
to make them atomic with the binder_get_ref* paths and
node inc/dec. For example, instead of:

  ref = binder_get_ref(proc, handle, strong);
  ...
  binder_dec_ref(ref, strong);

we now have:

  ret = binder_dec_ref_for_handle(proc, handle, strong, );

Since the actual ref is no longer exposed to callers, a
new struct binder_ref_data is introduced which can be used
to return a copy of ref state.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c   | 484 ++---
 drivers/android/binder_trace.h |  32 +--
 2 files changed, 379 insertions(+), 137 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index ca7d866b89e8..4d0b99862339 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -291,20 +291,51 @@ struct binder_ref_death {
binder_uintptr_t cookie;
 };
 
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:unique ID for the ref
+ * @desc:unique userspace handle for ref
+ * @strong:  strong ref count (debugging only if not locked)
+ * @weak:weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+   int debug_id;
+   uint32_t desc;
+   int strong;
+   int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ * @proc:binder_proc containing ref
+ * @node:binder_node of target node. When cleaning up a
+ *   ref for deletion in binder_cleanup_ref, a non-NULL
+ *   @node indicates the node must be freed
+ * @death:   pointer to death notification (ref_death) if requested
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
 struct binder_ref {
/* Lookups needed: */
/*   node + proc => ref (transaction) */
/*   desc + proc => ref (transaction, inc/dec ref) */
/*   node => refs + procs (proc exit) */
-   int debug_id;
+   struct binder_ref_data data;
struct rb_node rb_node_desc;
struct rb_node rb_node_node;
struct hlist_node node_entry;
struct binder_proc *proc;
struct binder_node *node;
-   uint32_t desc;
-   int strong;
-   int weak;
struct binder_ref_death *death;
 };
 
@@ -627,11 +658,11 @@ static struct binder_ref *binder_get_ref(struct 
binder_proc *proc,
while (n) {
ref = rb_entry(n, struct binder_ref, rb_node_desc);
 
-   if (desc < ref->desc) {
+   if (desc < ref->data.desc) {
n = n->rb_left;
-   } else if (desc > ref->desc) {
+   } else if (desc > ref->data.desc) {
n = n->rb_right;
-   } else if (need_strong_ref && !ref->strong) {
+   } else if (need_strong_ref && !ref->data.strong) {
binder_user_error("tried to use weak ref as strong 
ref\n");
return NULL;
} else {
@@ -641,14 +672,33 @@ static struct binder_ref *binder_get_ref(struct 
binder_proc *proc,
return NULL;
 }
 
+/**
+ * binder_get_ref_for_node() - get the ref associated with given node
+ * @proc:  binder_proc that owns the ref
+ * @node:  binder_node of target
+ * @new_ref:   newly allocated binder_ref to be initialized or %NULL
+ *
+ * Look up the ref for the given node and return it if it exists
+ *
+ * If it doesn't exist and the caller provides a newly allocated
+ * ref, initialize the fields of the newly allocated ref and insert
+ * into the given proc rb_trees and node refs list.
+ *
+ * Return: the ref for node. It is possible that another thread
+ * allocated/initialized the ref first in which case the
+ * returned ref would be different than the passed-in
+ * new_ref. new_ref must be kfree'd by the caller in
+ * this case.
+ */
 static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
- struct binder_node *node)
+ struct binder_node *node,
+ stru

[PATCH 28/37] binder: add spinlocks to protect todo lists

2017-06-29 Thread Todd Kjos
The todo lists in the proc, thread, and node structures
are accessed by other procs/threads to place work
items on the queue.

The todo lists are protected by the new proc->inner_lock.
No locks should ever be nested under these locks. As the
name suggests, an outer lock will be introduced in
a later patch.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 355 +++
 1 file changed, 269 insertions(+), 86 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 6c741416fa00..5a0389767843 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -279,8 +279,16 @@ struct binder_device {
struct binder_context context;
 };
 
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry: node enqueued on list
+ * @type:  type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
 struct binder_work {
struct list_head entry;
+
enum {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
@@ -303,6 +311,7 @@ struct binder_error {
  *(invariant after initialized)
  * @lock: lock for node fields
  * @work: worklist element for node work
+ *(protected by @proc->inner_lock)
  * @rb_node:  element for proc->nodes tree
  * @dead_node:element for binder_dead_nodes list
  *(protected by binder_dead_nodes_lock)
@@ -347,6 +356,7 @@ struct binder_error {
  * @min_priority: minimum scheduling priority
  *(invariant after initialized)
  * @async_todo:   list of async work items
+ *(protected by @proc->inner_lock)
  *
  * Bookkeeping structure for binder nodes.
  */
@@ -388,6 +398,11 @@ struct binder_node {
 };
 
 struct binder_ref_death {
+   /**
+* @work: worklist element for death notifications
+*(protected by inner_lock of the proc that
+*this ref belongs to)
+*/
struct binder_work work;
binder_uintptr_t cookie;
 };
@@ -467,11 +482,13 @@ enum binder_deferred_state {
  * @is_dead:  process is dead and awaiting free
  *when outstanding transactions are cleaned up
  * @todo: list of work for this process
+ *(protected by @inner_lock)
  * @wait: wait queue head to wait for proc work
  *(invariant after initialized)
  * @stats:per-process binder statistics
  *(atomics, no lock needed)
  * @delivered_death:  list of delivered death notification
+ *(protected by @inner_lock)
  * @max_threads:  cap on number of binder threads
  * @requested_threads:number of binder threads requested but not
  *yet started. In current implementation, can
@@ -542,6 +559,7 @@ enum {
  *(no lock needed)
  * @transaction_stack:stack of in-progress transactions for this thread
  * @todo: list of work to do for this thread
+ *(protected by @proc->inner_lock)
  * @return_error: transaction errors reported by this thread
  *(only accessed by this thread)
  * @reply_error:  transaction errors reported by target thread
@@ -689,6 +707,111 @@ _binder_node_unlock(struct binder_node *node, int line)
spin_unlock(>lock);
 }
 
+static bool binder_worklist_empty_ilocked(struct list_head *list)
+{
+   return list_empty(list);
+}
+
+/**
+ * binder_worklist_empty() - Check if no items on the work list
+ * @proc:   binder_proc associated with list
+ * @list:  list to check
+ *
+ * Return: true if there are no items on list, else false
+ */
+static bool binder_worklist_empty(struct binder_proc *proc,
+ struct list_head *list)
+{
+   bool ret;
+
+   binder_inner_proc_lock(proc);
+   ret = binder_worklist_empty_ilocked(list);
+   binder_inner_proc_unlock(proc);
+   return ret;
+}
+
+static void
+binder_enqueue_work_ilocked(struct binder_work *work,
+  struct list_head *target_list)
+{
+   BUG_ON(target_list == NULL);
+   BUG_ON(work->entry.next && !list_empty(>entry));
+   list_add_tail(>entry, target_list);
+}
+
+/**
+ * binder_enqueue_work() - Add an item to the work list
+ * @proc: binder_proc associated with list
+ * @work: struct binder_work to add to list
+ * @target_list:  list to add work to
+ *
+ * Adds the work to the specified list. Asserts that work
+ * is not already on a list.
+ */
+static void
+binder_enqueue_work(struct binder_proc *proc,
+   struct bind

[PATCH 37/37] binder: remove global binder lock

2017-06-29 Thread Todd Kjos
Remove global mutex and rely on fine-grained locking

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 46 +++---
 1 file changed, 3 insertions(+), 43 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1e50b034d49a..c8e9d5dfcd86 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -80,8 +80,6 @@
 #include "binder_alloc.h"
 #include "binder_trace.h"
 
-static DEFINE_MUTEX(binder_main_lock);
-
 static HLIST_HEAD(binder_deferred_list);
 static DEFINE_MUTEX(binder_deferred_lock);
 
@@ -924,19 +922,6 @@ static long task_close_fd(struct binder_proc *proc, 
unsigned int fd)
return retval;
 }
 
-static inline void binder_lock(const char *tag)
-{
-   trace_binder_lock(tag);
-   mutex_lock(_main_lock);
-   trace_binder_locked(tag);
-}
-
-static inline void binder_unlock(const char *tag)
-{
-   trace_binder_unlock(tag);
-   mutex_unlock(_main_lock);
-}
-
 static void binder_set_nice(long nice)
 {
long min_nice;
@@ -3557,8 +3542,6 @@ static int binder_thread_read(struct binder_proc *proc,
 
thread->looper |= BINDER_LOOPER_STATE_WAITING;
 
-   binder_unlock(__func__);
-
trace_binder_wait_for_work(wait_for_proc_work,
   !!thread->transaction_stack,
   !binder_worklist_empty(proc, >todo));
@@ -3584,8 +3567,6 @@ static int binder_thread_read(struct binder_proc *proc,
ret = wait_event_freezable(thread->wait, 
binder_has_thread_work(thread));
}
 
-   binder_lock(__func__);
-
binder_inner_proc_lock(proc);
if (wait_for_proc_work)
proc->ready_threads--;
@@ -4101,8 +4082,6 @@ static unsigned int binder_poll(struct file *filp,
struct binder_thread *thread = NULL;
int wait_for_proc_work;
 
-   binder_lock(__func__);
-
thread = binder_get_thread(proc);
 
binder_inner_proc_lock(thread->proc);
@@ -4110,8 +4089,6 @@ static unsigned int binder_poll(struct file *filp,
binder_worklist_empty_ilocked(>todo);
binder_inner_proc_unlock(thread->proc);
 
-   binder_unlock(__func__);
-
if (wait_for_proc_work) {
if (binder_has_proc_work(proc, thread))
return POLLIN;
@@ -4256,7 +4233,6 @@ static long binder_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
if (ret)
goto err_unlocked;
 
-   binder_lock(__func__);
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
@@ -4315,7 +4291,6 @@ static long binder_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
 err:
if (thread)
thread->looper_need_return = false;
-   binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, 
binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, 
current->pid, cmd, arg, ret);
@@ -4421,15 +4396,11 @@ static int binder_open(struct inode *nodp, struct file 
*filp)
proc->context = _dev->context;
binder_alloc_init(>alloc);
 
-   binder_lock(__func__);
-
binder_stats_created(BINDER_STAT_PROC);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(>delivered_death);
filp->private_data = proc;
 
-   binder_unlock(__func__);
-
mutex_lock(_procs_lock);
hlist_add_head(>proc_node, _procs);
mutex_unlock(_procs_lock);
@@ -4655,7 +4626,6 @@ static void binder_deferred_func(struct work_struct *work)
int defer;
 
do {
-   binder_lock(__func__);
mutex_lock(_deferred_lock);
if (!hlist_empty(_deferred_list)) {
proc = hlist_entry(binder_deferred_list.first,
@@ -4682,7 +4652,6 @@ static void binder_deferred_func(struct work_struct *work)
if (defer & BINDER_DEFERRED_RELEASE)
binder_deferred_release(proc); /* frees proc */
 
-   binder_unlock(__func__);
if (files)
put_files_struct(files);
} while (proc);
@@ -5097,8 +5066,6 @@ static int binder_state_show(struct seq_file *m, void 
*unused)
struct binder_node *node;
struct binder_node *last_node = NULL;
 
-   binder_lock(__func__);
-
seq_puts(m, "binder state:\n");
 
spin_lock(_dead_nodes_lock);
@@ -5128,7 +5095,7 @@ static int binder_state_show(struct seq_file *m, void 
*unused)
hlist_for_each_entry(proc, _procs, proc_node)
print_binder_proc(m, proc, 1);
mutex_unlock(_procs_lock);
-   binder_unlock(__func__);
+
return 0;
 }
 

[PATCH 18/37] binder: add more debug info when allocation fails.

2017-06-29 Thread Todd Kjos
From: Martijn Coenen 

Display information about allocated/free space whenever
binder buffer allocation fails on synchronous
transactions.

Signed-off-by: Martijn Coenen 
Signed-off-by: Siqi Lin 
---
 drivers/android/binder_alloc.c | 31 ++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 2a2e41b13de5..40f31df60580 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -337,8 +337,36 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct 
binder_alloc *alloc,
}
}
if (best_fit == NULL) {
+   size_t allocated_buffers = 0;
+   size_t largest_alloc_size = 0;
+   size_t total_alloc_size = 0;
+   size_t free_buffers = 0;
+   size_t largest_free_size = 0;
+   size_t total_free_size = 0;
+
+   for (n = rb_first(>allocated_buffers); n != NULL;
+n = rb_next(n)) {
+   buffer = rb_entry(n, struct binder_buffer, rb_node);
+   buffer_size = binder_alloc_buffer_size(alloc, buffer);
+   allocated_buffers++;
+   total_alloc_size += buffer_size;
+   if (buffer_size > largest_alloc_size)
+   largest_alloc_size = buffer_size;
+   }
+   for (n = rb_first(>free_buffers); n != NULL;
+n = rb_next(n)) {
+   buffer = rb_entry(n, struct binder_buffer, rb_node);
+   buffer_size = binder_alloc_buffer_size(alloc, buffer);
+   free_buffers++;
+   total_free_size += buffer_size;
+   if (buffer_size > largest_free_size)
+   largest_free_size = buffer_size;
+   }
pr_err("%d: binder_alloc_buf size %zd failed, no address 
space\n",
alloc->pid, size);
+   pr_err("allocated: %zd (num: %zd largest: %zd), free: %zd (num: 
%zd largest: %zd)\n",
+  total_alloc_size, allocated_buffers, largest_alloc_size,
+  total_free_size, free_buffers, largest_free_size);
return ERR_PTR(-ENOSPC);
}
if (n == NULL) {
@@ -698,9 +726,10 @@ void binder_alloc_deferred_release(struct binder_alloc 
*alloc)
 static void print_binder_buffer(struct seq_file *m, const char *prefix,
struct binder_buffer *buffer)
 {
-   seq_printf(m, "%s %d: %pK size %zd:%zd %s\n",
+   seq_printf(m, "%s %d: %pK size %zd:%zd:%zd %s\n",
   prefix, buffer->debug_id, buffer->data,
   buffer->data_size, buffer->offsets_size,
+  buffer->extra_buffers_size,
   buffer->transaction ? "active" : "delivered");
 }
 
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 25/37] binder: use node->tmp_refs to ensure node safety

2017-06-29 Thread Todd Kjos
When obtaining a node via binder_get_node(),
binder_get_node_from_ref() or binder_new_node(),
increment node->tmp_refs to take a
temporary reference on the node to ensure the node
persists while being used.  binder_put_node() must
be called to remove the temporary reference.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 124 +++
 1 file changed, 104 insertions(+), 20 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 4d0b99862339..ec050c6d1192 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -274,6 +274,7 @@ struct binder_node {
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
+   int tmp_refs;
binder_uintptr_t ptr;
binder_uintptr_t cookie;
unsigned has_strong_ref:1;
@@ -427,6 +428,7 @@ static void
 binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
 static void binder_free_thread(struct binder_thread *thread);
 static void binder_free_proc(struct binder_proc *proc);
+static void binder_inc_node_tmpref(struct binder_node *node);
 
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
@@ -521,8 +523,15 @@ static struct binder_node *binder_get_node(struct 
binder_proc *proc,
n = n->rb_left;
else if (ptr > node->ptr)
n = n->rb_right;
-   else
+   else {
+   /*
+* take an implicit weak reference
+* to ensure node stays alive until
+* call to binder_put_node()
+*/
+   binder_inc_node_tmpref(node);
return node;
+   }
}
return NULL;
 }
@@ -551,6 +560,7 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
if (node == NULL)
return NULL;
binder_stats_created(BINDER_STAT_NODE);
+   node->tmp_refs++;
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, >nodes);
node->debug_id = atomic_inc_return(_last_id);
@@ -615,7 +625,8 @@ static int binder_dec_node(struct binder_node *node, int 
strong, int internal)
} else {
if (!internal)
node->local_weak_refs--;
-   if (node->local_weak_refs || !hlist_empty(>refs))
+   if (node->local_weak_refs || node->tmp_refs ||
+   !hlist_empty(>refs))
return 0;
}
if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
@@ -625,7 +636,7 @@ static int binder_dec_node(struct binder_node *node, int 
strong, int internal)
}
} else {
if (hlist_empty(>refs) && !node->local_strong_refs &&
-   !node->local_weak_refs) {
+   !node->local_weak_refs && !node->tmp_refs) {
list_del_init(>work.entry);
if (node->proc) {
rb_erase(>rb_node, >proc->nodes);
@@ -648,6 +659,46 @@ static int binder_dec_node(struct binder_node *node, int 
strong, int internal)
return 0;
 }
 
+/**
+ * binder_inc_node_tmpref() - take a temporary reference on node
+ * @node:  node to reference
+ *
+ * Take reference on node to prevent the node from being freed
+ * while referenced only by a local variable
+ */
+static void binder_inc_node_tmpref(struct binder_node *node)
+{
+   /*
+* No call to binder_inc_node() is needed since we
+* don't need to inform userspace of any changes to
+* tmp_refs
+*/
+   node->tmp_refs++;
+}
+
+/**
+ * binder_dec_node_tmpref() - remove a temporary reference on node
+ * @node:  node to reference
+ *
+ * Release temporary reference on node taken via binder_inc_node_tmpref()
+ */
+static void binder_dec_node_tmpref(struct binder_node *node)
+{
+   node->tmp_refs--;
+   BUG_ON(node->tmp_refs < 0);
+   /*
+* Call binder_dec_node() to check if all refcounts are 0
+* and cleanup is needed. Calling with strong=0 and internal=1
+* causes no actual reference to be released in binder_dec_node().
+* If that changes, a change is needed here too.
+*/
+   binder_dec_node(node, 0, 1);
+}
+
+static void binder_put_node(struct binder_node *node)
+{
+   binder_dec_node_tmpref(node);
+}
 
 static struct binder_ref *binder_get_ref(struct binder_proc *proc,
 u32 desc, bool need_strong_ref)
@@ -888,6 +939,11 @@ static struct binder_node *binder_get_node_from_ref(
if (!ref)
goto err_no_ref;
node = ref-

[PATCH 15/37] binder: don't modify thread->looper from other threads

2017-06-29 Thread Todd Kjos
The looper member of struct binder_thread is a bitmask
of control bits. All of the existing bits are modified
by the affected thread except for BINDER_LOOPER_STATE_NEED_RETURN
which can be modified in binder_deferred_flush() by
another thread.

To avoid adding a spinlock around all read-mod-writes to
modify a bit, the BINDER_LOOPER_STATE_NEED_RETURN flag
is replaced by a separate field in struct binder_thread.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 71faf548482d..3c1129d91825 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -334,14 +334,14 @@ enum {
BINDER_LOOPER_STATE_EXITED  = 0x04,
BINDER_LOOPER_STATE_INVALID = 0x08,
BINDER_LOOPER_STATE_WAITING = 0x10,
-   BINDER_LOOPER_STATE_NEED_RETURN = 0x20
 };
 
 struct binder_thread {
struct binder_proc *proc;
struct rb_node rb_node;
int pid;
-   int looper;
+   int looper;  /* only modified by this thread */
+   bool looper_need_return; /* can be written by other thread */
struct binder_transaction *transaction_stack;
struct list_head todo;
uint32_t return_error; /* Write failed, return error code in read buf */
@@ -2276,14 +2276,13 @@ static void binder_stat_br(struct binder_proc *proc,
 static int binder_has_proc_work(struct binder_proc *proc,
struct binder_thread *thread)
 {
-   return !list_empty(>todo) ||
-   (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+   return !list_empty(>todo) || thread->looper_need_return;
 }
 
 static int binder_has_thread_work(struct binder_thread *thread)
 {
return !list_empty(>todo) || thread->return_error != BR_OK ||
-   (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+   thread->looper_need_return;
 }
 
 static int binder_put_node_cmd(struct binder_proc *proc,
@@ -2412,8 +2411,7 @@ static int binder_thread_read(struct binder_proc *proc,
 entry);
} else {
/* no data added */
-   if (ptr - buffer == 4 &&
-   !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
+   if (ptr - buffer == 4 && !thread->looper_need_return)
goto retry;
break;
}
@@ -2727,7 +2725,7 @@ static struct binder_thread *binder_get_thread(struct 
binder_proc *proc)
INIT_LIST_HEAD(>todo);
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, >threads);
-   thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+   thread->looper_need_return = true;
thread->return_error = BR_OK;
thread->return_error2 = BR_OK;
}
@@ -2983,7 +2981,7 @@ static long binder_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
ret = 0;
 err:
if (thread)
-   thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
+   thread->looper_need_return = false;
binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, 
binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
@@ -3138,7 +3136,7 @@ static void binder_deferred_flush(struct binder_proc 
*proc)
for (n = rb_first(>threads); n != NULL; n = rb_next(n)) {
struct binder_thread *thread = rb_entry(n, struct 
binder_thread, rb_node);
 
-   thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+   thread->looper_need_return = true;
if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
wake_up_interruptible(>wait);
wake_count++;
@@ -3399,7 +3397,9 @@ static void print_binder_thread(struct seq_file *m,
size_t start_pos = m->count;
size_t header_pos;
 
-   seq_printf(m, "  thread %d: l %02x\n", thread->pid, thread->looper);
+   seq_printf(m, "  thread %d: l %02x need_return %d\n",
+   thread->pid, thread->looper,
+   thread->looper_need_return);
header_pos = m->count;
t = thread->transaction_stack;
while (t) {
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 20/37] binder: refactor binder_pop_transaction

2017-06-29 Thread Todd Kjos
binder_pop_transaction needs to be split into 2 pieces to
to allow the proc lock to be held on entry to dequeue the
transaction stack, but no lock when kfree'ing the transaction.

Split into binder_pop_transaction_locked and binder_free_transaction
(the actual locks are still to be added).

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index cb78a4e6872d..d2fcf3cc29a6 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -768,14 +768,16 @@ static int binder_dec_ref(struct binder_ref *ref, int 
strong)
 static void binder_pop_transaction(struct binder_thread *target_thread,
   struct binder_transaction *t)
 {
-   if (target_thread) {
-   BUG_ON(target_thread->transaction_stack != t);
-   BUG_ON(target_thread->transaction_stack->from != target_thread);
-   target_thread->transaction_stack =
-   target_thread->transaction_stack->from_parent;
-   t->from = NULL;
-   }
-   t->need_reply = 0;
+   BUG_ON(!target_thread);
+   BUG_ON(target_thread->transaction_stack != t);
+   BUG_ON(target_thread->transaction_stack->from != target_thread);
+   target_thread->transaction_stack =
+   target_thread->transaction_stack->from_parent;
+   t->from = NULL;
+}
+
+static void binder_free_transaction(struct binder_transaction *t)
+{
if (t->buffer)
t->buffer->transaction = NULL;
kfree(t);
@@ -808,6 +810,7 @@ static void binder_send_failed_reply(struct 
binder_transaction *t,
binder_pop_transaction(target_thread, t);
target_thread->return_error = error_code;
wake_up_interruptible(_thread->wait);
+   binder_free_transaction(t);
} else {
pr_err("reply failed, target thread, %d:%d, has 
error code %d already\n",
target_thread->proc->pid,
@@ -822,7 +825,7 @@ static void binder_send_failed_reply(struct 
binder_transaction *t,
 "send failed reply for transaction %d, target 
dead\n",
 t->debug_id);
 
-   binder_pop_transaction(target_thread, t);
+   binder_free_transaction(t);
if (next == NULL) {
binder_debug(BINDER_DEBUG_DEAD_BINDER,
 "reply failed, no target thread at 
root\n");
@@ -1806,6 +1809,7 @@ static void binder_transaction(struct binder_proc *proc,
if (reply) {
BUG_ON(t->buffer->async_transaction != 0);
binder_pop_transaction(target_thread, in_reply_to);
+   binder_free_transaction(in_reply_to);
} else if (!(t->flags & TF_ONE_WAY)) {
BUG_ON(t->buffer->async_transaction != 0);
t->need_reply = 1;
@@ -2635,9 +2639,7 @@ static int binder_thread_read(struct binder_proc *proc,
t->to_thread = thread;
thread->transaction_stack = t;
} else {
-   t->buffer->transaction = NULL;
-   kfree(t);
-   binder_stats_deleted(BINDER_STAT_TRANSACTION);
+   binder_free_transaction(t);
}
break;
}
@@ -2680,9 +2682,7 @@ static void binder_release_work(struct list_head *list)
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
"undelivered transaction %d\n",
t->debug_id);
-   t->buffer->transaction = NULL;
-   kfree(t);
-   binder_stats_deleted(BINDER_STAT_TRANSACTION);
+   binder_free_transaction(t);
}
} break;
case BINDER_WORK_TRANSACTION_COMPLETE: {
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 00/37] fine-grained locking in binder driver

2017-06-29 Thread Todd Kjos
The binder driver uses a global mutex to serialize access to state in a
multi-threaded environment. This global lock has been increasingly
problematic as Android devices have scaled to more cores. The problem is
not so much contention for the global lock which still remains relatively
low, but the priority inversion which occurs regularly when a lower
priority thread is preempted while holding the lock and a higher priority
thread becomes blocked on it. These cases can be especially painful if the
lower priority thread runs in the background on a slow core at a low
frequency. This often manifests as missed frames or other glitches.

For several years, a hacky solution has been used in many Android devices
which disables preemption for most of the time the global mutex is held.
This dramatically decreased the cases of glitches induced by priority
inversion and increased the average throughput for binder transactions.

Moving to fine-grained locking in this patchset results is a cleaner
and more scalable solution than the preempt disable hack. Priority
inversion is decreased significantly.

Here is a comparison of the binder throughputs for the 3 cases
with no payload (using binderThroughputTest on a 4-core Pixel device):

1 Client/Server Pair (iterations/s):
Global Mutex:4267
+ No-Preempt:   69688
Fine-Grained:   52313

2 Client/Server Pairs (iterations/s):
Global Mutex: 5608
+ No-Preempt:   111346
Fine-Grained:   117039

4 Client/Server Pairs (iterations/s):
Global Mutex:12839
+ No-Preempt:   118049
Fine-Grained:   189805

8 Client/Server Pairs (iterations/s):
Global Mutex:12991
+ No-Preempt:   111780
Fine-Grained:   203607

16 Client/Server Pairs (iterations/s):
Global Mutex:14467
+ No-Preempt:   106763
Fine-Grained:   202942

Note that global lock performance without preempt disable seems to perform
significantly worse on Pixel than on some other devices. This run used the
4.4 version of the binder driver that is currently upstream (and there
have been few lines changed since then which wouldn't explain the poor
performance).

The no-preempt version has better throughput in the single threaded case
where the new locking overhead adds to the transacton latency. However
with multiple concurent transactions, the lack of contention results in
better throughput for the fine-grained case.

In the patchset, the binder allocator is moved to a separate file and
protected with its own per-process mutex.

Most of the binder driver is now protected by 3 spinlocks which must be
acquired in the order shown:
1) proc->outer_lock : protects binder_ref binder_proc_lock() and
   binder_proc_unlock() are used to acq/rel.
2) node->lock : protects most fields of binder_node.  binder_node_lock()
   and binder_node_unlock() are used to acq/rel
3) proc->inner_lock : protects the thread and node lists (proc->threads,
   proc->waiting_threads, proc->nodes) and all todo lists associated with
   the binder_proc (proc->todo, thread->todo, proc->delivered_death and
   node->async_todo), as well as thread->transaction_stack
   binder_inner_proc_lock() and binder_inner_proc_unlock() are used
   to acq/rel

Any lock under procA must never be nested under any lock at the same
level or below on procB.

There was significant refactoring needed to implement the locking so there
are 37 patches in the set.

Here are the patches grouped into 4 categories:

1) bugfixes: 3 patches to fix behavior and are
   needed for fine-grained locking implementation
Revert "binder: Sanity check at binder ioctl"
  - note: introduces kernel race to fix userspace bug. An
  attempt to fix this was submitted in
  "[PATCH v2] android: binder: fix dangling pointer comparison"
  however that discussion concluded that this
  patch should be reverted and the problem fixed
  in userspace. Doing the revert now since this patch
  conflicts with some of the fine-grained locking
  patches.
binder: use group leader instead of open thread
binder: Use wake up hint for synchronous transactions.

2) Separate binder allocator into a separate file from binder driver
binder: separate binder allocator structure from binder proc
binder: remove unneeded cleanup code
binder: separate out binder_alloc functions
binder: move binder_alloc to separate file

3) Refactor binder driver to support locking
binder: remove binder_debug_no_lock mechanism
binder: add protection for non-perf cases
binder: change binder_stats to atomics
binder: make binder_last_id an atomic
binder: add log information for binder transaction failures
binder: refactor queue management in binder_thread_read
binder: avoid race conditions when enqueuing txn 
binder: don't modify thread->looper from other threads
binder: remove dead code in 

[PATCH 23/37] binder: make sure accesses to proc/thread are safe

2017-06-29 Thread Todd Kjos
binder_thread and binder_proc may be accessed by other
threads when processing transaction. Therefore they
must be prevented from being freed while a transaction
is in progress that references them.

This is done by introducing a temporary reference
counter for threads and procs that indicates that the
object is in use and must not be freed. binder_thread_dec_tmpref()
and binder_proc_dec_tmpref() are used to decrement
the temporary reference.

It is safe to free a binder_thread if there
is no reference and it has been released
(indicated by thread->is_dead).

It is safe to free a binder_proc if it has no
remaining threads and no reference.

A spinlock is added to the binder_transaction
to safely access and set references for t->from
and for debug code to safely access t->to_thread
and t->to_proc.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 233 +--
 1 file changed, 206 insertions(+), 27 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index fb79f40111eb..ca7d866b89e8 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -325,6 +325,7 @@ struct binder_proc {
struct files_struct *files;
struct hlist_node deferred_work_node;
int deferred_work;
+   bool is_dead;
 
struct list_head todo;
wait_queue_head_t wait;
@@ -334,6 +335,7 @@ struct binder_proc {
int requested_threads;
int requested_threads_started;
int ready_threads;
+   int tmp_ref;
long default_priority;
struct dentry *debugfs_entry;
struct binder_alloc alloc;
@@ -360,6 +362,8 @@ struct binder_thread {
struct binder_error reply_error;
wait_queue_head_t wait;
struct binder_stats stats;
+   atomic_t tmp_ref;
+   bool is_dead;
 };
 
 struct binder_transaction {
@@ -379,10 +383,19 @@ struct binder_transaction {
longpriority;
longsaved_priority;
kuid_t  sender_euid;
+   /**
+* @lock:  protects @from, @to_proc, and @to_thread
+*
+* @from, @to_proc, and @to_thread can be set to NULL
+* during thread teardown
+*/
+   spinlock_t lock;
 };
 
 static void
 binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
+static void binder_free_thread(struct binder_thread *thread);
+static void binder_free_proc(struct binder_proc *proc);
 
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
@@ -780,6 +793,79 @@ static void binder_pop_transaction(struct binder_thread 
*target_thread,
t->from = NULL;
 }
 
+/**
+ * binder_thread_dec_tmpref() - decrement thread->tmp_ref
+ * @thread:thread to decrement
+ *
+ * A thread needs to be kept alive while being used to create or
+ * handle a transaction. binder_get_txn_from() is used to safely
+ * extract t->from from a binder_transaction and keep the thread
+ * indicated by t->from from being freed. When done with that
+ * binder_thread, this function is called to decrement the
+ * tmp_ref and free if appropriate (thread has been released
+ * and no transaction being processed by the driver)
+ */
+static void binder_thread_dec_tmpref(struct binder_thread *thread)
+{
+   /*
+* atomic is used to protect the counter value while
+* it cannot reach zero or thread->is_dead is false
+*
+* TODO: future patch adds locking to ensure that the
+* check of tmp_ref and is_dead is done with a lock held
+*/
+   atomic_dec(>tmp_ref);
+   if (thread->is_dead && !atomic_read(>tmp_ref)) {
+   binder_free_thread(thread);
+   return;
+   }
+}
+
+/**
+ * binder_proc_dec_tmpref() - decrement proc->tmp_ref
+ * @proc:  proc to decrement
+ *
+ * A binder_proc needs to be kept alive while being used to create or
+ * handle a transaction. proc->tmp_ref is incremented when
+ * creating a new transaction or the binder_proc is currently in-use
+ * by threads that are being released. When done with the binder_proc,
+ * this function is called to decrement the counter and free the
+ * proc if appropriate (proc has been released, all threads have
+ * been released and not currenly in-use to process a transaction).
+ */
+static void binder_proc_dec_tmpref(struct binder_proc *proc)
+{
+   proc->tmp_ref--;
+   if (proc->is_dead && RB_EMPTY_ROOT(>threads) &&
+   !proc->tmp_ref) {
+   binder_free_proc(proc);
+   return;
+   }
+}
+
+/**
+ * binder_get_txn_from() - safely extract the "from" thread in transaction
+ * @t: binder transaction for t->from
+ *
+ * Atomically return the "from" thread and increment the tmp_ref
+ * count for the thread to ensure it stays alive until
+ * binder_thread_dec_tmpref() is called.
+ *
+ * 

[PATCH 27/37] binder: use inner lock to sync work dq and node counts

2017-06-29 Thread Todd Kjos
For correct behavior we need to hold the inner lock when
dequeuing and processing node work in binder_thread_read.
We now hold the inner lock when we enter the switch statement
and release it after processing anything that might be
affected by other threads.

We also need to hold the inner lock to protect the node
weak/strong ref tracking fields as long as node->proc
is non-NULL (if it is NULL then we are guaranteed that
we don't have any node work queued).

This means that other functions that manipulate these fields
must hold the inner lock. Refactored these functions to use
the inner lock.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 249 +--
 1 file changed, 198 insertions(+), 51 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 91fece5c067f..6c741416fa00 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -311,17 +311,36 @@ struct binder_error {
  * @refs: list of references on this node
  * @internal_strong_refs: used to take strong references when
  *initiating a transaction
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @local_weak_refs:  weak user refs from local process
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @local_strong_refs:strong user refs from local process
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @tmp_refs: temporary kernel refs
+ *(protected by @proc->inner_lock while @proc
+ *is valid, and by binder_dead_nodes_lock
+ *if @proc is NULL. During inc/dec and node release
+ *it is also protected by @lock to provide safety
+ *as the node dies and @proc becomes NULL)
  * @ptr:  userspace pointer for node
  *(invariant, no lock needed)
  * @cookie:   userspace cookie for node
  *(invariant, no lock needed)
  * @has_strong_ref:   userspace notified of strong ref
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @pending_strong_ref:   userspace has acked notification of strong ref
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @has_weak_ref: userspace notified of weak ref
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @pending_weak_ref: userspace has acked notification of weak ref
+ *(protected by @proc->inner_lock if @proc
+ *and by @lock)
  * @has_async_transaction: async transaction to node in progress
  * @accept_fds:   file descriptor operations supported for node
  *(invariant after initialized)
@@ -347,13 +366,24 @@ struct binder_node {
int tmp_refs;
binder_uintptr_t ptr;
binder_uintptr_t cookie;
-   unsigned has_strong_ref:1;
-   unsigned pending_strong_ref:1;
-   unsigned has_weak_ref:1;
-   unsigned pending_weak_ref:1;
-   unsigned has_async_transaction:1;
-   unsigned accept_fds:1;
-   unsigned min_priority:8;
+   struct {
+   /*
+* bitfield elements protected by
+* proc inner_lock
+*/
+   u8 has_strong_ref:1;
+   u8 pending_strong_ref:1;
+   u8 has_weak_ref:1;
+   u8 pending_weak_ref:1;
+   };
+   struct {
+   /*
+* invariant after initialization
+*/
+   u8 accept_fds:1;
+   u8 min_priority;
+   };
+   bool has_async_transaction;
struct list_head async_todo;
 };
 
@@ -813,9 +843,18 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
return node;
 }
 
-static int binder_inc_node(struct binder_node *node, int strong, int internal,
-  struct list_head *target_list)
+static void binder_free_node(struct binder_node *node)
 {
+   kfree(node);
+   binder_stats_deleted(BINDER_STAT_NODE);
+}
+
+static int binder_inc_node_ilocked(struct binder_node *node, int strong,
+  int internal,
+  struct list_head *target_list)
+{
+   if (node->proc)
+   BUG_ON(!spin_is_locked(>proc->inner_lock));
if (strong) {
if (internal) {
if (target_list == NULL &&
@@ -849,23 +888,43 @@ static int binder_inc_node(struct binder_node *node, int 
strong

[PATCH 30/37] binder: protect proc->nodes with inner lock

2017-06-29 Thread Todd Kjos
When locks for binder_ref handling are added, proc->nodes
will need to be modified while holding the outer lock

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 112 +--
 1 file changed, 89 insertions(+), 23 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5654187555be..4d08b5141b01 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -313,6 +313,7 @@ struct binder_error {
  * @work: worklist element for node work
  *(protected by @proc->inner_lock)
  * @rb_node:  element for proc->nodes tree
+ *(protected by @proc->inner_lock)
  * @dead_node:element for binder_dead_nodes list
  *(protected by binder_dead_nodes_lock)
  * @proc: binder_proc that owns this node
@@ -470,6 +471,7 @@ enum binder_deferred_state {
  * @threads:  rbtree of binder_threads in this proc
  * @nodes:rbtree of binder nodes associated with
  *this proc ordered by node->ptr
+ *(protected by @inner_lock)
  * @refs_by_desc: rbtree of refs ordered by ref->desc
  * @refs_by_node: rbtree of refs ordered by ref->node
  * @pid   PID of group_leader of process
@@ -856,7 +858,7 @@ static void
 binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
 static void binder_free_thread(struct binder_thread *thread);
 static void binder_free_proc(struct binder_proc *proc);
-static void binder_inc_node_tmpref(struct binder_node *node);
+static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
@@ -938,12 +940,14 @@ static void binder_set_nice(long nice)
binder_user_error("%d RLIMIT_NICE not set\n", current->pid);
 }
 
-static struct binder_node *binder_get_node(struct binder_proc *proc,
-  binder_uintptr_t ptr)
+static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc,
+  binder_uintptr_t ptr)
 {
struct rb_node *n = proc->nodes.rb_node;
struct binder_node *node;
 
+   BUG_ON(!spin_is_locked(>inner_lock));
+
while (n) {
node = rb_entry(n, struct binder_node, rb_node);
 
@@ -957,15 +961,28 @@ static struct binder_node *binder_get_node(struct 
binder_proc *proc,
 * to ensure node stays alive until
 * call to binder_put_node()
 */
-   binder_inc_node_tmpref(node);
+   binder_inc_node_tmpref_ilocked(node);
return node;
}
}
return NULL;
 }
 
-static struct binder_node *binder_new_node(struct binder_proc *proc,
-  struct flat_binder_object *fp)
+static struct binder_node *binder_get_node(struct binder_proc *proc,
+  binder_uintptr_t ptr)
+{
+   struct binder_node *node;
+
+   binder_inner_proc_lock(proc);
+   node = binder_get_node_ilocked(proc, ptr);
+   binder_inner_proc_unlock(proc);
+   return node;
+}
+
+static struct binder_node *binder_init_node_ilocked(
+   struct binder_proc *proc,
+   struct binder_node *new_node,
+   struct flat_binder_object *fp)
 {
struct rb_node **p = >nodes.rb_node;
struct rb_node *parent = NULL;
@@ -974,7 +991,9 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
binder_uintptr_t cookie = fp ? fp->cookie : 0;
__u32 flags = fp ? fp->flags : 0;
 
+   BUG_ON(!spin_is_locked(>inner_lock));
while (*p) {
+
parent = *p;
node = rb_entry(parent, struct binder_node, rb_node);
 
@@ -982,13 +1001,17 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
p = &(*p)->rb_left;
else if (ptr > node->ptr)
p = &(*p)->rb_right;
-   else
-   return NULL;
+   else {
+   /*
+* A matching node is already in
+* the rb tree. Abandon the init
+* and return it.
+*/
+   binder_inc_node_tmpref_ilocked(node);
+   return node;
+   }
}
-
-   node = kzalloc(sizeof(*node), GFP_KERNEL);
-   if (node == NULL)
-   return NULL;
+   node = ne

[PATCH 26/37] binder: introduce locking helper functions

2017-06-29 Thread Todd Kjos
There are 3 main spinlocks which must be acquired in this
order:
1) proc->outer_lock : protects most fields of binder_proc,
binder_thread, and binder_ref structures. binder_proc_lock()
and binder_proc_unlock() are used to acq/rel.
2) node->lock : protects most fields of binder_node.
binder_node_lock() and binder_node_unlock() are
used to acq/rel
3) proc->inner_lock : protects the thread and node lists
(proc->threads, proc->nodes) and all todo lists associated
with the binder_proc (proc->todo, thread->todo,
proc->delivered_death and node->async_todo).
binder_inner_proc_lock() and binder_inner_proc_unlock()
are used to acq/rel

Any lock under procA must never be nested under any lock at the same
level or below on procB.

Functions that require a lock held on entry indicate which lock
in the suffix of the function name:

foo_olocked() : requires node->outer_lock
foo_nlocked() : requires node->lock
foo_ilocked() : requires proc->inner_lock
foo_iolocked(): requires proc->outer_lock and proc->inner_lock
foo_nilocked(): requires node->lock and proc->inner_lock

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 238 +++
 1 file changed, 238 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index ec050c6d1192..91fece5c067f 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -15,6 +15,39 @@
  *
  */
 
+/*
+ * Locking overview
+ *
+ * There are 3 main spinlocks which must be acquired in the
+ * order shown:
+ *
+ * 1) proc->outer_lock : protects binder_ref
+ *binder_proc_lock() and binder_proc_unlock() are
+ *used to acq/rel.
+ * 2) node->lock : protects most fields of binder_node.
+ *binder_node_lock() and binder_node_unlock() are
+ *used to acq/rel
+ * 3) proc->inner_lock : protects the thread and node lists
+ *(proc->threads, proc->nodes) and all todo lists associated
+ *with the binder_proc (proc->todo, thread->todo,
+ *proc->delivered_death and node->async_todo).
+ *binder_inner_proc_lock() and binder_inner_proc_unlock()
+ *are used to acq/rel
+ *
+ * Any lock under procA must never be nested under any lock at the same
+ * level or below on procB.
+ *
+ * Functions that require a lock held on entry indicate which lock
+ * in the suffix of the function name:
+ *
+ * foo_olocked() : requires node->outer_lock
+ * foo_nlocked() : requires node->lock
+ * foo_ilocked() : requires proc->inner_lock
+ * foo_oilocked(): requires proc->outer_lock and proc->inner_lock
+ * foo_nilocked(): requires node->lock and proc->inner_lock
+ * ...
+ */
+
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
@@ -36,6 +69,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_ANDROID_BINDER_IPC_32BIT
 #define BINDER_IPC_32BIT 1
@@ -106,6 +140,7 @@ enum {
BINDER_DEBUG_FREE_BUFFER= 1U << 11,
BINDER_DEBUG_INTERNAL_REFS  = 1U << 12,
BINDER_DEBUG_PRIORITY_CAP   = 1U << 13,
+   BINDER_DEBUG_SPINLOCKS  = 1U << 14,
 };
 static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
@@ -262,8 +297,43 @@ struct binder_error {
uint32_t cmd;
 };
 
+/**
+ * struct binder_node - binder node bookkeeping
+ * @debug_id: unique ID for debugging
+ *(invariant after initialized)
+ * @lock: lock for node fields
+ * @work: worklist element for node work
+ * @rb_node:  element for proc->nodes tree
+ * @dead_node:element for binder_dead_nodes list
+ *(protected by binder_dead_nodes_lock)
+ * @proc: binder_proc that owns this node
+ *(invariant after initialized)
+ * @refs: list of references on this node
+ * @internal_strong_refs: used to take strong references when
+ *initiating a transaction
+ * @local_weak_refs:  weak user refs from local process
+ * @local_strong_refs:strong user refs from local process
+ * @tmp_refs: temporary kernel refs
+ * @ptr:  userspace pointer for node
+ *(invariant, no lock needed)
+ * @cookie:   userspace cookie for node
+ *(invariant, no lock needed)
+ * @has_strong_ref:   userspace notified of strong ref
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ * @has_weak_ref: userspace notified of weak ref
+ * @pending_weak_ref: userspace has acked notification of weak ref
+ * @has_async_transaction: async transaction to node in progress
+ * @accept_fds:   file descriptor op

[PATCH 22/37] binder: make sure target_node has strong ref

2017-06-29 Thread Todd Kjos
When initiating a transaction, the target_node must
have a strong ref on it. Then we take a second
strong ref to make sure the node survives until the
transaction is complete.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 84a57dd7b973..fb79f40111eb 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1469,8 +1469,19 @@ static void binder_transaction(struct binder_proc *proc,
if (tr->target.handle) {
struct binder_ref *ref;
 
+   /*
+* There must already be a strong ref
+* on this node. If so, do a strong
+* increment on the node to ensure it
+* stays alive until the transaction is
+* done.
+*/
ref = binder_get_ref(proc, tr->target.handle, true);
-   if (ref == NULL) {
+   if (ref) {
+   binder_inc_node(ref->node, 1, 0, NULL);
+   target_node = ref->node;
+   }
+   if (target_node == NULL) {
binder_user_error("%d:%d got transaction to 
invalid handle\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -1478,7 +1489,6 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_invalid_target_handle;
}
-   target_node = ref->node;
} else {
mutex_lock(>context_mgr_node_lock);
target_node = context->binder_context_mgr_node;
@@ -1488,6 +1498,7 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_no_context_mgr_node;
}
+   binder_inc_node(target_node, 1, 0, NULL);
mutex_unlock(>context_mgr_node_lock);
}
e->to_node = target_node->debug_id;
@@ -1608,9 +1619,6 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->transaction = t;
t->buffer->target_node = target_node;
trace_binder_transaction_alloc_buf(t->buffer);
-   if (target_node)
-   binder_inc_node(target_node, 1, 0, NULL);
-
off_start = (binder_size_t *)(t->buffer->data +
  ALIGN(tr->data_size, sizeof(void *)));
offp = off_start;
@@ -1846,6 +1854,7 @@ static void binder_transaction(struct binder_proc *proc,
 err_copy_data_failed:
trace_binder_transaction_failed_buffer_release(t->buffer);
binder_transaction_buffer_release(target_proc, t->buffer, offp);
+   target_node = NULL;
t->buffer->transaction = NULL;
binder_alloc_free_buf(_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
@@ -1860,6 +1869,9 @@ static void binder_transaction(struct binder_proc *proc,
 err_dead_binder:
 err_invalid_target_handle:
 err_no_context_mgr_node:
+   if (target_node)
+   binder_dec_node(target_node, 1, 0);
+
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n",
 proc->pid, thread->pid, return_error, return_error_param,
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 19/37] binder: use atomic for transaction_log index

2017-06-29 Thread Todd Kjos
The log->next index for the transaction log was
not protected when incremented. This led to a
case where log->next++ resulted in an index
larger than ARRAY_SIZE(log->entry) and eventually
a bad access to memory.

Fixed by making the log index an atomic64 and
converting to an array by using "% ARRAY_SIZE(log->entry)"

Also added "complete" field to the log entry which is
written last to tell the print code whether the
entry is complete

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 75 +---
 1 file changed, 59 insertions(+), 16 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a1912a22c89c..cb78a4e6872d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -187,6 +187,7 @@ static inline void binder_stats_created(enum 
binder_stat_types type)
 
 struct binder_transaction_log_entry {
int debug_id;
+   int debug_id_done;
int call_type;
int from_proc;
int from_thread;
@@ -202,8 +203,8 @@ struct binder_transaction_log_entry {
const char *context_name;
 };
 struct binder_transaction_log {
-   int next;
-   int full;
+   atomic_t cur;
+   bool full;
struct binder_transaction_log_entry entry[32];
 };
 static struct binder_transaction_log binder_transaction_log;
@@ -213,14 +214,19 @@ static struct binder_transaction_log_entry 
*binder_transaction_log_add(
struct binder_transaction_log *log)
 {
struct binder_transaction_log_entry *e;
+   unsigned int cur = atomic_inc_return(>cur);
 
-   e = >entry[log->next];
-   memset(e, 0, sizeof(*e));
-   log->next++;
-   if (log->next == ARRAY_SIZE(log->entry)) {
-   log->next = 0;
+   if (cur >= ARRAY_SIZE(log->entry))
log->full = 1;
-   }
+   e = >entry[cur % ARRAY_SIZE(log->entry)];
+   WRITE_ONCE(e->debug_id_done, 0);
+   /*
+* write-barrier to synchronize access to e->debug_id_done.
+* We make sure the initialized 0 value is seen before
+* memset() other fields are zeroed by memset.
+*/
+   smp_wmb();
+   memset(e, 0, sizeof(*e));
return e;
 }
 
@@ -1400,8 +1406,10 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_buffer_object *last_fixup_obj = NULL;
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
+   int t_debug_id = atomic_inc_return(_last_id);
 
e = binder_transaction_log_add(_transaction_log);
+   e->debug_id = t_debug_id;
e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
e->from_proc = proc->pid;
e->from_thread = thread->pid;
@@ -1545,8 +1553,7 @@ static void binder_transaction(struct binder_proc *proc,
}
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
 
-   t->debug_id = atomic_inc_return(_last_id);
-   e->debug_id = t->debug_id;
+   t->debug_id = t_debug_id;
 
if (reply)
binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1821,6 +1828,12 @@ static void binder_transaction(struct binder_proc *proc,
else
wake_up_interruptible(target_wait);
}
+   /*
+* write barrier to synchronize with initialization
+* of log entry
+*/
+   smp_wmb();
+   WRITE_ONCE(e->debug_id_done, t_debug_id);
return;
 
 err_translate_failed:
@@ -1858,6 +1871,13 @@ static void binder_transaction(struct binder_proc *proc,
e->return_error_line = return_error_line;
fe = binder_transaction_log_add(_transaction_log_failed);
*fe = *e;
+   /*
+* write barrier to synchronize with initialization
+* of log entry
+*/
+   smp_wmb();
+   WRITE_ONCE(e->debug_id_done, t_debug_id);
+   WRITE_ONCE(fe->debug_id_done, t_debug_id);
}
 
BUG_ON(thread->return_error != BR_OK);
@@ -3718,27 +3738,47 @@ static int binder_proc_show(struct seq_file *m, void 
*unused)
 static void print_binder_transaction_log_entry(struct seq_file *m,
struct binder_transaction_log_entry *e)
 {
+   int debug_id = READ_ONCE(e->debug_id_done);
+   /*
+* read barrier to guarantee debug_id_done read before
+* we print the log values
+*/
+   smp_rmb();
seq_printf(m,
-  "%d: %s from %d:%d to %d:%d context %s node %d handle %d 
size %d:%d ret %d/%d l=%d\n",
+  "%d: %s from %d:%d to %d:%d context %s node %d handle %d 
size %d:%d ret %d/%d l=%d",
   e->debug_id, (e->call_type == 2) ? "reply" :

[PATCH 05/37] binder: remove unneeded cleanup code

2017-06-29 Thread Todd Kjos
The buffer's transaction has already been freed before
binder_deferred_release. No need to do it again.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1097d056ea6b..2cbd7558fc3f 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3631,7 +3631,6 @@ static int binder_node_release(struct binder_node *node, 
int refs)
 
 static void binder_deferred_release(struct binder_proc *proc)
 {
-   struct binder_transaction *t;
struct binder_context *context = proc->context;
struct rb_node *n;
int threads, nodes, incoming_refs, outgoing_refs, buffers,
@@ -3689,14 +3688,8 @@ static void binder_deferred_release(struct binder_proc 
*proc)
 
buffer = rb_entry(n, struct binder_buffer, rb_node);
 
-   t = buffer->transaction;
-   if (t) {
-   t->buffer = NULL;
-   buffer->transaction = NULL;
-   pr_err("release proc %d, transaction %d, not freed\n",
-  proc->pid, t->debug_id);
-   /*BUG();*/
-   }
+   /* Transaction should already have been freed */
+   BUG_ON(buffer->transaction);
 
binder_free_buf(proc, buffer);
buffers++;
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 02/37] binder: use group leader instead of open thread

2017-06-29 Thread Todd Kjos
The binder allocator assumes that the thread that
called binder_open will never die for the lifetime of
that proc. That thread is normally the group_leader,
however it may not be. Use the group_leader instead
of current.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 157bd3e49ff4..9393924ae8e8 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3460,8 +3460,8 @@ static int binder_open(struct inode *nodp, struct file 
*filp)
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
if (proc == NULL)
return -ENOMEM;
-   get_task_struct(current);
-   proc->tsk = current;
+   get_task_struct(current->group_leader);
+   proc->tsk = current->group_leader;
INIT_LIST_HEAD(>todo);
init_waitqueue_head(>wait);
proc->default_priority = task_nice(current);
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 11/37] binder: make binder_last_id an atomic

2017-06-29 Thread Todd Kjos
Use an atomic for binder_last_id to avoid locking it

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index cd4191d027e1..25f30d81c7d0 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -59,7 +59,7 @@ static DEFINE_SPINLOCK(binder_dead_nodes_lock);
 
 static struct dentry *binder_debugfs_dir_entry_root;
 static struct dentry *binder_debugfs_dir_entry_proc;
-static int binder_last_id;
+static atomic_t binder_last_id;
 
 #define BINDER_DEBUG_ENTRY(name) \
 static int binder_##name##_open(struct inode *inode, struct file *file) \
@@ -496,7 +496,7 @@ static struct binder_node *binder_new_node(struct 
binder_proc *proc,
binder_stats_created(BINDER_STAT_NODE);
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, >nodes);
-   node->debug_id = ++binder_last_id;
+   node->debug_id = atomic_inc_return(_last_id);
node->proc = proc;
node->ptr = ptr;
node->cookie = cookie;
@@ -639,7 +639,7 @@ static struct binder_ref *binder_get_ref_for_node(struct 
binder_proc *proc,
if (new_ref == NULL)
return NULL;
binder_stats_created(BINDER_STAT_REF);
-   new_ref->debug_id = ++binder_last_id;
+   new_ref->debug_id = atomic_inc_return(_last_id);
new_ref->proc = proc;
new_ref->node = node;
rb_link_node(_ref->rb_node_node, parent, p);
@@ -1527,7 +1527,7 @@ static void binder_transaction(struct binder_proc *proc,
}
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
 
-   t->debug_id = ++binder_last_id;
+   t->debug_id = atomic_inc_return(_last_id);
e->debug_id = t->debug_id;
 
if (reply)
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 06/37] binder: separate out binder_alloc functions

2017-06-29 Thread Todd Kjos
Continuation of splitting the binder allocator from the binder
driver. Separate binder_alloc functions from normal binder
functions. Protect the allocator with a separate mutex.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c   | 649 +
 drivers/android/binder_trace.h |   9 +-
 2 files changed, 410 insertions(+), 248 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 2cbd7558fc3f..6c1d0b5b352b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -49,7 +49,7 @@
 
 static DEFINE_MUTEX(binder_main_lock);
 static DEFINE_MUTEX(binder_deferred_lock);
-static DEFINE_MUTEX(binder_mmap_lock);
+static DEFINE_MUTEX(binder_alloc_mmap_lock);
 
 static HLIST_HEAD(binder_devices);
 static HLIST_HEAD(binder_procs);
@@ -104,9 +104,7 @@ enum {
BINDER_DEBUG_TRANSACTION_COMPLETE   = 1U << 10,
BINDER_DEBUG_FREE_BUFFER= 1U << 11,
BINDER_DEBUG_INTERNAL_REFS  = 1U << 12,
-   BINDER_DEBUG_BUFFER_ALLOC   = 1U << 13,
-   BINDER_DEBUG_PRIORITY_CAP   = 1U << 14,
-   BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15,
+   BINDER_DEBUG_PRIORITY_CAP   = 1U << 13,
 };
 static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
@@ -159,6 +157,27 @@ module_param_call(stop_on_user_error, 
binder_set_stop_on_user_error,
 #define to_binder_fd_array_object(hdr) \
container_of(hdr, struct binder_fd_array_object, hdr)
 
+/*
+ * debug declarations for binder_alloc. To be
+ * moved to binder_alloc.c
+ */
+enum {
+   BINDER_ALLOC_DEBUG_OPEN_CLOSE = 1U << 1,
+   BINDER_ALLOC_DEBUG_BUFFER_ALLOC   = 1U << 2,
+   BINDER_ALLOC_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3,
+};
+static uint32_t binder_alloc_debug_mask;
+
+module_param_named(alloc_debug_mask, binder_alloc_debug_mask,
+  uint, 0644);
+
+#define binder_alloc_debug(mask, x...) \
+   do { \
+   if (binder_alloc_debug_mask & mask) \
+   pr_info(x); \
+   } while (0)
+/* end of binder_alloc debug declarations */
+
 enum binder_stat_types {
BINDER_STAT_PROC,
BINDER_STAT_THREAD,
@@ -342,6 +361,8 @@ enum binder_deferred_state {
  * struct binder_buffer objects used to track the user buffers
  */
 struct binder_alloc {
+   struct mutex mutex;
+   struct task_struct *tsk;
struct vm_area_struct *vma;
struct mm_struct *vma_vm_mm;
void *buffer;
@@ -352,6 +373,7 @@ struct binder_alloc {
size_t free_async_space;
struct page **pages;
size_t buffer_size;
+   int pid;
 };
 
 struct binder_proc {
@@ -423,6 +445,56 @@ struct binder_transaction {
kuid_t  sender_euid;
 };
 
+/*
+ * Forward declarations of binder_alloc functions.
+ * These will be moved to binder_alloc.h when
+ * binder_alloc is moved to its own files.
+ */
+extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
+ size_t data_size,
+ size_t offsets_size,
+ size_t extra_buffers_size,
+ int is_async);
+extern void binder_alloc_init(struct binder_alloc *alloc);
+extern void binder_alloc_vma_close(struct binder_alloc *alloc);
+extern struct binder_buffer *
+binder_alloc_buffer_lookup(struct binder_alloc *alloc,
+  uintptr_t user_ptr);
+extern void binder_alloc_free_buf(struct binder_alloc *alloc,
+ struct binder_buffer *buffer);
+extern int binder_alloc_mmap_handler(struct binder_alloc *alloc,
+struct vm_area_struct *vma);
+extern void binder_alloc_deferred_release(struct binder_alloc *alloc);
+extern int binder_alloc_get_allocated_count(struct binder_alloc *alloc);
+extern void binder_alloc_print_allocated(struct seq_file *m,
+struct binder_alloc *alloc);
+
+static inline size_t
+binder_alloc_get_free_async_space(struct binder_alloc *alloc)
+{
+   size_t free_async_space;
+
+   mutex_lock(>mutex);
+   free_async_space = alloc->free_async_space;
+   mutex_unlock(>mutex);
+   return free_async_space;
+}
+
+static inline ptrdiff_t
+binder_alloc_get_user_buffer_offset(struct binder_alloc *alloc)
+{
+   /*
+* user_buffer_offset is constant if vma is set and
+* undefined if vma is not set. It is possible to
+* get here with !alloc->vma if the target process
+* is dying while a transaction is being initiated.
+* Returning the old value is ok in this case and
+* the transaction will fail.
+*/
+   return al

[PATCH 12/37] binder: add log information for binder transaction failures

2017-06-29 Thread Todd Kjos
Add additional information to determine the cause of binder
failures. Adds the following to failed transaction log and
kernel messages:
return_error : value returned for transaction
return_error_param : errno returned by binder allocator
return_error_line : line number where error detected

Also, return BR_DEAD_REPLY if an allocation error indicates
a dead proc (-ESRCH)

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c   | 87 +-
 drivers/android/binder_alloc.c | 20 +-
 2 files changed, 88 insertions(+), 19 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 25f30d81c7d0..62ac0c41b8a6 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -196,6 +196,9 @@ struct binder_transaction_log_entry {
int to_node;
int data_size;
int offsets_size;
+   int return_error_line;
+   uint32_t return_error;
+   uint32_t return_error_param;
const char *context_name;
 };
 struct binder_transaction_log {
@@ -1142,7 +1145,7 @@ static int binder_translate_binder(struct 
flat_binder_object *fp,
 
ref = binder_get_ref_for_node(target_proc, node);
if (!ref)
-   return -EINVAL;
+   return -ENOMEM;
 
if (fp->hdr.type == BINDER_TYPE_BINDER)
fp->hdr.type = BINDER_TYPE_HANDLE;
@@ -1199,7 +1202,7 @@ static int binder_translate_handle(struct 
flat_binder_object *fp,
 
new_ref = binder_get_ref_for_node(target_proc, ref->node);
if (!new_ref)
-   return -EINVAL;
+   return -ENOMEM;
 
fp->binder = 0;
fp->handle = new_ref->desc;
@@ -1397,7 +1400,9 @@ static void binder_transaction(struct binder_proc *proc,
wait_queue_head_t *target_wait;
struct binder_transaction *in_reply_to = NULL;
struct binder_transaction_log_entry *e;
-   uint32_t return_error;
+   uint32_t return_error = 0;
+   uint32_t return_error_param = 0;
+   uint32_t return_error_line = 0;
struct binder_buffer_object *last_fixup_obj = NULL;
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
@@ -1417,6 +1422,8 @@ static void binder_transaction(struct binder_proc *proc,
binder_user_error("%d:%d got reply transaction with no 
transaction stack\n",
  proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
+   return_error_param = -EPROTO;
+   return_error_line = __LINE__;
goto err_empty_call_stack;
}
binder_set_nice(in_reply_to->saved_priority);
@@ -1428,6 +1435,8 @@ static void binder_transaction(struct binder_proc *proc,
in_reply_to->to_thread ?
in_reply_to->to_thread->pid : 0);
return_error = BR_FAILED_REPLY;
+   return_error_param = -EPROTO;
+   return_error_line = __LINE__;
in_reply_to = NULL;
goto err_bad_call_stack;
}
@@ -1435,6 +1444,7 @@ static void binder_transaction(struct binder_proc *proc,
target_thread = in_reply_to->from;
if (target_thread == NULL) {
return_error = BR_DEAD_REPLY;
+   return_error_line = __LINE__;
goto err_dead_binder;
}
if (target_thread->transaction_stack != in_reply_to) {
@@ -1444,6 +1454,8 @@ static void binder_transaction(struct binder_proc *proc,
target_thread->transaction_stack->debug_id : 0,
in_reply_to->debug_id);
return_error = BR_FAILED_REPLY;
+   return_error_param = -EPROTO;
+   return_error_line = __LINE__;
in_reply_to = NULL;
target_thread = NULL;
goto err_dead_binder;
@@ -1458,6 +1470,8 @@ static void binder_transaction(struct binder_proc *proc,
binder_user_error("%d:%d got transaction to 
invalid handle\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
+   return_error_param = -EINVAL;
+   return_error_line = __LINE__;
goto err_invalid_target_handle;
}
target_node = ref->node;
@@ -1467,6 +1481,7 @@ static void bin

[PATCH 09/37] binder: add protection for non-perf cases

2017-06-29 Thread Todd Kjos
Add binder_dead_nodes_lock, binder_procs_lock, and
binder_context_mgr_node_lock to protect the associated global lists

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 81 +---
 1 file changed, 63 insertions(+), 18 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 10fda7ab9fa5..fb484c6acd3e 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -46,12 +46,16 @@
 #include "binder_trace.h"
 
 static DEFINE_MUTEX(binder_main_lock);
+
+static HLIST_HEAD(binder_deferred_list);
 static DEFINE_MUTEX(binder_deferred_lock);
 
 static HLIST_HEAD(binder_devices);
 static HLIST_HEAD(binder_procs);
-static HLIST_HEAD(binder_deferred_list);
+static DEFINE_MUTEX(binder_procs_lock);
+
 static HLIST_HEAD(binder_dead_nodes);
+static DEFINE_SPINLOCK(binder_dead_nodes_lock);
 
 static struct dentry *binder_debugfs_dir_entry_root;
 static struct dentry *binder_debugfs_dir_entry_proc;
@@ -219,6 +223,8 @@ static struct binder_transaction_log_entry 
*binder_transaction_log_add(
 
 struct binder_context {
struct binder_node *binder_context_mgr_node;
+   struct mutex context_mgr_node_lock;
+
kuid_t binder_context_mgr_uid;
const char *name;
 };
@@ -570,7 +576,9 @@ static int binder_dec_node(struct binder_node *node, int 
strong, int internal)
 "refless node %d deleted\n",
 node->debug_id);
} else {
+   spin_lock(_dead_nodes_lock);
hlist_del(>dead_node);
+   spin_unlock(_dead_nodes_lock);
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
 "dead node %d deleted\n",
 node->debug_id);
@@ -1454,11 +1462,14 @@ static void binder_transaction(struct binder_proc *proc,
}
target_node = ref->node;
} else {
+   mutex_lock(>context_mgr_node_lock);
target_node = context->binder_context_mgr_node;
if (target_node == NULL) {
return_error = BR_DEAD_REPLY;
+   mutex_unlock(>context_mgr_node_lock);
goto err_no_context_mgr_node;
}
+   mutex_unlock(>context_mgr_node_lock);
}
e->to_node = target_node->debug_id;
target_proc = target_node->proc;
@@ -1824,22 +1835,31 @@ static int binder_thread_write(struct binder_proc *proc,
case BC_RELEASE:
case BC_DECREFS: {
uint32_t target;
-   struct binder_ref *ref;
+   struct binder_ref *ref = NULL;
const char *debug_string;
 
if (get_user(target, (uint32_t __user *)ptr))
return -EFAULT;
+
ptr += sizeof(uint32_t);
-   if (target == 0 && context->binder_context_mgr_node &&
+   if (target == 0 &&
(cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
-   ref = binder_get_ref_for_node(proc,
-   context->binder_context_mgr_node);
-   if (ref->desc != target) {
-   binder_user_error("%d:%d tried to 
acquire reference to desc 0, got %d instead\n",
-   proc->pid, thread->pid,
-   ref->desc);
+   struct binder_node *ctx_mgr_node;
+
+   mutex_lock(>context_mgr_node_lock);
+   ctx_mgr_node = context->binder_context_mgr_node;
+   if (ctx_mgr_node) {
+   ref = binder_get_ref_for_node(proc,
+   ctx_mgr_node);
+   if (ref && ref->desc != target) {
+   binder_user_error("%d:%d tried 
to acquire reference to desc 0, got %d instead\n",
+   proc->pid, thread->pid,
+   ref->desc);
+   }
}
-   } else
+   mutex_unlock(

[PATCH 04/37] binder: separate binder allocator structure from binder proc

2017-06-29 Thread Todd Kjos
The binder allocator is logically separate from the rest
of the binder drivers. Separating the data structures
to prepare for splitting into separate file with separate
locking.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c   | 212 +
 drivers/android/binder_trace.h |   2 +-
 2 files changed, 129 insertions(+), 85 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f7665c31feca..1097d056ea6b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -319,6 +319,41 @@ enum binder_deferred_state {
BINDER_DEFERRED_RELEASE  = 0x04,
 };
 
+/**
+ * struct binder_alloc - per-binder proc state for binder allocator
+ * @vma:   vm_area_struct passed to mmap_handler
+ * (invarient after mmap)
+ * @vma_vm_mm: copy of vma->vm_mm (invarient after mmap)
+ * @buffer:base of per-proc address space mapped via mmap
+ * @user_buffer_offset: offset between user and kernel VAs for buffer
+ * @buffers:   list of all buffers for this proc
+ * @free_buffers:  rb tree of buffers available for allocation
+ * sorted by size
+ * @allocated_buffers: rb tree of allocated buffers sorted by address
+ * @free_async_space:  VA space available for async buffers. This is
+ * initialized at mmap time to 1/2 the full VA space
+ * @pages: array of physical page addresses for each page of
+ * mmap'd space
+ * @buffer_size:   size of address space (could be less than requested)
+ *
+ * Bookkeeping structure for per-proc address space management for binder
+ * buffers. It is normally initialized during binder_init() and binder_mmap()
+ * calls. The address space is used for both user-visible buffers and for
+ * struct binder_buffer objects used to track the user buffers
+ */
+struct binder_alloc {
+   struct vm_area_struct *vma;
+   struct mm_struct *vma_vm_mm;
+   void *buffer;
+   ptrdiff_t user_buffer_offset;
+   struct list_head buffers;
+   struct rb_root free_buffers;
+   struct rb_root allocated_buffers;
+   size_t free_async_space;
+   struct page **pages;
+   size_t buffer_size;
+};
+
 struct binder_proc {
struct hlist_node proc_node;
struct rb_root threads;
@@ -326,23 +361,11 @@ struct binder_proc {
struct rb_root refs_by_desc;
struct rb_root refs_by_node;
int pid;
-   struct vm_area_struct *vma;
-   struct mm_struct *vma_vm_mm;
struct task_struct *tsk;
struct files_struct *files;
struct hlist_node deferred_work_node;
int deferred_work;
-   void *buffer;
-   ptrdiff_t user_buffer_offset;
 
-   struct list_head buffers;
-   struct rb_root free_buffers;
-   struct rb_root allocated_buffers;
-   size_t free_async_space;
-
-   struct page **pages;
-   size_t buffer_size;
-   uint32_t buffer_free;
struct list_head todo;
wait_queue_head_t wait;
struct binder_stats stats;
@@ -353,6 +376,7 @@ struct binder_proc {
int ready_threads;
long default_priority;
struct dentry *debugfs_entry;
+   struct binder_alloc alloc;
struct binder_context *context;
 };
 
@@ -485,8 +509,10 @@ static void binder_set_nice(long nice)
 static size_t binder_buffer_size(struct binder_proc *proc,
 struct binder_buffer *buffer)
 {
-   if (list_is_last(>entry, >buffers))
-   return proc->buffer + proc->buffer_size - (void *)buffer->data;
+   if (list_is_last(>entry, >alloc.buffers))
+   return proc->alloc.buffer +
+   proc->alloc.buffer_size -
+   (void *)buffer->data;
return (size_t)list_entry(buffer->entry.next,
  struct binder_buffer, entry) - (size_t)buffer->data;
 }
@@ -494,7 +520,7 @@ static size_t binder_buffer_size(struct binder_proc *proc,
 static void binder_insert_free_buffer(struct binder_proc *proc,
  struct binder_buffer *new_buffer)
 {
-   struct rb_node **p = >free_buffers.rb_node;
+   struct rb_node **p = >alloc.free_buffers.rb_node;
struct rb_node *parent = NULL;
struct binder_buffer *buffer;
size_t buffer_size;
@@ -521,13 +547,13 @@ static void binder_insert_free_buffer(struct binder_proc 
*proc,
p = >rb_right;
}
rb_link_node(_buffer->rb_node, parent, p);
-   rb_insert_color(_buffer->rb_node, >free_buffers);
+   rb_insert_color(_buffer->rb_node, >alloc.free_buffers);
 }
 
 static void binder_insert_allocated_buffer(struct binder_proc *proc,
   struct binder_buffer *new_buffer)
 {
-   struct

[PATCH 03/37] binder: Use wake up hint for synchronous transactions.

2017-06-29 Thread Todd Kjos
From: Riley Andrews <riandr...@google.com>

Use wake_up_interruptible_sync() to hint to the scheduler binder
transactions are synchronous wakeups. Disable preemption while waking
to avoid ping-ponging on the binder lock.

Signed-off-by: Todd Kjos <tk...@google.com>
Signed-off-by: Omprakash Dhyade <odhy...@codeaurora.org>
---
 drivers/android/binder.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 9393924ae8e8..f7665c31feca 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2200,8 +2200,12 @@ static void binder_transaction(struct binder_proc *proc,
list_add_tail(>work.entry, target_list);
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(>entry, >todo);
-   if (target_wait)
-   wake_up_interruptible(target_wait);
+   if (target_wait) {
+   if (reply || !(t->flags & TF_ONE_WAY))
+   wake_up_interruptible_sync(target_wait);
+   else
+   wake_up_interruptible(target_wait);
+   }
return;
 
 err_translate_failed:
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 01/37] Revert "android: binder: Sanity check at binder ioctl"

2017-06-29 Thread Todd Kjos
This reverts commit a906d6931f3ccaf7de805643190765ddd7378e27.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index aae4d8d4be36..157bd3e49ff4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3247,10 +3247,6 @@ static long binder_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
 
-   if (unlikely(current->mm != proc->vma_vm_mm)) {
-   pr_err("current mm mismatch proc mm\n");
-   return -EINVAL;
-   }
trace_binder_ioctl(cmd, arg);
 
ret = wait_event_interruptible(binder_user_error_wait, 
binder_stop_on_user_error < 2);
@@ -3466,7 +3462,6 @@ static int binder_open(struct inode *nodp, struct file 
*filp)
return -ENOMEM;
get_task_struct(current);
proc->tsk = current;
-   proc->vma_vm_mm = current->mm;
INIT_LIST_HEAD(>todo);
init_waitqueue_head(>wait);
proc->default_priority = task_nice(current);
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 21/37] binder: guarantee txn complete / errors delivered in-order

2017-06-29 Thread Todd Kjos
Since errors are tracked in the return_error/return_error2
fields of the binder_thread object and BR_TRANSACTION_COMPLETEs
can be tracked either in those fields or via the thread todo
work list, it is possible for errors to be reported ahead
of the associated txn complete.

Use the thread todo work list for errors to guarantee
order. Also changed binder_send_failed_reply to pop
the transaction even if it failed to send a reply.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 127 +++
 1 file changed, 73 insertions(+), 54 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d2fcf3cc29a6..84a57dd7b973 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -249,6 +249,7 @@ struct binder_work {
enum {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
+   BINDER_WORK_RETURN_ERROR,
BINDER_WORK_NODE,
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
@@ -256,6 +257,11 @@ struct binder_work {
} type;
 };
 
+struct binder_error {
+   struct binder_work work;
+   uint32_t cmd;
+};
+
 struct binder_node {
int debug_id;
struct binder_work work;
@@ -350,10 +356,8 @@ struct binder_thread {
bool looper_need_return; /* can be written by other thread */
struct binder_transaction *transaction_stack;
struct list_head todo;
-   uint32_t return_error; /* Write failed, return error code in read buf */
-   uint32_t return_error2; /* Write failed, return error code in read */
-   /* buffer. Used when sending a reply to a dead process that */
-   /* we are also waiting on */
+   struct binder_error return_error;
+   struct binder_error reply_error;
wait_queue_head_t wait;
struct binder_stats stats;
 };
@@ -794,29 +798,24 @@ static void binder_send_failed_reply(struct 
binder_transaction *t,
while (1) {
target_thread = t->from;
if (target_thread) {
-   if (target_thread->return_error != BR_OK &&
-  target_thread->return_error2 == BR_OK) {
-   target_thread->return_error2 =
-   target_thread->return_error;
-   target_thread->return_error = BR_OK;
-   }
-   if (target_thread->return_error == BR_OK) {
-   binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-"send failed reply for transaction 
%d to %d:%d\n",
- t->debug_id,
- target_thread->proc->pid,
- target_thread->pid);
-
-   binder_pop_transaction(target_thread, t);
-   target_thread->return_error = error_code;
+   binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+"send failed reply for transaction %d to 
%d:%d\n",
+ t->debug_id,
+ target_thread->proc->pid,
+ target_thread->pid);
+
+   binder_pop_transaction(target_thread, t);
+   if (target_thread->reply_error.cmd == BR_OK) {
+   target_thread->reply_error.cmd = error_code;
+   list_add_tail(
+   _thread->reply_error.work.entry,
+   _thread->todo);
wake_up_interruptible(_thread->wait);
-   binder_free_transaction(t);
} else {
-   pr_err("reply failed, target thread, %d:%d, has 
error code %d already\n",
-   target_thread->proc->pid,
-   target_thread->pid,
-   target_thread->return_error);
+   WARN(1, "Unexpected reply error: %u\n",
+   target_thread->reply_error.cmd);
}
+   binder_free_transaction(t);
return;
}
next = t->from_parent;
@@ -1884,12 +1883,17 @@ static void binder_transaction(struct binder_proc *proc,
WRITE_ONCE(fe->debug_id_done, t_debug_id);
}
 
-   BUG_ON(thread->return_error != BR_OK);
+   BUG_ON(thread->return_error.cm

[PATCH 16/37] binder: remove dead code in binder_get_ref_for_node

2017-06-29 Thread Todd Kjos
node is always non-NULL in binder_get_ref_for_node so the
conditional and else clause are not needed

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 16 +---
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 3c1129d91825..3bbfb2455b70 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -670,18 +670,12 @@ static struct binder_ref *binder_get_ref_for_node(struct 
binder_proc *proc,
}
rb_link_node(_ref->rb_node_desc, parent, p);
rb_insert_color(_ref->rb_node_desc, >refs_by_desc);
-   if (node) {
-   hlist_add_head(_ref->node_entry, >refs);
+   hlist_add_head(_ref->node_entry, >refs);
 
-   binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-"%d new ref %d desc %d for node %d\n",
- proc->pid, new_ref->debug_id, new_ref->desc,
- node->debug_id);
-   } else {
-   binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-"%d new ref %d desc %d for dead node\n",
- proc->pid, new_ref->debug_id, new_ref->desc);
-   }
+   binder_debug(BINDER_DEBUG_INTERNAL_REFS,
+"%d new ref %d desc %d for node %d\n",
+ proc->pid, new_ref->debug_id, new_ref->desc,
+ node->debug_id);
return new_ref;
 }
 
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 08/37] binder: remove binder_debug_no_lock mechanism

2017-06-29 Thread Todd Kjos
With the global lock, there was a mechanism to access
binder driver debugging information with the global
lock disabled to debug deadlocks or other issues.
This mechanism is rarely (if ever) used anymore
and wasn't needed during the development of
fine-grained locking in the binder driver.
Removing it.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 31 ---
 1 file changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 0512971cfc53..10fda7ab9fa5 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -107,9 +107,6 @@ static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR 
|
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
 module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
 
-static bool binder_debug_no_lock;
-module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | 
S_IRUGO);
-
 static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
 module_param_named(devices, binder_devices_param, charp, 0444);
 
@@ -3507,10 +3504,8 @@ static int binder_state_show(struct seq_file *m, void 
*unused)
 {
struct binder_proc *proc;
struct binder_node *node;
-   int do_lock = !binder_debug_no_lock;
 
-   if (do_lock)
-   binder_lock(__func__);
+   binder_lock(__func__);
 
seq_puts(m, "binder state:\n");
 
@@ -3521,18 +3516,15 @@ static int binder_state_show(struct seq_file *m, void 
*unused)
 
hlist_for_each_entry(proc, _procs, proc_node)
print_binder_proc(m, proc, 1);
-   if (do_lock)
-   binder_unlock(__func__);
+   binder_unlock(__func__);
return 0;
 }
 
 static int binder_stats_show(struct seq_file *m, void *unused)
 {
struct binder_proc *proc;
-   int do_lock = !binder_debug_no_lock;
 
-   if (do_lock)
-   binder_lock(__func__);
+   binder_lock(__func__);
 
seq_puts(m, "binder stats:\n");
 
@@ -3540,24 +3532,20 @@ static int binder_stats_show(struct seq_file *m, void 
*unused)
 
hlist_for_each_entry(proc, _procs, proc_node)
print_binder_proc_stats(m, proc);
-   if (do_lock)
-   binder_unlock(__func__);
+   binder_unlock(__func__);
return 0;
 }
 
 static int binder_transactions_show(struct seq_file *m, void *unused)
 {
struct binder_proc *proc;
-   int do_lock = !binder_debug_no_lock;
 
-   if (do_lock)
-   binder_lock(__func__);
+   binder_lock(__func__);
 
seq_puts(m, "binder transactions:\n");
hlist_for_each_entry(proc, _procs, proc_node)
print_binder_proc(m, proc, 0);
-   if (do_lock)
-   binder_unlock(__func__);
+   binder_unlock(__func__);
return 0;
 }
 
@@ -3565,10 +3553,8 @@ static int binder_proc_show(struct seq_file *m, void 
*unused)
 {
struct binder_proc *itr;
int pid = (unsigned long)m->private;
-   int do_lock = !binder_debug_no_lock;
 
-   if (do_lock)
-   binder_lock(__func__);
+   binder_lock(__func__);
 
hlist_for_each_entry(itr, _procs, proc_node) {
if (itr->pid == pid) {
@@ -3576,8 +3562,7 @@ static int binder_proc_show(struct seq_file *m, void 
*unused)
print_binder_proc(m, itr, 1);
}
}
-   if (do_lock)
-   binder_unlock(__func__);
+   binder_unlock(__func__);
return 0;
 }
 
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 17/37] binder: protect against two threads freeing buffer

2017-06-29 Thread Todd Kjos
Adds protection against malicious user code freeing
the same buffer at the same time which could cause
a crash. Cannot happen under normal use.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c   |  4 ++--
 drivers/android/binder_alloc.c | 22 +-
 drivers/android/binder_alloc.h |  7 ---
 3 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 3bbfb2455b70..a1912a22c89c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2024,8 +2024,8 @@ static int binder_thread_write(struct binder_proc *proc,
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
 
-   buffer = binder_alloc_buffer_lookup(>alloc,
-   data_ptr);
+   buffer = binder_alloc_prepare_to_free(>alloc,
+ data_ptr);
if (buffer == NULL) {
binder_user_error("%d:%d BC_FREE_BUFFER 
u%016llx no match\n",
proc->pid, thread->pid, (u64)data_ptr);
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index a0af1419cc79..2a2e41b13de5 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -116,7 +116,7 @@ static void binder_insert_allocated_buffer_locked(
rb_insert_color(_buffer->rb_node, >allocated_buffers);
 }
 
-static struct binder_buffer *binder_alloc_buffer_lookup_locked(
+static struct binder_buffer *binder_alloc_prepare_to_free_locked(
struct binder_alloc *alloc,
uintptr_t user_ptr)
 {
@@ -135,8 +135,19 @@ static struct binder_buffer 
*binder_alloc_buffer_lookup_locked(
n = n->rb_left;
else if (kern_ptr > buffer)
n = n->rb_right;
-   else
+   else {
+   /*
+* Guard against user threads attempting to
+* free the buffer twice
+*/
+   if (buffer->free_in_progress) {
+   pr_err("%d:%d FREE_BUFFER u%016llx user freed 
buffer twice\n",
+  alloc->pid, current->pid, (u64)user_ptr);
+   return NULL;
+   }
+   buffer->free_in_progress = 1;
return buffer;
+   }
}
return NULL;
 }
@@ -152,13 +163,13 @@ static struct binder_buffer 
*binder_alloc_buffer_lookup_locked(
  *
  * Return: Pointer to buffer or NULL
  */
-struct binder_buffer *binder_alloc_buffer_lookup(struct binder_alloc *alloc,
-uintptr_t user_ptr)
+struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc,
+  uintptr_t user_ptr)
 {
struct binder_buffer *buffer;
 
mutex_lock(>mutex);
-   buffer = binder_alloc_buffer_lookup_locked(alloc, user_ptr);
+   buffer = binder_alloc_prepare_to_free_locked(alloc, user_ptr);
mutex_unlock(>mutex);
return buffer;
 }
@@ -358,6 +369,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct 
binder_alloc *alloc,
 
rb_erase(best_fit, >free_buffers);
buffer->free = 0;
+   buffer->free_in_progress = 0;
binder_insert_allocated_buffer_locked(alloc, buffer);
if (buffer_size != size) {
struct binder_buffer *new_buffer = (void *)buffer->data + size;
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index 721c511431f9..088e4ffc6230 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -48,7 +48,8 @@ struct binder_buffer {
unsigned free:1;
unsigned allow_user_free:1;
unsigned async_transaction:1;
-   unsigned debug_id:29;
+   unsigned free_in_progress:1;
+   unsigned debug_id:28;
 
struct binder_transaction *transaction;
 
@@ -109,8 +110,8 @@ extern struct binder_buffer *binder_alloc_new_buf(struct 
binder_alloc *alloc,
 extern void binder_alloc_init(struct binder_alloc *alloc);
 extern void binder_alloc_vma_close(struct binder_alloc *alloc);
 extern struct binder_buffer *
-binder_alloc_buffer_lookup(struct binder_alloc *alloc,
-  uintptr_t user_ptr);
+binder_alloc_prepare_to_free(struct binder_alloc *alloc,
+uintptr_t user_ptr);
 extern void binder_alloc_free_buf(struct binder_alloc *alloc,
  struct binder_buffer *buffer);
 extern int binder_alloc_mmap_handler(struct binder_alloc *alloc,
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 14/37] binder: avoid race conditions when enqueuing txn

2017-06-29 Thread Todd Kjos
Currently, the transaction complete work item is queued
after the transaction. This means that it is possible
for the transaction to be handled and a reply to be
enqueued in the current thread before the transaction
complete is enqueued, which violates the protocol
with userspace who may not expect the transaction
complete. Fixed by always enqueing the transaction
complete first.

Also, once the transaction is enqueued, it is unsafe
to access since it might be freed. Currently,
t->flags is accessed to determine whether a sync
wake is needed. Changed to access tr->flags
instead.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f17d1dfa5b02..71faf548482d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1799,6 +1799,9 @@ static void binder_transaction(struct binder_proc *proc,
goto err_bad_object_type;
}
}
+   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+   list_add_tail(>entry, >todo);
+
if (reply) {
BUG_ON(t->buffer->async_transaction != 0);
binder_pop_transaction(target_thread, in_reply_to);
@@ -1818,10 +1821,8 @@ static void binder_transaction(struct binder_proc *proc,
}
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(>work.entry, target_list);
-   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
-   list_add_tail(>entry, >todo);
if (target_wait) {
-   if (reply || !(t->flags & TF_ONE_WAY))
+   if (reply || !(tr->flags & TF_ONE_WAY))
wake_up_interruptible_sync(target_wait);
else
wake_up_interruptible(target_wait);
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH 01/37] Revert "android: binder: Sanity check at binder ioctl"

2017-07-05 Thread Todd Kjos
This reverts commit a906d6931f3ccaf7de805643190765ddd7378e27.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index aae4d8d4be36..157bd3e49ff4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3247,10 +3247,6 @@ static long binder_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
 
-   if (unlikely(current->mm != proc->vma_vm_mm)) {
-   pr_err("current mm mismatch proc mm\n");
-   return -EINVAL;
-   }
trace_binder_ioctl(cmd, arg);
 
ret = wait_event_interruptible(binder_user_error_wait, 
binder_stop_on_user_error < 2);
@@ -3466,7 +3462,6 @@ static int binder_open(struct inode *nodp, struct file 
*filp)
return -ENOMEM;
get_task_struct(current);
proc->tsk = current;
-   proc->vma_vm_mm = current->mm;
INIT_LIST_HEAD(>todo);
init_waitqueue_head(>wait);
proc->default_priority = task_nice(current);
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH v2 01/37] Revert "android: binder: Sanity check at binder ioctl"

2017-07-05 Thread Todd Kjos
This reverts commit a906d6931f3ccaf7de805643190765ddd7378e27.

The patch introduced a race in the binder driver. An attempt to fix the
race was submitted in "[PATCH v2] android: binder: fix dangling pointer
comparison", however the conclusion in the discussion for that patch
was that the original patch should be reverted.

The reversion is being done as part of the fine-grained locking
patchset since the patch would need to be refactored when
proc->vmm_vm_mm is removed from struct binder_proc and added
in the binder allocator.

Also needs reversion in 4.9 LTS

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index aae4d8d4be36..157bd3e49ff4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3247,10 +3247,6 @@ static long binder_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
 
-   if (unlikely(current->mm != proc->vma_vm_mm)) {
-   pr_err("current mm mismatch proc mm\n");
-   return -EINVAL;
-   }
trace_binder_ioctl(cmd, arg);
 
ret = wait_event_interruptible(binder_user_error_wait, 
binder_stop_on_user_error < 2);
@@ -3466,7 +3462,6 @@ static int binder_open(struct inode *nodp, struct file 
*filp)
return -ENOMEM;
get_task_struct(current);
proc->tsk = current;
-   proc->vma_vm_mm = current->mm;
INIT_LIST_HEAD(>todo);
init_waitqueue_head(>wait);
proc->default_priority = task_nice(current);
-- 
2.13.2.725.g09c95d1e9-goog



[PATCH] binder: fix incorrect cmd to binder_stat_br

2017-08-08 Thread Todd Kjos
commit 26549d177410 ("binder: guarantee txn complete / errors delivered
in-order") passed the locally declared and undefined cmd
to binder_stat_br() which results in a bogus cmd field in a trace
event and BR stats are incremented incorrectly.

Change to use e->cmd which has been initialized.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 9f95d7093f32..f34fcb513c64 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3619,7 +3619,7 @@ static int binder_thread_read(struct binder_proc *proc,
e->cmd = BR_OK;
ptr += sizeof(uint32_t);
 
-   binder_stat_br(proc, thread, cmd);
+   binder_stat_br(proc, thread, e->cmd);
} break;
case BINDER_WORK_TRANSACTION_COMPLETE: {
binder_inner_proc_unlock(proc);
-- 
2.14.0.434.g98096fd7a8-goog



Re: [PATCH v3 3/6] android: binder: Move buffer out of area shared with user space

2017-08-30 Thread Todd Kjos
I just went back through it -- turns out my email bounced back from
linux-kernel@vger.kernel.org (reason was "may contain a virus"). Sorry
I didn't notice that and resend.

On Wed, Aug 30, 2017 at 1:20 PM, Dan Carpenter  wrote:
> On Wed, Aug 30, 2017 at 01:04:31PM -0700, Arve Hjønnevåg wrote:
>> On Wed, Aug 30, 2017 at 2:29 AM, Dan Carpenter  
>> wrote:
>> > On Tue, Aug 29, 2017 at 05:46:59PM -0700, Sherry Yang wrote:
>> >> Binder driver allocates buffer meta data in a region that is mapped
>> >> in user space. These meta data contain pointers in the kernel.
>> >>
>> >> This patch allocates buffer meta data on the kernel heap that is
>> >> not mapped in user space, and uses a pointer to refer to the data mapped.
>> >>
>> >> Also move alloc->buffers initialization from mmap to init since it's
>> >> now used even when mmap failed or was not called.
>> >>
>> >> Signed-off-by: Sherry Yang 
>> >> ---
>> >
>> > The difference between v2 and v3 is that we've shifted some
>> > initialization around to fix the crashing bug that kbuild found.  You
>> > should not that difference here under the --- cut off.
>> >
>> >>  drivers/android/binder_alloc.c  | 146 
>> >> +++-
>> >>  drivers/android/binder_alloc.h  |   2 +-
>> >>  drivers/android/binder_alloc_selftest.c |  11 ++-
>> >>  3 files changed, 91 insertions(+), 68 deletions(-)
>> >
>> > But really we still need to have some answers or discussion about the
>> > questions that Greg and I raised.  Greg asked if the other Android devs
>> > had Acked this.  Please ping Arve to Ack this.
>> >
>> tk...@google.com replied and ack'ed v2. The changes have been reviewed
>> on android-review.googlesource.com. Do you want and ack or review tag
>> included in the patchset or do you want separate ack emails on each
>> patchset (or on each patch)?
>
> Just acking it once is fine.  I don't see that email from Todd in my
> inbox and can't find it on the web archive either...  Something must
> have gone wrong but I don't know what.
>
> regards,
> dan carpenter
>


Re: [PATCH] binder: fix memory corruption in binder_transaction binder

2017-09-11 Thread Todd Kjos
(resend in plain-text mode -- sorry about that)

Amit,

Are you sure this patch is the culprit? That is pretty surprising
since this change can only be hit in a uncommon case (the target node
is valid when we start creating the transaction, but dead when we
check right before sending it) so it is unlikely to be hit during a
normal boot. It also fixes a corruption -- so if you were actually
hitting the case, it would likely have caused issues before and not
now. Take a look at it and see if you think it is really possible.

I just booted hikey to Android with this patch 10 times in a row with
no issues (used hikey-linaro 4.9 kernel which has this patch).

-Todd

> On Mon, Sep 11, 2017 at 5:18 AM, Amit Pundir <amit.pun...@linaro.org> wrote:
>>
>> On 5 September 2017 at 22:51, Todd Kjos <tk...@android.com> wrote:
>> > From: Xu YiPing <xuyip...@hisilicon.com>
>> >
>> > commit 7a4408c6bd3e ("binder: make sure accesses to proc/thread are
>> > safe") made a change to enqueue tcomplete to thread->todo before
>> > enqueuing the transaction. However, in err_dead_proc_or_thread case,
>> > the tcomplete is directly freed, without dequeued. It may cause the
>> > thread->todo list to be corrupted.
>> >
>> > So, dequeue it before freeing.
>>
>> I see Android boot loops with this patch on hikey tracking
>> linux/master branch. 1st boot is fine but hikey runs into an
>> unexpected short boot loops on 2nd and successive boots.
>>
>> It takes about 3-4 iterations to finally come to sane state and boot
>> to UI. I don't see this behaviour if I revert this patch.
>>
>> Regards,
>> Amit Pundir
>>
>> >
>> > Signed-off-by: Xu YiPing <xuyip...@hisilicon.com>
>> > Signed-off-by: Todd Kjos <tk...@google.com>
>> > ---
>> >  drivers/android/binder.c | 1 +
>> >  1 file changed, 1 insertion(+)
>> >
>> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
>> > index d055b3f2a207..96cc28afa383 100644
>> > --- a/drivers/android/binder.c
>> > +++ b/drivers/android/binder.c
>> > @@ -3083,6 +3083,7 @@ static void binder_transaction(struct binder_proc
>> > *proc,
>> >  err_dead_proc_or_thread:
>> > return_error = BR_DEAD_REPLY;
>> > return_error_line = __LINE__;
>> > +   binder_dequeue_work(proc, tcomplete);
>> >  err_translate_failed:
>> >  err_bad_object_type:
>> >  err_bad_offset:
>> > --
>> > 2.14.1.581.gf28d330327-goog
>> >
>
>


[PATCH] binder: fix an ret value override

2017-09-05 Thread Todd Kjos
From: Xu YiPing <xuyip...@hisilicon.com>

commit 372e3147df70 ("binder: guarantee txn complete / errors delivered
in-order") incorrectly defined a local ret value.  This ret value will
be invalid when out of the if block

Signed-off-by: Xu YiPing <xuyip...@hislicon.com>
Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 96cc28afa383..7ef9e7f05e17 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2326,7 +2326,6 @@ static int binder_translate_handle(struct 
flat_binder_object *fp,
 (u64)node->ptr);
binder_node_unlock(node);
} else {
-   int ret;
struct binder_ref_data dest_rdata;
 
binder_node_unlock(node);
-- 
2.14.1.581.gf28d330327-goog



[PATCH] binder: fix memory corruption in binder_transaction binder

2017-09-05 Thread Todd Kjos
From: Xu YiPing <xuyip...@hisilicon.com>

commit 7a4408c6bd3e ("binder: make sure accesses to proc/thread are
safe") made a change to enqueue tcomplete to thread->todo before
enqueuing the transaction. However, in err_dead_proc_or_thread case,
the tcomplete is directly freed, without dequeued. It may cause the
thread->todo list to be corrupted.

So, dequeue it before freeing.

Signed-off-by: Xu YiPing <xuyip...@hisilicon.com>
Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d055b3f2a207..96cc28afa383 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3083,6 +3083,7 @@ static void binder_transaction(struct binder_proc *proc,
 err_dead_proc_or_thread:
return_error = BR_DEAD_REPLY;
return_error_line = __LINE__;
+   binder_dequeue_work(proc, tcomplete);
 err_translate_failed:
 err_bad_object_type:
 err_bad_offset:
-- 
2.14.1.581.gf28d330327-goog



Re: [PATCH] binder: fix memory corruption in binder_transaction binder

2017-09-11 Thread Todd Kjos
Amit,

I tested with 
https://android-git.linaro.org/kernel/linaro-android.git/log/?h=test/hikey-llct.
I added a pr_info() above the patch's single line change and in
binder_init (so I could easily prove that I was running the correct
kernel).

First I did 10 reboots with the patch. I saw one failure to reach the
Android home screen in boot #7 (but the new line of code was never
reached, so the patch cannot be the cause)... so 9 out of 10 reboots
were fine and the failure does not point to this patch.

Then I did 10 reboots without the patch. No failures.

Then 10 more with the patch. No failures.

Then with the patch: power-on, reboot twice, no failures (repeat, no failures).

I think the issue you are seeing cannot be caused by this patch --
take a look at it and see if you think its really possible...

-Todd

On Mon, Sep 11, 2017 at 9:55 AM, Amit Pundir <amit.pun...@linaro.org> wrote:
> Hi Todd,
>
> On 11 September 2017 at 21:10, Todd Kjos <tk...@google.com> wrote:
>> (resend in plain-text mode -- sorry about that)
>>
>> Amit,
>>
>> Are you sure this patch is the culprit? That is pretty surprising
>> since this change can only be hit in a uncommon case (the target node
>> is valid when we start creating the transaction, but dead when we
>> check right before sending it) so it is unlikely to be hit during a
>> normal boot. It also fixes a corruption -- so if you were actually
>> hitting the case, it would likely have caused issues before and not
>> now. Take a look at it and see if you think it is really possible.
>>
>> I just booted hikey to Android with this patch 10 times in a row with
>> no issues (used hikey-linaro 4.9 kernel which has this patch).
>
> Sorry for not being clear enough in the bug report. android-4.9 is
> fine, I see this issue on linux mainline tree with this patch.
>
> I can reproduce it on John's minimal Android tree for hikey hosted
> here 
> https://git.linaro.org/people/john.stultz/android-dev.git/log/?h=dev/hikey-mainline-WIP
> and hikey-llct (android-4.9 patchset rebased to mainline) tree hosted
> here 
> https://android-git.linaro.org/kernel/linaro-android.git/log/?h=test/hikey-llct.
> I have already reverted this patch in hikey-llct so you have to revert
> that revert to reproduce this issue on hikey-llct tree.
>
> Regards,
> Amit Pundir
>
>>
>> -Todd
>>
>>> On Mon, Sep 11, 2017 at 5:18 AM, Amit Pundir <amit.pun...@linaro.org> wrote:
>>>>
>>>> On 5 September 2017 at 22:51, Todd Kjos <tk...@android.com> wrote:
>>>> > From: Xu YiPing <xuyip...@hisilicon.com>
>>>> >
>>>> > commit 7a4408c6bd3e ("binder: make sure accesses to proc/thread are
>>>> > safe") made a change to enqueue tcomplete to thread->todo before
>>>> > enqueuing the transaction. However, in err_dead_proc_or_thread case,
>>>> > the tcomplete is directly freed, without dequeued. It may cause the
>>>> > thread->todo list to be corrupted.
>>>> >
>>>> > So, dequeue it before freeing.
>>>>
>>>> I see Android boot loops with this patch on hikey tracking
>>>> linux/master branch. 1st boot is fine but hikey runs into an
>>>> unexpected short boot loops on 2nd and successive boots.
>>>>
>>>> It takes about 3-4 iterations to finally come to sane state and boot
>>>> to UI. I don't see this behaviour if I revert this patch.
>>>>
>>>> Regards,
>>>> Amit Pundir
>>>>
>>>> >
>>>> > Signed-off-by: Xu YiPing <xuyip...@hisilicon.com>
>>>> > Signed-off-by: Todd Kjos <tk...@google.com>
>>>> > ---
>>>> >  drivers/android/binder.c | 1 +
>>>> >  1 file changed, 1 insertion(+)
>>>> >
>>>> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
>>>> > index d055b3f2a207..96cc28afa383 100644
>>>> > --- a/drivers/android/binder.c
>>>> > +++ b/drivers/android/binder.c
>>>> > @@ -3083,6 +3083,7 @@ static void binder_transaction(struct binder_proc
>>>> > *proc,
>>>> >  err_dead_proc_or_thread:
>>>> > return_error = BR_DEAD_REPLY;
>>>> > return_error_line = __LINE__;
>>>> > +   binder_dequeue_work(proc, tcomplete);
>>>> >  err_translate_failed:
>>>> >  err_bad_object_type:
>>>> >  err_bad_offset:
>>>> > --
>>>> > 2.14.1.581.gf28d330327-goog
>>>> >
>>>
>>>


[PATCH] binder: fix use-after-free in binder_transaction()

2017-09-29 Thread Todd Kjos
User-space normally keeps the node alive when creating a transaction
since it has a reference to the target. The local strong ref keeps it
alive if the sending process dies before the target process processes
the transaction. If the source process is malicious or has a reference
counting bug, this can fail.

In this case, when we attempt to decrement the node in the failure
path, the node has already been freed.

This is fixed by taking a tmpref on the node while constructing
the transaction. To avoid re-acquiring the node lock and inner
proc lock to increment the proc's tmpref, a helper is used that
does the ref increments on both the node and proc.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 93 ++--
 1 file changed, 66 insertions(+), 27 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d055b3f2a207..40e8a58391cc 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2583,6 +2583,48 @@ static bool binder_proc_transaction(struct 
binder_transaction *t,
return true;
 }
 
+/**
+ * binder_get_node_refs_for_txn() - Get required refs on node for txn
+ * @node: struct binder_node for which to get refs
+ * @proc: returns @node->proc if valid
+ * @error:if no @proc then returns BR_DEAD_REPLY
+ *
+ * User-space normally keeps the node alive when creating a transaction
+ * since it has a reference to the target. The local strong ref keeps it
+ * alive if the sending process dies before the target process processes
+ * the transaction. If the source process is malicious or has a reference
+ * counting bug, relying on the local strong ref can fail.
+ *
+ * Since user-space can cause the local strong ref to go away, we also take
+ * a tmpref on the node to ensure it survives while we are constructing
+ * the transaction. We also need a tmpref on the proc while we are
+ * constructing the transaction, so we take that here as well.
+ *
+ * Return: The target_node with refs taken or NULL if no @node->proc is NULL.
+ * Also sets @proc if valid. If the @node->proc is NULL indicating that the
+ * target proc has died, @error is set to BR_DEAD_REPLY
+ */
+static struct binder_node *binder_get_node_refs_for_txn(
+   struct binder_node *node,
+   struct binder_proc **procp,
+   uint32_t *error)
+{
+   struct binder_node *target_node = NULL;
+
+   binder_node_inner_lock(node);
+   if (node->proc) {
+   target_node = node;
+   binder_inc_node_nilocked(node, 1, 0, NULL);
+   binder_inc_node_tmpref_ilocked(node);
+   node->proc->tmp_ref++;
+   *procp = node->proc;
+   } else
+   *error = BR_DEAD_REPLY;
+   binder_node_inner_unlock(node);
+
+   return target_node;
+}
+
 static void binder_transaction(struct binder_proc *proc,
   struct binder_thread *thread,
   struct binder_transaction_data *tr, int reply,
@@ -2686,43 +2728,35 @@ static void binder_transaction(struct binder_proc *proc,
ref = binder_get_ref_olocked(proc, tr->target.handle,
 true);
if (ref) {
-   binder_inc_node(ref->node, 1, 0, NULL);
-   target_node = ref->node;
-   }
-   binder_proc_unlock(proc);
-   if (target_node == NULL) {
+   target_node = binder_get_node_refs_for_txn(
+   ref->node, _proc,
+   _error);
+   } else {
binder_user_error("%d:%d got transaction to 
invalid handle\n",
-   proc->pid, thread->pid);
+ proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
-   return_error_param = -EINVAL;
-   return_error_line = __LINE__;
-   goto err_invalid_target_handle;
}
+   binder_proc_unlock(proc);
} else {
mutex_lock(>context_mgr_node_lock);
target_node = context->binder_context_mgr_node;
-   if (target_node == NULL) {
+   if (target_node)
+   target_node = binder_get_node_refs_for_txn(
+   target_node, _proc,
+   _error);
+   else
return_error = BR_DEAD_REPLY;

[PATCH] binder: fix proc->files use-after-free

2017-11-14 Thread Todd Kjos
proc->files cleanup is initiated by binder_vma_close. Therefore
a reference on the binder_proc is not enough to prevent the
files_struct from being released while the binder_proc still has
a reference. This can lead to an attempt to dereference the
stale pointer obtained from proc->files prior to proc->files
cleanup. This has been seen once in task_get_unused_fd_flags()
when __alloc_fd() is called with a stale "files".

The fix is to always use get_files_struct() to obtain struct_files
so that the refcount on the files_struct is used to prevent
a premature free. proc->files is removed since we get it every
time.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 63 +++-
 1 file changed, 30 insertions(+), 33 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index fddf76ef5bd6..794e58c14b15 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -458,9 +458,8 @@ struct binder_ref {
 };
 
 enum binder_deferred_state {
-   BINDER_DEFERRED_PUT_FILES= 0x01,
-   BINDER_DEFERRED_FLUSH= 0x02,
-   BINDER_DEFERRED_RELEASE  = 0x04,
+   BINDER_DEFERRED_FLUSH= 0x01,
+   BINDER_DEFERRED_RELEASE  = 0x02,
 };
 
 /**
@@ -481,8 +480,6 @@ enum binder_deferred_state {
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
- * @files files_struct for process
- *(invariant after initialized)
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -529,7 +526,6 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
-   struct files_struct *files;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -875,22 +871,34 @@ static void binder_free_thread(struct binder_thread 
*thread);
 static void binder_free_proc(struct binder_proc *proc);
 static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
+struct files_struct *binder_get_files_struct(struct binder_proc *proc)
+{
+   return get_files_struct(proc->tsk);
+}
+
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
-   struct files_struct *files = proc->files;
+   struct files_struct *files;
unsigned long rlim_cur;
unsigned long irqs;
+   int ret;
 
+   files = binder_get_files_struct(proc);
if (files == NULL)
return -ESRCH;
 
-   if (!lock_task_sighand(proc->tsk, ))
-   return -EMFILE;
+   if (!lock_task_sighand(proc->tsk, )) {
+   ret = -EMFILE;
+   goto err;
+   }
 
rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
unlock_task_sighand(proc->tsk, );
 
-   return __alloc_fd(files, 0, rlim_cur, flags);
+   ret = __alloc_fd(files, 0, rlim_cur, flags);
+err:
+   put_files_struct(files);
+   return ret;
 }
 
 /*
@@ -899,8 +907,12 @@ static int task_get_unused_fd_flags(struct binder_proc 
*proc, int flags)
 static void task_fd_install(
struct binder_proc *proc, unsigned int fd, struct file *file)
 {
-   if (proc->files)
-   __fd_install(proc->files, fd, file);
+   struct files_struct *files = binder_get_files_struct(proc);
+
+   if (files) {
+   __fd_install(files, fd, file);
+   put_files_struct(files);
+   }
 }
 
 /*
@@ -908,18 +920,20 @@ static void task_fd_install(
  */
 static long task_close_fd(struct binder_proc *proc, unsigned int fd)
 {
+   struct files_struct *files = binder_get_files_struct(proc);
int retval;
 
-   if (proc->files == NULL)
+   if (files == NULL)
return -ESRCH;
 
-   retval = __close_fd(proc->files, fd);
+   retval = __close_fd(files, fd);
/* can't restart close syscall because file table entry was cleared */
if (unlikely(retval == -ERESTARTSYS ||
 retval == -ERESTARTNOINTR ||
 retval == -ERESTARTNOHAND ||
 retval == -ERESTART_RESTARTBLOCK))
retval = -EINTR;
+   put_files_struct(files);
 
return retval;
 }
@@ -4561,7 +4575,6 @@ static void binder_vma_close(struct vm_area_struct *vma)
 (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
 (unsigned long)pgprot_val(vma->vm_page_prot));
binder_alloc_vma_close(>alloc);
-   binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
 }
 
 static int binder_vm_fault(struct vm_fault *vmf)
@@ -4603,10 +4616,8 @@ static int binder_mmap(struct file *filp, struct

[PATCH v3] binder: fix proc->files use-after-free

2017-11-27 Thread Todd Kjos
proc->files cleanup is initiated by binder_vma_close. Therefore
a reference on the binder_proc is not enough to prevent the
files_struct from being released while the binder_proc still has
a reference. This can lead to an attempt to dereference the
stale pointer obtained from proc->files prior to proc->files
cleanup. This has been seen once in task_get_unused_fd_flags()
when __alloc_fd() is called with a stale "files".

The fix is to protect proc->files with a mutex to prevent cleanup
while in use.

Signed-off-by: Todd Kjos <tk...@google.com>
---
v2: declare binder_get_files_struct as static
v3: rework to protect proc->files with a mutex instead of using get_files_struct

Also needed in 4.14

 drivers/android/binder.c | 44 +++-
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a73596a4f804..7c027ee61375 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -482,7 +482,8 @@ enum binder_deferred_state {
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
  * @files files_struct for process
- *(invariant after initialized)
+ *(protected by @files_lock)
+ * @files_lockmutex to protect @files
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -530,6 +531,7 @@ struct binder_proc {
int pid;
struct task_struct *tsk;
struct files_struct *files;
+   struct mutex files_lock;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -877,20 +879,26 @@ static void binder_inc_node_tmpref_ilocked(struct 
binder_node *node);
 
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
-   struct files_struct *files = proc->files;
unsigned long rlim_cur;
unsigned long irqs;
+   int ret;
 
-   if (files == NULL)
-   return -ESRCH;
-
-   if (!lock_task_sighand(proc->tsk, ))
-   return -EMFILE;
-
+   mutex_lock(>files_lock);
+   if (proc->files == NULL) {
+   ret = -ESRCH;
+   goto err;
+   }
+   if (!lock_task_sighand(proc->tsk, )) {
+   ret = -EMFILE;
+   goto err;
+   }
rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
unlock_task_sighand(proc->tsk, );
 
-   return __alloc_fd(files, 0, rlim_cur, flags);
+   ret = __alloc_fd(proc->files, 0, rlim_cur, flags);
+err:
+   mutex_unlock(>files_lock);
+   return ret;
 }
 
 /*
@@ -899,8 +907,10 @@ static int task_get_unused_fd_flags(struct binder_proc 
*proc, int flags)
 static void task_fd_install(
struct binder_proc *proc, unsigned int fd, struct file *file)
 {
+   mutex_lock(>files_lock);
if (proc->files)
__fd_install(proc->files, fd, file);
+   mutex_unlock(>files_lock);
 }
 
 /*
@@ -910,9 +920,11 @@ static long task_close_fd(struct binder_proc *proc, 
unsigned int fd)
 {
int retval;
 
-   if (proc->files == NULL)
-   return -ESRCH;
-
+   mutex_lock(>files_lock);
+   if (proc->files == NULL) {
+   retval = -ESRCH;
+   goto err;
+   }
retval = __close_fd(proc->files, fd);
/* can't restart close syscall because file table entry was cleared */
if (unlikely(retval == -ERESTARTSYS ||
@@ -920,7 +932,8 @@ static long task_close_fd(struct binder_proc *proc, 
unsigned int fd)
 retval == -ERESTARTNOHAND ||
 retval == -ERESTART_RESTARTBLOCK))
retval = -EINTR;
-
+err:
+   mutex_unlock(>files_lock);
return retval;
 }
 
@@ -4605,7 +4618,9 @@ static int binder_mmap(struct file *filp, struct 
vm_area_struct *vma)
ret = binder_alloc_mmap_handler(>alloc, vma);
if (ret)
return ret;
+   mutex_lock(>files_lock);
proc->files = get_files_struct(current);
+   mutex_unlock(>files_lock);
return 0;
 
 err_bad_arg:
@@ -4629,6 +4644,7 @@ static int binder_open(struct inode *nodp, struct file 
*filp)
spin_lock_init(>outer_lock);
get_task_struct(current->group_leader);
proc->tsk = current->group_leader;
+   mutex_init(>files_lock);
INIT_LIST_HEAD(>todo);
proc->default_priority = task_nice(current);
binder_dev = container_of(filp->private_data, struct binder_device,
@@ -4881,9 +4897,11 @@ static void binder_deferred_func(struct work_struct 
*work)
 
files = NULL;
if (defer & BINDER_DEFERRED_PUT_FILES) {
+ 

Re: [PATCH v2] binder: fix proc->files use-after-free

2017-11-20 Thread Todd Kjos
Al, thanks for the detailed feedback. I didn't know about these rules
(are they written down somewhere?). I'll rework this and post a
compliant v3.

On Fri, Nov 17, 2017 at 11:31 AM, Al Viro <v...@zeniv.linux.org.uk> wrote:
> On Thu, Nov 16, 2017 at 09:56:50AM -0800, Todd Kjos wrote:
>
>> +static struct files_struct *binder_get_files_struct(struct binder_proc 
>> *proc)
>> +{
>> + return get_files_struct(proc->tsk);
>> +}
>
> Hell, _no_.  You should never, ever use the result of get_files_struct() for
> write access.  It's strictly for "let me look at other process' descriptor
> table".  The whole reason for proc->files is that we want to keep a reference
> that *could* be used for modifying the damn thing.  And such can be obtained
> only by the process itself.
>
> The rules are:
> * you can use current->files both for read and write
> * you can use get_files_struct(current) to get a reference that
> can be used for modifying the damn thing.  Then it can be passed to
> any other process and used by it.
> * you can use get_files_struct(some_other_task) to get a reference
> that can be used for examining the descriptor table of that other task.
>
> Violation of those rules means an exploitable race.  Here's the logics
> fdget() and friends are based on: "I'm going to do something to file
> refered by descriptor N.  If my descriptor table is not shared, all
> struct file references in it will stay around - I'm not changing it,
> nobody else has it as their ->current, so any additional references
> to that descriptor table will *not* be used for modifying it.
> In other words, I don't need to bump the refcount of struct file I'm
> about to work with - the reference from my descriptor table will keep
> it alive".
>
> Your patch breaks those assumptions.  NAK.


Re: [PATCH] binder: fix proc->files use-after-free

2017-11-16 Thread Todd Kjos
> @@ -875,22 +871,34 @@ static void binder_free_thread(struct binder_thread 
> *thread);
>  static void binder_free_proc(struct binder_proc *proc);
>  static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
>
> +struct files_struct *binder_get_files_struct(struct binder_proc *proc)

This should be declared static:
  static struct files_struct *binder_get_files_struct(struct binder_proc *proc)

Greg- should I send a "v2" for this?

> +{
> +   return get_files_struct(proc->tsk);
> +}
> +


[PATCH v2] binder: fix proc->files use-after-free

2017-11-16 Thread Todd Kjos
proc->files cleanup is initiated by binder_vma_close. Therefore
a reference on the binder_proc is not enough to prevent the
files_struct from being released while the binder_proc still has
a reference. This can lead to an attempt to dereference the
stale pointer obtained from proc->files prior to proc->files
cleanup. This has been seen once in task_get_unused_fd_flags()
when __alloc_fd() is called with a stale "files".

The fix is to always use get_files_struct() to obtain struct_files
so that the refcount on the files_struct is used to prevent
a premature free. proc->files is removed since we get it every
time.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 63 +++-
 1 file changed, 30 insertions(+), 33 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index fddf76ef5bd6..ea07b35fb533 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -458,9 +458,8 @@ struct binder_ref {
 };
 
 enum binder_deferred_state {
-   BINDER_DEFERRED_PUT_FILES= 0x01,
-   BINDER_DEFERRED_FLUSH= 0x02,
-   BINDER_DEFERRED_RELEASE  = 0x04,
+   BINDER_DEFERRED_FLUSH= 0x01,
+   BINDER_DEFERRED_RELEASE  = 0x02,
 };
 
 /**
@@ -481,8 +480,6 @@ enum binder_deferred_state {
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
- * @files files_struct for process
- *(invariant after initialized)
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -529,7 +526,6 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
-   struct files_struct *files;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -875,22 +871,34 @@ static void binder_free_thread(struct binder_thread 
*thread);
 static void binder_free_proc(struct binder_proc *proc);
 static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
+static struct files_struct *binder_get_files_struct(struct binder_proc *proc)
+{
+   return get_files_struct(proc->tsk);
+}
+
 static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 {
-   struct files_struct *files = proc->files;
+   struct files_struct *files;
unsigned long rlim_cur;
unsigned long irqs;
+   int ret;
 
+   files = binder_get_files_struct(proc);
if (files == NULL)
return -ESRCH;
 
-   if (!lock_task_sighand(proc->tsk, ))
-   return -EMFILE;
+   if (!lock_task_sighand(proc->tsk, )) {
+   ret = -EMFILE;
+   goto err;
+   }
 
rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
unlock_task_sighand(proc->tsk, );
 
-   return __alloc_fd(files, 0, rlim_cur, flags);
+   ret = __alloc_fd(files, 0, rlim_cur, flags);
+err:
+   put_files_struct(files);
+   return ret;
 }
 
 /*
@@ -899,8 +907,12 @@ static int task_get_unused_fd_flags(struct binder_proc 
*proc, int flags)
 static void task_fd_install(
struct binder_proc *proc, unsigned int fd, struct file *file)
 {
-   if (proc->files)
-   __fd_install(proc->files, fd, file);
+   struct files_struct *files = binder_get_files_struct(proc);
+
+   if (files) {
+   __fd_install(files, fd, file);
+   put_files_struct(files);
+   }
 }
 
 /*
@@ -908,18 +920,20 @@ static void task_fd_install(
  */
 static long task_close_fd(struct binder_proc *proc, unsigned int fd)
 {
+   struct files_struct *files = binder_get_files_struct(proc);
int retval;
 
-   if (proc->files == NULL)
+   if (files == NULL)
return -ESRCH;
 
-   retval = __close_fd(proc->files, fd);
+   retval = __close_fd(files, fd);
/* can't restart close syscall because file table entry was cleared */
if (unlikely(retval == -ERESTARTSYS ||
 retval == -ERESTARTNOINTR ||
 retval == -ERESTARTNOHAND ||
 retval == -ERESTART_RESTARTBLOCK))
retval = -EINTR;
+   put_files_struct(files);
 
return retval;
 }
@@ -4561,7 +4575,6 @@ static void binder_vma_close(struct vm_area_struct *vma)
 (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
 (unsigned long)pgprot_val(vma->vm_page_prot));
binder_alloc_vma_close(>alloc);
-   binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
 }
 
 static int binder_vm_fault(struct vm_fault *vmf)
@@ -4603,10 +4616,8 @@ static int binder_mmap(struct fil

Re: [PATCH v2] binder: fix proc->files use-after-free

2017-11-16 Thread Todd Kjos
Sorry about that, do you want a v3 with correct annotations?

On Thu, Nov 16, 2017 at 12:27 PM, Greg KH <gre...@linuxfoundation.org> wrote:
> On Thu, Nov 16, 2017 at 09:56:50AM -0800, Todd Kjos wrote:
>> proc->files cleanup is initiated by binder_vma_close. Therefore
>> a reference on the binder_proc is not enough to prevent the
>> files_struct from being released while the binder_proc still has
>> a reference. This can lead to an attempt to dereference the
>> stale pointer obtained from proc->files prior to proc->files
>> cleanup. This has been seen once in task_get_unused_fd_flags()
>> when __alloc_fd() is called with a stale "files".
>>
>> The fix is to always use get_files_struct() to obtain struct_files
>> so that the refcount on the files_struct is used to prevent
>> a premature free. proc->files is removed since we get it every
>> time.
>>
>> Signed-off-by: Todd Kjos <tk...@google.com>
>> ---
>>  drivers/android/binder.c | 63 
>> +++-
>>  1 file changed, 30 insertions(+), 33 deletions(-)
>
> For a v2 patch (or v3 or whatever), you need to put below the --- line
> what changed from the previous version(s).
> Documentation/SubmittingPatches describes this pretty well :)
>
> thanks,
>
> greg k-h


Re: [PATCH 1/2] sched: force update of blocked load of idle cpus

2017-11-09 Thread Todd Kjos
> @@ -8683,6 +8692,10 @@ static void nohz_balancer_kick(void)
>
> if (test_and_set_bit(NOHZ_BALANCE_KICK, nohz_flags(ilb_cpu)))
> return;
> +
> +   if (only_update)
> +   set_bit(NOHZ_STATS_KICK, nohz_flags(ilb_cpu));

Should there be an "else clear_bit(NOHZ_STATS_KICK, nohz_flags(ilb_cpu));" ?

Seems like any time this is called as !only_update, we should stop
inhibiting rebalance. In fact, we should perhaps go a little further
so that an only_update never inhibits rebalance from a concurrent
!only_update.


Re: [PATCH v3] binder: fix proc->files use-after-free

2017-12-11 Thread Todd Kjos
Greg- when this is in, we'll want it in 4.14 as well.

On Mon, Nov 27, 2017 at 9:32 AM, Todd Kjos <tk...@android.com> wrote:
> proc->files cleanup is initiated by binder_vma_close. Therefore
> a reference on the binder_proc is not enough to prevent the
> files_struct from being released while the binder_proc still has
> a reference. This can lead to an attempt to dereference the
> stale pointer obtained from proc->files prior to proc->files
> cleanup. This has been seen once in task_get_unused_fd_flags()
> when __alloc_fd() is called with a stale "files".
>
> The fix is to protect proc->files with a mutex to prevent cleanup
> while in use.
>
> Signed-off-by: Todd Kjos <tk...@google.com>
> ---
> v2: declare binder_get_files_struct as static
> v3: rework to protect proc->files with a mutex instead of using 
> get_files_struct
>
> Also needed in 4.14
>
>  drivers/android/binder.c | 44 +++-
>  1 file changed, 31 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index a73596a4f804..7c027ee61375 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -482,7 +482,8 @@ enum binder_deferred_state {
>   * @tsk   task_struct for group_leader of process
>   *(invariant after initialized)
>   * @files files_struct for process
> - *(invariant after initialized)
> + *(protected by @files_lock)
> + * @files_lockmutex to protect @files
>   * @deferred_work_node:   element for binder_deferred_list
>   *(protected by binder_deferred_lock)
>   * @deferred_work:bitmap of deferred work to perform
> @@ -530,6 +531,7 @@ struct binder_proc {
> int pid;
> struct task_struct *tsk;
> struct files_struct *files;
> +   struct mutex files_lock;
> struct hlist_node deferred_work_node;
> int deferred_work;
> bool is_dead;
> @@ -877,20 +879,26 @@ static void binder_inc_node_tmpref_ilocked(struct 
> binder_node *node);
>
>  static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
>  {
> -   struct files_struct *files = proc->files;
> unsigned long rlim_cur;
> unsigned long irqs;
> +   int ret;
>
> -   if (files == NULL)
> -   return -ESRCH;
> -
> -   if (!lock_task_sighand(proc->tsk, ))
> -   return -EMFILE;
> -
> +   mutex_lock(>files_lock);
> +   if (proc->files == NULL) {
> +   ret = -ESRCH;
> +   goto err;
> +   }
> +   if (!lock_task_sighand(proc->tsk, )) {
> +   ret = -EMFILE;
> +   goto err;
> +   }
> rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
> unlock_task_sighand(proc->tsk, );
>
> -   return __alloc_fd(files, 0, rlim_cur, flags);
> +   ret = __alloc_fd(proc->files, 0, rlim_cur, flags);
> +err:
> +   mutex_unlock(>files_lock);
> +   return ret;
>  }
>
>  /*
> @@ -899,8 +907,10 @@ static int task_get_unused_fd_flags(struct binder_proc 
> *proc, int flags)
>  static void task_fd_install(
> struct binder_proc *proc, unsigned int fd, struct file *file)
>  {
> +   mutex_lock(>files_lock);
> if (proc->files)
> __fd_install(proc->files, fd, file);
> +   mutex_unlock(>files_lock);
>  }
>
>  /*
> @@ -910,9 +920,11 @@ static long task_close_fd(struct binder_proc *proc, 
> unsigned int fd)
>  {
> int retval;
>
> -   if (proc->files == NULL)
> -   return -ESRCH;
> -
> +   mutex_lock(>files_lock);
> +   if (proc->files == NULL) {
> +   retval = -ESRCH;
> +   goto err;
> +   }
> retval = __close_fd(proc->files, fd);
> /* can't restart close syscall because file table entry was cleared */
> if (unlikely(retval == -ERESTARTSYS ||
> @@ -920,7 +932,8 @@ static long task_close_fd(struct binder_proc *proc, 
> unsigned int fd)
>  retval == -ERESTARTNOHAND ||
>  retval == -ERESTART_RESTARTBLOCK))
> retval = -EINTR;
> -
> +err:
> +   mutex_unlock(>files_lock);
> return retval;
>  }
>
> @@ -4605,7 +4618,9 @@ static int binder_mmap(struct file *filp, struct 
> vm_area_struct *vma)
> ret = binder_alloc_mmap_handler(>alloc, vma);
> if (ret)
> return ret;
> +   mutex_lock(>files_lock

Re: [PATCH] ANDROID: binder: correct the cmd print for BINDER_WORK_RETURN_ERROR

2018-05-09 Thread Todd Kjos
On Wed, May 9, 2018 at 12:31 AM 宋金时  wrote:

> In case of the BINDER_WORK_RETURN_ERROR the cmd is no assignment,
> so it's value will be old value or dirty value, before modifying
> e->cmd, assign the value of the e->cmd to cmd to ensure the correct
> print of binder_stat_br.


That's not the problem... the problem is that e->cmd is unconditionally set
to BR_OK prior to the call to binder_stat_br(proc, thread, e->cmd) so the
reported cmd is always BR_OK.


> Signed-off-by: songjinshi 
> ---

> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 4ffc84d..acd7d44a 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -4086,6 +4086,7 @@
>  struct binder_error *e = container_of(
>  w, struct binder_error, work);

> +   cmd = e->cmd;
>  WARN_ON(e->cmd == BR_OK);
>  binder_inner_proc_unlock(proc);
>  if (put_user(e->cmd, (uint32_t __user *)ptr))


Don't you also need to use cmd in the call to binder_state_br() below?

-   binder_stat_br(proc, thread, e->cmd);
+   binder_stat_br(proc, thread, cmd);

-Todd


Re: [PATCH] binder: check for binder_thread allocation failure in binder_poll()

2018-01-31 Thread Todd Kjos
Looks good to me.

On Tue, Jan 30, 2018 at 11:11 PM, Eric Biggers  wrote:
> From: Eric Biggers 
>
> If the kzalloc() in binder_get_thread() fails, binder_poll()
> dereferences the resulting NULL pointer.
>
> Fix it by returning POLLERR if the memory allocation failed.
>
> This bug was found by syzkaller using fault injection.
>
> Reported-by: syzbot 
> Fixes: 457b9a6f09f0 ("Staging: android: add binder driver")
> Cc: sta...@vger.kernel.org
> Signed-off-by: Eric Biggers 
> ---
>  drivers/android/binder.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index d21040c5d343f..326ca8ea9ebcf 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -4391,6 +4391,8 @@ static __poll_t binder_poll(struct file *filp,
> bool wait_for_proc_work;
>
> thread = binder_get_thread(proc);
> +   if (!thread)
> +   return POLLERR;
>
> binder_inner_proc_lock(thread->proc);
> thread->looper |= BINDER_LOOPER_STATE_POLL;
> --
> 2.16.1
>


[PATCH] ANDROID: binder: remove WARN() for redundant txn error

2018-02-07 Thread Todd Kjos
binder_send_failed_reply() is called when a synchronous
transaction fails. It reports an error to the thread that
is waiting for the completion. Given that the transaction
is synchronous, there should never be more than 1 error
response to that thread -- this was being asserted with
a WARN().

However, when exercising the driver with syzbot tests, cases
were observed where multiple "synchronous" requests were
sent without waiting for responses, so it is possible that
multiple errors would be reported to the thread. This testing
was conducted with panic_on_warn set which forced the crash.

This is easily reproduced by sending back-to-back
"synchronous" transactions without checking for any
response (eg, set read_size to 0):

bwr.write_buffer = (uintptr_t)
bwr.write_size = sizeof(bc1);
bwr.read_buffer = (uintptr_t)
bwr.read_size = 0;
ioctl(fd, BINDER_WRITE_READ, );
sleep(1);
bwr2.write_buffer = (uintptr_t)
bwr2.write_size = sizeof(bc2);
bwr2.read_buffer = (uintptr_t)
bwr2.read_size = 0;
ioctl(fd, BINDER_WRITE_READ, );
sleep(1);

The first transaction is sent to the servicemanager and the reply
fails because no VMA is set up by this client. After
binder_send_failed_reply() is called, the BINDER_WORK_RETURN_ERROR
is sitting on the thread's todo list since the read_size was 0 and
the client is not waiting for a response.

The 2nd transaction is sent and the BINDER_WORK_RETURN_ERROR has not
been consumed, so the thread's reply_error.cmd is still set (normally
cleared when the BINDER_WORK_RETURN_ERROR is handled). Therefore
when the servicemanager attempts to reply to the 2nd failed
transaction, the error is already set and it triggers this warning.

This is a user error since it is not waiting for the synchronous
transaction to complete. If it ever does check, it will see an
error.

Changed the WARN() to a pr_warn().

Signed-off-by: Todd Kjos <tk...@android.com>
Reported-by: syzbot <syzkal...@googlegroups.com>
---
 drivers/android/binder.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a7ecfde66b7b..37289683939c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1933,8 +1933,14 @@ static void binder_send_failed_reply(struct 
binder_transaction *t,
_thread->todo);
wake_up_interruptible(_thread->wait);
} else {
-   WARN(1, "Unexpected reply error: %u\n",
-   target_thread->reply_error.cmd);
+   /*
+* Cannot get here for normal operation, but
+* we can if multiple synchronous transactions
+* are sent without blocking for responses.
+* Just ignore the 2nd error in this case.
+*/
+   pr_warn("Unexpected reply error: %u\n",
+   target_thread->reply_error.cmd);
}
binder_inner_proc_unlock(target_thread->proc);
binder_thread_dec_tmpref(target_thread);
-- 
2.16.0.rc1.238.g530d649a79-goog



[PATCH] binder: replace "%p" with "%pK"

2018-02-07 Thread Todd Kjos
The format specifier "%p" can leak kernel addresses. Use
"%pK" instead. There were 4 remaining cases in binder.c.

Signed-off-by: Todd Kjos <tk...@google.com>
---
 drivers/android/binder.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 37289683939c..7da09b10dae8 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2141,7 +2141,7 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
int debug_id = buffer->debug_id;
 
binder_debug(BINDER_DEBUG_TRANSACTION,
-"%d buffer release %d, size %zd-%zd, failed at %p\n",
+"%d buffer release %d, size %zd-%zd, failed at %pK\n",
 proc->pid, buffer->debug_id,
 buffer->data_size, buffer->offsets_size, failed_at);
 
@@ -3653,7 +3653,7 @@ static int binder_thread_write(struct binder_proc *proc,
}
}
binder_debug(BINDER_DEBUG_DEAD_BINDER,
-"%d:%d BC_DEAD_BINDER_DONE %016llx found 
%p\n",
+"%d:%d BC_DEAD_BINDER_DONE %016llx found 
%pK\n",
 proc->pid, thread->pid, (u64)cookie,
 death);
if (death == NULL) {
@@ -4968,7 +4968,7 @@ static void print_binder_transaction_ilocked(struct 
seq_file *m,
spin_lock(>lock);
to_proc = t->to_proc;
seq_printf(m,
-  "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+  "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld 
r%d",
   prefix, t->debug_id, t,
   t->from ? t->from->proc->pid : 0,
   t->from ? t->from->pid : 0,
@@ -4992,7 +4992,7 @@ static void print_binder_transaction_ilocked(struct 
seq_file *m,
}
if (buffer->target_node)
seq_printf(m, " node %d", buffer->target_node->debug_id);
-   seq_printf(m, " size %zd:%zd data %p\n",
+   seq_printf(m, " size %zd:%zd data %pK\n",
   buffer->data_size, buffer->offsets_size,
   buffer->data);
 }
-- 
2.16.0.rc1.238.g530d649a79-goog



Re: KASAN: use-after-free Read in remove_wait_queue

2018-02-12 Thread Todd Kjos
On Mon, Feb 12, 2018 at 7:57 AM, Dmitry Vyukov  wrote:
>
> On Mon, Feb 12, 2018 at 4:54 PM, syzbot
>  wrote:
> > Hello,
> >
> > syzbot hit the following crash on upstream commit
> > f1517df8701c9f12dae9ce7f43a5d300a6917619 (Thu Feb 8 23:18:32 2018 +)
> > Merge tag 'nfsd-4.16' of git://linux-nfs.org/~bfields/linux
> >
> > So far this crash happened 3 times on upstream.
> > C reproducer is attached.
> > syzkaller reproducer is attached.
> > Raw console output is attached.
> > compiler: gcc (GCC) 7.1.1 20170620
> > .config is attached.
> > user-space arch: i386
>
> This seems to be binder, so +binder maintainers.


There's a fix queued for 4.16: https://patchwork.kernel.org/patch/10146253/

>
>
> > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > Reported-by: syzbot+a2a3c4909716e2714...@syzkaller.appspotmail.com
> > It will help syzbot understand when the bug is fixed. See footer for
> > details.
> > If you forward the report, please keep this part and the footer.
> >
> > ==
> > BUG: KASAN: use-after-free in debug_spin_lock_before
> > kernel/locking/spinlock_debug.c:83 [inline]
> > BUG: KASAN: use-after-free in do_raw_spin_lock+0x1e0/0x220
> > kernel/locking/spinlock_debug.c:112
> > Read of size 4 at addr 8801db1608a4 by task syzkaller818560/5118
> >
> > CPU: 1 PID: 5118 Comm: syzkaller818560 Not tainted 4.15.0+ #215
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> > Google 01/01/2011
> > Call Trace:
> >  __dump_stack lib/dump_stack.c:17 [inline]
> >  dump_stack+0x194/0x257 lib/dump_stack.c:53
> >  print_address_description+0x73/0x250 mm/kasan/report.c:256
> >  kasan_report_error mm/kasan/report.c:354 [inline]
> >  kasan_report+0x23b/0x360 mm/kasan/report.c:412
> >  __asan_report_load4_noabort+0x14/0x20 mm/kasan/report.c:432
> >  debug_spin_lock_before kernel/locking/spinlock_debug.c:83 [inline]
> >  do_raw_spin_lock+0x1e0/0x220 kernel/locking/spinlock_debug.c:112
> >  __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:117 [inline]
> >  _raw_spin_lock_irqsave+0x9e/0xc0 kernel/locking/spinlock.c:152
> >  remove_wait_queue+0x81/0x350 kernel/sched/wait.c:50
> >  ep_remove_wait_queue fs/eventpoll.c:595 [inline]
> >  ep_unregister_pollwait.isra.7+0x18c/0x590 fs/eventpoll.c:613
> >  ep_free+0x13f/0x320 fs/eventpoll.c:830
> >  ep_eventpoll_release+0x44/0x60 fs/eventpoll.c:862
> >  __fput+0x327/0x7e0 fs/file_table.c:209
> >  fput+0x15/0x20 fs/file_table.c:243
> >  task_work_run+0x199/0x270 kernel/task_work.c:113
> >  tracehook_notify_resume include/linux/tracehook.h:191 [inline]
> >  exit_to_usermode_loop+0x275/0x2f0 arch/x86/entry/common.c:166
> >  prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline]
> >  syscall_return_slowpath arch/x86/entry/common.c:265 [inline]
> >  do_syscall_32_irqs_on arch/x86/entry/common.c:336 [inline]
> >  do_fast_syscall_32+0xbe8/0xfa1 arch/x86/entry/common.c:392
> >  entry_SYSENTER_compat+0x54/0x63 arch/x86/entry/entry_64_compat.S:129
> > RIP: 0023:0xf7f56c79
> > RSP: 002b:f7f3112c EFLAGS: 0286 ORIG_RAX: 014a
> > RAX: 0009 RBX: 0008 RCX: 0009
> > RDX:  RSI: 00f0 RDI: 08120030
> > RBP:  R08:  R09: 
> > R10:  R11:  R12: 
> > R13:  R14:  R15: 
> >
> > Allocated by task 5105:
> >  save_stack+0x43/0xd0 mm/kasan/kasan.c:447
> >  set_track mm/kasan/kasan.c:459 [inline]
> >  kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:552
> >  kmem_cache_alloc_trace+0x136/0x740 mm/slab.c:3607
> >  kmalloc include/linux/slab.h:512 [inline]
> >  kzalloc include/linux/slab.h:701 [inline]
> >  binder_get_thread+0x1cf/0x870 drivers/android/binder.c:4279
> >  binder_poll+0x8c/0x390 drivers/android/binder.c:4393
> >  ep_item_poll.isra.10+0xf2/0x320 fs/eventpoll.c:885
> >  ep_insert+0x6a2/0x1ac0 fs/eventpoll.c:1457
> >  SYSC_epoll_ctl fs/eventpoll.c:2104 [inline]
> >  SyS_epoll_ctl+0x12bf/0x1a80 fs/eventpoll.c:1990
> >  do_syscall_32_irqs_on arch/x86/entry/common.c:330 [inline]
> >  do_fast_syscall_32+0x3ee/0xfa1 arch/x86/entry/common.c:392
> >  entry_SYSENTER_compat+0x54/0x63 arch/x86/entry/entry_64_compat.S:129
> >
> > Freed by task 5105:
> >  save_stack+0x43/0xd0 mm/kasan/kasan.c:447
> >  set_track mm/kasan/kasan.c:459 [inline]
> >  __kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:520
> >  kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:527
> >  __cache_free mm/slab.c:3485 [inline]
> >  kfree+0xd9/0x260 mm/slab.c:3800
> >  binder_free_thread drivers/android/binder.c:4306 [inline]
> >  binder_thread_dec_tmpref+0x27f/0x310 drivers/android/binder.c:1879
> >  binder_thread_release+0x4a1/0x6b0 drivers/android/binder.c:4382
> >  binder_ioctl+0xc02/0x1417 

[RFC] vruntime updated incorrectly when rt_mutex boots prio?

2018-08-07 Thread Todd Kjos
This issue was discovered on a 4.9-based android device, but the
relevant mainline code appears to be the same. The symptom is that
over time the some workloads become sluggish resulting in missed
frames or sluggishness. It appears to be the same issue described in
http://lists.infradead.org/pipermail/linux-arm-kernel/2018-March/567836.html.

Here is the scenario: A task is deactivated while still in the fair
class. The task is then boosted to RT, so rt_mutex_setprio() is
called. This changes the task to RT and calls check_class_changed(),
which eventually calls detach_task_cfs_rq(), which is where
vruntime_normalized() sees that the task's state is TASK_WAKING, which
results in skipping the subtraction of the rq's min_vruntime from the
task's vruntime. Later, when the prio is deboosted and the task is
moved back to the fair class, the fair rq's min_vruntime is added to
the task's vruntime, resulting in vruntime inflation.

When investigating the problem, it was found that the change below
fixes the problem by forcing vruntime_normalized() to return false if
the sched_class is not CFS (though we're concerned that it might
introduce other issues):

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 91f7b3322a15..267056f2e2ca 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -11125,7 +11125,7 @@ static inline bool vruntime_normalized(struct
task_struct *p)
 * - A task which has been woken up by try_to_wake_up() and
 *   waiting for actually being woken up by sched_ttwu_pending().
 */
-   if (!se->sum_exec_runtime || p->state == TASK_WAKING)
+   if (!se->sum_exec_runtime || (p->state == TASK_WAKING &&
p->sched_class == _sched_class))
return true;

return false;

Do folks agree that this is incorrect behavior? Does this fix look
appropriate and safe? Other ideas?

-Todd


[PATCH] binder: use standard functions to allocate fds

2018-08-28 Thread Todd Kjos
Binder uses internal fs interfaces to allocate and install fds:

__alloc_fd
__fd_install
__close_fd
get_files_struct
put_files_struct

These were used to support the passing of fds between processes
as part of a transaction. The actual allocation and installation
of the fds in the target process was handled by the sending
process so the standard functions, alloc_fd() and fd_install()
which assume task==current couldn't be used.

This patch refactors this mechanism so that the fds are
allocated and installed by the target process allowing the
standard functions to be used.

The sender now creates a list of fd fixups that contains the
struct *file and the address to fixup with the new fd once
it is allocated. This list is processed by the target process
when the transaction is dequeued.

A new error case is introduced by this change. If an async
transaction with file descriptors cannot allocate new
fds in the target (probably due to out of file descriptors),
the transaction is discarded with a log message. In the old
implementation this would have been detected in the sender
context and failed prior to sending.

Signed-off-by: Todd Kjos 
---
 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 387 -
 drivers/android/binder_trace.h |  36 ++-
 3 files changed, 260 insertions(+), 165 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 432e9ad770703..51e8250d113fa 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -10,7 +10,7 @@ if ANDROID
 
 config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
-   depends on MMU
+   depends on MMU && !CPU_CACHE_VIVT
default n
---help---
  Binder is used in Android for both communication between processes,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d58763b6b0090..50856319bc7da 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -71,6 +71,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -457,9 +458,8 @@ struct binder_ref {
 };
 
 enum binder_deferred_state {
-   BINDER_DEFERRED_PUT_FILES= 0x01,
-   BINDER_DEFERRED_FLUSH= 0x02,
-   BINDER_DEFERRED_RELEASE  = 0x04,
+   BINDER_DEFERRED_FLUSH= 0x01,
+   BINDER_DEFERRED_RELEASE  = 0x02,
 };
 
 /**
@@ -480,9 +480,6 @@ enum binder_deferred_state {
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
- * @files files_struct for process
- *(protected by @files_lock)
- * @files_lockmutex to protect @files
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -527,8 +524,6 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
-   struct files_struct *files;
-   struct mutex files_lock;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -611,6 +606,23 @@ struct binder_thread {
bool is_dead;
 };
 
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:  list entry
+ * @file: struct file to be associated with new fd
+ * @offset:   offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+   struct list_head fixup_entry;
+   struct file *file;
+   size_t offset;
+};
+
 struct binder_transaction {
int debug_id;
struct binder_work work;
@@ -628,6 +640,7 @@ struct binder_transaction {
longpriority;
longsaved_priority;
kuid_t  sender_euid;
+   struct list_head fd_fixups;
/**
 * @lock:  protects @from, @to_proc, and @to_thread
 *
@@ -920,66 +933,6 @@ static void binder_free_thread(struct binder_thread 
*thread);
 static void binder_free_proc(struct binder_proc *proc);
 static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
-static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
-{
-   unsigned long rlim_cur;
-   unsigned long irqs;
-   int ret;
-
-   mutex_lock(>files_lock);
-   if (proc->files == NULL) {
-   ret = -ESRCH;
-   goto err;
-   }
-   if (!lock_task_sighand(proc->tsk, )) {
-   ret = -EMFILE;
-   goto err;
-   }
-   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
-   unlock_task_sighand(proc->tsk, );
-
-   ret = __alloc_fd(proc-

[PATCH] binder: use standard functions to allocate fds

2018-08-28 Thread Todd Kjos
Binder uses internal fs interfaces to allocate and install fds:

__alloc_fd
__fd_install
__close_fd
get_files_struct
put_files_struct

These were used to support the passing of fds between processes
as part of a transaction. The actual allocation and installation
of the fds in the target process was handled by the sending
process so the standard functions, alloc_fd() and fd_install()
which assume task==current couldn't be used.

This patch refactors this mechanism so that the fds are
allocated and installed by the target process allowing the
standard functions to be used.

The sender now creates a list of fd fixups that contains the
struct *file and the address to fixup with the new fd once
it is allocated. This list is processed by the target process
when the transaction is dequeued.

A new error case is introduced by this change. If an async
transaction with file descriptors cannot allocate new
fds in the target (probably due to out of file descriptors),
the transaction is discarded with a log message. In the old
implementation this would have been detected in the sender
context and failed prior to sending.

Signed-off-by: Todd Kjos 
---
v2: use "%zu" printk format for size_t

 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 387 -
 drivers/android/binder_trace.h |  36 ++-
 3 files changed, 260 insertions(+), 165 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 432e9ad770703..51e8250d113fa 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -10,7 +10,7 @@ if ANDROID
 
 config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
-   depends on MMU
+   depends on MMU && !CPU_CACHE_VIVT
default n
---help---
  Binder is used in Android for both communication between processes,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d58763b6b0090..50856319bc7da 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -71,6 +71,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -457,9 +458,8 @@ struct binder_ref {
 };
 
 enum binder_deferred_state {
-   BINDER_DEFERRED_PUT_FILES= 0x01,
-   BINDER_DEFERRED_FLUSH= 0x02,
-   BINDER_DEFERRED_RELEASE  = 0x04,
+   BINDER_DEFERRED_FLUSH= 0x01,
+   BINDER_DEFERRED_RELEASE  = 0x02,
 };
 
 /**
@@ -480,9 +480,6 @@ enum binder_deferred_state {
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
- * @files files_struct for process
- *(protected by @files_lock)
- * @files_lockmutex to protect @files
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -527,8 +524,6 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
-   struct files_struct *files;
-   struct mutex files_lock;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -611,6 +606,23 @@ struct binder_thread {
bool is_dead;
 };
 
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:  list entry
+ * @file: struct file to be associated with new fd
+ * @offset:   offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+   struct list_head fixup_entry;
+   struct file *file;
+   size_t offset;
+};
+
 struct binder_transaction {
int debug_id;
struct binder_work work;
@@ -628,6 +640,7 @@ struct binder_transaction {
longpriority;
longsaved_priority;
kuid_t  sender_euid;
+   struct list_head fd_fixups;
/**
 * @lock:  protects @from, @to_proc, and @to_thread
 *
@@ -920,66 +933,6 @@ static void binder_free_thread(struct binder_thread 
*thread);
 static void binder_free_proc(struct binder_proc *proc);
 static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
-static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
-{
-   unsigned long rlim_cur;
-   unsigned long irqs;
-   int ret;
-
-   mutex_lock(>files_lock);
-   if (proc->files == NULL) {
-   ret = -ESRCH;
-   goto err;
-   }
-   if (!lock_task_sighand(proc->tsk, )) {
-   ret = -EMFILE;
-   goto err;
-   }
-   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
-   unlock_task_sighand(

Re: [PATCH v2] binder: use standard functions to allocate fds

2018-08-28 Thread Todd Kjos
Sorry, forgot to bump the version. Ignore this one.
On Tue, Aug 28, 2018 at 1:43 PM Todd Kjos  wrote:
>
> Binder uses internal fs interfaces to allocate and install fds:
>
> __alloc_fd
> __fd_install
> __close_fd
> get_files_struct
> put_files_struct
>
> These were used to support the passing of fds between processes
> as part of a transaction. The actual allocation and installation
> of the fds in the target process was handled by the sending
> process so the standard functions, alloc_fd() and fd_install()
> which assume task==current couldn't be used.
>
> This patch refactors this mechanism so that the fds are
> allocated and installed by the target process allowing the
> standard functions to be used.
>
> The sender now creates a list of fd fixups that contains the
> struct *file and the address to fixup with the new fd once
> it is allocated. This list is processed by the target process
> when the transaction is dequeued.
>
> A new error case is introduced by this change. If an async
> transaction with file descriptors cannot allocate new
> fds in the target (probably due to out of file descriptors),
> the transaction is discarded with a log message. In the old
> implementation this would have been detected in the sender
> context and failed prior to sending.
>
> Signed-off-by: Todd Kjos 
> ---
> v2: use "%zu" printk format for size_t
>
>  drivers/android/Kconfig|   2 +-
>  drivers/android/binder.c   | 387 -
>  drivers/android/binder_trace.h |  36 ++-
>  3 files changed, 260 insertions(+), 165 deletions(-)
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 432e9ad770703..51e8250d113fa 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -10,7 +10,7 @@ if ANDROID
>
>  config ANDROID_BINDER_IPC
> bool "Android Binder IPC Driver"
> -   depends on MMU
> +   depends on MMU && !CPU_CACHE_VIVT
> default n
> ---help---
>   Binder is used in Android for both communication between processes,
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index d58763b6b0090..50856319bc7da 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -71,6 +71,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  #include 
>
> @@ -457,9 +458,8 @@ struct binder_ref {
>  };
>
>  enum binder_deferred_state {
> -   BINDER_DEFERRED_PUT_FILES= 0x01,
> -   BINDER_DEFERRED_FLUSH= 0x02,
> -   BINDER_DEFERRED_RELEASE  = 0x04,
> +   BINDER_DEFERRED_FLUSH= 0x01,
> +   BINDER_DEFERRED_RELEASE  = 0x02,
>  };
>
>  /**
> @@ -480,9 +480,6 @@ enum binder_deferred_state {
>   *(invariant after initialized)
>   * @tsk   task_struct for group_leader of process
>   *(invariant after initialized)
> - * @files files_struct for process
> - *(protected by @files_lock)
> - * @files_lockmutex to protect @files
>   * @deferred_work_node:   element for binder_deferred_list
>   *(protected by binder_deferred_lock)
>   * @deferred_work:bitmap of deferred work to perform
> @@ -527,8 +524,6 @@ struct binder_proc {
> struct list_head waiting_threads;
> int pid;
> struct task_struct *tsk;
> -   struct files_struct *files;
> -   struct mutex files_lock;
> struct hlist_node deferred_work_node;
> int deferred_work;
> bool is_dead;
> @@ -611,6 +606,23 @@ struct binder_thread {
> bool is_dead;
>  };
>
> +/**
> + * struct binder_txn_fd_fixup - transaction fd fixup list element
> + * @fixup_entry:  list entry
> + * @file: struct file to be associated with new fd
> + * @offset:   offset in buffer data to this fixup
> + *
> + * List element for fd fixups in a transaction. Since file
> + * descriptors need to be allocated in the context of the
> + * target process, we pass each fd to be processed in this
> + * struct.
> + */
> +struct binder_txn_fd_fixup {
> +   struct list_head fixup_entry;
> +   struct file *file;
> +   size_t offset;
> +};
> +
>  struct binder_transaction {
> int debug_id;
> struct binder_work work;
> @@ -628,6 +640,7 @@ struct binder_transaction {
> longpriority;
> longsaved_priority;
> kuid_t  sender_euid;
> +   struct list_head fd_fixups;
> /**
>  * @lock:  protects @from, @to_proc, and

[PATCH v2] binder: use standard functions to allocate fds

2018-08-28 Thread Todd Kjos
Binder uses internal fs interfaces to allocate and install fds:

__alloc_fd
__fd_install
__close_fd
get_files_struct
put_files_struct

These were used to support the passing of fds between processes
as part of a transaction. The actual allocation and installation
of the fds in the target process was handled by the sending
process so the standard functions, alloc_fd() and fd_install()
which assume task==current couldn't be used.

This patch refactors this mechanism so that the fds are
allocated and installed by the target process allowing the
standard functions to be used.

The sender now creates a list of fd fixups that contains the
struct *file and the address to fixup with the new fd once
it is allocated. This list is processed by the target process
when the transaction is dequeued.

A new error case is introduced by this change. If an async
transaction with file descriptors cannot allocate new
fds in the target (probably due to out of file descriptors),
the transaction is discarded with a log message. In the old
implementation this would have been detected in the sender
context and failed prior to sending.

Signed-off-by: Todd Kjos 
---
v2: use "%zu" printk format for size_t

 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 387 -
 drivers/android/binder_trace.h |  36 ++-
 3 files changed, 260 insertions(+), 165 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 432e9ad770703..51e8250d113fa 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -10,7 +10,7 @@ if ANDROID
 
 config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
-   depends on MMU
+   depends on MMU && !CPU_CACHE_VIVT
default n
---help---
  Binder is used in Android for both communication between processes,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d58763b6b0090..50856319bc7da 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -71,6 +71,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -457,9 +458,8 @@ struct binder_ref {
 };
 
 enum binder_deferred_state {
-   BINDER_DEFERRED_PUT_FILES= 0x01,
-   BINDER_DEFERRED_FLUSH= 0x02,
-   BINDER_DEFERRED_RELEASE  = 0x04,
+   BINDER_DEFERRED_FLUSH= 0x01,
+   BINDER_DEFERRED_RELEASE  = 0x02,
 };
 
 /**
@@ -480,9 +480,6 @@ enum binder_deferred_state {
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
- * @files files_struct for process
- *(protected by @files_lock)
- * @files_lockmutex to protect @files
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -527,8 +524,6 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
-   struct files_struct *files;
-   struct mutex files_lock;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -611,6 +606,23 @@ struct binder_thread {
bool is_dead;
 };
 
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:  list entry
+ * @file: struct file to be associated with new fd
+ * @offset:   offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+   struct list_head fixup_entry;
+   struct file *file;
+   size_t offset;
+};
+
 struct binder_transaction {
int debug_id;
struct binder_work work;
@@ -628,6 +640,7 @@ struct binder_transaction {
longpriority;
longsaved_priority;
kuid_t  sender_euid;
+   struct list_head fd_fixups;
/**
 * @lock:  protects @from, @to_proc, and @to_thread
 *
@@ -920,66 +933,6 @@ static void binder_free_thread(struct binder_thread 
*thread);
 static void binder_free_proc(struct binder_proc *proc);
 static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
-static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
-{
-   unsigned long rlim_cur;
-   unsigned long irqs;
-   int ret;
-
-   mutex_lock(>files_lock);
-   if (proc->files == NULL) {
-   ret = -ESRCH;
-   goto err;
-   }
-   if (!lock_task_sighand(proc->tsk, )) {
-   ret = -EMFILE;
-   goto err;
-   }
-   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
-   unlock_task_sighand(

[PATCH v2] binder: use standard functions to allocate fds

2018-08-28 Thread Todd Kjos
Binder uses internal fs interfaces to allocate and install fds:

__alloc_fd
__fd_install
__close_fd
get_files_struct
put_files_struct

These were used to support the passing of fds between processes
as part of a transaction. The actual allocation and installation
of the fds in the target process was handled by the sending
process so the standard functions, alloc_fd() and fd_install()
which assume task==current couldn't be used.

This patch refactors this mechanism so that the fds are
allocated and installed by the target process allowing the
standard functions to be used.

The sender now creates a list of fd fixups that contains the
struct *file and the address to fixup with the new fd once
it is allocated. This list is processed by the target process
when the transaction is dequeued.

A new error case is introduced by this change. If an async
transaction with file descriptors cannot allocate new
fds in the target (probably due to out of file descriptors),
the transaction is discarded with a log message. In the old
implementation this would have been detected in the sender
context and failed prior to sending.

Signed-off-by: Todd Kjos 
---
v2: use "%zu" printk format for size_t

 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 387 -
 drivers/android/binder_trace.h |  36 ++-
 3 files changed, 260 insertions(+), 165 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 432e9ad770703..51e8250d113fa 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -10,7 +10,7 @@ if ANDROID
 
 config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
-   depends on MMU
+   depends on MMU && !CPU_CACHE_VIVT
default n
---help---
  Binder is used in Android for both communication between processes,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d58763b6b0090..50856319bc7da 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -71,6 +71,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -457,9 +458,8 @@ struct binder_ref {
 };
 
 enum binder_deferred_state {
-   BINDER_DEFERRED_PUT_FILES= 0x01,
-   BINDER_DEFERRED_FLUSH= 0x02,
-   BINDER_DEFERRED_RELEASE  = 0x04,
+   BINDER_DEFERRED_FLUSH= 0x01,
+   BINDER_DEFERRED_RELEASE  = 0x02,
 };
 
 /**
@@ -480,9 +480,6 @@ enum binder_deferred_state {
  *(invariant after initialized)
  * @tsk   task_struct for group_leader of process
  *(invariant after initialized)
- * @files files_struct for process
- *(protected by @files_lock)
- * @files_lockmutex to protect @files
  * @deferred_work_node:   element for binder_deferred_list
  *(protected by binder_deferred_lock)
  * @deferred_work:bitmap of deferred work to perform
@@ -527,8 +524,6 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
-   struct files_struct *files;
-   struct mutex files_lock;
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead;
@@ -611,6 +606,23 @@ struct binder_thread {
bool is_dead;
 };
 
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:  list entry
+ * @file: struct file to be associated with new fd
+ * @offset:   offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+   struct list_head fixup_entry;
+   struct file *file;
+   size_t offset;
+};
+
 struct binder_transaction {
int debug_id;
struct binder_work work;
@@ -628,6 +640,7 @@ struct binder_transaction {
longpriority;
longsaved_priority;
kuid_t  sender_euid;
+   struct list_head fd_fixups;
/**
 * @lock:  protects @from, @to_proc, and @to_thread
 *
@@ -920,66 +933,6 @@ static void binder_free_thread(struct binder_thread 
*thread);
 static void binder_free_proc(struct binder_proc *proc);
 static void binder_inc_node_tmpref_ilocked(struct binder_node *node);
 
-static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
-{
-   unsigned long rlim_cur;
-   unsigned long irqs;
-   int ret;
-
-   mutex_lock(>files_lock);
-   if (proc->files == NULL) {
-   ret = -ESRCH;
-   goto err;
-   }
-   if (!lock_task_sighand(proc->tsk, )) {
-   ret = -EMFILE;
-   goto err;
-   }
-   rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
-   unlock_task_sighand(

Re: [PATCH] binder: use standard functions to allocate fds

2018-08-30 Thread Todd Kjos
On Wed, Aug 29, 2018 at 12:00 AM Christoph Hellwig  wrote:
>
> >  config ANDROID_BINDER_IPC
> >   bool "Android Binder IPC Driver"
> > - depends on MMU
> > + depends on MMU && !CPU_CACHE_VIVT
>
> Thats is a purely arm specific symbol which should not be
> used in common code.  Nevermind that there generally should
> be no good reason for it.

It is true that the current design (10+ years old) has this flaw. VIVT
cache support was the rationale for using the non-standard functions
to allocate file descriptors from the sender context. There are no
known cases of recent android releases running on a device with
a VIVT cache architecture, but I did want to call this out.

We're working on refactoring to eliminate this issue.

>
> > + fixup->offset = (uintptr_t)fdp - (uintptr_t)t->buffer->data;
>
> This looks completely broken.  Why would you care at what exact
> place the fd is placed?  Oh, because you share an array with fds
> with userspace, which is a hell of a bad idea, and then maninpulate
> that buffer mapped to userspace from kernel threads.

Well, android apps rely on this behavior (and have for 10+ years) so
there is no way to avoid the need to manipulate the buffer from
the kernel. We are working to refactor the driver to do this
using standard mechanisms instead of relying on low-level internal
functions.

>
> I think we just need to rm -rf drivers/android/binder*.c and be done
> with it, as this piece of crap should never have been merged to start
> with.


Re: [PATCH] binder: use lockless list for deferred_work

2018-01-22 Thread Todd Kjos
Vitaly, can you say more about the behavior you observed that led you
to make this change? It is not obvious what workload would cause the
contention on this mutex to make a difference (at least in an Android
environment).

On Mon, Jan 22, 2018 at 7:44 AM, Greg Kroah-Hartman
 wrote:
> On Mon, Jan 08, 2018 at 02:55:18PM +0100, Vitaly Wool wrote:
>> Binder uses hlist for deferred list, which isn't a good match.
>> It's slow and requires mutual exclusion mechanism to protect its
>> operations. Moreover, having schedule_work() called under a mutex
>> may cause significant delays and creates noticeable adverse effect
>> on Binder performance.
>>
>> Deferred list in Binder is actually treated in a very simple way:
>> either add an entry to it or delete the first entry from it. llist
>> (lockless list) is a good match for such usage pattern, and it is
>> of course quite a bit faster and doesn't require locking.
>>
>> To be able to add an entry to an llist only if it's not already on
>> another llist, this patch adds two small helper functions. That is,
>> llist_add_exclusive would only add a node if it's not already on a
>> list, and llist_del_first_exclusive will delete the first node off
>> the list and mark it as not being on any list.
>>
>> Signed-off-by: Vitaly Vul 
>> ---
>>  drivers/android/binder.c | 87 
>> 
>>  1 file changed, 66 insertions(+), 21 deletions(-)
>
> Martijn and Todd, any objections to this patch?
>
> thanks,
>
> greg k-h


Re: [PATCH v3] android: binder: use VM_ALLOC to get vm area

2018-01-22 Thread Todd Kjos
On Mon, Jan 22, 2018 at 7:54 AM, Greg KH  wrote:
> On Wed, Jan 10, 2018 at 10:49:05AM +0800, Ganesh Mahendran wrote:
>> VM_IOREMAP is used to access hardware through a mechanism called
>> I/O mapped memory. Android binder is a IPC machanism which will
>> not access I/O memory.
>>
>> And VM_IOREMAP has alignment requiement which may not needed in
>> binder.
>> __get_vm_area_node()
>> {
>> ...
>> if (flags & VM_IOREMAP)
>> align = 1ul << clamp_t(int, fls_long(size),
>>PAGE_SHIFT, IOREMAP_MAX_ORDER);
>> ...
>> }
>>
>> This patch will save some kernel vm area, especially for 32bit os.
>>
>> In 32bit OS, kernel vm area is only 240MB. We may got below
>> error when launching a app:
>>
>> <3>[ 4482.440053] binder_alloc: binder_alloc_mmap_handler: 15728 
>> 8ce67000-8cf65000 get_vm_area failed -12
>> <3>[ 4483.218817] binder_alloc: binder_alloc_mmap_handler: 15745 
>> 8ce67000-8cf65000 get_vm_area failed -12
>>
>> Signed-off-by: Ganesh Mahendran 
>> 
>> V3: update comments
>> V2: update comments
>> ---
>>  drivers/android/binder_alloc.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> Martijn and Todd, any objections to this patch?

Looks fine to me. Arve, do you remember the rationale for using VM_IOREMAP?

>
> thanks,
>
> greg k-h


Re: [PATCH v2 2/4] ARM: amba: Fix race condition with driver_override

2018-04-25 Thread Todd Kjos
Reviewed-by: Todd Kjos <tk...@android.com>

On Tue, Apr 10, 2018 at 6:21 AM, Geert Uytterhoeven
<geert+rene...@glider.be> wrote:
> The driver_override implementation is susceptible to a race condition
> when different threads are reading vs storing a different driver
> override.  Add locking to avoid this race condition.
>
> Cfr. commits 6265539776a0810b ("driver core: platform: fix race
> condition with driver_override") and 9561475db680f714 ("PCI: Fix race
> condition with driver_override").
>
> Fixes: 3cf385713460eb2b ("ARM: 8256/1: driver coamba: add device binding path 
> 'driver_override'")
> Signed-off-by: Geert Uytterhoeven <geert+rene...@glider.be>
> ---
>  drivers/amba/bus.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 6ffd778352e6d953..36c5653ced5742b7 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -69,8 +69,12 @@ static ssize_t driver_override_show(struct device *_dev,
> struct device_attribute *attr, char *buf)
>  {
> struct amba_device *dev = to_amba_device(_dev);
> +   ssize_t len;
>
> -   return sprintf(buf, "%s\n", dev->driver_override);
> +   device_lock(_dev);
> +   len = sprintf(buf, "%s\n", dev->driver_override);
> +   device_unlock(_dev);
> +   return len;
>  }
>
>  static ssize_t driver_override_store(struct device *_dev,
> @@ -78,7 +82,7 @@ static ssize_t driver_override_store(struct device *_dev,
>  const char *buf, size_t count)
>  {
> struct amba_device *dev = to_amba_device(_dev);
> -   char *driver_override, *old = dev->driver_override, *cp;
> +   char *driver_override, *old, *cp;
>
> if (count > PATH_MAX)
> return -EINVAL;
> @@ -91,12 +95,15 @@ static ssize_t driver_override_store(struct device *_dev,
> if (cp)
> *cp = '\0';
>
> +   device_lock(_dev);
> +   old = dev->driver_override;
> if (strlen(driver_override)) {
> dev->driver_override = driver_override;
> } else {
>kfree(driver_override);
>dev->driver_override = NULL;
> }
> +   device_unlock(_dev);
>
> kfree(old);
>
> --
> 2.7.4
>


Re: [PATCH v2 3/4] ARM: amba: Don't read past the end of sysfs "driver_override" buffer

2018-04-25 Thread Todd Kjos
Reviewed-by: Todd Kjos <tk...@android.com>

On Tue, Apr 10, 2018 at 6:21 AM, Geert Uytterhoeven
<geert+rene...@glider.be> wrote:
> When printing the driver_override parameter when it is 4095 and 4094
> bytes long, the printing code would access invalid memory because we
> need count + 1 bytes for printing.
>
> Cfr. commits 4efe874aace57dba ("PCI: Don't read past the end of sysfs
> "driver_override" buffer") and bf563b01c2895a4b ("driver core: platform:
> Don't read past the end of "driver_override" buffer").
>
> Fixes: 3cf385713460eb2b ("ARM: 8256/1: driver coamba: add device binding path 
> 'driver_override'")
> Signed-off-by: Geert Uytterhoeven <geert+rene...@glider.be>
> ---
>  drivers/amba/bus.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 36c5653ced5742b7..4a3ac31c07d0ee49 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -84,7 +84,8 @@ static ssize_t driver_override_store(struct device *_dev,
> struct amba_device *dev = to_amba_device(_dev);
> char *driver_override, *old, *cp;
>
> -   if (count > PATH_MAX)
> +   /* We need to keep extra room for a newline */
> +   if (count >= (PAGE_SIZE - 1))
> return -EINVAL;
>
> driver_override = kstrndup(buf, count, GFP_KERNEL);
> --
> 2.7.4
>


Re: [PATCH v2 1/4] ARM: amba: Make driver_override output consistent with other buses

2018-04-25 Thread Todd Kjos
Reviewed-by: Todd Kjos <tk...@google.com>

On Tue, Apr 10, 2018 at 6:21 AM, Geert Uytterhoeven
<geert+rene...@glider.be> wrote:
> For AMBA devices with unconfigured driver override, the
> "driver_override" sysfs virtual file is empty, while it contains
> "(null)" for platform and PCI devices.
>
> Make AMBA consistent with other buses by dropping the test for a NULL
> pointer.
>
> Note that contrary to popular belief, sprintf() handles NULL pointers
> fine; they are printed as "(null)".
>
> Signed-off-by: Geert Uytterhoeven <geert+rene...@glider.be>
> ---
>  drivers/amba/bus.c | 3 ---
>  1 file changed, 3 deletions(-)
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 594c228d2f021123..6ffd778352e6d953 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -70,9 +70,6 @@ static ssize_t driver_override_show(struct device *_dev,
>  {
> struct amba_device *dev = to_amba_device(_dev);
>
> -   if (!dev->driver_override)
> -   return 0;
> -
> return sprintf(buf, "%s\n", dev->driver_override);
>  }
>
> --
> 2.7.4
>


Re: [PATCH v2 4/4] ARM: amba: Fix wrong indentation in driver_override_store()

2018-04-25 Thread Todd Kjos
Reviewed-by: Todd Kjos <tk...@android.com>

On Tue, Apr 10, 2018 at 6:21 AM, Geert Uytterhoeven
<geert+rene...@glider.be> wrote:
> Indentation is one TAB and 7 spaces instead of 2 TABs.
>
> Fixes: 3cf385713460eb2b ("ARM: 8256/1: driver coamba: add device binding path 
> 'driver_override'")
> Signed-off-by: Geert Uytterhoeven <geert+rene...@glider.be>
> ---
>  drivers/amba/bus.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 4a3ac31c07d0ee49..842314a439fdd4eb 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -101,8 +101,8 @@ static ssize_t driver_override_store(struct device *_dev,
> if (strlen(driver_override)) {
> dev->driver_override = driver_override;
> } else {
> -  kfree(driver_override);
> -  dev->driver_override = NULL;
> +   kfree(driver_override);
> +   dev->driver_override = NULL;
> }
> device_unlock(_dev);
>
> --
> 2.7.4
>


Re: [PATCH 2/4] ARM: amba: Fix race condition with driver_override

2018-03-02 Thread Todd Kjos
+stable

what is the status of this patch? We'd like to get it into the android
common branches to fix possible double free.

On Fri, Jan 19, 2018 at 7:24 AM, Geert Uytterhoeven
 wrote:
> The driver_override implementation is susceptible to a race condition
> when different threads are reading vs storing a different driver
> override.  Add locking to avoid this race condition.
>
> Cfr. commits 6265539776a0810b ("driver core: platform: fix race
> condition with driver_override") and 9561475db680f714 ("PCI: Fix race
> condition with driver_override").
>
> Fixes: 3cf385713460eb2b ("ARM: 8256/1: driver coamba: add device binding path 
> 'driver_override'")
> Signed-off-by: Geert Uytterhoeven 
> ---
>  drivers/amba/bus.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 6ffd778352e6d953..36c5653ced5742b7 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -69,8 +69,12 @@ static ssize_t driver_override_show(struct device *_dev,
> struct device_attribute *attr, char *buf)
>  {
> struct amba_device *dev = to_amba_device(_dev);
> +   ssize_t len;
>
> -   return sprintf(buf, "%s\n", dev->driver_override);
> +   device_lock(_dev);
> +   len = sprintf(buf, "%s\n", dev->driver_override);
> +   device_unlock(_dev);
> +   return len;
>  }
>
>  static ssize_t driver_override_store(struct device *_dev,
> @@ -78,7 +82,7 @@ static ssize_t driver_override_store(struct device *_dev,
>  const char *buf, size_t count)
>  {
> struct amba_device *dev = to_amba_device(_dev);
> -   char *driver_override, *old = dev->driver_override, *cp;
> +   char *driver_override, *old, *cp;
>
> if (count > PATH_MAX)
> return -EINVAL;
> @@ -91,12 +95,15 @@ static ssize_t driver_override_store(struct device *_dev,
> if (cp)
> *cp = '\0';
>
> +   device_lock(_dev);
> +   old = dev->driver_override;
> if (strlen(driver_override)) {
> dev->driver_override = driver_override;
> } else {
>kfree(driver_override);
>dev->driver_override = NULL;
> }
> +   device_unlock(_dev);
>
> kfree(old);
>
> --
> 2.7.4
>


Re: [PATCH v2] staging: android: ashmem: Fix lockdep issue during llseek

2018-02-26 Thread Todd Kjos
Ack. I confirmed that the syzbot could not reproduce the issue with this patch.

On Thu, Feb 22, 2018 at 1:02 PM, Joel Fernandes <joe...@google.com> wrote:
> (reposting in plain text, sorry for the previous HTML email, I should
> have not posted from the Phone)
>
> On Thu, Feb 22, 2018 at 5:48 AM, Greg Kroah-Hartman
> <gre...@linuxfoundation.org> wrote:
>> On Fri, Feb 16, 2018 at 11:02:01AM -0800, Joel Fernandes wrote:
>>> ashmem_mutex create a chain of dependencies like so:
>>>
>>> (1)
>>> mmap syscall ->
>>>   mmap_sem ->  (acquired)
>>>   ashmem_mmap
>>>   ashmem_mutex (try to acquire)
>>>   (block)
>>>
>>> (2)
>>> llseek syscall ->
>>>   ashmem_llseek ->
>>>   ashmem_mutex ->  (acquired)
>>>   inode_lock ->
>>>   inode->i_rwsem (try to acquire)
>>>   (block)
>>>
>>> (3)
>>> getdents ->
>>>   iterate_dir ->
>>>   inode_lock ->
>>>   inode->i_rwsem   (acquired)
>>>   copy_to_user ->
>>>   mmap_sem (try to acquire)
>>>
>>> There is a lock ordering created between mmap_sem and inode->i_rwsem
>>> causing a lockdep splat [2] during a syzcaller test, this patch fixes
>>> the issue by unlocking the mutex earlier. Functionally that's Ok since
>>> we don't need to protect vfs_llseek.
>>>
>>> [1] https://patchwork.kernel.org/patch/10185031/
>>> [2] https://lkml.org/lkml/2018/1/10/48
>>>
>>> Cc: Todd Kjos <tk...@google.com>
>>> Cc: Arve Hjonnevag <a...@android.com>
>>> Cc: Greg Hackmann <ghackm...@google.com>
>>> Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
>>> Cc: sta...@vger.kernel.org
>>> Reported-by: syzbot+8ec30bb7bf1a981a2...@syzkaller.appspotmail.com
>>> Signed-off-by: Joel Fernandes <joe...@google.com>
>>> ---
>>> Changes since first version:
>>> Don't relock after vfs call since its not needed. Only reason we lock is
>>> to protect races with asma->file.
>>> https://patchwork.kernel.org/patch/10185031/
>>
>> I'd like some acks from others before I take this patch.
>
> GregH, Todd, could you provide Acks?
>
>>
>> Joel, did the original reporter say this patch solved their issue or
>> not?  For some reason I didn't think it worked properly...
>
> That's a different but similar issue:
> https://patchwork.kernel.org/patch/10202127/. That was related to
> RECLAIM_FS lockdep recursion. That was posted as an RFC unlike this
> one, and its still being investigated since Miles reported that the
> lockdep inode annotation doesn't fix the issue.
>
> This one on the other hand has a straightforward fix, and was verified
> by the syzbot.
>
> I can see why its easy to confuse the two issues.
>
> Thanks,
>
> - Joel


Re: [PATCH v2] ANDROID: binder: Add BINDER_GET_NODE_INFO_FOR_REF ioctl.

2018-10-17 Thread Todd Kjos
On Fri, Sep 7, 2018 at 6:38 AM Martijn Coenen  wrote:
>
> This allows the context manager to retrieve information about nodes
> that it holds a reference to, such as the current number of
> references to those nodes.
>
> Such information can for example be used to determine whether the
> servicemanager is the only process holding a reference to a node.
> This information can then be passed on to the process holding the
> node, which can in turn decide whether it wants to shut down to
> reduce resource usage.
>
> Signed-off-by: Martijn Coenen 
> ---
> v2: made sure reserved fields are aligned, and enforce caller zeroes
> all fields except handle, as suggested by Dan Carpenter.
>
>  drivers/android/binder.c| 55 +
>  include/uapi/linux/android/binder.h | 10 ++
>  2 files changed, 65 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index d58763b6b0090..5b25412e15ccf 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -4544,6 +4544,42 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
> return ret;
>  }
>
> +static int binder_ioctl_get_node_info_for_ref(struct binder_proc *proc,
> +   struct binder_node_info_for_ref *info)
> +{
> +   struct binder_node *node;
> +   struct binder_context *context = proc->context;
> +   __u32 handle = info->handle;
> +
> +   if (info->strong_count || info->weak_count || info->reserved1 ||
> +   info->reserved2 || info->reserved3) {
> +   binder_user_error("%d BINDER_GET_NODE_INFO_FOR_REF: only 
> handle may be non-zero.",
> + proc->pid);
> +   return -EINVAL;
> +   }
> +
> +   /* This ioctl may only be used by the context manager */
> +   mutex_lock(>context_mgr_node_lock);
> +   if (!context->binder_context_mgr_node ||
> +   context->binder_context_mgr_node->proc != proc) {
> +   mutex_unlock(>context_mgr_node_lock);
> +   return -EPERM;
> +   }
> +   mutex_unlock(>context_mgr_node_lock);
> +
> +   node = binder_get_node_from_ref(proc, handle, true, NULL);
> +   if (!node)
> +   return -EINVAL;
> +
> +   info->strong_count = node->local_strong_refs +
> +   node->internal_strong_refs;
> +   info->weak_count = node->local_weak_refs;

Aren't we under-reporting the weak refs here? The "internal weak" refs
are the count of elements in node->refs, so we need to add something
like:

hlist_for_each_entry(ref, >refs, node_entry)
info->weak_count++;

> +
> +   binder_put_node(node);
> +
> +   return 0;
> +}
> +
>  static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
> struct binder_node_debug_info *info)
>  {
> @@ -4638,6 +4674,25 @@ static long binder_ioctl(struct file *filp, unsigned 
> int cmd, unsigned long arg)
> }
> break;
> }
> +   case BINDER_GET_NODE_INFO_FOR_REF: {
> +   struct binder_node_info_for_ref info;
> +
> +   if (copy_from_user(, ubuf, sizeof(info))) {
> +   ret = -EFAULT;
> +   goto err;
> +   }
> +
> +   ret = binder_ioctl_get_node_info_for_ref(proc, );
> +   if (ret < 0)
> +   goto err;
> +
> +   if (copy_to_user(ubuf, , sizeof(info))) {
> +   ret = -EFAULT;
> +   goto err;
> +   }
> +
> +   break;
> +   }
> case BINDER_GET_NODE_DEBUG_INFO: {
> struct binder_node_debug_info info;
>
> diff --git a/include/uapi/linux/android/binder.h 
> b/include/uapi/linux/android/binder.h
> index bfaec6903b8bc..b9ba520f7e4bb 100644
> --- a/include/uapi/linux/android/binder.h
> +++ b/include/uapi/linux/android/binder.h
> @@ -200,6 +200,15 @@ struct binder_node_debug_info {
> __u32has_weak_ref;
>  };
>
> +struct binder_node_info_for_ref {
> +   __u32handle;
> +   __u32strong_count;
> +   __u32weak_count;
> +   __u32reserved1;
> +   __u32reserved2;
> +   __u32reserved3;
> +};
> +
>  #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, __u32)
> @@ -208,6 +217,7 @@ struct binder_node_debug_info {
>  #define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
>  #define BINDER_VERSION _IOWR('b', 9, struct binder_version)
>  #define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct 
> binder_node_debug_info)
> +#define BINDER_GET_NODE_INFO_FOR_REF   _IOWR('b', 12, struct 
> binder_node_info_for_ref)
>
>  /*
>   * NOTE: Two special error codes you should check for when 

Re: [PATCH] binder: ipc namespace support for android binder

2018-10-29 Thread Todd Kjos
+christ...@brauner.io

On Sun, Oct 28, 2018 at 7:29 PM chouryzhou(周威)  wrote:
...
>
> > It's not obvious from this patch where this dependency comes
> > from...why is SYSVIPC required? I'd like to not have to require IPC_NS
> > either for devices.
>
> Yes, the patch is not highly dependent on SYSVIPC, but it will be convenient
> if require it. I will update it to drop dependency of it in V2 patch. This 
> patch
> doesn't need IPC_NS set at present.

Actually it is dependent on IPC_NS since it makes changes to
ipc/namespace.c which is
compiled only if CONFIG_IPC_NS.

There are a couple more implementations similar to this one.
https://lwn.net/Articles/577957/ and some submissions to AOSP derived
from that one
that introduce a generic registration function for namespace support [1], and
changes to binder to implement namespaces [2].

If this is really needed, then we should have a solution that works
for devices without
requiring IPC_NS or SYSVIPC. Also, we should not add binder-specific code to
ipc/namespace.c or include/linux/ipc_namespace.h.

-Todd

[1] https://android-review.googlesource.com/c/kernel/common/+/471961
[2] https://android-review.googlesource.com/c/kernel/common/+/471825


Re: [PATCH] binder: ipc namespace support for android binder

2018-10-26 Thread Todd Kjos
On Fri, Oct 26, 2018 at 2:20 AM chouryzhou(周威)  wrote:
>
> Hi
>   We are working for running android in container, but we found that binder is
> not isolated by ipc namespace. Since binder is a form of IPC and therefore 
> should
> be tied to ipc namespace. With this patch, we can run more than one android
> container on one host.
>   This patch move "binder_procs" and "binder_context" into ipc_namespace,
> driver will find the context from it when opening. Althought statistics in 
> debugfs
> remain global.
>
> Signed-off-by: choury zhou 
> ---
>  drivers/android/Kconfig   |   2 +-
>  drivers/android/binder.c  | 126 +-
>  include/linux/ipc_namespace.h |  14 
>  ipc/namespace.c   |   4 ++
>  4 files changed, 111 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 432e9ad77070..09883443b2da 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -10,7 +10,7 @@ if ANDROID
>
>  config ANDROID_BINDER_IPC
> bool "Android Binder IPC Driver"
> -   depends on MMU
> +   depends on MMU && SYSVIPC

NAK. We can't force SYSVIPC on for Android. The notion of running
binder in a container is reasonable, but needs to be done without
explicit requirement for SYSVIPC. binder-in-container is a topic in
the android microconf at Linux plumbers -- are you going to be at LPC?

It's not obvious from this patch where this dependency comes
from...why is SYSVIPC required? I'd like to not have to require IPC_NS
either for devices.

> default n
> ---help---
>   Binder is used in Android for both communication between processes,
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index d58763b6b009..e061dba9b8b3 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -68,6 +68,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -79,13 +80,12 @@
>  #include "binder_alloc.h"
>  #include "binder_trace.h"
>
> +#define ipcns  (current->nsproxy->ipc_ns)
> +
>  static HLIST_HEAD(binder_deferred_list);
>  static DEFINE_MUTEX(binder_deferred_lock);
>
>  static HLIST_HEAD(binder_devices);
> -static HLIST_HEAD(binder_procs);
> -static DEFINE_MUTEX(binder_procs_lock);
> -
>  static HLIST_HEAD(binder_dead_nodes);
>  static DEFINE_SPINLOCK(binder_dead_nodes_lock);
>
> @@ -231,7 +231,7 @@ struct binder_transaction_log_entry {
> int return_error_line;
> uint32_t return_error;
> uint32_t return_error_param;
> -   const char *context_name;
> +   int context_device;
>  };
>  struct binder_transaction_log {
> atomic_t cur;
> @@ -262,19 +262,66 @@ static struct binder_transaction_log_entry 
> *binder_transaction_log_add(
>  }
>
>  struct binder_context {
> +   struct hlist_node hlist;
> struct binder_node *binder_context_mgr_node;
> struct mutex context_mgr_node_lock;
>
> kuid_t binder_context_mgr_uid;
> -   const char *name;
> +   intdevice;
>  };
>
>  struct binder_device {
> struct hlist_node hlist;
> struct miscdevice miscdev;
> -   struct binder_context context;
>  };
>
> +void binder_exit_ns(struct ipc_namespace *ns)
> +{
> +   struct binder_context *context;
> +   struct hlist_node *tmp;
> +
> +   mutex_destroy(>binder_procs_lock);
> +   mutex_destroy(>binder_contexts_lock);
> +   hlist_for_each_entry_safe(context, tmp, >binder_contexts, hlist) {
> +   mutex_destroy(>context_mgr_node_lock);
> +   hlist_del(>hlist);
> +   kfree(context);
> +   }
> +}
> +
> +int binder_init_ns(struct ipc_namespace *ns)
> +{
> +   int ret;
> +   struct binder_device *device;
> +
> +   mutex_init(>binder_procs_lock);
> +   INIT_HLIST_HEAD(>binder_procs);
> +   mutex_init(>binder_contexts_lock);
> +   INIT_HLIST_HEAD(>binder_contexts);
> +
> +   hlist_for_each_entry(device, _devices, hlist) {
> +   struct binder_context *context;
> +
> +   context = kzalloc(sizeof(*context), GFP_KERNEL);
> +   if (!context) {
> +   ret = -ENOMEM;
> +   goto err;
> +   }
> +
> +   context->device = device->miscdev.minor;
> +   context->binder_context_mgr_uid = INVALID_UID;
> +   mutex_init(>context_mgr_node_lock);
> +
> +   hlist_add_head(>hlist, >binder_contexts);
> +   }
> +
> +   return 0;
> +err:
> +   binder_exit_ns(ns);
> +   return ret;
> +}
> +
> +
>  /**
>   * struct binder_work - work enqueued on a worklist
>   * @entry: node enqueued on list
> @@ -2748,7 +2795,7 @@ static void binder_transaction(struct binder_proc *proc,
> e->target_handle = tr->target.handle;
> e->data_size = tr->data_size;
> e->offsets_size = tr->offsets_size;
> -   e->context_name 

[PATCH] binder: fix race that allows malicious free of live buffer

2018-11-06 Thread Todd Kjos
Malicious code can attempt to free buffers using the
BC_FREE_BUFFER ioctl to binder. There are protections
against a user freeing a buffer while in use by the
kernel, however there was a window where BC_FREE_BUFFER
could be used to free a recently allocated buffer that
was not completely initialized. This resulted in a
use-after-free detected by KASAN with a malicious
test program.

This window is closed by setting the buffer's
allow_user_free attribute to 0 when the buffer
is allocated or when the user has previously
freed it instead of waiting for the caller
to set it. The problem was that when the struct
buffer was recycled, allow_user_free was stale
and set to 1 allowing a free to go through.

Signed-off-by: Todd Kjos 
Acked-by: Arve Hjønnevåg 
---
 drivers/android/binder.c   | 21 -
 drivers/android/binder_alloc.c | 16 ++--
 drivers/android/binder_alloc.h |  3 +--
 3 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index cb30a524d16d8..9f1000d2a40c7 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2974,7 +2974,6 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer = NULL;
goto err_binder_alloc_buf_failed;
}
-   t->buffer->allow_user_free = 0;
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
@@ -3510,14 +3509,18 @@ static int binder_thread_write(struct binder_proc *proc,
 
buffer = binder_alloc_prepare_to_free(>alloc,
  data_ptr);
-   if (buffer == NULL) {
-   binder_user_error("%d:%d BC_FREE_BUFFER 
u%016llx no match\n",
-   proc->pid, thread->pid, (u64)data_ptr);
-   break;
-   }
-   if (!buffer->allow_user_free) {
-   binder_user_error("%d:%d BC_FREE_BUFFER 
u%016llx matched unreturned buffer\n",
-   proc->pid, thread->pid, (u64)data_ptr);
+   if (IS_ERR_OR_NULL(buffer)) {
+   if (PTR_ERR(buffer) == -EPERM) {
+   binder_user_error(
+   "%d:%d BC_FREE_BUFFER u%016llx 
matched unreturned or currently freeing buffer\n",
+   proc->pid, thread->pid,
+   (u64)data_ptr);
+   } else {
+   binder_user_error(
+   "%d:%d BC_FREE_BUFFER u%016llx 
no match\n",
+   proc->pid, thread->pid,
+   (u64)data_ptr);
+   }
break;
}
binder_debug(BINDER_DEBUG_FREE_BUFFER,
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 64fd96eada31f..030c98f35cca7 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -151,16 +151,12 @@ static struct binder_buffer 
*binder_alloc_prepare_to_free_locked(
else {
/*
 * Guard against user threads attempting to
-* free the buffer twice
+* free the buffer when in use by kernel or
+* after it's already been freed.
 */
-   if (buffer->free_in_progress) {
-   binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
-  "%d:%d FREE_BUFFER u%016llx 
user freed buffer twice\n",
-  alloc->pid, current->pid,
-  (u64)user_ptr);
-   return NULL;
-   }
-   buffer->free_in_progress = 1;
+   if (!buffer->allow_user_free)
+   return ERR_PTR(-EPERM);
+   buffer->allow_user_free = 0;
return buffer;
}
}
@@ -500,7 +496,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 
rb_erase(best_fit, >free_buffers);
buffer->free = 0;
-   buffer->free_in_progress = 0;
+   buffer->allow_user_free = 0;
binder_insert_allocated_buffer_locked(alloc, buffer);
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,

[PATCH] binder: fix sparse warnings on locking context

2018-11-06 Thread Todd Kjos
Add __acquire()/__release() annnotations to fix warnings
in sparse context checking

There is one case where the warning was due to a lack of
a "default:" case in a switch statement where a lock was
being released in each of the cases, so the default
case was added.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c   | 43 +-
 drivers/android/binder_alloc.c |  1 +
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 9f1000d2a40c7..9f2059d24ae2d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -660,6 +660,7 @@ struct binder_transaction {
 #define binder_proc_lock(proc) _binder_proc_lock(proc, __LINE__)
 static void
 _binder_proc_lock(struct binder_proc *proc, int line)
+   __acquires(>outer_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -675,6 +676,7 @@ _binder_proc_lock(struct binder_proc *proc, int line)
 #define binder_proc_unlock(_proc) _binder_proc_unlock(_proc, __LINE__)
 static void
 _binder_proc_unlock(struct binder_proc *proc, int line)
+   __releases(>outer_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -690,6 +692,7 @@ _binder_proc_unlock(struct binder_proc *proc, int line)
 #define binder_inner_proc_lock(proc) _binder_inner_proc_lock(proc, __LINE__)
 static void
 _binder_inner_proc_lock(struct binder_proc *proc, int line)
+   __acquires(>inner_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -705,6 +708,7 @@ _binder_inner_proc_lock(struct binder_proc *proc, int line)
 #define binder_inner_proc_unlock(proc) _binder_inner_proc_unlock(proc, 
__LINE__)
 static void
 _binder_inner_proc_unlock(struct binder_proc *proc, int line)
+   __releases(>inner_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -720,6 +724,7 @@ _binder_inner_proc_unlock(struct binder_proc *proc, int 
line)
 #define binder_node_lock(node) _binder_node_lock(node, __LINE__)
 static void
 _binder_node_lock(struct binder_node *node, int line)
+   __acquires(>lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -735,6 +740,7 @@ _binder_node_lock(struct binder_node *node, int line)
 #define binder_node_unlock(node) _binder_node_unlock(node, __LINE__)
 static void
 _binder_node_unlock(struct binder_node *node, int line)
+   __releases(>lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -751,12 +757,16 @@ _binder_node_unlock(struct binder_node *node, int line)
 #define binder_node_inner_lock(node) _binder_node_inner_lock(node, __LINE__)
 static void
 _binder_node_inner_lock(struct binder_node *node, int line)
+   __acquires(>lock) __acquires(>proc->inner_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
spin_lock(>lock);
if (node->proc)
binder_inner_proc_lock(node->proc);
+   else
+   /* annotation for sparse */
+   __acquire(>proc->inner_lock);
 }
 
 /**
@@ -768,6 +778,7 @@ _binder_node_inner_lock(struct binder_node *node, int line)
 #define binder_node_inner_unlock(node) _binder_node_inner_unlock(node, 
__LINE__)
 static void
 _binder_node_inner_unlock(struct binder_node *node, int line)
+   __releases(>lock) __releases(>proc->inner_lock)
 {
struct binder_proc *proc = node->proc;
 
@@ -775,6 +786,9 @@ _binder_node_inner_unlock(struct binder_node *node, int 
line)
 "%s: line=%d\n", __func__, line);
if (proc)
binder_inner_proc_unlock(proc);
+   else
+   /* annotation for sparse */
+   __release(>proc->inner_lock);
spin_unlock(>lock);
 }
 
@@ -1384,10 +1398,14 @@ static void binder_dec_node_tmpref(struct binder_node 
*node)
binder_node_inner_lock(node);
if (!node->proc)
spin_lock(_dead_nodes_lock);
+   else
+   __acquire(_dead_nodes_lock);
node->tmp_refs--;
BUG_ON(node->tmp_refs < 0);
if (!node->proc)
spin_unlock(_dead_nodes_lock);
+   else
+   __release(_dead_nodes_lock);
/*
 * Call binder_dec_node() to check if all refcounts are 0
 * and cleanup is needed. Calling with strong=0 and internal=1
@@ -1890,18 +1908,22 @@ static struct binder_thread *binder_get_txn_from(
  */
 static struct binder_thread *binder_get_txn_from_and_acq_inner(
struct binder_transaction *t)
+   __acquires(>from

Re: Re: [PATCH V3] binder: ipc namespace support for android binder(Internet mail)

2018-11-09 Thread Todd Kjos
On Fri, Nov 9, 2018 at 8:43 PM chouryzhou(周威)  wrote:

>
> If IPC_NS is disabled, "current-nsporxy->ipc_ns" will also exists,  it will 
> be a static
> reference of "init_ipc_ns" (in ipc/msgutil.c, not defined in binder.c by me) 
> with
> no namespace-ization. You will get the same one in all processes, everything 
> is
> the same as  without this patch.

except, as far as I can tell, binder_init_ns() would never have been
called on it so the mutex and list heads are not initialized so its
completely broken. Am I missing something? How do those fields get
initialized in this case?

>
> - choury -
>


Re: Re: [PATCH V3] binder: ipc namespace support for android binder

2018-11-09 Thread Todd Kjos
On Fri, Nov 9, 2018 at 7:09 PM chouryzhou(周威)  wrote:
>
> >
> > I still don't understand the dependencies on SYSVIPC or POSIX_MQUEUE.
> > It seems like this mechanism would work even if both are disabled --
> > as long as IPC_NS is enabled. Seems cleaner to change init/Kconfig and
> > allow IPC_NS if CONFIG_ANDROID_BINDER_IPC and change this line to
> > "#ifndef CONFIG_IPC_NS"
>
> Let me explain it in detail. If SYSIPC and IPC_NS are both defined,
> current->nsproxy->ipc_ns will save the ipc namespace variables. We just use
> it. If SYSIPC (or POSIX_MQUEUE) is defined while IPC_NS is not set,
> current->nsproxy->ipc_ns will always refer to init_ipc_ns in ipc/msgutil.c,
> which is also fine to us. But if neither SYSIPC nor POSIX_MQUEUE is set
> (IPC_NS can't be set in this situation), there is no current->nsproxy->ipc_ns.
> We make a fack init_ipc_ns here and use it.

Yes, I can read the code. I'm wondering specifically about SYSVIPC and
POSIX_MQUEUE. Even with your code changes, binder has no dependency on
these configs. Why are you creating one? The actual dependency with
your changes is on "current->nsproxy->ipc_ns" being initialized for
binder -- which is dependent on CONFIG_IPC_NS being enabled, isn't it?

If SYSVIPC or POSIX_MQUEUE are enabled, but IPC_NS is disabled, does this work?

>
> > why eliminate name? The string name is very useful for differentiating
> > normal "framework" binder transactions vs "hal" or "vendor"
> > transactions. If we just have a device number it will be hard to tell
> > in the logs even which namespace it belongs to. We need to keep both
> > the "name" (for which there might be multiple in each ns) and some
> > indication of which namespace this is. Maybe we assign some sort of
> > namespace ID during binder_init_ns().
>
>  I will remain the name of device. The  inum of ipc_ns can be treated as
> namespace ID in ipc_ns.
>
> > As mentioned above, we need to retain name and probably also want a ns
> > id of some sort. So context now has 3 components if IPC_NS, so maybe a
> > helper function to print context like:
> >
> > static void binder_seq_print_context(struct seq_file *m, struct
> > binder_context *context)
> > {
> > #ifdef CONFIG_IPC_NS
> >   seq_printf(m, "%d-%d-%s", context->ns_id, context->device,
> > context->name);
> > #else
> >   seq_printf(m, "%d", context->name);
> > #endif
> > }
> >
> > (same comment below everywhere context is printed)
> >
> > Should these debugfs nodes should be ns aware and only print debugging
> > info for the context of the thread accessing the node? If so, we would
> > also want to be namespace-aware when printing pids.
>
> Nowadays, debugfs is not namespace-ized, and pid namespace is not associated
> with ipc namespace.  Will it be more complicated to debug this if we just 
> print
> the info for current thread? Because we will have to enter the ipc namespace
> firstly. But add ipc inum should be no problem.

With the name and ns id, debugging would be fine from the host-side. I
don't understand the container use cases enough to know if you need to
be able to debug binder transaction failures from within the container
-- in which case it seems like you'd want the container-version of the
PIDs -- but obviously this depends on how the containers are set up
and what the use-cases really are. I'm ok with leaving that for a
later patch.

>
> - choury -
>
>


Re: Re: [PATCH V3] binder: ipc namespace support for android binder(Internet mail)

2018-11-09 Thread Todd Kjos
On Fri, Nov 9, 2018 at 9:43 PM chouryzhou(周威)  wrote:
>
> > >
> > > If IPC_NS is disabled, "current-nsporxy->ipc_ns" will also exists,  it 
> > > will be a static
> > > reference of "init_ipc_ns" (in ipc/msgutil.c, not defined in binder.c by 
> > > me) with
> > > no namespace-ization. You will get the same one in all processes, 
> > > everything is
> > > the same as  without this patch.
> >
> > except, as far as I can tell, binder_init_ns() would never have been
> > called on it so the mutex and list heads are not initialized so its
> > completely broken. Am I missing something? How do those fields get
> > initialized in this case?
>
> > @@ -5832,8 +5888,12 @@ static int __init binder_init(void)
> > goto err_init_binder_device_failed;
> > }
> >
> > -   return ret;
> > +   ret = binder_init_ns(_ipc_ns);
> > +   if (ret)
> > +   goto err_init_namespace_failed;
> >
> > +   return ret;
>
> They are initialized here.

Ok, This init_ipc_ns is a global declared in msgutil.c if SYSVIPC ||
POSIX_MQUEUE. This seems kinda hacky, but now I finally see why the
dependancy... msgutil.c is the only file we can count on if !IPC_NS &&
(SYSVIPC || POSIX_MQUEUE). There must be a cleaner way to do this, I
really don't like this dependency... wouldn't it be cleaner to do:

#ifndef CONFIG_IPC_NS
static struct ipc_namespace binder_ipc_ns;
#define ipcns  (_ipc_ns)
#else
#define ipcns  (current->nsproxy->ipc_ns)
#endif

(and make the initialization of binder_ipc_ns conditional on IPC_NS)

This gets us the same thing without the incestuous dependency on the
msgutil.c version of init_ipc_ns...and then binder doesn't rely on
SYSVIPC or POSIX_MQUEUE directly.

>
> - choury -
>


Re: [PATCH V4] binder: ipc namespace support for android binder

2018-11-13 Thread Todd Kjos
On Tue, Nov 13, 2018 at 12:12 AM chouryzhou(周威)  wrote:
>
> > I have not received an answer to my questions in the last version of this 
> > patch
> > set. Also it would be good if I could be Cc'ed by default. I can't hunt 
> > down all
> > patches.
> > I do not know of any kernel entity, specifically devices, that change 
> > namespaces
> > on open().
> > This seems like an invitation for all kinds of security bugs.
> > A device node belongs to one namespace only which is attached to the
> > underlying kobject. Opening the device should never change that.
> > Please look at how mqueue or shm are doing this. They don't change
> > namespaces on open either.
> > I have to say that is one of the main reasons why I disagree with that 
> > design.
> >
> >
>
> If we must return the same context when every open in proc, we can only 
> isolate
> binder with mnt namespace instead of ipc namespace, what do you think, Todd?

I don't have strong feelings on this -- it seems like a bizarre
use-case to send the fd through a backchannel as christian describes,
but I do agree it is strange behavior (though it seems safe to me
since it prevents communication between unrelated entities). I don't
know how mqueue and shm work, its worth a look since this patch is
modelling their behavior...

We'll talk about it here at LPC and then on this thread.


Re: [PATCH] binder: fix race that allows malicious free of live buffer

2018-11-09 Thread Todd Kjos
On Fri, Nov 9, 2018 at 4:32 AM Greg KH  wrote:
>
> On Tue, Nov 06, 2018 at 03:55:32PM -0800, Todd Kjos wrote:
> > Malicious code can attempt to free buffers using the
> > BC_FREE_BUFFER ioctl to binder. There are protections
> > against a user freeing a buffer while in use by the
> > kernel, however there was a window where BC_FREE_BUFFER
> > could be used to free a recently allocated buffer that
> > was not completely initialized. This resulted in a
> > use-after-free detected by KASAN with a malicious
> > test program.
> >
> > This window is closed by setting the buffer's
> > allow_user_free attribute to 0 when the buffer
> > is allocated or when the user has previously
> > freed it instead of waiting for the caller
> > to set it. The problem was that when the struct
> > buffer was recycled, allow_user_free was stale
> > and set to 1 allowing a free to go through.
> >
> > Signed-off-by: Todd Kjos 
> > Acked-by: Arve Hjønnevåg 
>
> No "stable" tag here?  Any idea how far back the stable backporting
> should go, if any?

Sorry about that. It should be backported to 4.14 and later.

>
> thanks,
>
> greg k-h


Re: [PATCH V4] binder: ipc namespace support for android binder

2018-11-12 Thread Todd Kjos
+christ...@brauner.io +Martijn Coenen

Christian,

Does this patch work for your container use-cases? If not, please
comment on this thread. Let's discuss at LPC this week.

-Todd

On Mon, Nov 12, 2018 at 1:38 AM chouryzhou(周威)  wrote:
>
> Currently android's binder is not isolated by ipc namespace. Since binder
> is a form of IPC and therefore should be tied to ipc namespace. With this
> patch, we can run multiple instances of  android container on one host.
>
> This patch move "binder_procs" and "binder_context" into ipc_namespace,
> driver will find the context from it when opening. For debugfs, binder_proc
> is namespace-aware, but not for binder dead nodes, binder_stats and
> binder_transaction_log_entry (we added ipc inum to trace it).
>
> Signed-off-by: chouryzhou 
> Reviewed-by: Davidlohr Bueso 
> ---
>  drivers/android/binder.c  | 133 
> --
>  include/linux/ipc_namespace.h |  15 +
>  ipc/namespace.c   |  10 +++-
>  3 files changed, 125 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index cb30a524d16d..453265505b04 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -67,6 +67,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -80,13 +82,21 @@
>  #include "binder_alloc.h"
>  #include "binder_trace.h"
>
> +
> +#ifndef CONFIG_IPC_NS
> +static struct ipc_namespace binder_ipc_ns = {
> +   .ns.inum = PROC_IPC_INIT_INO,
> +};
> +
> +#define ipcns  (_ipc_ns)
> +#else
> +#define ipcns  (current->nsproxy->ipc_ns)
> +#endif
> +
>  static HLIST_HEAD(binder_deferred_list);
>  static DEFINE_MUTEX(binder_deferred_lock);
>
>  static HLIST_HEAD(binder_devices);
> -static HLIST_HEAD(binder_procs);
> -static DEFINE_MUTEX(binder_procs_lock);
> -
>  static HLIST_HEAD(binder_dead_nodes);
>  static DEFINE_SPINLOCK(binder_dead_nodes_lock);
>
> @@ -233,6 +243,7 @@ struct binder_transaction_log_entry {
> uint32_t return_error;
> uint32_t return_error_param;
> const char *context_name;
> +   unsigned int ipc_inum;
>  };
>  struct binder_transaction_log {
> atomic_t cur;
> @@ -263,19 +274,66 @@ static struct binder_transaction_log_entry 
> *binder_transaction_log_add(
>  }
>
>  struct binder_context {
> +   struct hlist_node hlist;
> struct binder_node *binder_context_mgr_node;
> struct mutex context_mgr_node_lock;
>
> kuid_t binder_context_mgr_uid;
> +   int   device;
> const char *name;
>  };
>
>  struct binder_device {
> struct hlist_node hlist;
> struct miscdevice miscdev;
> -   struct binder_context context;
>  };
>
> +void binder_exit_ns(struct ipc_namespace *ns)
> +{
> +   struct binder_context *context;
> +   struct hlist_node *tmp;
> +
> +   mutex_destroy(>binder_procs_lock);
> +   hlist_for_each_entry_safe(context, tmp, >binder_contexts, hlist) {
> +   mutex_destroy(>context_mgr_node_lock);
> +   hlist_del(>hlist);
> +   kfree(context);
> +   }
> +}
> +
> +int binder_init_ns(struct ipc_namespace *ns)
> +{
> +   int ret;
> +   struct binder_device *device;
> +
> +   mutex_init(>binder_procs_lock);
> +   INIT_HLIST_HEAD(>binder_procs);
> +   INIT_HLIST_HEAD(>binder_contexts);
> +
> +   hlist_for_each_entry(device, _devices, hlist) {
> +   struct binder_context *context;
> +
> +   context = kzalloc(sizeof(*context), GFP_KERNEL);
> +   if (!context) {
> +   ret = -ENOMEM;
> +   goto err;
> +   }
> +
> +   context->device = device->miscdev.minor;
> +   context->name = device->miscdev.name;
> +   context->binder_context_mgr_uid = INVALID_UID;
> +   mutex_init(>context_mgr_node_lock);
> +
> +   hlist_add_head(>hlist, >binder_contexts);
> +   }
> +
> +   return 0;
> +err:
> +   binder_exit_ns(ns);
> +   return ret;
> +}
> +
> +
>  /**
>   * struct binder_work - work enqueued on a worklist
>   * @entry: node enqueued on list
> @@ -2728,6 +2786,7 @@ static void binder_transaction(struct binder_proc *proc,
> e->data_size = tr->data_size;
> e->offsets_size = tr->offsets_size;
> e->context_name = proc->context->name;
> +   e->ipc_inum = ipcns->ns.inum;
>
> if (reply) {
> binder_inner_proc_lock(proc);
> @@ -4922,6 +4981,7 @@ static int binder_open(struct inode *nodp, struct file 
> *filp)
>  {
> struct binder_proc *proc;
> struct binder_device *binder_dev;
> +   struct binder_context *context;
>
> binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
>  current->group_leader->pid, current->pid);
> @@ -4937,7 +4997,15 @@ static int binder_open(struct inode *nodp, struct 

Re: [PATCH V3] binder: ipc namespace support for android binder

2018-11-09 Thread Todd Kjos
On Fri, Nov 9, 2018 at 10:27 AM Davidlohr Bueso  wrote:
>
> On Thu, 08 Nov 2018, chouryzhou(??) wrote:
>
> >+#ifdef CONFIG_ANDROID_BINDER_IPC
> >+   /* next fields are for binder */
> >+   struct mutex  binder_procs_lock;
> >+   struct hlist_head binder_procs;
> >+   struct hlist_head binder_contexts;
> >+#endif
>
> Now, I took a look at how the binder_procs list is used; and no, what
> follows isn't really related to this patch, but a general observation.
>
> I think that a mutex is also an overkill and you might wanna replace it
> with a spinlock/rwlock. Can anything block while holding the 
> binder_procs_lock?
> I don't see anything... you mainly need it for consulting the hlist calling
> print_binder_proc[_stat]() - which will take the proc->inner_lock anyway, so
> no blocking there.

print_binder_proc() drops proc->inner_lock and calls
binder_alloc_print_allocated() which acquires proc->alloc->mutex.
Likewise, print_binder_stats() calls print_binder_proc_stats() which
drops its locks to call binder_alloc_print_pages() which also acquires
proc->alloc->mutex. So binder_procs_lock needs to be a mutex since it
can block on proc->alloc->mutex.

> Also, if this is perhaps because of long hold times, dunno,
> the rb_first_cached primitive might reduce some of it, although I don't know
> how big the rbtrees in binder can get and if it matters at all.
>
> Anyway, that said and along with addressing Todd's comments, the ipc/ bits 
> look
> good. Feel free to add my:
>
> Reviewed-by: Davidlohr Bueso 
>
> Thanks,
> Davidlohr


Re: [PATCH V3] binder: ipc namespace support for android binder

2018-11-09 Thread Todd Kjos
On Thu, Nov 8, 2018 at 5:02 AM chouryzhou(周威)  wrote:
>
>   We are working for running android in container, but we found that binder is
> not isolated by ipc namespace. Since binder is a form of IPC and therefore 
> should
> be tied to ipc namespace. With this patch, we can run more than one android
> container on one host.
>   This patch move "binder_procs" and "binder_context" into ipc_namespace,
> driver will find the context from it when opening. Although statistics in 
> debugfs
> remain global.
>
> Signed-off-by: chouryzhou 
> ---
>  drivers/android/binder.c  | 128 
> +++---
>  include/linux/ipc_namespace.h |  15 +
>  ipc/namespace.c   |  10 +++-
>  3 files changed, 117 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index cb30a524d16d..22e45bb937e6 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -68,6 +68,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -80,13 +81,18 @@
>  #include "binder_alloc.h"
>  #include "binder_trace.h"
>
> +
> +#if !defined(CONFIG_SYSVIPC) &&  !defined(CONFIG_POSIX_MQUEUE)

I still don't understand the dependencies on SYSVIPC or POSIX_MQUEUE.
It seems like this mechanism would work even if both are disabled --
as long as IPC_NS is enabled. Seems cleaner to change init/Kconfig and
allow IPC_NS if CONFIG_ANDROID_BINDER_IPC and change this line to
"#ifndef CONFIG_IPC_NS"

> +struct ipc_namespace init_ipc_ns;
> +#define ipcns  (_ipc_ns)
> +#else
> +#define ipcns  (current->nsproxy->ipc_ns)
> +#endif
> +
>  static HLIST_HEAD(binder_deferred_list);
>  static DEFINE_MUTEX(binder_deferred_lock);
>
>  static HLIST_HEAD(binder_devices);
> -static HLIST_HEAD(binder_procs);
> -static DEFINE_MUTEX(binder_procs_lock);
> -
>  static HLIST_HEAD(binder_dead_nodes);
>  static DEFINE_SPINLOCK(binder_dead_nodes_lock);
>
> @@ -232,7 +238,7 @@ struct binder_transaction_log_entry {
> int return_error_line;
> uint32_t return_error;
> uint32_t return_error_param;
> -   const char *context_name;
> +   int context_device;
>  };
>  struct binder_transaction_log {
> atomic_t cur;
> @@ -263,19 +269,64 @@ static struct binder_transaction_log_entry 
> *binder_transaction_log_add(
>  }
>
>  struct binder_context {
> +   struct hlist_node hlist;
> struct binder_node *binder_context_mgr_node;
> struct mutex context_mgr_node_lock;
>
> kuid_t binder_context_mgr_uid;
> -   const char *name;
> +   intdevice;
>  };
>
>  struct binder_device {
> struct hlist_node hlist;
> struct miscdevice miscdev;
> -   struct binder_context context;
>  };
>
> +void binder_exit_ns(struct ipc_namespace *ns)
> +{
> +   struct binder_context *context;
> +   struct hlist_node *tmp;
> +
> +   mutex_destroy(>binder_procs_lock);
> +   hlist_for_each_entry_safe(context, tmp, >binder_contexts, hlist) {
> +   mutex_destroy(>context_mgr_node_lock);
> +   hlist_del(>hlist);
> +   kfree(context);
> +   }
> +}
> +
> +int binder_init_ns(struct ipc_namespace *ns)
> +{
> +   int ret;
> +   struct binder_device *device;
> +
> +   mutex_init(>binder_procs_lock);
> +   INIT_HLIST_HEAD(>binder_procs);
> +   INIT_HLIST_HEAD(>binder_contexts);
> +
> +   hlist_for_each_entry(device, _devices, hlist) {
> +   struct binder_context *context;
> +
> +   context = kzalloc(sizeof(*context), GFP_KERNEL);
> +   if (!context) {
> +   ret = -ENOMEM;
> +   goto err;
> +   }
> +
> +   context->device = device->miscdev.minor;
> +   context->binder_context_mgr_uid = INVALID_UID;
> +   mutex_init(>context_mgr_node_lock);
> +
> +   hlist_add_head(>hlist, >binder_contexts);
> +   }
> +
> +   return 0;
> +err:
> +   binder_exit_ns(ns);
> +   return ret;
> +}
> +
> +
>  /**
>   * struct binder_work - work enqueued on a worklist
>   * @entry: node enqueued on list
> @@ -2727,7 +2778,7 @@ static void binder_transaction(struct binder_proc *proc,
> e->target_handle = tr->target.handle;
> e->data_size = tr->data_size;
> e->offsets_size = tr->offsets_size;
> -   e->context_name = proc->context->name;
> +   e->context_device = proc->context->device;

why eliminate name? The string name is very useful for differentiating
normal "framework" binder transactions vs "hal" or "vendor"
transactions. If we just have a device number it will be hard to tell
in the logs even which namespace it belongs to. We need to keep both
the "name" (for which there might be multiple in each ns) and some
indication of which namespace this is. Maybe we assign some sort of
namespace ID during binder_init_ns().

>
> if (reply) {
>   

Re: [PATCH] MAINTAINERS: Add me to Android drivers

2018-10-09 Thread Todd Kjos
On Thu, Oct 4, 2018 at 6:50 PM Joel Fernandes (Google)
 wrote:
>
> I am one of the main engineers working on ashmem. I have been fixing
> bugs in the driver and have been involved in the memfd conversion
> discussions and sending patches about that. I also have an understanding
> of the binder driver and was involved with some of the development on
> finer grained locking. So I would like to be added to the MAINTAINERS
> file for android drivers for review and maintenance of ashmem and other
> Android drivers.
>
> Cc: tk...@google.com
> Cc: gre...@linuxfoundation.org
> Signed-off-by: Joel Fernandes (Google) 
> ---
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 544cac829cf4..d639c4d04438 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -894,6 +894,7 @@ M:  Greg Kroah-Hartman 
>  M: Arve Hjønnevåg 
>  M: Todd Kjos 
>  M: Martijn Coenen 
> +M: Joel Fernandes 
>  T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
>  L: de...@driverdev.osuosl.org
>  S: Supported
> --
> 2.19.0.605.g01d371f741-goog
>

Nice to have someone focused on ashmem maintenance!

Acked-by: Todd Kjos 


Re: possible deadlock in __do_page_fault

2018-09-20 Thread Todd Kjos
+Joel Fernandes

On Thu, Sep 20, 2018 at 2:11 PM Andrew Morton  wrote:
>
>
> Thanks.  Let's cc the ashmem folks.
>
> On Thu, 20 Sep 2018 14:04:05 -0700 syzbot 
>  wrote:
>
> > Hello,
> >
> > syzbot found the following crash on:
> >
> > HEAD commit:a0cb0cabe4bb Add linux-next specific files for 20180920
> > git tree:   linux-next
> > console output: https://syzkaller.appspot.com/x/log.txt?x=1513972140
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=786006c5dafbadf6
> > dashboard link: https://syzkaller.appspot.com/bug?extid=a76129f18c89f3e2ddd4
> > compiler:   gcc (GCC) 8.0.1 20180413 (experimental)
> >
> > Unfortunately, I don't have any reproducer for this crash yet.
> >
> > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > Reported-by: syzbot+a76129f18c89f3e2d...@syzkaller.appspotmail.com
> >
> >
> > ==
> > WARNING: possible circular locking dependency detected
> > 4.19.0-rc4-next-20180920+ #76 Not tainted
> > --
> > syz-executor3/21327 is trying to acquire lock:
> > 9bc5286f (>mmap_sem){}, at: __do_page_fault+0xb61/0xec0
> > arch/x86/mm/fault.c:1333
> >
> > but task is already holding lock:
> > a2c51c08 (>s_type->i_mutex_key#10){+.+.}, at: inode_lock
> > include/linux/fs.h:745 [inline]
> > a2c51c08 (>s_type->i_mutex_key#10){+.+.}, at:
> > generic_file_write_iter+0xed/0x870 mm/filemap.c:3304
> >
> > which lock already depends on the new lock.
> >
> >
> > the existing dependency chain (in reverse order) is:
> >
> > -> #2 (>s_type->i_mutex_key#10){+.+.}:
> > down_write+0x8a/0x130 kernel/locking/rwsem.c:70
> > inode_lock include/linux/fs.h:745 [inline]
> > shmem_fallocate+0x18b/0x12c0 mm/shmem.c:2651
> > ashmem_shrink_scan+0x238/0x660 drivers/staging/android/ashmem.c:455
> > ashmem_ioctl+0x3ae/0x13a0 drivers/staging/android/ashmem.c:797
> > vfs_ioctl fs/ioctl.c:46 [inline]
> > file_ioctl fs/ioctl.c:501 [inline]
> > do_vfs_ioctl+0x1de/0x1720 fs/ioctl.c:685
> > ksys_ioctl+0xa9/0xd0 fs/ioctl.c:702
> > __do_sys_ioctl fs/ioctl.c:709 [inline]
> > __se_sys_ioctl fs/ioctl.c:707 [inline]
> > __x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:707
> > do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
> > entry_SYSCALL_64_after_hwframe+0x49/0xbe
> >
> > -> #1 (ashmem_mutex){+.+.}:
> > __mutex_lock_common kernel/locking/mutex.c:925 [inline]
> > __mutex_lock+0x166/0x1700 kernel/locking/mutex.c:1072
> > mutex_lock_nested+0x16/0x20 kernel/locking/mutex.c:1087
> > ashmem_mmap+0x55/0x520 drivers/staging/android/ashmem.c:361
> > call_mmap include/linux/fs.h:1830 [inline]
> > mmap_region+0xe82/0x1cd0 mm/mmap.c:1762
> > do_mmap+0xa10/0x1220 mm/mmap.c:1535
> > do_mmap_pgoff include/linux/mm.h:2298 [inline]
> > vm_mmap_pgoff+0x213/0x2c0 mm/util.c:357
> > ksys_mmap_pgoff+0x4da/0x660 mm/mmap.c:1585
> > __do_sys_mmap arch/x86/kernel/sys_x86_64.c:100 [inline]
> > __se_sys_mmap arch/x86/kernel/sys_x86_64.c:91 [inline]
> > __x64_sys_mmap+0xe9/0x1b0 arch/x86/kernel/sys_x86_64.c:91
> > do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
> > entry_SYSCALL_64_after_hwframe+0x49/0xbe
> >
> > -> #0 (>mmap_sem){}:
> > lock_acquire+0x1ed/0x520 kernel/locking/lockdep.c:3900
> > down_read+0x8d/0x120 kernel/locking/rwsem.c:24
> > __do_page_fault+0xb61/0xec0 arch/x86/mm/fault.c:1333
> > do_page_fault+0xed/0x7d1 arch/x86/mm/fault.c:1472
> > page_fault+0x1e/0x30 arch/x86/entry/entry_64.S:1139
> > fault_in_pages_readable include/linux/pagemap.h:601 [inline]
> > iov_iter_fault_in_readable+0x1b4/0x450 lib/iov_iter.c:421
> > generic_perform_write+0x216/0x6a0 mm/filemap.c:3144
> > __generic_file_write_iter+0x26e/0x630 mm/filemap.c:3279
> > generic_file_write_iter+0x436/0x870 mm/filemap.c:3307
> > call_write_iter include/linux/fs.h:1825 [inline]
> > do_iter_readv_writev+0x8b0/0xa80 fs/read_write.c:680
> > do_iter_write+0x185/0x5f0 fs/read_write.c:959
> > vfs_writev+0x1f1/0x360 fs/read_write.c:1004
> > do_pwritev+0x1cc/0x280 fs/read_write.c:1093
> > __do_sys_pwritev fs/read_write.c:1140 [inline]
> > __se_sys_pwritev fs/read_write.c:1135 [inline]
> > __x64_sys_pwritev+0x9a/0xf0 fs/read_write.c:1135
> > do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
> > entry_SYSCALL_64_after_hwframe+0x49/0xbe
> >
> > other info that might help us debug this:
> >
> > Chain exists of:
> >>mmap_sem --> ashmem_mutex --> >s_type->i_mutex_key#10
> >
> >   Possible unsafe locking scenario:
> >
> > CPU0CPU1
> > 
> >

Re: [PATCH V4] binder: ipc namespace support for android binder

2018-11-16 Thread Todd Kjos
On Thu, Nov 15, 2018 at 2:54 PM gre...@linuxfoundation.org
 wrote:
...
>
> A number of us have talked about this in the plumbers Android track, and
> a different proposal for how to solve this has been made that should be
> much more resiliant.  So I will drop this patch from my queue and wait
> for the patches based on the discussions we had there.
>
> I think there's some notes/slides on the discussion online somewhere,
> but it hasn't been published as the conference is still happening,
> otherwise I would link to it here...

Here is a link to the session where you can look at the slides [1].
There was consensus that "binderfs" (slide 5) was the most promising
-- but would be behind a config option to provide backwards
compatibility for non-container use-cases.

The etherpad notes are at [2] (look at "Dynamically Allocated Binder
Devices" section)

Christian Brauner will be sending out more details.

-Todd

[1] https://linuxplumbersconf.org/event/2/contributions/222/
[2] https://etherpad.openstack.org/p/Android

>
> thanks,
>
> greg k-h


[PATCH 3/3] binder: filter out nodes when showing binder procs

2018-12-05 Thread Todd Kjos
When dumping out binder transactions via a debug node,
the output is too verbose if a process has many nodes.
Change the output for transaction dumps to only display
nodes with pending async transactions.

Signed-off-by: Todd Kjos 
---
v2: no change, just resubmitted as #3 of 3 patches instead of by itself
There is no actual dependancy on patches 1 and 2 of the series

 drivers/android/binder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 172c207fbf99d..cbaef3b0d3078 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -5440,6 +5440,9 @@ static void print_binder_proc(struct seq_file *m,
for (n = rb_first(>nodes); n != NULL; n = rb_next(n)) {
struct binder_node *node = rb_entry(n, struct binder_node,
rb_node);
+   if (!print_all && !node->has_async_transaction)
+   continue;
+
/*
 * take a temporary reference on the node so it
 * survives and isn't removed from the tree
-- 
2.20.0.rc1.387.gf8505762e3-goog



[PATCH v2 1/3] binder: fix sparse warnings on locking context

2018-12-05 Thread Todd Kjos
Add __acquire()/__release() annnotations to fix warnings
in sparse context checking

There is one case where the warning was due to a lack of
a "default:" case in a switch statement where a lock was
being released in each of the cases, so the default
case was added.

Signed-off-by: Todd Kjos 
---
v2: no change, just resubmitted as #1 of 3 patches instead of by itself

 drivers/android/binder.c   | 43 +-
 drivers/android/binder_alloc.c |  1 +
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d6979cf7b2dad..172c207fbf99d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -660,6 +660,7 @@ struct binder_transaction {
 #define binder_proc_lock(proc) _binder_proc_lock(proc, __LINE__)
 static void
 _binder_proc_lock(struct binder_proc *proc, int line)
+   __acquires(>outer_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -675,6 +676,7 @@ _binder_proc_lock(struct binder_proc *proc, int line)
 #define binder_proc_unlock(_proc) _binder_proc_unlock(_proc, __LINE__)
 static void
 _binder_proc_unlock(struct binder_proc *proc, int line)
+   __releases(>outer_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -690,6 +692,7 @@ _binder_proc_unlock(struct binder_proc *proc, int line)
 #define binder_inner_proc_lock(proc) _binder_inner_proc_lock(proc, __LINE__)
 static void
 _binder_inner_proc_lock(struct binder_proc *proc, int line)
+   __acquires(>inner_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -705,6 +708,7 @@ _binder_inner_proc_lock(struct binder_proc *proc, int line)
 #define binder_inner_proc_unlock(proc) _binder_inner_proc_unlock(proc, 
__LINE__)
 static void
 _binder_inner_proc_unlock(struct binder_proc *proc, int line)
+   __releases(>inner_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -720,6 +724,7 @@ _binder_inner_proc_unlock(struct binder_proc *proc, int 
line)
 #define binder_node_lock(node) _binder_node_lock(node, __LINE__)
 static void
 _binder_node_lock(struct binder_node *node, int line)
+   __acquires(>lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -735,6 +740,7 @@ _binder_node_lock(struct binder_node *node, int line)
 #define binder_node_unlock(node) _binder_node_unlock(node, __LINE__)
 static void
 _binder_node_unlock(struct binder_node *node, int line)
+   __releases(>lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
@@ -751,12 +757,16 @@ _binder_node_unlock(struct binder_node *node, int line)
 #define binder_node_inner_lock(node) _binder_node_inner_lock(node, __LINE__)
 static void
 _binder_node_inner_lock(struct binder_node *node, int line)
+   __acquires(>lock) __acquires(>proc->inner_lock)
 {
binder_debug(BINDER_DEBUG_SPINLOCKS,
 "%s: line=%d\n", __func__, line);
spin_lock(>lock);
if (node->proc)
binder_inner_proc_lock(node->proc);
+   else
+   /* annotation for sparse */
+   __acquire(>proc->inner_lock);
 }
 
 /**
@@ -768,6 +778,7 @@ _binder_node_inner_lock(struct binder_node *node, int line)
 #define binder_node_inner_unlock(node) _binder_node_inner_unlock(node, 
__LINE__)
 static void
 _binder_node_inner_unlock(struct binder_node *node, int line)
+   __releases(>lock) __releases(>proc->inner_lock)
 {
struct binder_proc *proc = node->proc;
 
@@ -775,6 +786,9 @@ _binder_node_inner_unlock(struct binder_node *node, int 
line)
 "%s: line=%d\n", __func__, line);
if (proc)
binder_inner_proc_unlock(proc);
+   else
+   /* annotation for sparse */
+   __release(>proc->inner_lock);
spin_unlock(>lock);
 }
 
@@ -1384,10 +1398,14 @@ static void binder_dec_node_tmpref(struct binder_node 
*node)
binder_node_inner_lock(node);
if (!node->proc)
spin_lock(_dead_nodes_lock);
+   else
+   __acquire(_dead_nodes_lock);
node->tmp_refs--;
BUG_ON(node->tmp_refs < 0);
if (!node->proc)
spin_unlock(_dead_nodes_lock);
+   else
+   __release(_dead_nodes_lock);
/*
 * Call binder_dec_node() to check if all refcounts are 0
 * and cleanup is needed. Calling with strong=0 and internal=1
@@ -1890,18 +1908,22 @@ static struct binder_thread *binder_get_txn_from(
  */
 static struct binder_thread *binder_get_txn_from_and_acq_inner(

  1   2   3   4   >