Re: [PATCH 02/57] staging: android: ashmem: Supply description for 'new_range'

2021-04-15 Thread Todd Kjos
On Wed, Apr 14, 2021 at 11:11 AM Lee Jones  wrote:
>
> Fixes the following W=1 kernel build warning(s):
>
>  drivers/staging/android/ashmem.c:189: warning: Function parameter or member 
> 'new_range' not described in 'range_alloc'
>
> Cc: Greg Kroah-Hartman 
> Cc: "Arve Hjønnevåg" 
> Cc: Todd Kjos 
> Cc: Martijn Coenen 
> Cc: Joel Fernandes 
> Cc: Christian Brauner 
> Cc: Hridya Valsaraju 
> Cc: Suren Baghdasaryan 
> Cc: Robert Love 
> Cc: linux-stag...@lists.linux.dev
> Signed-off-by: Lee Jones 

Acked-by: Todd Kjos 

> ---
>  drivers/staging/android/ashmem.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/staging/android/ashmem.c 
> b/drivers/staging/android/ashmem.c
> index d66a64e42273a..8ee4320a5dc6d 100644
> --- a/drivers/staging/android/ashmem.c
> +++ b/drivers/staging/android/ashmem.c
> @@ -179,6 +179,7 @@ static inline void lru_del(struct ashmem_range *range)
>   * @purged:   Initial purge status (ASMEM_NOT_PURGED or 
> ASHMEM_WAS_PURGED)
>   * @start:The starting page (inclusive)
>   * @end:  The ending page (inclusive)
> + * @new_range:The placeholder for the new range
>   *
>   * This function is protected by ashmem_mutex.
>   */
> --
> 2.27.0
>


Re: [PATCH 2/2] binder: tell userspace to dump current backtrace when detected oneway spamming

2021-04-09 Thread Todd Kjos
On Fri, Apr 9, 2021 at 2:42 AM Hang Lu  wrote:
>
> When async binder buffer got exhausted, some normal oneway transactions
> will also be discarded and may cause system or application failures. By
> that time, the binder debug information we dump may not be relevant to
> the root cause. And this issue is difficult to debug if without the
> backtrace of the thread sending spam.
>
> This change will send BR_ONEWAY_SPAM_SUSPECT to userspace when oneway
> spamming is detected, request to dump current backtrace. Oneway spamming
> will be reported only once when exceeding the threshold (target process
> dips below 80% of its oneway space, and current process is responsible for
> either more than 50 transactions, or more than 50% of the oneway space).
> And the detection will restart when the async buffer has returned to a
> healthy state.
>
> Signed-off-by: Hang Lu 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c| 27 ---
>  drivers/android/binder_alloc.c  | 15 ---
>  drivers/android/binder_alloc.h  |  8 +++-
>  drivers/android/binder_internal.h   |  6 +-
>  include/uapi/linux/android/binder.h |  8 
>  5 files changed, 56 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index be34da3..63d2c43 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3020,7 +3020,10 @@ static void binder_transaction(struct binder_proc 
> *proc,
> goto err_bad_object_type;
> }
> }
> -   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
> +   if (t->buffer->oneway_spam_suspect)
> +   tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
> +   else
> +   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
> t->work.type = BINDER_WORK_TRANSACTION;
>
> if (reply) {
> @@ -3893,9 +3896,14 @@ static int binder_thread_read(struct binder_proc *proc,
>
> binder_stat_br(proc, thread, cmd);
> } break;
> -   case BINDER_WORK_TRANSACTION_COMPLETE: {
> +   case BINDER_WORK_TRANSACTION_COMPLETE:
> +   case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
> +   if (proc->oneway_spam_detection_enabled &&
> +  w->type == 
> BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
> +   cmd = BR_ONEWAY_SPAM_SUSPECT;
> +   else
> +   cmd = BR_TRANSACTION_COMPLETE;
> binder_inner_proc_unlock(proc);
> -   cmd = BR_TRANSACTION_COMPLETE;
> kfree(w);
> 
> binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> if (put_user(cmd, (uint32_t __user *)ptr))
> @@ -4897,6 +4905,18 @@ static long binder_ioctl(struct file *filp, unsigned 
> int cmd, unsigned long arg)
> }
> break;
> }
> +   case BINDER_ENABLE_ONEWAY_SPAM_DETECTION: {
> +   uint32_t enable;
> +
> +   if (copy_from_user(&enable, ubuf, sizeof(enable))) {
> +   ret = -EINVAL;
> +   goto err;
> +   }
> +   binder_inner_proc_lock(proc);
> +   proc->oneway_spam_detection_enabled = (bool)enable;
> +   binder_inner_proc_unlock(proc);
> +   break;
> +   }
> default:
> ret = -EINVAL;
> goto err;
> @@ -5561,6 +5581,7 @@ static const char * const binder_return_strings[] = {
> "BR_CLEAR_DEATH_NOTIFICATION_DONE",
> "BR_FAILED_REPLY",
> "BR_FROZEN_REPLY",
> +   "BR_ONEWAY_SPAM_SUSPECT",
>  };
>
>  static const char * const binder_command_strings[] = {
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 7caf74a..340515f 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -338,7 +338,7 @@ static inline struct vm_area_struct *binder_alloc_get_vma(
> return vma;
>  }
>
> -static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
> +static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
>  {
> /*
>  * Find the amount and size of buffers allocated by the current 
> caller;
> @@ -366,13 +366,19 @@ static void debug_low_async_space_locked(struct 
> binder_alloc *alloc, int 

Re: [PATCH 1/2] binder: fix the missing BR_FROZEN_REPLY in binder_return_strings

2021-04-09 Thread Todd Kjos
+Li Li

On Fri, Apr 9, 2021 at 2:42 AM Hang Lu  wrote:
>
> Add BR_FROZEN_REPLY in binder_return_strings to support stat function.
>
> Fixes: ae28c1be1e54 ("binder: BINDER_GET_FROZEN_INFO ioctl")
> Signed-off-by: Hang Lu 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c  | 3 ++-
>  drivers/android/binder_internal.h | 2 +-
>  2 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index e1a484a..be34da3 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -5559,7 +5559,8 @@ static const char * const binder_return_strings[] = {
> "BR_FINISHED",
> "BR_DEAD_BINDER",
> "BR_CLEAR_DEATH_NOTIFICATION_DONE",
> -   "BR_FAILED_REPLY"
> +   "BR_FAILED_REPLY",
> +   "BR_FROZEN_REPLY",
>  };
>
>  static const char * const binder_command_strings[] = {
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index 2872a7d..a507166 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -155,7 +155,7 @@ enum binder_stat_types {
>  };
>
>  struct binder_stats {
> -   atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> +   atomic_t br[_IOC_NR(BR_FROZEN_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];
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>


Re: [PATCH v4] binder: tell userspace to dump current backtrace when detecting oneway spamming

2021-04-07 Thread Todd Kjos
On Tue, Apr 6, 2021 at 9:15 PM Hang Lu  wrote:
>
> When async binder buffer got exhausted, some normal oneway transactions
> will also be discarded and may cause system or application failures. By
> that time, the binder debug information we dump may not be relevant to
> the root cause. And this issue is difficult to debug if without the
> backtrace of the thread sending spam.
>
> This change will send BR_ONEWAY_SPAM_SUSPECT to userspace when oneway
> spamming is detected, request to dump current backtrace. Oneway spamming
> will be reported only once when exceeding the threshold (target process
> dips below 80% of its oneway space, and current process is responsible for
> either more than 50 transactions, or more than 50% of the oneway space).
> And the detection will restart when the async buffer has returned to a
> healthy state.
>
> Signed-off-by: Hang Lu 
> ---
> v4: add placeholder for BR_FROZEN_REPLY in binder_return_strings for not 
> triggering BUG_ON in print_binder_stats

Instead of a placeholder, please rebase this series onto Greg's
char-misc-next branch in
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git and
add a new patch that fixes the missing "BR_FROZEN_REPLY".

>
> v3: add BR_ONEWAY_SPAM_SUSPECT to binder_return_strings
>
> v2: make the detection on/off switch to be per-proc
>
>  drivers/android/binder.c| 31 +++
>  drivers/android/binder_alloc.c  | 15 ---
>  drivers/android/binder_alloc.h  |  8 +++-
>  drivers/android/binder_internal.h   |  6 +-
>  include/uapi/linux/android/binder.h |  8 
>  5 files changed, 59 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index c119736..7046af90 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3007,7 +3007,10 @@ static void binder_transaction(struct binder_proc 
> *proc,
> goto err_bad_object_type;
> }
> }
> -   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
> +   if (t->buffer->oneway_spam_suspect)
> +   tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
> +   else
> +   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
> t->work.type = BINDER_WORK_TRANSACTION;
>
> if (reply) {
> @@ -3875,9 +3878,14 @@ static int binder_thread_read(struct binder_proc *proc,
>
> binder_stat_br(proc, thread, cmd);
> } break;
> -   case BINDER_WORK_TRANSACTION_COMPLETE: {
> +   case BINDER_WORK_TRANSACTION_COMPLETE:
> +   case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
> +   if (proc->oneway_spam_detection_enabled &&
> +  w->type == 
> BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
> +   cmd = BR_ONEWAY_SPAM_SUSPECT;
> +   else
> +   cmd = BR_TRANSACTION_COMPLETE;
> binder_inner_proc_unlock(proc);
> -   cmd = BR_TRANSACTION_COMPLETE;
> kfree(w);
> 
> binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> if (put_user(cmd, (uint32_t __user *)ptr))
> @@ -4727,6 +4735,18 @@ static long binder_ioctl(struct file *filp, unsigned 
> int cmd, unsigned long arg)
> }
> break;
> }
> +   case BINDER_ENABLE_ONEWAY_SPAM_DETECTION: {
> +   uint32_t enable;
> +
> +   if (copy_from_user(&enable, ubuf, sizeof(enable))) {
> +   ret = -EINVAL;
> +   goto err;
> +   }
> +   binder_inner_proc_lock(proc);
> +   proc->oneway_spam_detection_enabled = (bool)enable;
> +   binder_inner_proc_unlock(proc);
> +   break;
> +   }
> default:
> ret = -EINVAL;
> goto err;
> @@ -5385,7 +5405,10 @@ static const char * const binder_return_strings[] = {
> "BR_FINISHED",
> "BR_DEAD_BINDER",
> "BR_CLEAR_DEATH_NOTIFICATION_DONE",
> -   "BR_FAILED_REPLY"
> +   "BR_FAILED_REPLY",
> +   /* set placeholder for BR_FROZEN_REPLY */
> +   "PLACEHOLDER",

This should be in a new patch that fixes the issue for the previous patch.

> +   "BR_ONEWAY_SPAM_SUSPECT"
>  };
>
>  static const char * const binder_command_strings[] = {
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 7caf74a..340515f 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -338,7 +338,7 @@ static inline struct vm_area_struct *binder_alloc_get_vma(
> return vma;
>  }
>
> -static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
> +static bool debug_low_async_space_locked(struct binder_alloc

Re: [PATCH v2] binder: tell userspace to dump current backtrace when detecting oneway spamming

2021-04-06 Thread Todd Kjos
On Thu, Apr 1, 2021 at 1:29 AM Hang Lu  wrote:
>
> When async binder buffer got exhausted, some normal oneway transaction
> will also be discarded and finally caused system/app stop.

"...be discarded and may cause system or application failures" ?

> By that time,
> the binder debug information we dump may not relevant to the root cause.

"may not be relevant"

> And this issue is difficult to debug if without the backtrace of thread
> sending spam.

"...backtrace of the thread..."

>
> This change will send BR_ONEWAY_SPAM_SUSPECT to userspace when detecting
> oneway spamming, request to dump current backtrace.

"to userspace when oneway spamming is detected

> The detection will
> happened only once when exceeding the threshold (target process dips

"Oneway spamming will be reported only once..."

> below 80% of its oneway space, and current process is responsible for
> either more than 50 transactions, or more than 50% of the oneway space).
> And the detection will restart when the async buffer has returned to a
> healthy state.
>
> Signed-off-by: Hang Lu 
> ---
> v2: make the detection on/off switch to be per-proc
>
>  drivers/android/binder.c| 26 +++---
>  drivers/android/binder_alloc.c  | 15 ---
>  drivers/android/binder_alloc.h  |  8 +++-
>  drivers/android/binder_internal.h   |  4 
>  include/uapi/linux/android/binder.h |  8 
>  5 files changed, 54 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index c119736..93964d1 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3007,7 +3007,10 @@ static void binder_transaction(struct binder_proc 
> *proc,
> goto err_bad_object_type;
> }
> }
> -   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
> +   if (t->buffer->oneway_spam_suspect)
> +   tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
> +   else
> +   tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
> t->work.type = BINDER_WORK_TRANSACTION;
>
> if (reply) {
> @@ -3875,9 +3878,14 @@ static int binder_thread_read(struct binder_proc *proc,
>
> binder_stat_br(proc, thread, cmd);
> } break;
> -   case BINDER_WORK_TRANSACTION_COMPLETE: {
> +   case BINDER_WORK_TRANSACTION_COMPLETE:
> +   case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
> +   if (proc->oneway_spam_detection_enabled &&
> +  w->type == 
> BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
> +   cmd = BR_ONEWAY_SPAM_SUSPECT;

Doesn't "BR_ONEWAY_SPAM_SUSPECT" need to be added to binder_return_strings[]?

> +   else
> +   cmd = BR_TRANSACTION_COMPLETE;
> binder_inner_proc_unlock(proc);
> -   cmd = BR_TRANSACTION_COMPLETE;
> kfree(w);
> 
> binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> if (put_user(cmd, (uint32_t __user *)ptr))
> @@ -4727,6 +4735,18 @@ static long binder_ioctl(struct file *filp, unsigned 
> int cmd, unsigned long arg)
> }
> break;
> }
> +   case BINDER_ENABLE_ONEWAY_SPAM_DETECTION: {
> +   uint32_t enable;
> +
> +   if (copy_from_user(&enable, ubuf, sizeof(enable))) {
> +   ret = -EINVAL;
> +   goto err;
> +   }
> +   binder_inner_proc_lock(proc);
> +   proc->oneway_spam_detection_enabled = (bool)enable;
> +   binder_inner_proc_unlock(proc);
> +   break;
> +   }
> default:
> ret = -EINVAL;
> goto err;
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 7caf74a..a09872b 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -338,7 +338,7 @@ static inline struct vm_area_struct *binder_alloc_get_vma(
> return vma;
>  }
>
> -static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
> +static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
>  {
> /*
>  * Find the amount and size of buffers allocated by the current 
> caller;
> @@ -366,13 +366,19 @@ static void debug_low_async_space_locked(struct 
> binder_alloc *alloc, int pid)
>
> /*
>  * Warn if this pid has more than 50 transactions, or more than 50% of
> -* async space (which is 25% of total buffer size).
> +* async space (which is 25% of total buffer size). Oneway spam only
> +* detect once when exceed the threshold.

"Oneway spam is only detected when the threshold is exceeded"

>  */
> if (num_buff

Re: [PATCH v3 0/3] Binder: Enable App Freezing Capability

2021-03-18 Thread Todd Kjos
On Wed, Mar 17, 2021 at 1:17 PM Jann Horn  wrote:
>
> On Wed, Mar 17, 2021 at 7:00 PM Christian Brauner
>  wrote:
> > On Mon, Mar 15, 2021 at 06:16:27PM -0700, Li Li wrote:
> > > To improve the user experience when switching between recently used
> > > applications, the background applications which are not currently needed
> > > are cached in the memory. Normally, a well designed application will not
> > > consume valuable CPU resources in the background. However, it's possible
> > > some applications are not able or willing to behave as expected, wasting
> > > energy even after being cached.
> > >
> > > It is a good idea to freeze those applications when they're only being
> > > kept alive for the sake of faster startup and energy saving. These kernel
> > > patches will provide the necessary infrastructure for user space framework
> > > to freeze and thaw a cached process, check the current freezing status and
> > > correctly deal with outstanding binder transactions to frozen processes.
>
> I just have some comments on the overall design:
>
> This seems a bit convoluted to me; and I'm not sure whether this is
> really something the kernel should get involved in, or whether this
> patchset is operating at the right layer.

The issue is that there is lot's of per-process state in the binder
driver that needs to be quiesced prior to freezing the process (using
the standard freeze mechanism of
Documentation/admin-guide/cgroup-v1/freezer-subsystem.rst). That's all
this series does... quiesces binder state prior to freeze and then
re-enable transactions when the process is thawed.

>
> If there are non-binder threads that are misbehaving, could you
> instead stop all those threads in pure userspace code (e.g. by sending
> a thread-directed signal to all of them and letting the signal handler
> sleep on a futex); and if the binder thread receives a transaction
> that should be handled, wake up those threads again?

It is not an issue of stopping threads. It's an issue of quiescing
binder for a process so clients aren't blocked waiting for a response
from a frozen process that may never handle the transaction. This
series causes the soon-to-be-frozen process to reject new transactions
and allows user-space to detect when the transactions have drained
from the queues prior to freezing the process.

>
> Or alternatively you could detect that the application is being woken
> up frequently even though it's supposed to be idle (e.g. using
> information from procfs), and kill it since you consider it to be
> misbehaving?
>
> Or if there are specific usage patterns you see frequently that you
> consider to be wasting CPU resources (e.g. setting an interval timer
> that fires in short intervals), you could try to delay such timers.
>
>
> With your current approach, you're baking the assumption that all IPC
> goes through binder into the kernel API; things like passing a file
> descriptor to a pipe through binder or using shared futexes are no

No, we're dealing with an issue that is particular to binder IPC when
freezing a process. I suspect that other IPC mechanisms do not have
this issue -- and if any do for Android, then they would need
equivalent pre-freeze/post-freeze mechanisms. So far in the testing of
freezing in Android R, there haven't been issues with pipes or futexes
that required this kind of explicit quiescing (at least none that I
know of -- dualli@, please comment if there have been these kinds of
issues).

> longer usable for cross-process communication without making more
> kernel changes. I'm not sure whether that's a good idea. On top of
> that, if you freeze a process while it is in the middle of some
> operation, resources associated with the operation will probably stay
> in use for quite some time; for example, if an app is in the middle of
> downloading some data over HTTP, and you freeze it, this may cause the
> TCP connection to remain active and consume resources for send/receive
> buffers on both the device and the server.


Re: [PATCH v3 1/3] binder: BINDER_FREEZE ioctl

2021-03-16 Thread Todd Kjos
On Mon, Mar 15, 2021 at 6:16 PM Li Li  wrote:
>
> From: Marco Ballesio 
>
> Frozen tasks can't process binder transactions, so a way is required to
> inform transmitting ends of communication failures due to the frozen
> state of their receiving counterparts. Additionally, races are possible
> between transitions to frozen state and binder transactions enqueued to
> a specific process.
>
> Implement BINDER_FREEZE ioctl for user space to inform the binder driver
> about the intention to freeze or unfreeze a process. When the ioctl is
> called, block the caller until any pending binder transactions toward
> the target process are flushed. Return an error to transactions to
> processes marked as frozen.
>
> Signed-off-by: Marco Ballesio 
> Co-developed-by: Todd Kjos 
> Signed-off-by: Todd Kjos 
> Signed-off-by: Li Li 

For the series, you can add

Acked-by: Todd Kjos 


> ---
>  drivers/android/binder.c| 139 ++--
>  drivers/android/binder_internal.h   |  12 +++
>  include/uapi/linux/android/binder.h |  13 +++
>  3 files changed, 154 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index c119736ca56a..b93ca53bb90f 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1506,6 +1506,12 @@ static void binder_free_transaction(struct 
> binder_transaction *t)
>
> if (target_proc) {
> binder_inner_proc_lock(target_proc);
> +   target_proc->outstanding_txns--;
> +   if (target_proc->outstanding_txns < 0)
> +   pr_warn("%s: Unexpected outstanding_txns %d\n",
> +   __func__, target_proc->outstanding_txns);
> +   if (!target_proc->outstanding_txns && target_proc->is_frozen)
> +   wake_up_interruptible_all(&target_proc->freeze_wait);
> if (t->buffer)
> t->buffer->transaction = NULL;
> binder_inner_proc_unlock(target_proc);
> @@ -2331,10 +2337,11 @@ static int binder_fixup_parent(struct 
> binder_transaction *t,
>   * If the @thread parameter is not NULL, the transaction is always queued
>   * to the waitlist of that specific thread.
>   *
> - * Return: true if the transactions was successfully queued
> - * false if the target process or thread is dead
> + * Return: 0 if the transaction was successfully queued
> + * BR_DEAD_REPLY if the target process or thread is dead
> + * BR_FROZEN_REPLY if the target process or thread is frozen
>   */
> -static bool binder_proc_transaction(struct binder_transaction *t,
> +static int binder_proc_transaction(struct binder_transaction *t,
> struct binder_proc *proc,
> struct binder_thread *thread)
>  {
> @@ -2354,10 +2361,11 @@ static bool binder_proc_transaction(struct 
> binder_transaction *t,
>
> binder_inner_proc_lock(proc);
>
> -   if (proc->is_dead || (thread && thread->is_dead)) {
> +   if ((proc->is_frozen && !oneway) || proc->is_dead ||
> +   (thread && thread->is_dead)) {
> binder_inner_proc_unlock(proc);
> binder_node_unlock(node);
> -   return false;
> +   return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY;
> }
>
> if (!thread && !pending_async)
> @@ -2373,10 +2381,11 @@ static bool binder_proc_transaction(struct 
> binder_transaction *t,
> if (!pending_async)
> binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync 
> */);
>
> +   proc->outstanding_txns++;
> binder_inner_proc_unlock(proc);
> binder_node_unlock(node);
>
> -   return true;
> +   return 0;
>  }
>
>  /**
> @@ -3013,13 +3022,16 @@ static void binder_transaction(struct binder_proc 
> *proc,
> if (reply) {
> binder_enqueue_thread_work(thread, tcomplete);
> binder_inner_proc_lock(target_proc);
> -   if (target_thread->is_dead) {
> +   if (target_thread->is_dead || target_proc->is_frozen) {
> +   return_error = target_thread->is_dead ?
> +   BR_DEAD_REPLY : BR_FROZEN_REPLY;
> binder_inner_proc_unlock(target_proc);
> goto err_dead_proc_or_thread;
> }
> BUG_ON(t->buffer->async_transaction != 0);
> binder_pop_tr

Re: [PATCH v2 3/3] binder: BINDER_GET_FROZEN_INFO ioctl

2021-03-12 Thread Todd Kjos
On Thu, Mar 11, 2021 at 10:46 AM Li Li  wrote:
>
> From: Marco Ballesio 
>
> User space needs to know if binder transactions occurred to frozen
> processes. Introduce a new BINDER_GET_FROZEN ioctl and keep track of
> transactions occurring to frozen proceses.
>
> Signed-off-by: Marco Ballesio 
> Signed-off-by: Li Li 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c| 55 +
>  drivers/android/binder_internal.h   |  6 
>  include/uapi/linux/android/binder.h |  7 
>  3 files changed, 68 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 38bbf9a4ce99..b4999ed04b2e 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2360,6 +2360,10 @@ static int binder_proc_transaction(struct 
> binder_transaction *t,
> }
>
> binder_inner_proc_lock(proc);
> +   if (proc->is_frozen) {
> +   proc->sync_recv |= !oneway;
> +   proc->async_recv |= oneway;
> +   }
>
> if ((proc->is_frozen && !oneway) || proc->is_dead ||
> (thread && thread->is_dead)) {
> @@ -4636,6 +4640,8 @@ static int binder_ioctl_freeze(struct 
> binder_freeze_info *info,
>
> if (!info->enable) {
> binder_inner_proc_lock(target_proc);
> +   target_proc->sync_recv = false;
> +   target_proc->async_recv = false;
> target_proc->is_frozen = false;
> binder_inner_proc_unlock(target_proc);
> return 0;
> @@ -4647,6 +4653,8 @@ static int binder_ioctl_freeze(struct 
> binder_freeze_info *info,
>  * for transactions to drain.
>  */
> binder_inner_proc_lock(target_proc);
> +   target_proc->sync_recv = false;
> +   target_proc->async_recv = false;
> target_proc->is_frozen = true;
> binder_inner_proc_unlock(target_proc);
>
> @@ -4668,6 +4676,33 @@ static int binder_ioctl_freeze(struct 
> binder_freeze_info *info,
> return ret;
>  }
>
> +static int binder_ioctl_get_freezer_info(
> +   struct binder_frozen_status_info *info)
> +{
> +   struct binder_proc *target_proc;
> +   bool found = false;
> +
> +   info->sync_recv = 0;
> +   info->async_recv = 0;
> +
> +   mutex_lock(&binder_procs_lock);
> +   hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
> +   if (target_proc->pid == info->pid) {
> +   found = true;
> +   binder_inner_proc_lock(target_proc);
> +   info->sync_recv |= target_proc->sync_recv;
> +   info->async_recv |= target_proc->async_recv;
> +   binder_inner_proc_unlock(target_proc);
> +   }
> +   }
> +   mutex_unlock(&binder_procs_lock);
> +
> +   if (!found)
> +   return -EINVAL;
> +
> +   return 0;
> +}
> +
>  static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long 
> arg)
>  {
> int ret;
> @@ -4846,6 +4881,24 @@ static long binder_ioctl(struct file *filp, unsigned 
> int cmd, unsigned long arg)
> goto err;
> break;
> }
> +   case BINDER_GET_FROZEN_INFO: {
> +   struct binder_frozen_status_info info;
> +
> +   if (copy_from_user(&info, ubuf, sizeof(info))) {
> +   ret = -EFAULT;
> +   goto err;
> +   }
> +
> +   ret = binder_ioctl_get_freezer_info(&info);
> +   if (ret < 0)
> +   goto err;
> +
> +   if (copy_to_user(ubuf, &info, sizeof(info))) {
> +   ret = -EFAULT;
> +   goto err;
> +   }
> +   break;
> +   }
> default:
> ret = -EINVAL;
> goto err;
> @@ -5156,6 +5209,8 @@ static void binder_deferred_release(struct binder_proc 
> *proc)
>
> proc->is_dead = true;
> proc->is_frozen = false;
> +   proc->sync_recv = false;
> +   proc->async_recv = false;
> threads = 0;
> active_transactions = 0;
> while ((n = rb_first(&proc->threads))) {
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index e6a53e98c6da..2872a7de68e1 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_

Re: [PATCH v2 2/3] binder: use EINTR for interrupted wait for work

2021-03-12 Thread Todd Kjos
On Thu, Mar 11, 2021 at 10:46 AM Li Li  wrote:
>
> From: Marco Ballesio 
>
> when interrupted by a signal, binder_wait_for_work currently returns
> -ERESTARTSYS. This error code isn't propagated to user space, but a way
> to handle interruption due to signals must be provided to code using
> this API.
>
> Replace this instance of -ERESTARTSYS with -EINTR, which is propagated
> to user space.
>
> Test: built, booted, interrupted a worker thread within
> binder_wait_for_work
> Signed-off-by: Marco Ballesio 
> Signed-off-by: Li Li 

Acked-by: Todd Kjos 

> ---
>  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 76ea558df03e..38bbf9a4ce99 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3712,7 +3712,7 @@ static int binder_wait_for_work(struct binder_thread 
> *thread,
> binder_inner_proc_lock(proc);
> list_del_init(&thread->waiting_thread_node);
> if (signal_pending(current)) {
> -   ret = -ERESTARTSYS;
> +   ret = -EINTR;
> break;
> }
> }
> @@ -4855,7 +4855,7 @@ static long binder_ioctl(struct file *filp, unsigned 
> int cmd, unsigned long arg)
> if (thread)
> thread->looper_need_return = false;
> wait_event_interruptible(binder_user_error_wait, 
> binder_stop_on_user_error < 2);
> -   if (ret && ret != -ERESTARTSYS)
> +   if (ret && ret != -EINTR)
> pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, 
> current->pid, cmd, arg, ret);
>  err_unlocked:
> trace_binder_ioctl_done(ret);
> --
> 2.31.0.rc2.261.g7f71774620-goog
>


Re: [PATCH v2 1/3] binder: BINDER_FREEZE ioctl

2021-03-12 Thread Todd Kjos
On Thu, Mar 11, 2021 at 10:46 AM Li Li  wrote:
>
> From: Marco Ballesio 
>
> Frozen tasks can't process binder transactions, so a way is required to
> inform transmitting ends of communication failures due to the frozen
> state of their receiving counterparts. Additionally, races are possible
> between transitions to frozen state and binder transactions enqueued to
> a specific process.
>
> Implement BINDER_FREEZE ioctl for user space to inform the binder driver
> about the intention to freeze or unfreeze a process. When the ioctl is
> called, block the caller until any pending binder transactions toward
> the target process are flushed. Return an error to transactions to
> processes marked as frozen.
>
> Signed-off-by: Marco Ballesio 
> Co-developed-by: Todd Kjos 
> Signed-off-by: Todd Kjos 
> Signed-off-by: Li Li 
> ---
>  drivers/android/binder.c| 141 ++--
>  drivers/android/binder_internal.h   |  12 +++
>  include/uapi/linux/android/binder.h |  13 +++
>  3 files changed, 156 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index c119736ca56a..76ea558df03e 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1506,6 +1506,12 @@ static void binder_free_transaction(struct 
> binder_transaction *t)
>
> if (target_proc) {
> binder_inner_proc_lock(target_proc);
> +   target_proc->outstanding_txns--;
> +   if (target_proc->outstanding_txns < 0)
> +   pr_warn("%s: Unexpected outstanding_txns %d\n",
> +   __func__, target_proc->outstanding_txns);

Shouldn't this be something like "outstanding_txns is negative"? If we
ever see one of these, is this enough information to be useful? Should
we at least print the target proc's pid so someone can figure out what
process had the messed up count?

> +   if (!target_proc->outstanding_txns && target_proc->is_frozen)
> +   wake_up_interruptible_all(&target_proc->freeze_wait);
> if (t->buffer)
> t->buffer->transaction = NULL;
> binder_inner_proc_unlock(target_proc);
> @@ -2331,10 +2337,11 @@ static int binder_fixup_parent(struct 
> binder_transaction *t,
>   * If the @thread parameter is not NULL, the transaction is always queued
>   * to the waitlist of that specific thread.
>   *
> - * Return: true if the transactions was successfully queued
> - * false if the target process or thread is dead
> + * Return: 0 if the transaction was successfully queued
> + * BR_DEAD_REPLY if the target process or thread is dead
> + * BR_FROZEN_REPLY if the target process or thread is frozen
>   */
> -static bool binder_proc_transaction(struct binder_transaction *t,
> +static int binder_proc_transaction(struct binder_transaction *t,
> struct binder_proc *proc,
> struct binder_thread *thread)
>  {
> @@ -2354,10 +2361,13 @@ static bool binder_proc_transaction(struct 
> binder_transaction *t,
>
> binder_inner_proc_lock(proc);
>
> -   if (proc->is_dead || (thread && thread->is_dead)) {
> +   if ((proc->is_frozen && !oneway) || proc->is_dead ||
> +   (thread && thread->is_dead)) {
> +   bool proc_is_dead = proc->is_dead
> +   || (thread && thread->is_dead);
> binder_inner_proc_unlock(proc);
> binder_node_unlock(node);
> -   return false;
> +   return proc_is_dead ? BR_DEAD_REPLY : BR_FROZEN_REPLY;

Do we need the proc_is_dead local? This could be:
return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY

> }
>
> if (!thread && !pending_async)
> @@ -2373,10 +2383,11 @@ static bool binder_proc_transaction(struct 
> binder_transaction *t,
> if (!pending_async)
> binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync 
> */);
>
> +   proc->outstanding_txns++;
> binder_inner_proc_unlock(proc);
> binder_node_unlock(node);
>
> -   return true;
> +   return 0;
>  }
>
>  /**
> @@ -3013,13 +3024,16 @@ static void binder_transaction(struct binder_proc 
> *proc,
> if (reply) {
> binder_enqueue_thread_work(thread, tcomplete);
> binder_inner_proc_lock(target_proc);
> -   if (target_thread->is_dead) {
> + 

Re: [PATCH] driver: staging: count ashmem_range into SLAB_RECLAIMBLE

2020-12-21 Thread Todd Kjos
+Hridya Valsaraju +Suren Baghdasaryan


On Thu, Dec 17, 2020 at 11:48 PM Huangzhaoyang  wrote:
>
> From: Zhaoyang Huang 
>
> Add SLAB_RECLAIM_ACCOUNT to ashmem_range cache since it has registered
> shrinker, which make memAvailable more presiced.
>
> Signed-off-by: Zhaoyang Huang 

Acked-by: Todd Kjos 

> ---
>  drivers/staging/android/ashmem.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/staging/android/ashmem.c 
> b/drivers/staging/android/ashmem.c
> index 74d497d..b79301f 100644
> --- a/drivers/staging/android/ashmem.c
> +++ b/drivers/staging/android/ashmem.c
> @@ -893,7 +893,7 @@ static int __init ashmem_init(void)
>
> ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
> sizeof(struct ashmem_range),
> -   0, 0, NULL);
> +   0, SLAB_RECLAIM_ACCOUNT, 
> NULL);
> if (!ashmem_range_cachep) {
> pr_err("failed to create slab cache\n");
> goto out_free1;
> --
> 1.9.1
>


Re: [PATCH] binder: add flag to clear buffer on txn complete

2020-11-21 Thread Todd Kjos
On Fri, Nov 20, 2020 at 11:14 PM Greg KH  wrote:
>
> On Fri, Nov 20, 2020 at 03:37:43PM -0800, Todd Kjos wrote:
> > Add a per-transaction flag to indicate that the buffer
> > must be cleared when the transaction is complete to
> > prevent copies of sensitive data from being preserved
> > in memory.
> >
> > Signed-off-by: Todd Kjos 
> > ---
>
> DOes this need to be backported to stable kernels as well?

It doesn't technically qualify for stable since it is a new feature --
not a bug fix. We will want it for Android S launch devices (5.4+), so
it would be handy to have it in 5.4.y and later.

>
> thanks,
>
> greg k-h
>
> --
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to kernel-team+unsubscr...@android.com.
>


[PATCH] binder: add flag to clear buffer on txn complete

2020-11-20 Thread Todd Kjos
Add a per-transaction flag to indicate that the buffer
must be cleared when the transaction is complete to
prevent copies of sensitive data from being preserved
in memory.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c|  1 +
 drivers/android/binder_alloc.c  | 48 +
 drivers/android/binder_alloc.h  |  4 ++-
 include/uapi/linux/android/binder.h |  1 +
 4 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index b5117576792b..2a3952925855 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3146,6 +3146,7 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
+   t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
trace_binder_transaction_alloc_buf(t->buffer);
 
if (binder_alloc_copy_user_to_buffer(
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 2f846b7ae8b8..7caf74ad2405 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -696,6 +696,8 @@ static void binder_free_buf_locked(struct binder_alloc 
*alloc,
binder_insert_free_buffer(alloc, buffer);
 }
 
+static void binder_alloc_clear_buf(struct binder_alloc *alloc,
+  struct binder_buffer *buffer);
 /**
  * binder_alloc_free_buf() - free a binder buffer
  * @alloc: binder_alloc for this proc
@@ -706,6 +708,18 @@ static void binder_free_buf_locked(struct binder_alloc 
*alloc,
 void binder_alloc_free_buf(struct binder_alloc *alloc,
struct binder_buffer *buffer)
 {
+   /*
+* We could eliminate the call to binder_alloc_clear_buf()
+* from binder_alloc_deferred_release() by moving this to
+* binder_alloc_free_buf_locked(). However, that could
+* increase contention for the alloc mutex if clear_on_free
+* is used frequently for large buffers. The mutex is not
+* needed for correctness here.
+*/
+   if (buffer->clear_on_free) {
+   binder_alloc_clear_buf(alloc, buffer);
+   buffer->clear_on_free = false;
+   }
mutex_lock(&alloc->mutex);
binder_free_buf_locked(alloc, buffer);
mutex_unlock(&alloc->mutex);
@@ -802,6 +816,10 @@ void binder_alloc_deferred_release(struct binder_alloc 
*alloc)
/* Transaction should already have been freed */
BUG_ON(buffer->transaction);
 
+   if (buffer->clear_on_free) {
+   binder_alloc_clear_buf(alloc, buffer);
+   buffer->clear_on_free = false;
+   }
binder_free_buf_locked(alloc, buffer);
buffers++;
}
@@ -1135,6 +1153,36 @@ static struct page *binder_alloc_get_page(struct 
binder_alloc *alloc,
return lru_page->page_ptr;
 }
 
+/**
+ * binder_alloc_clear_buf() - zero out buffer
+ * @alloc: binder_alloc for this proc
+ * @buffer: binder buffer to be cleared
+ *
+ * memset the given buffer to 0
+ */
+static void binder_alloc_clear_buf(struct binder_alloc *alloc,
+  struct binder_buffer *buffer)
+{
+   size_t bytes = binder_alloc_buffer_size(alloc, buffer);
+   binder_size_t buffer_offset = 0;
+
+   while (bytes) {
+   unsigned long size;
+   struct page *page;
+   pgoff_t pgoff;
+   void *kptr;
+
+   page = binder_alloc_get_page(alloc, buffer,
+buffer_offset, &pgoff);
+   size = min_t(size_t, bytes, PAGE_SIZE - pgoff);
+   kptr = kmap(page) + pgoff;
+   memset(kptr, 0, size);
+   kunmap(page);
+   bytes -= size;
+   buffer_offset += size;
+   }
+}
+
 /**
  * binder_alloc_copy_user_to_buffer() - copy src user to tgt user
  * @alloc: binder_alloc for this proc
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index 55d8b4106766..6e8e001381af 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -23,6 +23,7 @@ struct binder_transaction;
  * @entry:  entry alloc->buffers
  * @rb_node:node for allocated_buffers/free_buffers rb trees
  * @free:   %true if buffer is free
+ * @clear_on_free:  %true if buffer must be zeroed after use
  * @allow_user_free:%true if user is allowed to free buffer
  * @async_transaction:  %true if buffer is in use for an async txn
  * @debug_id:   unique ID for debugging
@@ -41,9 +42,10 @@ struct binder_buffer {
struct rb_node rb_node; /* free entry by size or allocated entry */
/* by address */

Re: [PATCH] binder: fix UAF when releasing todo list

2020-10-09 Thread Todd Kjos
On Fri, Oct 9, 2020 at 4:24 PM Todd Kjos  wrote:
>
> When releasing a thread todo list when tearing down
> a binder_proc, the following race was possible which
> could result in a use-after-free:
>
> 1.  Thread 1: enter binder_release_work from binder_thread_release
> 2.  Thread 2: binder_update_ref_for_handle() -> binder_dec_node_ilocked()
> 3.  Thread 2: dec nodeA --> 0 (will free node)
> 4.  Thread 1: ACQ inner_proc_lock
> 5.  Thread 2: block on inner_proc_lock
> 6.  Thread 1: dequeue work (BINDER_WORK_NODE, part of nodeA)
> 7.  Thread 1: REL inner_proc_lock
> 8.  Thread 2: ACQ inner_proc_lock
> 9.  Thread 2: todo list cleanup, but work was already dequeued
> 10. Thread 2: free node
> 11. Thread 2: REL inner_proc_lock
> 12. Thread 1: deref w->type (UAF)
>
> The problem was that for a BINDER_WORK_NODE, the binder_work element
> must not be accessed after releasing the inner_proc_lock while
> processing the todo list elements since another thread might be
> handling a deref on the node containing the binder_work element
> leading to the node being freed.
>
> Signed-off-by: Todd Kjos 

Cc:  # 4.14, 4.19, 5.4, 5.8

> ---
>  drivers/android/binder.c | 35 ++-
>  1 file changed, 10 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index f936530a19b0..e8a1db4a86ed 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -223,7 +223,7 @@ static struct binder_transaction_log_entry 
> *binder_transaction_log_add(
>  struct binder_work {
> struct list_head entry;
>
> -   enum {
> +   enum binder_work_type {
> BINDER_WORK_TRANSACTION = 1,
> BINDER_WORK_TRANSACTION_COMPLETE,
> BINDER_WORK_RETURN_ERROR,
> @@ -885,27 +885,6 @@ static struct binder_work 
> *binder_dequeue_work_head_ilocked(
> return w;
>  }
>
> -/**
> - * binder_dequeue_work_head() - Dequeues the item at head of list
> - * @proc: binder_proc associated with list
> - * @list: list to dequeue head
> - *
> - * Removes the head of the list if there are items on the list
> - *
> - * Return: pointer dequeued binder_work, NULL if list was empty
> - */
> -static struct binder_work *binder_dequeue_work_head(
> -   struct binder_proc *proc,
> -   struct list_head *list)
> -{
> -   struct binder_work *w;
> -
> -   binder_inner_proc_lock(proc);
> -   w = binder_dequeue_work_head_ilocked(list);
> -   binder_inner_proc_unlock(proc);
> -   return w;
> -}
> -
>  static void
>  binder_defer_work(struct binder_proc *proc, enum binder_deferred_state 
> defer);
>  static void binder_free_thread(struct binder_thread *thread);
> @@ -4587,13 +4566,17 @@ static void binder_release_work(struct binder_proc 
> *proc,
> struct list_head *list)
>  {
> struct binder_work *w;
> +   enum binder_work_type wtype;
>
> while (1) {
> -   w = binder_dequeue_work_head(proc, list);
> +   binder_inner_proc_lock(proc);
> +   w = binder_dequeue_work_head_ilocked(list);
> +   wtype = w ? w->type : 0;
> +   binder_inner_proc_unlock(proc);
> if (!w)
> return;
>
> -   switch (w->type) {
> +   switch (wtype) {
> case BINDER_WORK_TRANSACTION: {
> struct binder_transaction *t;
>
> @@ -4627,9 +4610,11 @@ static void binder_release_work(struct binder_proc 
> *proc,
> kfree(death);
> binder_stats_deleted(BINDER_STAT_DEATH);
> } break;
> +   case BINDER_WORK_NODE:
> +   break;
> default:
> pr_err("unexpected work type, %d, not freed\n",
> -  w->type);
> +  wtype);
> break;
> }
> }
> --
> 2.28.0.1011.ga647a8990f-goog
>


[PATCH] binder: fix UAF when releasing todo list

2020-10-09 Thread Todd Kjos
When releasing a thread todo list when tearing down
a binder_proc, the following race was possible which
could result in a use-after-free:

1.  Thread 1: enter binder_release_work from binder_thread_release
2.  Thread 2: binder_update_ref_for_handle() -> binder_dec_node_ilocked()
3.  Thread 2: dec nodeA --> 0 (will free node)
4.  Thread 1: ACQ inner_proc_lock
5.  Thread 2: block on inner_proc_lock
6.  Thread 1: dequeue work (BINDER_WORK_NODE, part of nodeA)
7.  Thread 1: REL inner_proc_lock
8.  Thread 2: ACQ inner_proc_lock
9.  Thread 2: todo list cleanup, but work was already dequeued
10. Thread 2: free node
11. Thread 2: REL inner_proc_lock
12. Thread 1: deref w->type (UAF)

The problem was that for a BINDER_WORK_NODE, the binder_work element
must not be accessed after releasing the inner_proc_lock while
processing the todo list elements since another thread might be
handling a deref on the node containing the binder_work element
leading to the node being freed.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 35 ++-
 1 file changed, 10 insertions(+), 25 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f936530a19b0..e8a1db4a86ed 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -223,7 +223,7 @@ static struct binder_transaction_log_entry 
*binder_transaction_log_add(
 struct binder_work {
struct list_head entry;
 
-   enum {
+   enum binder_work_type {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
BINDER_WORK_RETURN_ERROR,
@@ -885,27 +885,6 @@ static struct binder_work 
*binder_dequeue_work_head_ilocked(
return w;
 }
 
-/**
- * binder_dequeue_work_head() - Dequeues the item at head of list
- * @proc: binder_proc associated with list
- * @list: list to dequeue head
- *
- * Removes the head of the list if there are items on the list
- *
- * Return: pointer dequeued binder_work, NULL if list was empty
- */
-static struct binder_work *binder_dequeue_work_head(
-   struct binder_proc *proc,
-   struct list_head *list)
-{
-   struct binder_work *w;
-
-   binder_inner_proc_lock(proc);
-   w = binder_dequeue_work_head_ilocked(list);
-   binder_inner_proc_unlock(proc);
-   return w;
-}
-
 static void
 binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
 static void binder_free_thread(struct binder_thread *thread);
@@ -4587,13 +4566,17 @@ static void binder_release_work(struct binder_proc 
*proc,
struct list_head *list)
 {
struct binder_work *w;
+   enum binder_work_type wtype;
 
while (1) {
-   w = binder_dequeue_work_head(proc, list);
+   binder_inner_proc_lock(proc);
+   w = binder_dequeue_work_head_ilocked(list);
+   wtype = w ? w->type : 0;
+   binder_inner_proc_unlock(proc);
if (!w)
return;
 
-   switch (w->type) {
+   switch (wtype) {
case BINDER_WORK_TRANSACTION: {
struct binder_transaction *t;
 
@@ -4627,9 +4610,11 @@ static void binder_release_work(struct binder_proc *proc,
kfree(death);
binder_stats_deleted(BINDER_STAT_DEATH);
} break;
+   case BINDER_WORK_NODE:
+   break;
default:
pr_err("unexpected work type, %d, not freed\n",
-  w->type);
+  wtype);
break;
}
}
-- 
2.28.0.1011.ga647a8990f-goog



Re: [PATCH][next] binder: remove redundant assignment to pointer n

2020-09-10 Thread Todd Kjos
On Thu, Sep 10, 2020 at 8:12 AM Colin King  wrote:
>
> From: Colin Ian King 
>
> The pointer n is being initialized with a value that is
> never read and it is being updated later with a new value. The
> initialization is redundant and can be removed.
>
> Addresses-Coverity: ("Unused value")
> Signed-off-by: Colin Ian King 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder_alloc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 910c53ba2c91..2f846b7ae8b8 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -347,7 +347,7 @@ static void debug_low_async_space_locked(struct 
> binder_alloc *alloc, int pid)
>  * and at some point we'll catch them in the act. This is more 
> efficient
>  * than keeping a map per pid.
>  */
> -   struct rb_node *n = alloc->free_buffers.rb_node;
> +   struct rb_node *n;
> struct binder_buffer *buffer;
> size_t total_alloc_size = 0;
> size_t num_buffers = 0;
> --
> 2.27.0
>


Re: [PATCH v3] binder: print warnings when detecting oneway spamming.

2020-08-21 Thread Todd Kjos
On Fri, Aug 21, 2020 at 5:25 AM Martijn Coenen  wrote:
>
> The most common cause of the binder transaction buffer filling up is a
> client rapidly firing oneway transactions into a process, before it has
> a chance to handle them. Yet the root cause of this is often hard to
> debug, because either the system or the app will stop, and by that time
> binder debug information we dump in bugreports is no longer relevant.
>
> This change warns as soon as a process dips below 80% of its oneway
> space (less than 100kB available in the configuration), when any one
> process is responsible for either more than 50 transactions, or more
> than 50% of the oneway space.
>
> Signed-off-by: Martijn Coenen 

Acked-by: Todd Kjos 

> ---
> v2: fixed call-site in binder_alloc_selftest
>
> v3: include size of struct binder_buffer in calculation, fix comments
>
>  drivers/android/binder.c|  2 +-
>  drivers/android/binder_alloc.c  | 55 +++--
>  drivers/android/binder_alloc.h  |  5 ++-
>  drivers/android/binder_alloc_selftest.c |  2 +-
>  4 files changed, 58 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index f936530a19b0..946332bc871a 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3136,7 +3136,7 @@ static void binder_transaction(struct binder_proc *proc,
>
> t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
> tr->offsets_size, extra_buffers_size,
> -   !reply && (t->flags & TF_ONE_WAY));
> +   !reply && (t->flags & TF_ONE_WAY), current->tgid);
> if (IS_ERR(t->buffer)) {
> /*
>  * -ESRCH indicates VMA cleared. The target is dying.
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 69609696a843..b5b6c9cf1b0b 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -338,12 +338,50 @@ static inline struct vm_area_struct 
> *binder_alloc_get_vma(
> return vma;
>  }
>
> +static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
> +{
> +   /*
> +* Find the amount and size of buffers allocated by the current 
> caller;
> +* The idea is that once we cross the threshold, whoever is 
> responsible
> +* for the low async space is likely to try to send another async txn,
> +* and at some point we'll catch them in the act. This is more 
> efficient
> +* than keeping a map per pid.
> +*/
> +   struct rb_node *n = alloc->free_buffers.rb_node;
> +   struct binder_buffer *buffer;
> +   size_t total_alloc_size = 0;
> +   size_t num_buffers = 0;
> +
> +   for (n = rb_first(&alloc->allocated_buffers); n != NULL;
> +n = rb_next(n)) {
> +   buffer = rb_entry(n, struct binder_buffer, rb_node);
> +   if (buffer->pid != pid)
> +   continue;
> +   if (!buffer->async_transaction)
> +   continue;
> +   total_alloc_size += binder_alloc_buffer_size(alloc, buffer)
> +   + sizeof(struct binder_buffer);
> +   num_buffers++;
> +   }
> +
> +   /*
> +* Warn if this pid has more than 50 transactions, or more than 50% of
> +* async space (which is 25% of total buffer size).
> +*/
> +   if (num_buffers > 50 || total_alloc_size > alloc->buffer_size / 4) {
> +   binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
> +"%d: pid %d spamming oneway? %zd buffers 
> allocated for a total size of %zd\n",
> + alloc->pid, pid, num_buffers, total_alloc_size);
> +   }
> +}
> +
>  static struct binder_buffer *binder_alloc_new_buf_locked(
> struct binder_alloc *alloc,
> size_t data_size,
> size_t offsets_size,
> size_t extra_buffers_size,
> -   int is_async)
> +   int is_async,
> +   int pid)
>  {
> struct rb_node *n = alloc->free_buffers.rb_node;
> struct binder_buffer *buffer;
> @@ -486,11 +524,20 @@ static struct binder_buffer 
> *binder_alloc_new_buf_locked(
> buffer->offsets_size = offsets_size;
> buffer->async_transaction = is_async;
> buffer->extra_buffers_size = extra_buffers_si

Re: [PATCH v2] ANDROID: binder: print warnings when detecting oneway spamming.

2020-08-20 Thread Todd Kjos
On Thu, Aug 20, 2020 at 4:50 AM Martijn Coenen  wrote:
>
> The most common cause of the binder transaction buffer filling up is a
> client rapidly firing oneway transactions into a process, before it has
> a chance to handle them. Yet the root cause of this is often hard to
> debug, because either the system or the app will stop, and by that time
> binder debug information we dump in bugreports is no longer relevant.
>
> This change warns as soon as a process dips below 80% of its oneway
> space (less than 100kB available in the configuration), when any one
> process is responsible for either more than 50 transactions, or more
> than 50% of the oneway space.
>
> Signed-off-by: Martijn Coenen 

A few minor comment issues below. When resolved:
Acked-by: Todd Kjos 

> ---
> v2: fixed call-site in binder_alloc_selftest
>
>  drivers/android/binder.c|  2 +-
>  drivers/android/binder_alloc.c  | 49 +++--
>  drivers/android/binder_alloc.h  |  5 ++-
>  drivers/android/binder_alloc_selftest.c |  2 +-
>  4 files changed, 52 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index f936530a19b0..946332bc871a 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3136,7 +3136,7 @@ static void binder_transaction(struct binder_proc *proc,
>
> t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
> tr->offsets_size, extra_buffers_size,
> -   !reply && (t->flags & TF_ONE_WAY));
> +   !reply && (t->flags & TF_ONE_WAY), current->tgid);
> if (IS_ERR(t->buffer)) {
> /*
>  * -ESRCH indicates VMA cleared. The target is dying.
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 69609696a843..76e8e633dbd4 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -338,12 +338,48 @@ static inline struct vm_area_struct 
> *binder_alloc_get_vma(
> return vma;
>  }
>
> +static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
> +{
> +   /*
> +* Find the amount and size of buffers allocated by the current 
> caller;
> +* The idea is that once we cross the threshold, whoever is 
> responsible
> +* for the low async space is likely to try to send another async txn,
> +* and at some point we'll catch them in the act. This is more 
> efficient
> +* than keeping a map per pid.
> +*/
> +   struct rb_node *n = alloc->free_buffers.rb_node;
> +   struct binder_buffer *buffer;
> +   size_t buffer_size;
> +   size_t total_alloc_size = 0;
> +   size_t num_buffers = 0;
> +
> +   for (n = rb_first(&alloc->allocated_buffers); n != NULL;
> +n = rb_next(n)) {
> +   buffer = rb_entry(n, struct binder_buffer, rb_node);
> +   if (buffer->pid != pid)
> +   continue;
> +   if (!buffer->async_transaction)
> +   continue;
> +   buffer_size = binder_alloc_buffer_size(alloc, buffer);
> +   total_alloc_size += buffer_size;
> +   num_buffers++;
> +   }
> +
> +   // Warn if this pid has more than 50% of async space, or more than 50 
> txns

/* .. */

Folks might be confused by 50% being calculated as (alloc->buffer_size
/4) which on the surface looks like 25%. Maybe either change the
comment to "25% of buffer space" or point out that async space is 50%
of the buffer.


> +   if (num_buffers > 50 || total_alloc_size > alloc->buffer_size / 4) {
> +   binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
> +"%d: pid %d spamming oneway? %zd buffers 
> allocated for a total size of %zd\n",
> + alloc->pid, pid, num_buffers, total_alloc_size);
> +   }
> +}
> +
>  static struct binder_buffer *binder_alloc_new_buf_locked(
> struct binder_alloc *alloc,
> size_t data_size,
> size_t offsets_size,
> size_t extra_buffers_size,
> -   int is_async)
> +   int is_async,
> +   int pid)
>  {
> struct rb_node *n = alloc->free_buffers.rb_node;
> struct binder_buffer *buffer;
> @@ -486,11 +522,16 @@ static struct binder_buffer 
> *binder_alloc_new_buf_locked(
> buffer

Re: [PATCH] binder: Remove bogus warning on failed same-process transaction

2020-08-06 Thread Todd Kjos
On Thu, Aug 6, 2020 at 9:54 AM Jann Horn  wrote:
>
> While binder transactions with the same binder_proc as sender and recipient
> are forbidden, transactions with the same task_struct as sender and
> recipient are possible (even though currently there is a weird check in
> binder_transaction() that rejects them in the target==0 case).
> Therefore, task_struct identities can't be used to distinguish whether
> the caller is running in the context of the sender or the recipient.
>
> Since I see no easy way to make this WARN_ON() useful and correct, let's
> just remove it.
>
> Fixes: 44d8047f1d87 ("binder: use standard functions to allocate fds")
> Reported-by: syzbot+e113a0b970b7b3f39...@syzkaller.appspotmail.com
> Signed-off-by: Jann Horn 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index f936530a19b0..5b0376344dbe 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2344,8 +2344,6 @@ static void binder_transaction_buffer_release(struct 
> binder_proc *proc,
>  * file is done when the transaction is torn
>  * down.
>  */
> -   WARN_ON(failed_at &&
> -   proc->tsk == current->group_leader);
> } break;
> case BINDER_TYPE_PTR:
> /*
>
> base-commit: 47ec5303d73ea344e84f46660fff693c57641386
> --
> 2.28.0.163.g6104cc2f0b6-goog
>


Re: WARNING in binder_transaction_buffer_release (2)

2020-08-06 Thread Todd Kjos
On Thu, Aug 6, 2020 at 9:09 AM Jann Horn  wrote:
>
> On Thu, Aug 6, 2020 at 1:19 PM syzbot
>  wrote:
> > syzbot suspects this issue was fixed by commit:
> >
> > commit 4b836a1426cb0f1ef2a6e211d7e553221594f8fc
> > Author: Jann Horn 
> > Date:   Mon Jul 27 12:04:24 2020 +
> >
> > binder: Prevent context manager from incrementing ref 0
> [...]
> > dashboard link: https://syzkaller.appspot.com/bug?extid=e113a0b970b7b3f394ba
> [...]
> > If the result looks correct, please mark the issue as fixed by replying 
> > with:
> >
> > #syz fix: binder: Prevent context manager from incrementing ref 0
>
> I think this issue still exists, syzbot probably just hit it in a
> weird way that doesn't work anymore.
>
> This warning:
>
> case BINDER_TYPE_FD: {
> /*
>  * No need to close the file here since user-space
>  * closes it for for successfully delivered
>  * transactions. For transactions that weren't
>  * delivered, the new fd was never allocated so
>  * there is no need to close and the fput on the
>  * file is done when the transaction is torn
>  * down.
>  */
> WARN_ON(failed_at &&
> proc->tsk == current->group_leader);
> } break;
>
> can be false-positive if the sender and recipient of the transaction
> are associated with the same task_struct. But there isn't really any
> reason why you wouldn't be able to have sender and recipient in the
> same process, as long as the binder_proc is different.
> (binder_transaction() has a weird check that refuses transactions to
> handle 0 based on task_struct equality - which IMO doesn't really make
> sense -, but transactions to other handles can happen just fine even
> if both ends are in the same task_struct.)
>
> Maybe the best fix is just to rip out that WARN_ON()?

Yes, probably so.


Re: [PATCH v7 3/3] binder: add transaction latency tracer

2020-08-04 Thread Todd Kjos
On Tue, Aug 4, 2020 at 6:59 AM Frankie Chang  wrote:
>
> From: "Frankie.Chang" 
>
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold
> (default 2 sec), if yes, printing related information for tracing.
>
> /* Implement details */
> - Add latency tracer module to monitor transaction
>   by attaching to new tracepoints introduced
>   when transactions are allocated and freed.
>   The trace_binder_txn_latency_free would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
>
> - Since some of modules would trigger timeout NE
>   if their binder transaction don't finish in time,
>   such as audio timeout (5 sec), even BT command
>   timeout (2 sec), etc.
>   Therefore, setting the timeout threshold as default
>   2 seconds could be helpful to debug.
>   But this timeout threshold is configurable, to let
>   all users determine the more suitable threshold.
>
> - The reason why printing the related information to
>   kernel information log but not trace buffer is that
>   some abnormal transactions may be pending for a long
>   time ago, they could not be recorded due to buffer
>   limited.
>
> Signed-off-by: Frankie.Chang 

Acked-by: Todd Kjos 

> ---
>  drivers/android/Kconfig |8 +++
>  drivers/android/Makefile|1 +
>  drivers/android/binder.c|2 +
>  drivers/android/binder_internal.h   |   13 
>  drivers/android/binder_latency_tracer.c |  112 
> +++
>  drivers/android/binder_trace.h  |   26 ++-
>  6 files changed, 159 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..91fff1e 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>   exhaustively with combinations of various buffer sizes and
>   alignments.
>
> +config BINDER_TRANSACTION_LATENCY_TRACKING
> +   tristate "Android Binder transaction tracking"
> +   help
> + Used for track abnormal binder transaction which is over threshold,
> + when the transaction is done or be free, this transaction would be
> + checked whether it executed overtime.
> + If yes, printing out the detailed info.
> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..c2ffdb6 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)   # needed for trace 
> events
>  obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)   += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)  += 
> binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 1bfadc2..22f7cc6 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2671,6 +2671,7 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_alloc_t_failed;
> }
> +   trace_binder_txn_latency_alloc(t);
> INIT_LIST_HEAD(&t->fd_fixups);
> binder_stats_created(BINDER_STAT_TRANSACTION);
> spin_lock_init(&t->lock);
> @@ -5159,6 +5160,7 @@ static void print_binder_transaction_ilocked(struct 
> seq_file *m,
>to_proc ? to_proc->pid : 0,
>t->to_thread ? t->to_thread->pid : 0,
>t->code, t->flags, t->priority, t->need_reply);
> +   trace_binder_txn_latency_info(m, t);
> spin_unlock(&t->lock);
>
> if (proc != to_proc) {
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index 5b65413..596db00 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -13,6 +13,11 @@
>  #include 
>  #include "binder_alloc.h"
>
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +#include 
> +#include 
> +#endif
> +
>  struct binder_context {
> struct binder_node *binder_context_mgr_node;
> struct mutex context_mgr_node_lock;
> @@ -521,6 +52

Re: [PATCH v7 2/3] binder: add trace at free transaction.

2020-08-04 Thread Todd Kjos
On Tue, Aug 4, 2020 at 7:09 AM Frankie Chang  wrote:
>
> From: "Frankie.Chang" 
>
> Since the original trace_binder_transaction_received cannot
> precisely present the real finished time of transaction, adding a
> trace_binder_txn_latency_free at the point of free transaction
> may be more close to it.
>
> Signed-off-by: Frankie.Chang 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c   |   18 ++
>  drivers/android/binder_trace.h |   29 +
>  2 files changed, 47 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 2df146f..1bfadc2 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1508,6 +1508,20 @@ static void binder_free_txn_fixups(struct 
> binder_transaction *t)
> }
>  }
>
> +static void binder_txn_latency_free(struct binder_transaction *t)
> +{
> +   int from_proc, from_thread, to_proc, to_thread;
> +
> +   spin_lock(&t->lock);
> +   from_proc = t->from ? t->from->proc->pid : 0;
> +   from_thread = t->from ? t->from->pid : 0;
> +   to_proc = t->to_proc ? t->to_proc->pid : 0;
> +   to_thread = t->to_thread ? t->to_thread->pid : 0;
> +   spin_unlock(&t->lock);
> +
> +   trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, 
> to_thread);
> +}
> +
>  static void binder_free_transaction(struct binder_transaction *t)
>  {
> struct binder_proc *target_proc = t->to_proc;
> @@ -1518,6 +1532,8 @@ static void binder_free_transaction(struct 
> binder_transaction *t)
> t->buffer->transaction = NULL;
> binder_inner_proc_unlock(target_proc);
> }
> +   if (trace_binder_txn_latency_free_enabled())
> +   binder_txn_latency_free(t);
> /*
>  * If the transaction has no target_proc, then
>  * t->buffer->transaction has already been cleared.
> @@ -3093,6 +3109,8 @@ static void binder_transaction(struct binder_proc *proc,
> kfree(tcomplete);
> binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +   if (trace_binder_txn_latency_free_enabled())
> +   binder_txn_latency_free(t);
> kfree(t);
> binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..eb2c53c 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,35 @@
>   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_txn_latency_free,
> +   TP_PROTO(struct binder_transaction *t
> +int from_proc, int from_thread
> +int to_proc, int to_thread),
> +   TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
> +   TP_STRUCT__entry(
> +   __field(int, debug_id)
> +   __field(int, from_proc)
> +   __field(int, from_thread)
> +   __field(int, to_proc)
> +   __field(int, to_thread)
> +   __field(unsigned int, code)
> +   __field(unsigned int, flags)
> +   ),
> +   TP_fast_assign(
> +   __entry->debug_id = t->debug_id;
> +   __entry->from_proc = from_proc;
> +   __entry->from_thread = from_thread;
> +   __entry->to_proc = to_proc;
> +   __entry->to_thread = to_thread;
> +   __entry->code = t->code;
> +   __entry->flags = t->flags;
> +   ),
> +   TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> + __entry->debug_id, __entry->from_proc, __entry->from_thread,
> + __entry->to_proc, __entry->to_thread, __entry->code,
> + __entry->flags)
> +);
> +
>  TRACE_EVENT(binder_transaction,
> TP_PROTO(bool reply, struct binder_transaction *t,
>  struct binder_node *target_node),
> --
> 1.7.9.5


Re: [PATCH v7 1/3] binder: move structs from core file to header file

2020-08-04 Thread Todd Kjos
On Tue, Aug 4, 2020 at 6:59 AM Frankie Chang  wrote:
>
> From: "Frankie.Chang" 
>
> Moving all structs to header file makes module more
> extendable, and makes all these structs to be defined
> in the same file.
>
> Signed-off-by: Frankie.Chang 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c  |  405 
> -
>  drivers/android/binder_internal.h |  404 
>  2 files changed, 404 insertions(+), 405 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index a6b2082..2df146f 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -72,7 +72,6 @@
>
>  #include 
>
> -#include "binder_alloc.h"
>  #include "binder_internal.h"
>  #include "binder_trace.h"
>
> @@ -160,24 +159,6 @@ static int binder_set_stop_on_user_error(const char *val,
>  #define to_binder_fd_array_object(hdr) \
> container_of(hdr, struct binder_fd_array_object, hdr)
>
> -enum binder_stat_types {
> -   BINDER_STAT_PROC,
> -   BINDER_STAT_THREAD,
> -   BINDER_STAT_NODE,
> -   BINDER_STAT_REF,
> -   BINDER_STAT_DEATH,
> -   BINDER_STAT_TRANSACTION,
> -   BINDER_STAT_TRANSACTION_COMPLETE,
> -   BINDER_STAT_COUNT
> -};
> -
> -struct binder_stats {
> -   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)
> @@ -213,278 +194,11 @@ static struct binder_transaction_log_entry 
> *binder_transaction_log_add(
> return e;
>  }
>
> -/**
> - * 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,
> -   BINDER_WORK_RETURN_ERROR,
> -   BINDER_WORK_NODE,
> -   BINDER_WORK_DEAD_BINDER,
> -   BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> -   BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> -   } type;
> -};
> -
> -struct binder_error {
> -   struct binder_work work;
> -   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
> - *(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
> - *(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
> - *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 loc

Re: [PATCH v6 2/3] binder: add trace at free transaction.

2020-08-03 Thread Todd Kjos
On Sun, Aug 2, 2020 at 8:11 PM Frankie Chang  wrote:
>
> On Fri, 2020-07-31 at 11:50 -0700, Todd Kjos wrote:
> > On Mon, Jul 27, 2020 at 8:28 PM Frankie Chang
> >  wrote:
> > >
> > > From: "Frankie.Chang" 
> > >
> > > Since the original trace_binder_transaction_received cannot
> > > precisely present the real finished time of transaction, adding a
> > > trace_binder_txn_latency_free at the point of free transaction
> > > may be more close to it.
> > >
> > > Signed-off-by: Frankie.Chang 
> > > ---
> > >  drivers/android/binder.c   |6 ++
> > >  drivers/android/binder_trace.h |   27 +++
> > >  2 files changed, 33 insertions(+)
> > >
> > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > index 2df146f..1e6fc40 100644
> > > --- a/drivers/android/binder.c
> > > +++ b/drivers/android/binder.c
> > > @@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct 
> > > binder_transaction *t)
> > >  * If the transaction has no target_proc, then
> > >  * t->buffer->transaction has already been cleared.
> > >  */
> > > +   spin_lock(&t->lock);
> > > +   trace_binder_txn_latency_free(t);
> > > +   spin_unlock(&t->lock);
> >
> > Hmm. I don't prefer taking the lock just to call a trace. It doesn't
> > make clear why the lock has to be taken. I'd prefer something like:
> >
> > if (trace_binder_txn_latency_free_enabled()) {
> c
> > }
> >
> > And then the trace would use the passed-in values instead of accessing
> > via t->to_proc/to_thread.
> >
> Then we still add lock protection in the hook function, when trace is
> disable ?

I don't understand... in the example I gave, the trace doesn't get
called if disabled. What do you mean to "add lock protection when the
trace is disabled()"?

>
> Or we also pass these to hook function, no matter the trace is enable or

What do you mean by "hook" function? If something has attached to the
trace, then xxx_enabled() will return true.

> not.I think this way is more clear that the lock protects @from,
> @to_proc and @to_thread.Then, there is no need to add the lock in hook
> function.

Why is it clearer (other than the fact that I missed including t->from
under the lock)?

>
> int from_proc, from_thread, to_proc, to_thread;
>
> spin_lock(&t->lock);
> from_proc = t->from ? t->from->proc->pid : 0;
> from_thread = t->from ? t->from->pid :0;
> to_proc = t->to_proc ? t->to_proc->pid : 0;
> to_thread = t->to_thread ? t->to_thread->pid : 0;
> spin_unlock(&t->lock);
> trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc,
> to_pid);

The main feedback is I'd like to see the fields dereferenced in the
same context as the lock acquisition instead of acquiring the lock and
calling the trace function, so this code would be fine. There will be
very little contention for t->lock so using xxx_enabled() is optional.

Since trace_binder_txn_latency_free() is called twice,  it would make
sense to have a helper function to do the above.

>
> > > binder_free_txn_fixups(t);
> > > kfree(t);
> > > binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > > @@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc 
> > > *proc,
> > > kfree(tcomplete);
> > > binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> > >  err_alloc_tcomplete_failed:
> > > +   spin_lock(&t->lock);
> > > +   trace_binder_txn_latency_free(t);
> > > +   spin_unlock(&t->lock);
> > > kfree(t);
> > > binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > >  err_alloc_t_failed:
> > > diff --git a/drivers/android/binder_trace.h 
> > > b/drivers/android/binder_trace.h
> > > index 6731c3c..8ac87d1 100644
> > > --- a/drivers/android/binder_trace.h
> > > +++ b/drivers/android/binder_trace.h
> > > @@ -95,6 +95,33 @@
> > >   __entry->thread_todo)
> > >  );
> > >
> > > +TRACE_EVENT(binder_txn_latency_free,
> > > +   TP_PROTO(struct binder_transaction *t),
> > > +   TP_ARGS(t),
> > > +   TP_STRUCT__entry(
> > > +   __field(int, debug_id)
> > > +   __field(int, from_proc)
> > > +   __field(int, from_thread

Re: [PATCH v6 2/3] binder: add trace at free transaction.

2020-07-31 Thread Todd Kjos
On Mon, Jul 27, 2020 at 8:28 PM Frankie Chang
 wrote:
>
> From: "Frankie.Chang" 
>
> Since the original trace_binder_transaction_received cannot
> precisely present the real finished time of transaction, adding a
> trace_binder_txn_latency_free at the point of free transaction
> may be more close to it.
>
> Signed-off-by: Frankie.Chang 
> ---
>  drivers/android/binder.c   |6 ++
>  drivers/android/binder_trace.h |   27 +++
>  2 files changed, 33 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 2df146f..1e6fc40 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct 
> binder_transaction *t)
>  * If the transaction has no target_proc, then
>  * t->buffer->transaction has already been cleared.
>  */
> +   spin_lock(&t->lock);
> +   trace_binder_txn_latency_free(t);
> +   spin_unlock(&t->lock);

Hmm. I don't prefer taking the lock just to call a trace. It doesn't
make clear why the lock has to be taken. I'd prefer something like:

if (trace_binder_txn_latency_free_enabled()) {
  int to_proc, to_thread;

  spin_lock(&t->lock);
  to_proc = t->to_proc ? t->to_proc->pid : 0;
  to_thread = t->to_thread ? t->to_thread->pid : 0;
  spin_unlock(&t->lock);
  trace_binder_txn_latency_free(t, to_proc, to_pid);
}

And then the trace would use the passed-in values instead of accessing
via t->to_proc/to_thread.

> binder_free_txn_fixups(t);
> kfree(t);
> binder_stats_deleted(BINDER_STAT_TRANSACTION);
> @@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc *proc,
> kfree(tcomplete);
> binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +   spin_lock(&t->lock);
> +   trace_binder_txn_latency_free(t);
> +   spin_unlock(&t->lock);
> kfree(t);
> binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..8ac87d1 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,33 @@
>   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_txn_latency_free,
> +   TP_PROTO(struct binder_transaction *t),
> +   TP_ARGS(t),
> +   TP_STRUCT__entry(
> +   __field(int, debug_id)
> +   __field(int, from_proc)
> +   __field(int, from_thread)
> +   __field(int, to_proc)
> +   __field(int, to_thread)
> +   __field(unsigned int, code)
> +   __field(unsigned int, flags)
> +   ),
> +   TP_fast_assign(
> +   __entry->debug_id = t->debug_id;
> +   __entry->from_proc = t->from ? t->from->proc->pid : 0;
> +   __entry->from_thread = t->from ? t->from->pid : 0;
> +   __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> +   __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> +   __entry->code = t->code;
> +   __entry->flags = t->flags;
> +   ),
> +   TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> + __entry->debug_id, __entry->from_proc, __entry->from_thread,
> + __entry->to_proc, __entry->to_thread, __entry->code,
> + __entry->flags)
> +);
> +
>  TRACE_EVENT(binder_transaction,
> TP_PROTO(bool reply, struct binder_transaction *t,
>  struct binder_node *target_node),
> --
> 1.7.9.5


Re: [PATCH v5 3/3] binder: add transaction latency tracer

2020-07-20 Thread Todd Kjos
On Wed, Jun 10, 2020 at 5:34 AM Frankie Chang
 wrote:
>
> From: "Frankie.Chang" 
>
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),
> if yes, printing related information for tracing.
>
> /* Implement details */
> - Add latency tracer module to monitor transaction
>   by attaching to new tracepoints introduced
>   when transactions are allocated and freed.
>   The trace_binder_txn_latency_free would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
>
> - Since some of modules would trigger timeout NE
>   if their binder transaction don't finish in time,
>   such as audio timeout (5 sec), even BT command
>   timeout (2 sec), etc.
>   Therefore, setting the timeout threshold as 2 seconds
>   could be helpful to debug.

Could there be cases that 500ms is too long so 1s should be the
threshold? Hard coded 2 seconds makes this less useful. How about
making it configurable with a default of 2 sec?

>
> - The reason why printing the related information to
>   kernel information log but not trace buffer is that
>   some abnormal transactions may be pending for a long
>   time ago, they could not be recorded due to buffer
>   limited.
>
> Signed-off-by: Frankie.Chang 
> ---
>  drivers/android/Kconfig |8 +++
>  drivers/android/Makefile|1 +
>  drivers/android/binder.c|2 +
>  drivers/android/binder_internal.h   |   13 
>  drivers/android/binder_latency_tracer.c |  107 
> +++
>  drivers/android/binder_trace.h  |   28 +++-
>  6 files changed, 156 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..39d47be 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>   exhaustively with combinations of various buffer sizes and
>   alignments.
>
> +config BINDER_TRANSACTION_LATENCY_TRACKING
> +   bool "Android Binder transaction tracking"

Any reason this can't be tristate?

> +   help
> + Used for track abnormal binder transaction which is over 2 seconds,
> + when the transaction is done or be free, this transaction would be
> + checked whether it executed overtime.
> + If yes, printing out the detailed info.
> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..c2ffdb6 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)   # needed for trace 
> events
>  obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)   += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)  += 
> binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 5ec9af8..846d69b 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_alloc_t_failed;
> }
> +   trace_binder_txn_latency_alloc(t, e);
> INIT_LIST_HEAD(&t->fd_fixups);
> binder_stats_created(BINDER_STAT_TRANSACTION);
> spin_lock_init(&t->lock);
> @@ -5144,6 +5145,7 @@ static void print_binder_transaction_ilocked(struct 
> seq_file *m,
>to_proc ? to_proc->pid : 0,
>t->to_thread ? t->to_thread->pid : 0,
>t->code, t->flags, t->priority, t->need_reply);
> +   trace_binder_txn_latency_info(m, t);
> spin_unlock(&t->lock);
>
> if (proc != to_proc) {
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index ed61b3e..bebc185 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -12,6 +12,11 @@
>  #include 
>  #include 
>
> +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> +#include 
> +#include 
> +#endif
> +
>  struct binder_context {
> struct binder_node *binder_context_mgr_node;
> struct mutex context_mgr_node_lock;
> @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
> uint32_t return_error;
> uint32_t return_error_param;
> char context_name[BINDERFS_MAX_NAME + 1];
> +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING

If you make binder_latency_tracer a module, then we could include
these fields unconditionally. Please add comments or give them better
names so it is o

Re: [PATCH v5 2/3] binder: add trace at free transaction.

2020-07-20 Thread Todd Kjos
On Wed, Jun 10, 2020 at 5:24 AM Frankie Chang
 wrote:
>
> From: "Frankie.Chang" 
>
> Since the original trace_binder_transaction_received cannot
> precisely present the real finished time of transaction, adding a
> trace_binder_txn_latency_free at the point of free transaction
> may be more close to it.
>
> Signed-off-by: Frankie.Chang 
> ---
>  drivers/android/binder.c   |2 ++
>  drivers/android/binder_trace.h |   27 +++
>  2 files changed, 29 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 1592396..5ec9af8 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1523,6 +1523,7 @@ static void binder_free_transaction(struct 
> binder_transaction *t)
>  * If the transaction has no target_proc, then
>  * t->buffer->transaction has already been cleared.
>  */
> +   trace_binder_txn_latency_free(t);
> binder_free_txn_fixups(t);
> kfree(t);
> binder_stats_deleted(BINDER_STAT_TRANSACTION);
> @@ -3094,6 +3095,7 @@ static void binder_transaction(struct binder_proc *proc,
> kfree(tcomplete);
> binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +   trace_binder_txn_latency_free(t);
> kfree(t);
> binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..8ac87d1 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,33 @@
>   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_txn_latency_free,
> +   TP_PROTO(struct binder_transaction *t),
> +   TP_ARGS(t),
> +   TP_STRUCT__entry(
> +   __field(int, debug_id)
> +   __field(int, from_proc)
> +   __field(int, from_thread)
> +   __field(int, to_proc)
> +   __field(int, to_thread)
> +   __field(unsigned int, code)
> +   __field(unsigned int, flags)
> +   ),
> +   TP_fast_assign(
> +   __entry->debug_id = t->debug_id;
> +   __entry->from_proc = t->from ? t->from->proc->pid : 0;
> +   __entry->from_thread = t->from ? t->from->pid : 0;
> +   __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> +   __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;

t->to_proc and t->to_thread are not safe to dereference without
holding t->lock. If the target process dies, these fields can be set
to NULL

> +   __entry->code = t->code;
> +   __entry->flags = t->flags;
> +   ),
> +   TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> + __entry->debug_id, __entry->from_proc, __entry->from_thread,
> + __entry->to_proc, __entry->to_thread, __entry->code,
> + __entry->flags)
> +);
> +
>  TRACE_EVENT(binder_transaction,
> TP_PROTO(bool reply, struct binder_transaction *t,
>  struct binder_node *target_node),
> --
> 1.7.9.5


Re: [PATCH v2] binder: Don't use mmput() from shrinker function.

2020-07-16 Thread Todd Kjos
On Thu, Jul 16, 2020 at 8:18 AM Michal Hocko  wrote:
>
> On Fri 17-07-20 00:12:15, Tetsuo Handa wrote:
> > syzbot is reporting that mmput() from shrinker function has a risk of
> > deadlock [1], for delayed_uprobe_add() from update_ref_ctr() calls
> > kzalloc(GFP_KERNEL) with delayed_uprobe_lock held, and
> > uprobe_clear_state() from __mmput() also holds delayed_uprobe_lock.
> >
> > Commit a1b2289cef92ef0e ("android: binder: drop lru lock in isolate
> > callback") replaced mmput() with mmput_async() in order to avoid sleeping
> > with spinlock held. But this patch replaces mmput() with mmput_async() in
> > order not to start __mmput() from shrinker context.
> >
> > [1] 
> > https://syzkaller.appspot.com/bug?id=bc9e7303f537c41b2b0cc2dfcea3fc42964c2d45
> >
> > Reported-by: syzbot 
> > Reported-by: syzbot 
> > Signed-off-by: Tetsuo Handa 
>
> Reviewed-by: Michal Hocko 

Acked-by: Todd Kjos 

>
> Thanks!
>
> > ---
> >  drivers/android/binder_alloc.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> > index 42c672f1584e..cbe6aa77d50d 100644
> > --- a/drivers/android/binder_alloc.c
> > +++ b/drivers/android/binder_alloc.c
> > @@ -947,7 +947,7 @@ enum lru_status binder_alloc_free_page(struct list_head 
> > *item,
> >   trace_binder_unmap_user_end(alloc, index);
> >   }
> >   mmap_read_unlock(mm);
> > - mmput(mm);
> > + mmput_async(mm);
> >
> >   trace_binder_unmap_kernel_start(alloc, index);
> >
> > --
> > 2.18.4
>
> --
> Michal Hocko
> SUSE Labs


Re: possible deadlock in shmem_fallocate (4)

2020-07-14 Thread Todd Kjos
+Suren Baghdasaryan +Hridya Valsaraju who support the ashmem driver.


On Tue, Jul 14, 2020 at 7:18 AM Michal Hocko  wrote:
>
> On Tue 14-07-20 22:08:59, Hillf Danton wrote:
> >
> > On Tue, 14 Jul 2020 10:26:29 +0200 Michal Hocko wrote:
> > > On Tue 14-07-20 13:32:05, Hillf Danton wrote:
> > > >
> > > > On Mon, 13 Jul 2020 20:41:11 -0700 Eric Biggers wrote:
> > > > > On Tue, Jul 14, 2020 at 11:32:52AM +0800, Hillf Danton wrote:
> > > > > >
> > > > > > Add FALLOC_FL_NOBLOCK and on the shmem side try to lock inode upon 
> > > > > > the
> > > > > > new flag. And the overall upside is to keep the current gfp either 
> > > > > > in
> > > > > > the khugepaged context or not.
> > > > > >
> > > > > > --- a/include/uapi/linux/falloc.h
> > > > > > +++ b/include/uapi/linux/falloc.h
> > > > > > @@ -77,4 +77,6 @@
> > > > > >   */
> > > > > >  #define FALLOC_FL_UNSHARE_RANGE  0x40
> > > > > >
> > > > > > +#define FALLOC_FL_NOBLOCK0x80
> > > > > > +
> > > > >
> > > > > You can't add a new UAPI flag to fix a kernel-internal problem like 
> > > > > this.
> > > >
> > > > Sounds fair, see below.
> > > >
> > > > What the report indicates is a missing PF_MEMALLOC_NOFS and it's
> > > > checked on the ashmem side and added as an exception before going
> > > > to filesystem. On shmem side, no more than a best effort is paid
> > > > on the inteded exception.
> > > >
> > > > --- a/drivers/staging/android/ashmem.c
> > > > +++ b/drivers/staging/android/ashmem.c
> > > > @@ -437,6 +437,7 @@ static unsigned long
> > > >  ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
> > > >  {
> > > >   unsigned long freed = 0;
> > > > + bool nofs;
> > > >
> > > >   /* We might recurse into filesystem code, so bail out if necessary */
> > > >   if (!(sc->gfp_mask & __GFP_FS))
> > > > @@ -445,6 +446,11 @@ ashmem_shrink_scan(struct shrinker *shri
> > > >   if (!mutex_trylock(&ashmem_mutex))
> > > >   return -1;
> > > >
> > > > + /* enter filesystem with caution: nonblock on locking */
> > > > + nofs = current->flags & PF_MEMALLOC_NOFS;
> > > > + if (!nofs)
> > > > + current->flags |= PF_MEMALLOC_NOFS;
> > > > +
> > > >   while (!list_empty(&ashmem_lru_list)) {
> > > >   struct ashmem_range *range =
> > > >   list_first_entry(&ashmem_lru_list, typeof(*range), 
> > > > lru);
> > >
> > > I do not think this is an appropriate fix. First of all is this a real
> > > deadlock or a lockdep false positive? Is it possible that ashmem just
> >
> > The warning matters and we can do something to quiesce it.
>
> The underlying issue should be fixed rather than _something_ done to
> silence it.
>
> > > needs to properly annotate its shmem inodes? Or is it possible that
> > > the internal backing shmem file is visible to the userspace so the write
> > > path would be possible?
> > >
> > > If this a real problem then the proper fix would be to set internal
> > > shmem mapping's gfp_mask to drop __GFP_FS.
> >
> > Thanks for the tip, see below.
> >
> > Can you expand a bit on how it helps direct reclaimers like khugepaged
> > in the syzbot report wrt deadlock?
>
> I do not understand your question.
>
> > TBH I have difficult time following
> > up after staring at the chart below for quite a while.
>
> Yes, lockdep reports are quite hard to follow and they tend to confuse
> one hell out of me. But this one says that there is a reclaim dependency
> between the shmem inode lock and the reclaim context.
>
> > Possible unsafe locking scenario:
> >
> >CPU0CPU1
> >
> >   lock(fs_reclaim);
> >lock(&sb->s_type->i_mutex_key#15);
> >lock(fs_reclaim);
> >
> >   lock(&sb->s_type->i_mutex_key#15);
>
> Please refrain from proposing fixes until the actual problem is
> understood. I suspect that this might be just false positive because the
> lockdep cannot tell the backing shmem which is internal to ashmem(?)
> with any general shmem. But somebody really familiar with ashmem code
> should have a look I believe.
>
> --
> Michal Hocko
> SUSE Labs


Re: [PATCH resend] binder: Prevent context manager from incrementing ref 0

2020-07-09 Thread Todd Kjos
On Thu, Jul 9, 2020 at 3:40 PM Jann Horn  wrote:
>
> Binder is designed such that a binder_proc never has references to
> itself. If this rule is violated, memory corruption can occur when a
> process sends a transaction to itself; see e.g.
> <https://syzkaller.appspot.com/bug?extid=09e05aba06723a94d43d>.
>
> There is a remaining edgecase through which such a transaction-to-self
> can still occur from the context of a task with BINDER_SET_CONTEXT_MGR
> access:
>
>  - task A opens /dev/binder twice, creating binder_proc instances P1
>and P2
>  - P1 becomes context manager
>  - P2 calls ACQUIRE on the magic handle 0, allocating index 0 in its
>handle table
>  - P1 dies (by closing the /dev/binder fd and waiting a bit)
>  - P2 becomes context manager
>  - P2 calls ACQUIRE on the magic handle 0, allocating index 1 in its
>handle table
>[this triggers a warning: "binder: 1974:1974 tried to acquire
>reference to desc 0, got 1 instead"]
>  - task B opens /dev/binder once, creating binder_proc instance P3
>  - P3 calls P2 (via magic handle 0) with (void*)1 as argument (two-way
>transaction)
>  - P2 receives the handle and uses it to call P3 (two-way transaction)
>  - P3 calls P2 (via magic handle 0) (two-way transaction)
>  - P2 calls P2 (via handle 1) (two-way transaction)
>
> And then, if P2 does *NOT* accept the incoming transaction work, but
> instead closes the binder fd, we get a crash.
>
> Solve it by preventing the context manager from using ACQUIRE on ref 0.
> There shouldn't be any legitimate reason for the context manager to do
> that.
>
> Additionally, print a warning if someone manages to find another way to
> trigger a transaction-to-self bug in the future.
>
> Cc: sta...@vger.kernel.org
> Fixes: 457b9a6f09f0 ("Staging: android: add binder driver")
> Signed-off-by: Jann Horn 

Nice catch.

Acked-by: Todd Kjos 

> ---
> sending again because I forgot to CC LKML the first time... sorry about
> the spam.
>
>  drivers/android/binder.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index f50c5f182bb5..cac65ff3a257 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2982,6 +2982,12 @@ static void binder_transaction(struct binder_proc 
> *proc,
> goto err_dead_binder;
> }
> e->to_node = target_node->debug_id;
> +   if (WARN_ON(proc == target_proc)) {
> +   return_error = BR_FAILED_REPLY;
> +   return_error_param = -EINVAL;
> +   return_error_line = __LINE__;
> +   goto err_invalid_target_handle;
> +   }
> if (security_binder_transaction(proc->tsk,
> target_proc->tsk) < 0) {
> return_error = BR_FAILED_REPLY;
> @@ -3635,10 +3641,16 @@ static int binder_thread_write(struct binder_proc 
> *proc,
> struct binder_node *ctx_mgr_node;
> mutex_lock(&context->context_mgr_node_lock);
> ctx_mgr_node = 
> context->binder_context_mgr_node;
> -   if (ctx_mgr_node)
> +   if (ctx_mgr_node) {
> +   if (ctx_mgr_node->proc == proc) {
> +   binder_user_error("%d:%d 
> context manager tried to acquire desc 0\n");
> +   
> mutex_unlock(&context->context_mgr_node_lock);
> +   return -EINVAL;
> +   }
> ret = binder_inc_ref_for_node(
> proc, ctx_mgr_node,
> strong, NULL, &rdata);
> +   }
> mutex_unlock(&context->context_mgr_node_lock);
> }
> if (ret)
>
> base-commit: 2a89b99f580371b86ae9bafd6cbeccd3bfab524a
> --
> 2.27.0.389.gc38d7665816-goog
>


Re: [PATCH 1/1] MAINTAINERS: add Hridya and myself into Android driver maintainers list

2020-07-09 Thread Todd Kjos
On Thu, Jul 9, 2020 at 1:18 AM Greg KH  wrote:
>
> On Wed, Jul 08, 2020 at 04:12:53PM -0700, Suren Baghdasaryan wrote:
> > Add new maintainers for ashmem driver to handle related issues.
> >
> > Signed-off-by: Suren Baghdasaryan 

Acked-by: Todd Kjos 

>
> Can I get an ack/reviewed-by/something by the existing maintainers to
> verify this?  :)
>
> And I thought we were deleting ashmem soon?
>
> thanks,
>
> greg k-h


Re: [PATCH] binder: fix null deref of proc->context

2020-06-22 Thread Todd Kjos
On Mon, Jun 22, 2020 at 1:18 PM Todd Kjos  wrote:
>
> On Mon, Jun 22, 2020 at 1:09 PM Christian Brauner
>  wrote:
> >
> > On Mon, Jun 22, 2020 at 01:07:15PM -0700, Todd Kjos wrote:
> > > The binder driver makes the assumption proc->context pointer is invariant 
> > > after
> > > initialization (as documented in the kerneldoc header for struct proc).
> > > However, in commit f0fe2c0f050d ("binder: prevent UAF for binderfs 
> > > devices II")
> > > proc->context is set to NULL during binder_deferred_release().
> > >
> > > Another proc was in the middle of setting up a transaction to the dying
> > > process and crashed on a NULL pointer deref on "context" which is a local
> > > set to &proc->context:
> > >
> > > new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 
> > > 1;
> > >
> > > Here's the stack:
> > >
> > > [ 5237.855435] Call trace:
> > > [ 5237.855441] binder_get_ref_for_node_olocked+0x100/0x2ec
> > > [ 5237.855446] binder_inc_ref_for_node+0x140/0x280
> > > [ 5237.855451] binder_translate_binder+0x1d0/0x388
> > > [ 5237.855456] binder_transaction+0x2228/0x3730
> > > [ 5237.855461] binder_thread_write+0x640/0x25bc
> > > [ 5237.855466] binder_ioctl_write_read+0xb0/0x464
> > > [ 5237.855471] binder_ioctl+0x30c/0x96c
> > > [ 5237.855477] do_vfs_ioctl+0x3e0/0x700
> > > [ 5237.855482] __arm64_sys_ioctl+0x78/0xa4
> > > [ 5237.855488] el0_svc_common+0xb4/0x194
> > > [ 5237.855493] el0_svc_handler+0x74/0x98
> > > [ 5237.855497] el0_svc+0x8/0xc
> > >
> > > The fix is to move the kfree of the binder_device to binder_free_proc()
> > > so the binder_device is freed when we know there are no references
> > > remaining on the binder_proc.
> > >
> > > Fixes: f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
> > > Signed-off-by: Todd Kjos 
>
> Forgot to include stable. The issue was introduced in 5.6, so fix needed in 
> 5.7.
> Cc: sta...@vger.kernel.org # 5.7

Turns out the patch with the issue was also backported to 5.4.y, so
the fix is needed there too.

>
>
> >
> >
> > Thanks, looks good to me!
> > Acked-by: Christian Brauner 
> >
> > Christian
> >
> > > ---
> > >  drivers/android/binder.c | 14 +++---
> > >  1 file changed, 7 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > index e47c8a4c83db..f50c5f182bb5 100644
> > > --- a/drivers/android/binder.c
> > > +++ b/drivers/android/binder.c
> > > @@ -4686,8 +4686,15 @@ static struct binder_thread 
> > > *binder_get_thread(struct binder_proc *proc)
> > >
> > >  static void binder_free_proc(struct binder_proc *proc)
> > >  {
> > > + struct binder_device *device;
> > > +
> > >   BUG_ON(!list_empty(&proc->todo));
> > >   BUG_ON(!list_empty(&proc->delivered_death));
> > > + device = container_of(proc->context, struct binder_device, context);
> > > + if (refcount_dec_and_test(&device->ref)) {
> > > + kfree(proc->context->name);
> > > + kfree(device);
> > > + }
> > >   binder_alloc_deferred_release(&proc->alloc);
> > >   put_task_struct(proc->tsk);
> > >   binder_stats_deleted(BINDER_STAT_PROC);
> > > @@ -5406,7 +5413,6 @@ static int binder_node_release(struct binder_node 
> > > *node, int refs)
> > >  static void binder_deferred_release(struct binder_proc *proc)
> > >  {
> > >   struct binder_context *context = proc->context;
> > > - struct binder_device *device;
> > >   struct rb_node *n;
> > >   int threads, nodes, incoming_refs, outgoing_refs, 
> > > active_transactions;
> > >
> > > @@ -5423,12 +5429,6 @@ static void binder_deferred_release(struct 
> > > binder_proc *proc)
> > >   context->binder_context_mgr_node = NULL;
> > >   }
> > >   mutex_unlock(&context->context_mgr_node_lock);
> > > - device = container_of(proc->context, struct binder_device, context);
> > > - if (refcount_dec_and_test(&device->ref)) {
> > > - kfree(context->name);
> > > - kfree(device);
> > > - }
> > > - proc->context = NULL;
> > >   binder_inner_proc_lock(proc);
> > >   /*
> > >* Make sure proc stays alive after we
> > > --
> > > 2.27.0.111.gc72c7da667-goog
> > >


Re: [PATCH] binder: fix null deref of proc->context

2020-06-22 Thread Todd Kjos
On Mon, Jun 22, 2020 at 1:09 PM Christian Brauner
 wrote:
>
> On Mon, Jun 22, 2020 at 01:07:15PM -0700, Todd Kjos wrote:
> > The binder driver makes the assumption proc->context pointer is invariant 
> > after
> > initialization (as documented in the kerneldoc header for struct proc).
> > However, in commit f0fe2c0f050d ("binder: prevent UAF for binderfs devices 
> > II")
> > proc->context is set to NULL during binder_deferred_release().
> >
> > Another proc was in the middle of setting up a transaction to the dying
> > process and crashed on a NULL pointer deref on "context" which is a local
> > set to &proc->context:
> >
> > new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;
> >
> > Here's the stack:
> >
> > [ 5237.855435] Call trace:
> > [ 5237.855441] binder_get_ref_for_node_olocked+0x100/0x2ec
> > [ 5237.855446] binder_inc_ref_for_node+0x140/0x280
> > [ 5237.855451] binder_translate_binder+0x1d0/0x388
> > [ 5237.855456] binder_transaction+0x2228/0x3730
> > [ 5237.855461] binder_thread_write+0x640/0x25bc
> > [ 5237.855466] binder_ioctl_write_read+0xb0/0x464
> > [ 5237.855471] binder_ioctl+0x30c/0x96c
> > [ 5237.855477] do_vfs_ioctl+0x3e0/0x700
> > [ 5237.855482] __arm64_sys_ioctl+0x78/0xa4
> > [ 5237.855488] el0_svc_common+0xb4/0x194
> > [ 5237.855493] el0_svc_handler+0x74/0x98
> > [ 5237.855497] el0_svc+0x8/0xc
> >
> > The fix is to move the kfree of the binder_device to binder_free_proc()
> > so the binder_device is freed when we know there are no references
> > remaining on the binder_proc.
> >
> > Fixes: f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
> > Signed-off-by: Todd Kjos 

Forgot to include stable. The issue was introduced in 5.6, so fix needed in 5.7.
Cc: sta...@vger.kernel.org # 5.7


>
>
> Thanks, looks good to me!
> Acked-by: Christian Brauner 
>
> Christian
>
> > ---
> >  drivers/android/binder.c | 14 +++---
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index e47c8a4c83db..f50c5f182bb5 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -4686,8 +4686,15 @@ static struct binder_thread 
> > *binder_get_thread(struct binder_proc *proc)
> >
> >  static void binder_free_proc(struct binder_proc *proc)
> >  {
> > + struct binder_device *device;
> > +
> >   BUG_ON(!list_empty(&proc->todo));
> >   BUG_ON(!list_empty(&proc->delivered_death));
> > + device = container_of(proc->context, struct binder_device, context);
> > + if (refcount_dec_and_test(&device->ref)) {
> > + kfree(proc->context->name);
> > + kfree(device);
> > + }
> >   binder_alloc_deferred_release(&proc->alloc);
> >   put_task_struct(proc->tsk);
> >   binder_stats_deleted(BINDER_STAT_PROC);
> > @@ -5406,7 +5413,6 @@ static int binder_node_release(struct binder_node 
> > *node, int refs)
> >  static void binder_deferred_release(struct binder_proc *proc)
> >  {
> >   struct binder_context *context = proc->context;
> > - struct binder_device *device;
> >   struct rb_node *n;
> >   int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
> >
> > @@ -5423,12 +5429,6 @@ static void binder_deferred_release(struct 
> > binder_proc *proc)
> >   context->binder_context_mgr_node = NULL;
> >   }
> >   mutex_unlock(&context->context_mgr_node_lock);
> > - device = container_of(proc->context, struct binder_device, context);
> > - if (refcount_dec_and_test(&device->ref)) {
> > - kfree(context->name);
> > - kfree(device);
> > - }
> > - proc->context = NULL;
> >   binder_inner_proc_lock(proc);
> >   /*
> >* Make sure proc stays alive after we
> > --
> > 2.27.0.111.gc72c7da667-goog
> >


[PATCH] binder: fix null deref of proc->context

2020-06-22 Thread Todd Kjos
The binder driver makes the assumption proc->context pointer is invariant after
initialization (as documented in the kerneldoc header for struct proc).
However, in commit f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
proc->context is set to NULL during binder_deferred_release().

Another proc was in the middle of setting up a transaction to the dying
process and crashed on a NULL pointer deref on "context" which is a local
set to &proc->context:

new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;

Here's the stack:

[ 5237.855435] Call trace:
[ 5237.855441] binder_get_ref_for_node_olocked+0x100/0x2ec
[ 5237.855446] binder_inc_ref_for_node+0x140/0x280
[ 5237.855451] binder_translate_binder+0x1d0/0x388
[ 5237.855456] binder_transaction+0x2228/0x3730
[ 5237.855461] binder_thread_write+0x640/0x25bc
[ 5237.855466] binder_ioctl_write_read+0xb0/0x464
[ 5237.855471] binder_ioctl+0x30c/0x96c
[ 5237.855477] do_vfs_ioctl+0x3e0/0x700
[ 5237.855482] __arm64_sys_ioctl+0x78/0xa4
[ 5237.855488] el0_svc_common+0xb4/0x194
[ 5237.855493] el0_svc_handler+0x74/0x98
[ 5237.855497] el0_svc+0x8/0xc

The fix is to move the kfree of the binder_device to binder_free_proc()
so the binder_device is freed when we know there are no references
remaining on the binder_proc.

Fixes: f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index e47c8a4c83db..f50c5f182bb5 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -4686,8 +4686,15 @@ static struct binder_thread *binder_get_thread(struct 
binder_proc *proc)
 
 static void binder_free_proc(struct binder_proc *proc)
 {
+   struct binder_device *device;
+
BUG_ON(!list_empty(&proc->todo));
BUG_ON(!list_empty(&proc->delivered_death));
+   device = container_of(proc->context, struct binder_device, context);
+   if (refcount_dec_and_test(&device->ref)) {
+   kfree(proc->context->name);
+   kfree(device);
+   }
binder_alloc_deferred_release(&proc->alloc);
put_task_struct(proc->tsk);
binder_stats_deleted(BINDER_STAT_PROC);
@@ -5406,7 +5413,6 @@ static int binder_node_release(struct binder_node *node, 
int refs)
 static void binder_deferred_release(struct binder_proc *proc)
 {
struct binder_context *context = proc->context;
-   struct binder_device *device;
struct rb_node *n;
int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
 
@@ -5423,12 +5429,6 @@ static void binder_deferred_release(struct binder_proc 
*proc)
context->binder_context_mgr_node = NULL;
}
mutex_unlock(&context->context_mgr_node_lock);
-   device = container_of(proc->context, struct binder_device, context);
-   if (refcount_dec_and_test(&device->ref)) {
-   kfree(context->name);
-   kfree(device);
-   }
-   proc->context = NULL;
binder_inner_proc_lock(proc);
/*
 * Make sure proc stays alive after we
-- 
2.27.0.111.gc72c7da667-goog



Re: [PATCH v4 3/3] binder: add transaction latency tracer

2020-05-07 Thread Todd Kjos
On Thu, May 7, 2020 at 1:11 AM Frankie Chang  wrote:
>
> From: "Frankie.Chang" 
>
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),

If this is a hard-coded threshold, provide rationale for why 2 sec is
the right value and it doesn't need to be tunable

> if yes, printing related information for tracing.
>
> /* Implement details */
> - Add latency tracer module to monitor slow transaction.
>   The trace_binder_free_transaction would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.

Please add a more complete description. This patch adds a module to
monitor transaction latency by attaching to new tracepoints introduced
when transactions are allocated and freed. Describe this in the commit
message.

>
> Signed-off-by: Frankie.Chang 
> ---
>  drivers/android/Kconfig |8 +++
>  drivers/android/Makefile|1 +
>  drivers/android/binder.c|2 +
>  drivers/android/binder_internal.h   |   13 
>  drivers/android/binder_latency_tracer.c |  105 
> +++
>  drivers/android/binder_trace.h  |   26 +++-
>  6 files changed, 152 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
>  Change from v4:
>split up into patch series.
>
>  Change from v3:
>use tracepoints for binder_update_info and print_binder_transaction_ext,
>instead of custom registration functions.
>
>  Change from v2:
>create transaction latency module to monitor slow transaction.
>
>  Change from v1:
>first patchset.
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..7ba80eb 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>   exhaustively with combinations of various buffer sizes and
>   alignments.
>
> +config BINDER_USER_TRACKING

Why not "BINDER_TRANSACTION_LATENCY_TRACKING"?

> +   bool "Android Binder transaction tracking"
> +   help
> + Used for track abnormal binder transaction which is over 2 seconds,
> + when the transaction is done or be free, this transaction would be
> + checked whether it executed overtime.
> + If yes, printing out the detail info about it.

"If yes, print out the detailed info"

> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..552e8ac 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)   # needed for trace 
> events
>  obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)   += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_USER_TRACKING) += binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 4c3dd98..b89d75a 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
> return_error_line = __LINE__;
> goto err_alloc_t_failed;
> }
> +   trace_binder_update_info(t, e);

Can this be a more descriptive name? Perhaps "trace_binder_txn_create()"

> INIT_LIST_HEAD(&t->fd_fixups);
> binder_stats_created(BINDER_STAT_TRANSACTION);
> spin_lock_init(&t->lock);
> @@ -5145,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct 
> seq_file *m,
>t->to_thread ? t->to_thread->pid : 0,
>t->code, t->flags, t->priority, t->need_reply);
> spin_unlock(&t->lock);
> +   trace_print_binder_transaction_ext(m, t);

Why do you need to trace when dumping out the transaction info?

>
> if (proc != to_proc) {
> /*
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index ed61b3e..24d7beb 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -12,6 +12,11 @@
>  #include 
>  #include 
>
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +#include 
> +#include 
> +#endif
> +
>  struct binder_context {
> struct binder_node *binder_context_mgr_node;
> struct mutex context_mgr_node_lock;
> @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
> uint32_t return_error;
> uint32_t return_error_param;
> char context_name[BINDERFS_MAX_NAME + 1];
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +   struct timespec timestamp;
> +   struct timeval tv;
> +#endif
>  };
>
>  struct binder_transaction_log {
> @@ -520,6 +529,10 @@ struct bin

Re: [PATCH 1/2] binder: Don't modify VMA bounds in ->mmap handler

2019-10-16 Thread Todd Kjos
On Wed, Oct 16, 2019 at 8:01 AM Jann Horn  wrote:
>
> binder_mmap() tries to prevent the creation of overly big binder mappings
> by silently truncating the size of the VMA to 4MiB. However, this violates
> the API contract of mmap(). If userspace attempts to create a large binder
> VMA, and later attempts to unmap that VMA, it will call munmap() on a range
> beyond the end of the VMA, which may have been allocated to another VMA in
> the meantime. This can lead to userspace memory corruption.
>
> The following sequence of calls leads to a segfault without this commit:
>
> int main(void) {
>   int binder_fd = open("/dev/binder", O_RDWR);
>   if (binder_fd == -1) err(1, "open binder");
>   void *binder_mapping = mmap(NULL, 0x80UL, PROT_READ, MAP_SHARED,
>   binder_fd, 0);
>   if (binder_mapping == MAP_FAILED) err(1, "mmap binder");
>   void *data_mapping = mmap(NULL, 0x40UL, PROT_READ|PROT_WRITE,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
>   if (data_mapping == MAP_FAILED) err(1, "mmap data");
>   munmap(binder_mapping, 0x80UL);
>   *(char*)data_mapping = 1;
>   return 0;
> }
>
> Cc: sta...@vger.kernel.org
> Signed-off-by: Jann Horn 

Acked-by: Todd Kjos 

> ---
>  drivers/android/binder.c   | 7 ---
>  drivers/android/binder_alloc.c | 6 --
>  2 files changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 5b9ac2122e89..265d9dd46a5e 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -97,10 +97,6 @@ DEFINE_SHOW_ATTRIBUTE(proc);
>  #define SZ_1K   0x400
>  #endif
>
> -#ifndef SZ_4M
> -#define SZ_4M   0x40
> -#endif
> -
>  #define FORBIDDEN_MMAP_FLAGS(VM_WRITE)
>
>  enum {
> @@ -5177,9 +5173,6 @@ static int binder_mmap(struct file *filp, struct 
> vm_area_struct *vma)
> if (proc->tsk != current->group_leader)
> return -EINVAL;
>
> -   if ((vma->vm_end - vma->vm_start) > SZ_4M)
> -   vma->vm_end = vma->vm_start + SZ_4M;
> -
> binder_debug(BINDER_DEBUG_OPEN_CLOSE,
>  "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
>  __func__, proc->pid, vma->vm_start, vma->vm_end,
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index d42a8b2f636a..eb76a823fbb2 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -22,6 +22,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "binder_alloc.h"
>  #include "binder_trace.h"
>
> @@ -689,7 +690,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
> alloc->buffer = (void __user *)vma->vm_start;
> mutex_unlock(&binder_alloc_mmap_lock);
>
> -   alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
> +   alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start,
> +  SZ_4M);
> +   alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE,
>sizeof(alloc->pages[0]),
>GFP_KERNEL);
> if (alloc->pages == NULL) {
> @@ -697,7 +700,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
> failure_string = "alloc page array";
> goto err_alloc_pages_failed;
> }
> -   alloc->buffer_size = vma->vm_end - vma->vm_start;
>
> buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
> if (!buffer) {
> --
> 2.23.0.700.g56cf767bdb-goog
>


Re: [PATCH] binder: prevent UAF read in print_binder_transaction_log_entry()

2019-10-09 Thread Todd Kjos
On Wed, Oct 9, 2019 at 3:40 AM Christian Brauner
 wrote:
>
> On Tue, Oct 08, 2019 at 02:05:16PM -0400, Joel Fernandes wrote:
> > On Tue, Oct 08, 2019 at 03:01:59PM +0200, Christian Brauner wrote:

[...]

> >
> > One more thought, this can be made dependent on CONFIG_BINDERFS since 
> > regular
> > binder devices cannot be unregistered AFAICS and as Jann said, the problem 
> > is
> > BINDERFS specific. That way we avoid the memcpy for _every_ transaction.
> > These can be thundering when Android starts up.
>
> Unless Todd sees this as a real performance problem I'm weary to
> introduce additional checking and record a pointer for non-binderfs and
> a memcpy() for binderfs devices. :)
>

I don't see this as a real problem. In practice, memcpy will be moving
< 10 bytes. Also, by the time this code is in an android device,
CONFIG_BINDERFS will always be enabled since this is how we are
removing binder's use of debugfs. So a micro-optimization of the
!BINDERFS case will not be meaningful.

[...]


Re: [PATCH] binder: prevent UAF read in print_binder_transaction_log_entry()

2019-10-08 Thread Todd Kjos
On Tue, Oct 8, 2019 at 6:02 AM Christian Brauner
 wrote:
>
> When a binder transaction is initiated on a binder device coming from a
> binderfs instance, a pointer to the name of the binder device is stashed
> in the binder_transaction_log_entry's context_name member. Later on it
> is used to print the name in print_binder_transaction_log_entry(). By
> the time print_binder_transaction_log_entry() accesses context_name
> binderfs_evict_inode() might have already freed the associated memory
> thereby causing a UAF. Do the simple thing and prevent this by copying
> the name of the binder device instead of stashing a pointer to it.
>
> Reported-by: Jann Horn 
> Fixes: 03e2e07e3814 ("binder: Make transaction_log available in binderfs")
> Link: 
> https://lore.kernel.org/r/cag48ez14q0-f8lqsvcnbyr2o6gpw8shxsm4u5jmd9mpstem...@mail.gmail.com
> Cc: Joel Fernandes 
> Cc: Todd Kjos 
> Cc: Hridya Valsaraju 
> Signed-off-by: Christian Brauner 
> ---
>  drivers/android/binder.c  | 4 +++-
>  drivers/android/binder_internal.h | 2 +-
>  2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index c0a491277aca..5b9ac2122e89 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -57,6 +57,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -66,6 +67,7 @@
>  #include 
>
>  #include 
> +#include 
>
>  #include 
>
> @@ -2876,7 +2878,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;
> +   strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
>
> if (reply) {
> binder_inner_proc_lock(proc);
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index bd47f7f72075..ae991097d14d 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -130,7 +130,7 @@ struct binder_transaction_log_entry {
> int return_error_line;
>     uint32_t return_error;
> uint32_t return_error_param;
> -   const char *context_name;
> +   char context_name[BINDERFS_MAX_NAME + 1];
>  };
>
>  struct binder_transaction_log {
> --
> 2.23.0
>

Acked-by: Todd Kjos 


Re: UAF read in print_binder_transaction_log_entry() on ANDROID_BINDERFS kernels

2019-10-07 Thread Todd Kjos
+Hridya Valsaraju


On Mon, Oct 7, 2019 at 1:50 PM Jann Horn  wrote:
>
> Hi!
>
> There is a use-after-free read in print_binder_transaction_log_entry()
> on ANDROID_BINDERFS kernels because
> print_binder_transaction_log_entry() prints the char* e->context_name
> as string, and if the transaction occurred on a binder device from
> binderfs, e->context_name belongs to the binder device and is freed
> when the inode disappears.
>
> Luckily this shouldn't have security implications, since:
>
> a) reading the binder transaction log is already a pretty privileged operation
> b) I can't find any actual users of ANDROID_BINDERFS
>
> I guess there are three ways to fix it:
> 1) Create a new shared global spinlock for binderfs_evict_inode() and
> binder_transaction_log_show(), and let binderfs_evict_inode() scan the
> transaction log for pointers to its name and replace them with
> pointers to a statically-allocated string "{DELETED}" or something
> like that.
> 2) Let the transaction log contain non-reusable device identifiers
> instead of name pointers, and let print_binder_transaction_log_entry()
> look them up in something like a hashtable.
> 3) Just copy the name into the transaction log every time.
>
> I'm not sure which one is better, or whether there's a nicer fourth
> option, so I'm leaving writing a patch for this to y'all.
>
>
> Trigger instructions (requires you to have some helpers that can
> register a context manager and send some transaction to it):
> ==
> root@test:/home/user# mkdir /tmp/binder
> root@test:/home/user# mount -t binder -o stats=global /dev/null /tmp/binder
> root@test:/home/user# ls -l /tmp/binder
> total 0
> crw--- 1 root root 248, 1 Oct  7 20:34 binder
> crw--- 1 root root 248, 0 Oct  7 20:34 binder-control
> drwxr-xr-x 3 root root  0 Oct  7 20:34 binder_logs
> crw--- 1 root root 248, 2 Oct  7 20:34 hwbinder
> crw--- 1 root root 248, 3 Oct  7 20:34 vndbinder
> root@test:/home/user# ln -s /tmp/binder/binder /dev/binder
> [run some simple binder demo code to temporarily register a context
> manager and send a binder transaction]
> root@test:/home/user# rm /tmp/binder/binder
> root@test:/home/user# cat /tmp/binder/binder_logs/transaction_log
> 2: call  from 2277:2277 to 2273:0 context @��� node 1 handle 0
> size 24:8 ret 0/0 l=0
> 5: call  from 2273:2273 to 2277:2277 context @��� node 3 handle 1
> size 0:0 ret 0/0 l=0
> 6: reply from 2277:2277 to 2273:2273 context @��� node 0 handle 0
> size 4:0 ret 0/0 l=0
> 7: reply from 2273:2273 to 2277:2277 context @��� node 0 handle 0
> size 4:0 ret 0/0 l=0
> root@test:/home/user#
> ==
>
> ASAN splat:
> [  333.300753] 
> ==
> [  333.303197] BUG: KASAN: use-after-free in string_nocheck+0x9d/0x160
> [  333.305081] Read of size 1 at addr 8880b0981258 by task cat/2279
>
> [  333.307415] CPU: 1 PID: 2279 Comm: cat Not tainted 5.4.0-rc1+ #513
> [  333.309304] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> BIOS 1.12.0-1 04/01/2014
> [  333.310987] Call Trace:
> [  333.312032]  dump_stack+0x7c/0xc0
> [  333.312581]  ? string_nocheck+0x9d/0x160
> [  333.313157]  print_address_description.constprop.7+0x36/0x50
> [  333.314030]  ? string_nocheck+0x9d/0x160
> [  333.314603]  ? string_nocheck+0x9d/0x160
> [  333.315236]  __kasan_report.cold.10+0x1a/0x35
> [  333.315972]  ? string_nocheck+0x9d/0x160
> [  333.316545]  kasan_report+0xe/0x20
> [  333.317104]  string_nocheck+0x9d/0x160
> [  333.317652]  ? widen_string+0x160/0x160
> [  333.318270]  ? string_nocheck+0x160/0x160
> [  333.318857]  ? unwind_get_return_address+0x2a/0x40
> [  333.319636]  ? profile_setup.cold.9+0x96/0x96
> [  333.320359]  string+0xb6/0xc0
> [  333.320800]  ? hex_string+0x280/0x280
> [  333.321398]  vsnprintf+0x20c/0x780
> [  333.321898]  ? num_to_str+0x180/0x180
> [  333.322503]  ? __kasan_kmalloc.constprop.6+0xc1/0xd0
> [  333.323235]  ? vfs_read+0xbc/0x1e0
> [  333.323814]  ? ksys_read+0xb5/0x150
> [  333.324323]  ? do_syscall_64+0xb9/0x3b0
> [  333.324948]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
> [  333.325756]  seq_vprintf+0x78/0xb0
> [  333.326253]  seq_printf+0x96/0xc0
> [  333.327132]  ? seq_vprintf+0xb0/0xb0
> [  333.327678]  ? match_held_lock+0x2e/0x240
> [  333.328450]  binder_transaction_log_show+0x237/0x2d0
> [  333.329163]  seq_read+0x266/0x690
> [  333.329705]  vfs_read+0xbc/0x1e0
> [  333.330178]  ksys_read+0xb5/0x150
> [  333.330724]  ? kernel_write+0xb0/0xb0
> [  333.331257]  ? trace_hardirqs_off_caller+0x57/0x130
> [  333.332045]  ? mark_held_locks+0x29/0xa0
> [  333.332678]  ? do_syscall_64+0x6b/0x3b0
> [  333.333235]  do_syscall_64+0xb9/0x3b0
> [  333.333856]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
> [  333.334635] RIP: 0033:0x7fbbb95d4461
> [  333.335153] Code: fe ff ff 50 48 8d 3d fe d0 09 00 e8 e9 03 02 00
> 66 0f 1f 84 00 00 00 00 00 48 8d 05 99 62 0d 00 8b 00 85 c0 75 13 31
> c0 0f 05 <48> 3d 00 f0 ff ff 77 57 c3 66 0f 

Re: [PATCH 4/4] binder: Add binder_proc logging to binderfs

2019-08-28 Thread Todd Kjos
On Wed, Aug 28, 2019 at 6:08 AM Christian Brauner
 wrote:
>
> On Tue, Aug 27, 2019 at 01:41:52PM -0700, Hridya Valsaraju wrote:
> > Currently /sys/kernel/debug/binder/proc contains
> > the debug data for every binder_proc instance.
> > This patch makes this information also available
> > in a binderfs instance mounted with a mount option
> > "stats=global" in addition to debugfs. The patch does
> > not affect the presence of the file in debugfs.
> >
> > If a binderfs instance is mounted at path /dev/binderfs,
> > this file would be present at /dev/binderfs/binder_logs/proc.
> > This change provides an alternate way to access this file when debugfs
> > is not mounted.
> >
> > Signed-off-by: Hridya Valsaraju 
>
> I'm still wondering whether there's a nicer way to create those debuf
> files per-process without doing it in binder_open() but it has worked
> fine for a long time with debugfs.
>
> Also, one minor question below. Otherwise
>
> Acked-by: Christian Brauner 

Acked-by: Todd Kjos 

>
> > ---
> >  drivers/android/binder.c  | 38 ++-
> >  drivers/android/binder_internal.h | 46 ++
> >  drivers/android/binderfs.c| 63 ++-
> >  3 files changed, 111 insertions(+), 36 deletions(-)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index bed217310197..37189838f32a 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -481,6 +481,7 @@ struct binder_priority {
> >   * @inner_lock:   can nest under outer_lock and/or node lock
> >   * @outer_lock:   no nesting under innor or node lock
> >   *Lock order: 1) outer, 2) node, 3) inner
> > + * @binderfs_entry:   process-specific binderfs log file
> >   *
> >   * Bookkeeping structure for binder processes
> >   */
> > @@ -510,6 +511,7 @@ struct binder_proc {
> >   struct binder_context *context;
> >   spinlock_t inner_lock;
> >   spinlock_t outer_lock;
> > + struct dentry *binderfs_entry;
> >  };
> >
> >  enum {
> > @@ -5347,6 +5349,8 @@ static int binder_open(struct inode *nodp, struct 
> > file *filp)
> >  {
> >   struct binder_proc *proc;
> >   struct binder_device *binder_dev;
> > + struct binderfs_info *info;
> > + struct dentry *binder_binderfs_dir_entry_proc = NULL;
> >
> >   binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
> >current->group_leader->pid, current->pid);
> > @@ -5368,11 +5372,14 @@ static int binder_open(struct inode *nodp, struct 
> > file *filp)
> >   }
> >
> >   /* binderfs stashes devices in i_private */
> > - if (is_binderfs_device(nodp))
> > + if (is_binderfs_device(nodp)) {
> >   binder_dev = nodp->i_private;
> > - else
> > + info = nodp->i_sb->s_fs_info;
> > + binder_binderfs_dir_entry_proc = info->proc_log_dir;
> > + } else {
> >   binder_dev = container_of(filp->private_data,
> > struct binder_device, miscdev);
> > + }
> >   proc->context = &binder_dev->context;
> >   binder_alloc_init(&proc->alloc);
> >
> > @@ -5403,6 +5410,27 @@ static int binder_open(struct inode *nodp, struct 
> > file *filp)
> >   &proc_fops);
> >   }
> >
> > + if (binder_binderfs_dir_entry_proc) {
> > + char strbuf[11];
> > + struct dentry *binderfs_entry;
> > +
> > + snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
> > + /*
> > +  * Similar to debugfs, the process specific log file is shared
> > +  * between contexts. If the file has already been created for 
> > a
> > +  * process, the following binderfs_create_file() call will
> > +  * fail if another context of the same process invoked
> > +  * binder_open(). This is ok since same as debugfs,
> > +  * the log file will contain information on all contexts of a
> > +  * given PID.
> > +  */
> > + binderfs_entry = 
> > binderfs_create_file(binder_binderfs_dir_entry_proc,
> > + strbuf, &proc_fops, (void *)(unsigned long)proc->pid);
> > + if (!IS_ERR(binderfs_entry))
> >

Re: [PATCH 3/4] binder: Make transaction_log available in binderfs

2019-08-28 Thread Todd Kjos
On Wed, Aug 28, 2019 at 5:59 AM Christian Brauner
 wrote:
>
> On Tue, Aug 27, 2019 at 01:41:51PM -0700, Hridya Valsaraju wrote:
> > Currently, the binder transaction log files 'transaction_log'
> > and 'failed_transaction_log' live in debugfs at the following locations:
> >
> > /sys/kernel/debug/binder/failed_transaction_log
> > /sys/kernel/debug/binder/transaction_log
> >
> > This patch makes these files also available in a binderfs instance
> > mounted with the mount option "stats=global".
> > It does not affect the presence of these files in debugfs.
> > If a binderfs instance is mounted at path /dev/binderfs, the location of
> > these files will be as follows:
> >
> > /dev/binderfs/binder_logs/failed_transaction_log
> > /dev/binderfs/binder_logs/transaction_log
> >
> > This change provides an alternate option to access these files when
> > debugfs is not mounted.
> >
> > Signed-off-by: Hridya Valsaraju 
>
> Acked-by: Christian Brauner 

Acked-by: Todd Kjos 

>
> > ---
> >  drivers/android/binder.c  | 34 +--
> >  drivers/android/binder_internal.h | 30 +++
> >  drivers/android/binderfs.c| 19 +
> >  3 files changed, 54 insertions(+), 29 deletions(-)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index de795bd229c4..bed217310197 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -197,30 +197,8 @@ static inline void binder_stats_created(enum 
> > binder_stat_types type)
> >   atomic_inc(&binder_stats.obj_created[type]);
> >  }
> >
> > -struct binder_transaction_log_entry {
> > - int debug_id;
> > - int debug_id_done;
> > - int call_type;
> > - int from_proc;
> > - int from_thread;
> > - int target_handle;
> > - int to_proc;
> > - int to_thread;
> > - 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 {
> > - atomic_t cur;
> > - bool full;
> > - struct binder_transaction_log_entry entry[32];
> > -};
> > -static struct binder_transaction_log binder_transaction_log;
> > -static struct binder_transaction_log binder_transaction_log_failed;
> > +struct binder_transaction_log binder_transaction_log;
> > +struct binder_transaction_log binder_transaction_log_failed;
> >
> >  static struct binder_transaction_log_entry *binder_transaction_log_add(
> >   struct binder_transaction_log *log)
> > @@ -6166,7 +6144,7 @@ static void print_binder_transaction_log_entry(struct 
> > seq_file *m,
> >   "\n" : " (incomplete)\n");
> >  }
> >
> > -static int transaction_log_show(struct seq_file *m, void *unused)
> > +int binder_transaction_log_show(struct seq_file *m, void *unused)
> >  {
> >   struct binder_transaction_log *log = m->private;
> >   unsigned int log_cur = atomic_read(&log->cur);
> > @@ -6198,8 +6176,6 @@ const struct file_operations binder_fops = {
> >   .release = binder_release,
> >  };
> >
> > -DEFINE_SHOW_ATTRIBUTE(transaction_log);
> > -
> >  static int __init init_binder_device(const char *name)
> >  {
> >   int ret;
> > @@ -6268,12 +6244,12 @@ static int __init binder_init(void)
> >   0444,
> >   binder_debugfs_dir_entry_root,
> >   &binder_transaction_log,
> > - &transaction_log_fops);
> > + &binder_transaction_log_fops);
> >   debugfs_create_file("failed_transaction_log",
> >   0444,
> >   binder_debugfs_dir_entry_root,
> >   &binder_transaction_log_failed,
> > - &transaction_log_fops);
> > + &binder_transaction_log_fops);
> >   }
> >
> >   if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&
> > diff --git a/drivers/android/binder_internal.h 
> > b/drivers/android/binder_internal.h
> > index 12ef96f256c6..b9be42d9464c 100644
> >

Re: WARNING in binder_transaction_buffer_release

2019-07-17 Thread Todd Kjos
+Hridya Valsaraju

Fix posted: 
https://lkml.kernel.org/lkml/20190715191804.112933-1-hri...@google.com/


On Wed, Jun 12, 2019 at 1:14 PM Todd Kjos  wrote:
>
> On Wed, Jun 12, 2019 at 12:23 PM Eric Biggers  wrote:
> >
> > On Mon, May 20, 2019 at 07:18:06AM -0700, syzbot wrote:
> > > Hello,
> > >
> > > syzbot found the following crash on:
> > >
> > > HEAD commit:72cf0b07 Merge tag 'sound-fix-5.2-rc1' of 
> > > git://git.kernel..
> > > git tree:   upstream
> > > console output: https://syzkaller.appspot.com/x/log.txt?x=17c7d4bca0
> > > kernel config:  https://syzkaller.appspot.com/x/.config?x=d103f114f9010324
> > > dashboard link: 
> > > https://syzkaller.appspot.com/bug?extid=8b3c354d33c4ac78bfad
> > > compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> > > userspace arch: i386
> > > syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=15b99b44a0
> > >
> > > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > > Reported-by: syzbot+8b3c354d33c4ac78b...@syzkaller.appspotmail.com
> > >
> > > WARNING: CPU: 1 PID: 8535 at drivers/android/binder.c:2368
> > > binder_transaction_buffer_release+0x673/0x8f0 
> > > drivers/android/binder.c:2368
> > > Kernel panic - not syncing: panic_on_warn set ...
> > > CPU: 1 PID: 8535 Comm: syz-executor.2 Not tainted 5.1.0+ #19
> > > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> > > Google 01/01/2011
> > > Call Trace:
> > >  __dump_stack lib/dump_stack.c:77 [inline]
> > >  dump_stack+0x172/0x1f0 lib/dump_stack.c:113
> > >  panic+0x2cb/0x715 kernel/panic.c:214
> > >  __warn.cold+0x20/0x4c kernel/panic.c:571
> > >  report_bug+0x263/0x2b0 lib/bug.c:186
> > >  fixup_bug arch/x86/kernel/traps.c:179 [inline]
> > >  fixup_bug arch/x86/kernel/traps.c:174 [inline]
> > >  do_error_trap+0x11b/0x200 arch/x86/kernel/traps.c:272
> > >  do_invalid_op+0x37/0x50 arch/x86/kernel/traps.c:291
> > >  invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:986
> > > RIP: 0010:binder_transaction_buffer_release+0x673/0x8f0
> > > drivers/android/binder.c:2368
> > > Code: 31 ff 41 89 c5 89 c6 e8 7b 04 1f fc 45 85 ed 0f 85 1f 41 01 00 49 8d
> > > 47 40 48 89 85 50 fe ff ff e9 9d fa ff ff e8 dd 02 1f fc <0f> 0b e9 7f fc 
> > > ff
> > > ff e8 d1 02 1f fc 48 89 d8 45 31 c9 4c 89 fe 4c
> > > RSP: 0018:88807b2775f0 EFLAGS: 00010293
> > > RAX: 888092b1e040 RBX: 0060 RCX: 111012563caa
> > > RDX:  RSI: 85519e13 RDI: 888097a2d248
> > > RBP: 88807b2777d8 R08: 888092b1e040 R09: ed100f64eee3
> > > R10: ed100f64eee2 R11: 88807b277717 R12: 88808fd2c340
> > > R13: 0068 R14: 88807b2777b0 R15: 88809f7ea580
> > >  binder_transaction+0x153d/0x6620 drivers/android/binder.c:3484
> > >  binder_thread_write+0x87e/0x2820 drivers/android/binder.c:3792
> > >  binder_ioctl_write_read drivers/android/binder.c:4836 [inline]
> > >  binder_ioctl+0x102f/0x1833 drivers/android/binder.c:5013
> > >  __do_compat_sys_ioctl fs/compat_ioctl.c:1052 [inline]
> > >  __se_compat_sys_ioctl fs/compat_ioctl.c:998 [inline]
> > >  __ia32_compat_sys_ioctl+0x195/0x620 fs/compat_ioctl.c:998
> > >  do_syscall_32_irqs_on arch/x86/entry/common.c:337 [inline]
> > >  do_fast_syscall_32+0x27b/0xd7d arch/x86/entry/common.c:408
> > >  entry_SYSENTER_compat+0x70/0x7f arch/x86/entry/entry_64_compat.S:139
> > > RIP: 0023:0xf7f9e849
> > > Code: 85 d2 74 02 89 0a 5b 5d c3 8b 04 24 c3 8b 14 24 c3 8b 3c 24 c3 90 90
> > > 90 90 90 90 90 90 90 90 90 90 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 
> > > 90
> > > 90 90 eb 0d 90 90 90 90 90 90 90 90 90 90 90 90
> > > RSP: 002b:f7f9a0cc EFLAGS: 0296 ORIG_RAX: 0036
> > > RAX: ffda RBX: 0004 RCX: c0306201
> > > RDX: 2140 RSI:  RDI: 
> > > RBP:  R08:  R09: 
> > > R10:  R11:  R12: 
> > > R13:  R14:  R15: 
> > > Kernel Offset: disabled
> > > Rebooting in 86400 seconds..
> > >
> > >
> > > ---
> > > This bug is generated by a bot. It may contain errors.
> > > See https://goo.gl/tpsmEJ for more information about syzbot.
> > > syzbot engineers can be reached at syzkal...@googlegroups.com.
> > >
> > > syzbot will keep track of this bug report. See:
> > > https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> > > syzbot can test patches for this bug, for details see:
> > > https://goo.gl/tpsmEJ#testing-patches
> > >
> >
> > Are any of the binder maintainers planning to fix this?  This seems to be 
> > the
> > only open syzbot report for binder on the upstream kernel.
>
> Taking a look.
>
> >
> > - Eric


Re: [PATCH] binder: prevent transactions to context manager from its own process.

2019-07-15 Thread Todd Kjos
On Mon, Jul 15, 2019 at 12:18 PM Hridya Valsaraju  wrote:
>
> Currently, a transaction to context manager from its own process
> is prevented by checking if its binder_proc struct is the same as
> that of the sender. However, this would not catch cases where the
> process opens the binder device again and uses the new fd to send
> a transaction to the context manager.
>
> Reported-by: syzbot+8b3c354d33c4ac78b...@syzkaller.appspotmail.com
> Signed-off-by: Hridya Valsaraju 

Acked-by: Todd Kjos 

> ---
>  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 e4d25ebec5be..89b9cedae088 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3138,7 +3138,7 @@ static void binder_transaction(struct binder_proc *proc,
> else
> return_error = BR_DEAD_REPLY;
> mutex_unlock(&context->context_mgr_node_lock);
> -   if (target_node && target_proc == proc) {
> +   if (target_node && target_proc->pid == proc->pid) {
> binder_user_error("%d:%d got transaction to 
> context manager from process owning it\n",
>   proc->pid, thread->pid);
> return_error = BR_FAILED_REPLY;
> --
> 2.22.0.510.g264f2c817a-goog
>


Re: Reminder: 3 open syzbot bugs in "android/binder" subsystem

2019-07-03 Thread Todd Kjos
On Tue, Jul 2, 2019 at 10:03 PM Eric Biggers  wrote:
>
> [This email was generated by a script.  Let me know if you have any 
> suggestions
> to make it better, or if you want it re-generated with the latest status.]
>
> Of the currently open syzbot reports against the upstream kernel, I've 
> manually
> marked 3 of them as possibly being bugs in the "android/binder" subsystem.  
> I've
> listed these reports below, sorted by an algorithm that tries to list first 
> the
> reports most likely to be still valid, important, and actionable.
>
> Of these 3 bugs, 1 was seen in mainline in the last week.
>
> Of these 3 bugs, 1 was bisected to a commit from the following person:
>
> Todd Kjos 
>
> If you believe a bug is no longer valid, please close the syzbot report by
> sending a '#syz fix', '#syz dup', or '#syz invalid' command in reply to the
> original thread, as explained at https://goo.gl/tpsmEJ#status
>
> If you believe I misattributed a bug to the "android/binder" subsystem, please
> let me know, and if possible forward the report to the correct people or 
> mailing
> list.
>
> Here are the bugs:
>
> 
> Title:  kernel BUG at drivers/android/binder_alloc.c:LINE! (4)
> Last occurred:  6 days ago
> Reported:   14 days ago
> Branches:   Mainline and others
> Dashboard link: 
> https://syzkaller.appspot.com/bug?id=bbf40136a49ffaa8ac60906edcbe77f825b2c406
> Original thread:
> https://lkml.kernel.org/lkml/0000b6b25b058b96d...@google.com/T/#u
>
> This bug has a C reproducer.
>
> This bug was bisected to:
>
> commit bde4a19fc04f5f46298c86b1acb7a4af1d5f138d
> Author: Todd Kjos 
> Date:   Fri Feb 8 18:35:20 2019 +
>
>   binder: use userspace pointer as base of buffer space
>
> The original thread for this bug has received 3 replies; the last was 4 days
> ago.

Fix posted: https://lore.kernel.org/lkml/20190628165012.4841-1-tk...@google.com/

>
> If you fix this bug, please add the following tag to the commit:
> Reported-by: syzbot+3ae18325f96190606...@syzkaller.appspotmail.com
>
> If you send any email or patch for this bug, please reply to the original
> thread, which had activity only 4 days ago.  For the git send-email command to
> use, or tips on how to reply if the thread isn't in your mailbox, see the 
> "Reply
> instructions" at 
> https://lkml.kernel.org/r/b6b25b058b96d...@google.com
>
> 
> Title:  WARNING in binder_transaction_buffer_release
> Last occurred:  0 days ago
> Reported:   43 days ago
> Branches:   Mainline and others
> Dashboard link: 
> https://syzkaller.appspot.com/bug?id=4e0a6a529aef923a8d61c5d20b8fc0605c730138
> Original thread:
> https://lkml.kernel.org/lkml/afe2c70589526...@google.com/T/#u

Assigned to Hridya Valsaraju (b/134585943)

>
> This bug has a syzkaller reproducer only.
>
> The original thread for this bug has received 2 replies; the last was 20 days
> ago.
>
> If you fix this bug, please add the following tag to the commit:
> Reported-by: syzbot+8b3c354d33c4ac78b...@syzkaller.appspotmail.com
>
> If you send any email or patch for this bug, please consider replying to the
> original thread.  For the git send-email command to use, or tips on how to 
> reply
> if the thread isn't in your mailbox, see the "Reply instructions" at
> https://lkml.kernel.org/r/afe2c70589526...@google.com
>
> 
> Title:  possible deadlock in uprobe_clear_state
> Last occurred:  165 days ago
> Reported:   202 days ago
> Branches:   Mainline
> Dashboard link: 
> https://syzkaller.appspot.com/bug?id=a1ce9b3da349209c5085bb8c4fee753d68c3697f
> Original thread:
> https://lkml.kernel.org/lkml/10a9fb057cd14...@google.com/T/#u
>
> Unfortunately, this bug does not have a reproducer.
>
> [Note: the uprobe developers think this is a bug in binder, not uprobes.
>  See https://marc.info/?l=linux-kernel&m=155119805728815&w=2
>  for a suggested fix for this bug.]

Just learned about this, but looks like a straightforward fix.

>
> If you fix this bug, please add the following tag to the commit:
> Reported-by: syzbot+1068f09c44d151250...@syzkaller.appspotmail.com
>
> If you send any email or patch for this bug, please consider replying to the
> original thread.  For the git send-email command to use, or tips on how to 
> reply
> if the thread isn't in your mailbox, see the "Reply instructions" at
> https://lkml.kernel.org/r/10a9fb057cd14...@google.com
>


Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (4)

2019-06-28 Thread Todd Kjos
On Tue, Jun 18, 2019 at 10:37 AM Todd Kjos  wrote:
>
> On Tue, Jun 18, 2019 at 5:18 AM Dan Carpenter  
> wrote:
> >
> > It's weird that that binder_alloc_copy_from_buffer() is a void function.
> > It would be easier to do the error handling at that point, instead of in
> > the callers.  It feels like we keep hitting similar bugs to this.

I took your advice. Fix posted: https://lkml.org/lkml/2019/6/28/857

-Todd

>
> The idea is that if it is an error that the user can cause, it is
> checked by the caller of binder_alloc_copy_from_buffer(). Most uses
> are kernel cases where the expected alignments should be fine and it's
> a BUG if they are not.
>
> Admittedly, a few cases (like this one) have slipped through since
> they cannot happen in Android (syzkaller has been very useful to find
> our bad assumptions).
>
> -Todd
>
> >
> > regards,
> > dan carpenter
> >


[PATCH] binder: return errors from buffer copy functions

2019-06-28 Thread Todd Kjos
The buffer copy functions assumed the caller would ensure
correct alignment and that the memory to be copied was
completely within the binder buffer. There have been
a few cases discovered by syzkallar where a malformed
transaction created by a user could violated the
assumptions and resulted in a BUG_ON.

The fix is to remove the BUG_ON and always return the
error to be handled appropriately by the caller.

Acked-by: Martijn Coenen 
Reported-by: syzbot+3ae18325f96190606...@syzkaller.appspotmail.com
Fixes: bde4a19fc04f ("binder: use userspace pointer as base of buffer space")
Suggested-by: Dan Carpenter 
Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c   | 153 -
 drivers/android/binder_alloc.c |  44 +-
 drivers/android/binder_alloc.h |  22 ++---
 3 files changed, 126 insertions(+), 93 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index bc26b5511f0a9..414492c136ddf 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2059,10 +2059,9 @@ static size_t binder_get_object(struct binder_proc *proc,
 
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
-   !IS_ALIGNED(offset, sizeof(u32)))
+   binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+ offset, read_size))
return 0;
-   binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
- offset, read_size);
 
/* Ok, now see if we read a complete object. */
hdr = &object->hdr;
@@ -2131,8 +2130,10 @@ static struct binder_buffer_object *binder_validate_ptr(
return NULL;
 
buffer_offset = start_offset + sizeof(binder_size_t) * index;
-   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
- b, buffer_offset, sizeof(object_offset));
+   if (binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ b, buffer_offset,
+ sizeof(object_offset)))
+   return NULL;
object_size = binder_get_object(proc, b, object_offset, object);
if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
@@ -2212,10 +2213,12 @@ static bool binder_validate_fixup(struct binder_proc 
*proc,
return false;
last_min_offset = last_bbo->parent_offset + sizeof(uintptr_t);
buffer_offset = objects_start_offset +
-   sizeof(binder_size_t) * last_bbo->parent,
-   binder_alloc_copy_from_buffer(&proc->alloc, &last_obj_offset,
- b, buffer_offset,
- sizeof(last_obj_offset));
+   sizeof(binder_size_t) * last_bbo->parent;
+   if (binder_alloc_copy_from_buffer(&proc->alloc,
+ &last_obj_offset,
+ b, buffer_offset,
+ sizeof(last_obj_offset)))
+   return false;
}
return (fixup_offset >= last_min_offset);
 }
@@ -2301,15 +2304,15 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
 buffer_offset += sizeof(binder_size_t)) {
struct binder_object_header *hdr;
-   size_t object_size;
+   size_t object_size = 0;
struct binder_object object;
binder_size_t object_offset;
 
-   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
- buffer, buffer_offset,
- sizeof(object_offset));
-   object_size = binder_get_object(proc, buffer,
-   object_offset, &object);
+   if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+  buffer, buffer_offset,
+  sizeof(object_offset)))
+   object_size = binder_get_object(proc, buffer,
+   object_offset, &object);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
   debug_id, (u64)object_offset, buffer->data_size);
@@ -2432,15 +2435,16 @@ static void binder_transaction

Re: memory leak in binder_transaction

2019-06-21 Thread Todd Kjos
On Thu, Jun 13, 2019 at 2:56 PM syzbot
 wrote:
>
> Hello,
>
> syzbot found the following crash on:
>
> HEAD commit:d1fdb6d8 Linux 5.2-rc4
> git tree:   upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=15e5ce1ea0
> kernel config:  https://syzkaller.appspot.com/x/.config?x=cb38d33cd06d8d48
> dashboard link: https://syzkaller.appspot.com/bug?extid=182ce46596c3f2e1eb24
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=1181703ea0
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=14e14392a0
>
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+182ce46596c3f2e1e...@syzkaller.appspotmail.com
>
> -executor774" scontext=unconfined_u:system_r:insmod_t:s0-s0:c0.c1023
> tcontext=unconfined_u:system_r:insmod_t:s0-s0:c0.c1023 tclass=binder
> permissive=1
> BUG: memory leak

Fix sent: https://lore.kernel.org/patchwork/patch/1092398/

>
> unreferenced object 0x888123934800 (size 32):
>comm "syz-executor774", pid 7083, jiffies 4294941834 (age 7.970s)
>hex dump (first 32 bytes):
>  00 48 93 23 81 88 ff ff 00 48 93 23 81 88 ff ff  .H.#.H.#
>  02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
>backtrace:
>  [<38ba7202>] kmemleak_alloc_recursive
> include/linux/kmemleak.h:43 [inline]
>  [<38ba7202>] slab_post_alloc_hook mm/slab.h:439 [inline]
>  [<38ba7202>] slab_alloc mm/slab.c:3326 [inline]
>  [<38ba7202>] kmem_cache_alloc_trace+0x13d/0x280 mm/slab.c:3553
>  [<04e63839>] kmalloc include/linux/slab.h:547 [inline]
>  [<04e63839>] kzalloc include/linux/slab.h:742 [inline]
>  [<04e63839>] binder_transaction+0x28b/0x2eb0
> drivers/android/binder.c:3072
>  [<50997ec4>] binder_thread_write+0x357/0x1430
> drivers/android/binder.c:3794
>  [] binder_ioctl_write_read
> drivers/android/binder.c:4827 [inline]
>  [] binder_ioctl+0x8bc/0xbb4
> drivers/android/binder.c:5004
>  [<2eec2b63>] vfs_ioctl fs/ioctl.c:46 [inline]
>  [<2eec2b63>] file_ioctl fs/ioctl.c:509 [inline]
>  [<2eec2b63>] do_vfs_ioctl+0x62a/0x810 fs/ioctl.c:696
>  [<48cfc9e6>] ksys_ioctl+0x86/0xb0 fs/ioctl.c:713
>  [<30bf392d>] __do_sys_ioctl fs/ioctl.c:720 [inline]
>  [<30bf392d>] __se_sys_ioctl fs/ioctl.c:718 [inline]
>  [<30bf392d>] __x64_sys_ioctl+0x1e/0x30 fs/ioctl.c:718
>  [<7dec438c>] do_syscall_64+0x76/0x1a0
> arch/x86/entry/common.c:301
>  [] entry_SYSCALL_64_after_hwframe+0x44/0xa9
>
>
>
> ---
> This bug is generated by a bot. It may contain errors.
> See https://goo.gl/tpsmEJ for more information about syzbot.
> syzbot engineers can be reached at syzkal...@googlegroups.com.
>
> syzbot will keep track of this bug report. See:
> https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> syzbot can test patches for this bug, for details see:
> https://goo.gl/tpsmEJ#testing-patches


[PATCH] binder: fix memory leak in error path

2019-06-21 Thread Todd Kjos
syzkallar found a 32-byte memory leak in a rarely executed error
case. The transaction complete work item was not freed if put_user()
failed when writing the BR_TRANSACTION_COMPLETE to the user command
buffer. Fixed by freeing it before put_user() is called.

Reported-by: syzbot+182ce46596c3f2e1e...@syzkaller.appspotmail.com
Signed-off-by: Todd Kjos 
---
 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 bc26b5511f0a9..8bf039fdeb918 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -4268,6 +4268,8 @@ static int binder_thread_read(struct binder_proc *proc,
case BINDER_WORK_TRANSACTION_COMPLETE: {
binder_inner_proc_unlock(proc);
cmd = BR_TRANSACTION_COMPLETE;
+   kfree(w);
+   binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
@@ -4276,8 +4278,6 @@ static int binder_thread_read(struct binder_proc *proc,
binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
 "%d:%d BR_TRANSACTION_COMPLETE\n",
 proc->pid, thread->pid);
-   kfree(w);
-   binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
} break;
case BINDER_WORK_NODE: {
struct binder_node *node = container_of(w, struct 
binder_node, work);
-- 
2.22.0.410.gd8fdbe21b5-goog



Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (4)

2019-06-18 Thread Todd Kjos
On Tue, Jun 18, 2019 at 5:18 AM Dan Carpenter  wrote:
>
> It's weird that that binder_alloc_copy_from_buffer() is a void function.
> It would be easier to do the error handling at that point, instead of in
> the callers.  It feels like we keep hitting similar bugs to this.

The idea is that if it is an error that the user can cause, it is
checked by the caller of binder_alloc_copy_from_buffer(). Most uses
are kernel cases where the expected alignments should be fine and it's
a BUG if they are not.

Admittedly, a few cases (like this one) have slipped through since
they cannot happen in Android (syzkaller has been very useful to find
our bad assumptions).

-Todd

>
> regards,
> dan carpenter
>


Re: [PATCH] binder: fix possible UAF when freeing buffer

2019-06-13 Thread Todd Kjos
On Wed, Jun 12, 2019 at 10:41 PM Greg KH  wrote:
>
> On Wed, Jun 12, 2019 at 01:29:27PM -0700, Todd Kjos wrote:
> > There is a race between the binder driver cleaning
> > up a completed transaction via binder_free_transaction()
> > and a user calling binder_ioctl(BC_FREE_BUFFER) to
> > release a buffer. It doesn't matter which is first but
> > they need to be protected against running concurrently
> > which can result in a UAF.
> >
> > Signed-off-by: Todd Kjos 
> > ---
> >  drivers/android/binder.c | 16 ++--
> >  1 file changed, 14 insertions(+), 2 deletions(-)
>
> Does this also need to go to the stable kernels?

This patch won't apply cleanly to stable kernels so I'll submit a new
patch directly to stable@ (4.14, 4.19) once this one lands.

>
> thanks,
>
> greg k-h


[PATCH] binder: fix possible UAF when freeing buffer

2019-06-12 Thread Todd Kjos
There is a race between the binder driver cleaning
up a completed transaction via binder_free_transaction()
and a user calling binder_ioctl(BC_FREE_BUFFER) to
release a buffer. It doesn't matter which is first but
they need to be protected against running concurrently
which can result in a UAF.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 748ac489ef7eb..bc26b5511f0a9 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1941,8 +1941,18 @@ static void binder_free_txn_fixups(struct 
binder_transaction *t)
 
 static void binder_free_transaction(struct binder_transaction *t)
 {
-   if (t->buffer)
-   t->buffer->transaction = NULL;
+   struct binder_proc *target_proc = t->to_proc;
+
+   if (target_proc) {
+   binder_inner_proc_lock(target_proc);
+   if (t->buffer)
+   t->buffer->transaction = NULL;
+   binder_inner_proc_unlock(target_proc);
+   }
+   /*
+* If the transaction has no target_proc, then
+* t->buffer->transaction has already been cleared.
+*/
binder_free_txn_fixups(t);
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -3551,10 +3561,12 @@ static void binder_transaction(struct binder_proc *proc,
 static void
 binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
 {
+   binder_inner_proc_lock(proc);
if (buffer->transaction) {
buffer->transaction->buffer = NULL;
buffer->transaction = NULL;
}
+   binder_inner_proc_unlock(proc);
if (buffer->async_transaction && buffer->target_node) {
struct binder_node *buf_node;
struct binder_work *w;
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog



Re: WARNING in binder_transaction_buffer_release

2019-06-12 Thread Todd Kjos
On Wed, Jun 12, 2019 at 12:23 PM Eric Biggers  wrote:
>
> On Mon, May 20, 2019 at 07:18:06AM -0700, syzbot wrote:
> > Hello,
> >
> > syzbot found the following crash on:
> >
> > HEAD commit:72cf0b07 Merge tag 'sound-fix-5.2-rc1' of git://git.kernel..
> > git tree:   upstream
> > console output: https://syzkaller.appspot.com/x/log.txt?x=17c7d4bca0
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=d103f114f9010324
> > dashboard link: https://syzkaller.appspot.com/bug?extid=8b3c354d33c4ac78bfad
> > compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> > userspace arch: i386
> > syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=15b99b44a0
> >
> > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > Reported-by: syzbot+8b3c354d33c4ac78b...@syzkaller.appspotmail.com
> >
> > WARNING: CPU: 1 PID: 8535 at drivers/android/binder.c:2368
> > binder_transaction_buffer_release+0x673/0x8f0 drivers/android/binder.c:2368
> > Kernel panic - not syncing: panic_on_warn set ...
> > CPU: 1 PID: 8535 Comm: syz-executor.2 Not tainted 5.1.0+ #19
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> > Google 01/01/2011
> > Call Trace:
> >  __dump_stack lib/dump_stack.c:77 [inline]
> >  dump_stack+0x172/0x1f0 lib/dump_stack.c:113
> >  panic+0x2cb/0x715 kernel/panic.c:214
> >  __warn.cold+0x20/0x4c kernel/panic.c:571
> >  report_bug+0x263/0x2b0 lib/bug.c:186
> >  fixup_bug arch/x86/kernel/traps.c:179 [inline]
> >  fixup_bug arch/x86/kernel/traps.c:174 [inline]
> >  do_error_trap+0x11b/0x200 arch/x86/kernel/traps.c:272
> >  do_invalid_op+0x37/0x50 arch/x86/kernel/traps.c:291
> >  invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:986
> > RIP: 0010:binder_transaction_buffer_release+0x673/0x8f0
> > drivers/android/binder.c:2368
> > Code: 31 ff 41 89 c5 89 c6 e8 7b 04 1f fc 45 85 ed 0f 85 1f 41 01 00 49 8d
> > 47 40 48 89 85 50 fe ff ff e9 9d fa ff ff e8 dd 02 1f fc <0f> 0b e9 7f fc ff
> > ff e8 d1 02 1f fc 48 89 d8 45 31 c9 4c 89 fe 4c
> > RSP: 0018:88807b2775f0 EFLAGS: 00010293
> > RAX: 888092b1e040 RBX: 0060 RCX: 111012563caa
> > RDX:  RSI: 85519e13 RDI: 888097a2d248
> > RBP: 88807b2777d8 R08: 888092b1e040 R09: ed100f64eee3
> > R10: ed100f64eee2 R11: 88807b277717 R12: 88808fd2c340
> > R13: 0068 R14: 88807b2777b0 R15: 88809f7ea580
> >  binder_transaction+0x153d/0x6620 drivers/android/binder.c:3484
> >  binder_thread_write+0x87e/0x2820 drivers/android/binder.c:3792
> >  binder_ioctl_write_read drivers/android/binder.c:4836 [inline]
> >  binder_ioctl+0x102f/0x1833 drivers/android/binder.c:5013
> >  __do_compat_sys_ioctl fs/compat_ioctl.c:1052 [inline]
> >  __se_compat_sys_ioctl fs/compat_ioctl.c:998 [inline]
> >  __ia32_compat_sys_ioctl+0x195/0x620 fs/compat_ioctl.c:998
> >  do_syscall_32_irqs_on arch/x86/entry/common.c:337 [inline]
> >  do_fast_syscall_32+0x27b/0xd7d arch/x86/entry/common.c:408
> >  entry_SYSENTER_compat+0x70/0x7f arch/x86/entry/entry_64_compat.S:139
> > RIP: 0023:0xf7f9e849
> > Code: 85 d2 74 02 89 0a 5b 5d c3 8b 04 24 c3 8b 14 24 c3 8b 3c 24 c3 90 90
> > 90 90 90 90 90 90 90 90 90 90 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 90
> > 90 90 eb 0d 90 90 90 90 90 90 90 90 90 90 90 90
> > RSP: 002b:f7f9a0cc EFLAGS: 0296 ORIG_RAX: 0036
> > RAX: ffda RBX: 0004 RCX: c0306201
> > RDX: 2140 RSI:  RDI: 
> > RBP:  R08:  R09: 
> > R10:  R11:  R12: 
> > R13:  R14:  R15: 
> > Kernel Offset: disabled
> > Rebooting in 86400 seconds..
> >
> >
> > ---
> > This bug is generated by a bot. It may contain errors.
> > See https://goo.gl/tpsmEJ for more information about syzbot.
> > syzbot engineers can be reached at syzkal...@googlegroups.com.
> >
> > syzbot will keep track of this bug report. See:
> > https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> > syzbot can test patches for this bug, for details see:
> > https://goo.gl/tpsmEJ#testing-patches
> >
>
> Are any of the binder maintainers planning to fix this?  This seems to be the
> only open syzbot report for binder on the upstream kernel.

Taking a look.

>
> - Eric


Re: binder stress testing

2019-06-05 Thread Todd Kjos
+Hridya Valsaraju

Dmitry, I filed an internal bug to track this case (b/134585943).
7aa135fcf263 didn't prevent it since your test program opens
/dev/binder0 twice and one proc instance is sending the fd to the
other proc instance. Definitely a bug in the driver (though not one
we'd ever see in a "normal" binder environment).

On Sat, May 18, 2019 at 12:25 AM Dmitry Vyukov  wrote:
>
> On Fri, May 17, 2019 at 8:34 PM Todd Kjos  wrote:
> > > On Fri, May 17, 2019 at 5:51 PM Dmitry Vyukov  wrote:
> > > > > > >
> > > > > > > From: Dmitry Vyukov 
> > > > > > > Date: Fri, May 17, 2019 at 3:26 AM
> > > > > > > To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos, Martijn Coenen,
> > > > > > > Joel Fernandes, Christian Brauner, open list:ANDROID DRIVERS, LKML
> > > > > > > Cc: syzkaller
> > > > > > >
> > > > > > > > Hi,
> > > > > > > >
> > > > > > > > I have 2 questions re drivers/android/binder.c stress testing.
> > > > > > > >
> > > > > > > > 1. Are there any docs on the kernel interface? Or some examples 
> > > > > > > > on how
> > > > > > > > to use it and reference syscall sequences to make it do 
> > > > > > > > something
> > > > > > > > meaningful?
> > > > > > > > I hopefully figured out struct layouts and offsets of objects 
> > > > > > > > thing,
> > > > > > > > but I still can't figure out handles, pointers, nodes, pointer 
> > > > > > > > to
> > > > > > > > nodes... pointer to data (?), references, cookies and where 
> > > > > > > > does one
> > > > > > > > get valid values for these.
> > > > > > >
> > > > > > > The kernel interface is not well documented since it isn't 
> > > > > > > intended to
> > > > > > > be used apart from libbinder. The best example for your purposes 
> > > > > > > is
> > > > > > > probably the binderDriverInterfaceTest which you can find at
> > > > > > > https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/tests/binderDriverInterfaceTest.cpp.
> > > > > > >
> > > > > > > The libbinder source is at
> > > > > > > https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder.
> > > > > > >
> > > > > > > >
> > > > > > > > 2. In my tests any transaction breaks binder device until the 
> > > > > > > > next reboot.
> > > > > > > > If I open binder device twice, mmap, set context and then the 
> > > > > > > > process
> > > > > > > > dies, then everything it released fine, in particular the 
> > > > > > > > context
> > > > > > > > (context_mgr_node gone). So the device is ready for a next test:
> > > > > > > >
> > > > > > > > [   40.247970][ T6239] binder: binder_open: 6238:6239
> > > > > > > > [   40.250819][ T6239] binder: 6238:6239 node 1 
> > > > > > > > u
> > > > > > > > c created
> > > > > > > > [   40.253365][ T6239] binder: binder_mmap: 6238 
> > > > > > > > 200a-200a2000 (8
> > > > > > > > K) vma f9 pagep 8025
> > > > > > > > [   40.256454][ T6239] binder: binder_open: 6238:6239
> > > > > > > > [   40.259604][ T6239] binder: binder_mmap: 6238 
> > > > > > > > 200c-200c2000 (8
> > > > > > > > K) vma f9 pagep 8025
> > > > > > > > [   40.271526][ T6238] binder: 6238 close vm area 
> > > > > > > > 200a-200a2000 (8
> > > > > > > > K) vma 180200d9 pagep 8025
> > > > > > > > [   40.273113][ T6238] binder: 6238 close vm area 
> > > > > > > > 200c-200c2000 (8
> > > > > > > > K) vma 180200d9 pagep 8025
> > > > > > > > [   40.275058][   T17] binder: binder_flush: 6238 woke 0 threads
> > > 

Re: binder stress testing

2019-05-17 Thread Todd Kjos
On Fri, May 17, 2019 at 8:55 AM Dmitry Vyukov  wrote:
>
> On Fri, May 17, 2019 at 5:51 PM Dmitry Vyukov  wrote:
> > > > >
> > > > > From: Dmitry Vyukov 
> > > > > Date: Fri, May 17, 2019 at 3:26 AM
> > > > > To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos, Martijn Coenen,
> > > > > Joel Fernandes, Christian Brauner, open list:ANDROID DRIVERS, LKML
> > > > > Cc: syzkaller
> > > > >
> > > > > > Hi,
> > > > > >
> > > > > > I have 2 questions re drivers/android/binder.c stress testing.
> > > > > >
> > > > > > 1. Are there any docs on the kernel interface? Or some examples on 
> > > > > > how
> > > > > > to use it and reference syscall sequences to make it do something
> > > > > > meaningful?
> > > > > > I hopefully figured out struct layouts and offsets of objects thing,
> > > > > > but I still can't figure out handles, pointers, nodes, pointer to
> > > > > > nodes... pointer to data (?), references, cookies and where does one
> > > > > > get valid values for these.
> > > > >
> > > > > The kernel interface is not well documented since it isn't intended to
> > > > > be used apart from libbinder. The best example for your purposes is
> > > > > probably the binderDriverInterfaceTest which you can find at
> > > > > https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/tests/binderDriverInterfaceTest.cpp.
> > > > >
> > > > > The libbinder source is at
> > > > > https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder.
> > > > >
> > > > > >
> > > > > > 2. In my tests any transaction breaks binder device until the next 
> > > > > > reboot.
> > > > > > If I open binder device twice, mmap, set context and then the 
> > > > > > process
> > > > > > dies, then everything it released fine, in particular the context
> > > > > > (context_mgr_node gone). So the device is ready for a next test:
> > > > > >
> > > > > > [   40.247970][ T6239] binder: binder_open: 6238:6239
> > > > > > [   40.250819][ T6239] binder: 6238:6239 node 1 u
> > > > > > c created
> > > > > > [   40.253365][ T6239] binder: binder_mmap: 6238 200a-200a2000 
> > > > > > (8
> > > > > > K) vma f9 pagep 8025
> > > > > > [   40.256454][ T6239] binder: binder_open: 6238:6239
> > > > > > [   40.259604][ T6239] binder: binder_mmap: 6238 200c-200c2000 
> > > > > > (8
> > > > > > K) vma f9 pagep 8025
> > > > > > [   40.271526][ T6238] binder: 6238 close vm area 200a-200a2000 
> > > > > > (8
> > > > > > K) vma 180200d9 pagep 8025
> > > > > > [   40.273113][ T6238] binder: 6238 close vm area 200c-200c2000 
> > > > > > (8
> > > > > > K) vma 180200d9 pagep 8025
> > > > > > [   40.275058][   T17] binder: binder_flush: 6238 woke 0 threads
> > > > > > [   40.275997][   T17] binder: binder_flush: 6238 woke 0 threads
> > > > > > [   40.276968][   T17] binder: binder_deferred_release: 6238 threads
> > > > > > 0, nodes 0 (ref 0), refs 0, active transactions 0
> > > > > > [   40.278626][   T17] binder: binder_deferred_release: 6238
> > > > > > context_mgr_node gone
> > > > > > [   40.279756][   T17] binder: binder_deferred_release: 6238 threads
> > > > > > 1, nodes 1 (ref 0), refs 0, active transactions 0
> > > > > >
> > > > > >
> > > > > > However, if I also send a transaction between these fd's, then
> > > > > > context_mgr_node is not released:
> > > > > >
> > > > > > [  783.851403][ T6167] binder: binder_open: 6166:6167
> > > > > > [  783.858801][ T6167] binder: 6166:6167 node 1 u
> > > > > > c created
> > > > > > [  783.862458][ T6167] binder: binder_mmap: 6166 200a-200a2000 
> > > > > > (8
> > > > > > K) vma f9 pagep 8025
>

Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (3)

2019-05-17 Thread Todd Kjos
On Fri, May 17, 2019 at 8:33 AM Dmitry Vyukov  wrote:
>
> On Fri, May 17, 2019 at 5:26 PM Todd Kjos  wrote:
> >
> > Yes (and syzbot seemed to confirm the fix). I didn't realize I needed
> > to manually close the issue. I guess you closed it yesterday.
>
> This is required to auto-close the bug when the commit is merged:
>
> > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > Reported-by: syzbot+f9f3f388440283da2...@syzkaller.appspotmail.com
>
> Otherwise somebody needs to say:
>
> #syz fix: binder: fix BUG_ON found by selinux-testsuite

It looks like you closed it with your #sys comment ^^^

>
>
> > From: Dmitry Vyukov 
> > Date: Fri, May 17, 2019 at 3:08 AM
> > To: syzbot
> > Cc: Arve Hjønnevåg, Christian Brauner, open list:ANDROID DRIVERS, Greg
> > Kroah-Hartman, Joel Fernandes, LKML, Martijn Coenen, syzkaller-bugs,
> > Todd Kjos , Todd Kjos 
> >
> > > On Fri, Mar 29, 2019 at 10:55 AM syzbot
> > >  wrote:
> > > >
> > > > Hello,
> > > >
> > > > syzbot has tested the proposed patch and the reproducer did not trigger
> > > > crash:
> > > >
> > > > Reported-and-tested-by:
> > > > syzbot+f9f3f388440283da2...@syzkaller.appspotmail.com
> > > >
> > > > Tested on:
> > > >
> > > > commit: 8c2ffd91 Linux 5.1-rc2
> > > > git tree:
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 
> > > > master
> > > > kernel config:  
> > > > https://syzkaller.appspot.com/x/.config?x=8dcdce25ea72bedf
> > > > compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> > > > patch:  
> > > > https://syzkaller.appspot.com/x/patch.diff?x=10fed66320
> > > >
> > > > Note: testing is done by a robot and is best-effort only.
> > >
> > >
> > > Todd,
> > >
> > > Should this patch fix the bug? Should we close the bug as fixed then?
> > > In my local testing I see this BUG still fires, but if we will leave
> > > old fixed bugs open, we will not get notifications about new crashes.


Re: binder stress testing

2019-05-17 Thread Todd Kjos
From: Dmitry Vyukov 
Date: Fri, May 17, 2019 at 3:26 AM
To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos, Martijn Coenen,
Joel Fernandes, Christian Brauner, open list:ANDROID DRIVERS, LKML
Cc: syzkaller

> Hi,
>
> I have 2 questions re drivers/android/binder.c stress testing.
>
> 1. Are there any docs on the kernel interface? Or some examples on how
> to use it and reference syscall sequences to make it do something
> meaningful?
> I hopefully figured out struct layouts and offsets of objects thing,
> but I still can't figure out handles, pointers, nodes, pointer to
> nodes... pointer to data (?), references, cookies and where does one
> get valid values for these.

The kernel interface is not well documented since it isn't intended to
be used apart from libbinder. The best example for your purposes is
probably the binderDriverInterfaceTest which you can find at
https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder/tests/binderDriverInterfaceTest.cpp.

The libbinder source is at
https://android.googlesource.com/platform/frameworks/native/+/refs/heads/master/libs/binder.

>
> 2. In my tests any transaction breaks binder device until the next reboot.
> If I open binder device twice, mmap, set context and then the process
> dies, then everything it released fine, in particular the context
> (context_mgr_node gone). So the device is ready for a next test:
>
> [   40.247970][ T6239] binder: binder_open: 6238:6239
> [   40.250819][ T6239] binder: 6238:6239 node 1 u
> c created
> [   40.253365][ T6239] binder: binder_mmap: 6238 200a-200a2000 (8
> K) vma f9 pagep 8025
> [   40.256454][ T6239] binder: binder_open: 6238:6239
> [   40.259604][ T6239] binder: binder_mmap: 6238 200c-200c2000 (8
> K) vma f9 pagep 8025
> [   40.271526][ T6238] binder: 6238 close vm area 200a-200a2000 (8
> K) vma 180200d9 pagep 8025
> [   40.273113][ T6238] binder: 6238 close vm area 200c-200c2000 (8
> K) vma 180200d9 pagep 8025
> [   40.275058][   T17] binder: binder_flush: 6238 woke 0 threads
> [   40.275997][   T17] binder: binder_flush: 6238 woke 0 threads
> [   40.276968][   T17] binder: binder_deferred_release: 6238 threads
> 0, nodes 0 (ref 0), refs 0, active transactions 0
> [   40.278626][   T17] binder: binder_deferred_release: 6238
> context_mgr_node gone
> [   40.279756][   T17] binder: binder_deferred_release: 6238 threads
> 1, nodes 1 (ref 0), refs 0, active transactions 0
>
>
> However, if I also send a transaction between these fd's, then
> context_mgr_node is not released:
>
> [  783.851403][ T6167] binder: binder_open: 6166:6167
> [  783.858801][ T6167] binder: 6166:6167 node 1 u
> c created
> [  783.862458][ T6167] binder: binder_mmap: 6166 200a-200a2000 (8
> K) vma f9 pagep 8025
> [  783.865777][ T6167] binder: binder_open: 6166:6167
> [  783.867892][ T6167] binder: binder_mmap: 6166 200c-200c2000 (8
> K) vma f9 pagep 8025
> [  783.870810][ T6167] binder: 6166:6167 write 76 at 2180,
> read 0 at 2300
> [  783.872211][ T6167] binder: 6166:6167 BC_TRANSACTION 2 -> 6166 -
> node 1, data 2200-22c0 size 88-24-16
> [  783.873819][ T6167] binder: 6166:6167 node 3 u
> c created
> [  783.875032][ T6167] binder: 6166 new ref 4 desc 1 for node 3
> [  783.875860][ T6167] binder: node 3 u -> ref 4 desc 
> 1
> [  783.876868][ T6167] binder: 6166:6167 wrote 76 of 76, read return 0 of 0
> [  783.886714][ T6167] binder: 6166 close vm area 200a-200a2000 (8
> K) vma 180200d9 pagep 8025
> [  783.888161][ T6167] binder: 6166 close vm area 200c-200c2000 (8
> K) vma 180200d9 pagep 8025
> [  783.890134][   T27] binder: binder_flush: 6166 woke 0 threads
> [  783.891036][   T27] binder: binder_flush: 6166 woke 0 threads
> [  783.892027][ T2903] binder: release 6166:6167 transaction 2 out, still 
> active
> [  783.893097][ T2903] binder: unexpected work type, 4, not freed
> [  783.893947][ T2903] binder: undelivered TRANSACTION_COMPLETE
> [  783.894849][ T2903] binder: node 3 now dead, refs 1, death 0
> [  783.895717][ T2903] binder: binder_deferred_release: 6166 threads
> 1, nodes 1 (ref 1), refs 0, active transactions 1
>
>
> And all subsequent tests will fail because "BINDER_SET_CONTEXT_MGR
> already set" presumably to the now unrecoverably dead process:
>
> [  831.085174][ T6191] binder: binder_open: 6190:6191
> [  831.087450][ T6191] binder: BINDER_SET_CONTEXT_MGR already set
> [  831.088910][ T6191] binder: 6190:6191 ioctl 4018620d 

Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (3)

2019-05-17 Thread Todd Kjos
Yes (and syzbot seemed to confirm the fix). I didn't realize I needed
to manually close the issue. I guess you closed it yesterday.

From: Dmitry Vyukov 
Date: Fri, May 17, 2019 at 3:08 AM
To: syzbot
Cc: Arve Hjønnevåg, Christian Brauner, open list:ANDROID DRIVERS, Greg
Kroah-Hartman, Joel Fernandes, LKML, Martijn Coenen, syzkaller-bugs,
Todd Kjos , Todd Kjos 

> On Fri, Mar 29, 2019 at 10:55 AM syzbot
>  wrote:
> >
> > Hello,
> >
> > syzbot has tested the proposed patch and the reproducer did not trigger
> > crash:
> >
> > Reported-and-tested-by:
> > syzbot+f9f3f388440283da2...@syzkaller.appspotmail.com
> >
> > Tested on:
> >
> > commit: 8c2ffd91 Linux 5.1-rc2
> > git tree:
> > git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git master
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=8dcdce25ea72bedf
> > compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> > patch:  https://syzkaller.appspot.com/x/patch.diff?x=10fed66320
> >
> > Note: testing is done by a robot and is best-effort only.
>
>
> Todd,
>
> Should this patch fix the bug? Should we close the bug as fixed then?
> In my local testing I see this BUG still fires, but if we will leave
> old fixed bugs open, we will not get notifications about new crashes.


[PATCH] binder: check for overflow when alloc for security context

2019-04-24 Thread Todd Kjos
When allocating space in the target buffer for the security context,
make sure the extra_buffers_size doesn't overflow. This can only
happen if the given size is invalid, but an overflow can turn it
into a valid size. Fail the transaction if an overflow is detected.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 4b9c7ca492e6d..6f0712f0767c5 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3121,6 +3121,7 @@ static void binder_transaction(struct binder_proc *proc,
 
if (target_node && target_node->txn_security_ctx) {
u32 secid;
+   size_t added_size;
 
security_task_getsecid(proc->tsk, &secid);
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
@@ -3130,7 +3131,15 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_get_secctx_failed;
}
-   extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+   added_size = ALIGN(secctx_sz, sizeof(u64));
+   extra_buffers_size += added_size;
+   if (extra_buffers_size < added_size) {
+   /* integer overflow of extra_buffers_size */
+   return_error = BR_FAILED_REPLY;
+   return_error_param = EINVAL;
+   return_error_line = __LINE__;
+   goto err_bad_extra_size;
+   }
}
 
trace_binder_transaction(reply, t, target_node);
@@ -3480,6 +3489,7 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->transaction = NULL;
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
+err_bad_extra_size:
if (secctx)
security_release_secctx(secctx, secctx_sz);
 err_get_secctx_failed:
-- 
2.21.0.593.g511ec345e18-goog



Re: [PATCH] binder: take read mode of mmap_sem in binder_alloc_free_page()

2019-04-22 Thread Todd Kjos
On Fri, Apr 12, 2019 at 2:59 PM Tyler Hicks  wrote:
>
> Restore the behavior of locking mmap_sem for reading in
> binder_alloc_free_page(), as was first done in commit 3013bf62b67a
> ("binder: reduce mmap_sem write-side lock"). That change was
> inadvertently reverted by commit 5cec2d2e5839 ("binder: fix race between
> munmap() and direct reclaim").
>
> In addition, change the name of the label for the error path to
> accurately reflect that we're taking the lock for reading.
>
> Backporting note: This fix is only needed when *both* of the commits
> mentioned above are applied. That's an unlikely situation since they
> both landed during the development of v5.1 but only one of them is
> targeted for stable.
>
> Fixes: 5cec2d2e5839 ("binder: fix race between munmap() and direct reclaim")
> Signed-off-by: Tyler Hicks 


Thanks for fixing this up.

Acked-by: Todd Kjos 

> ---
>
> Hello - I was backporting 5cec2d2e5839 and didn't think it looked quite
> right. The patch description doesn't specifically mention a need to acquire
> mmap_sem for writing and the two commits (5cec2d2e5839 and 3013bf62b67a) 
> landed
> relatively close in time to each other so I have a feeling that a mistake 
> could
> have happened while resolving conflicts.
>
> I also noticed that commit 3013bf62b67a was slightly incomplete because
> it didn't rename the err_down_write_mmap_sem_failed label to
> err_down_read_mmap_sem_failed.
>
> I've tested this change by enabling CONFIG_ANDROID_BINDER_IPC_SELFTEST
> and verified that the binderfs_test selftest passes.
>
> Tyler
>
>  drivers/android/binder_alloc.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
> index 195f120c4e8c..bb929eb87116 100644
> --- a/drivers/android/binder_alloc.c
> +++ b/drivers/android/binder_alloc.c
> @@ -931,8 +931,8 @@ enum lru_status binder_alloc_free_page(struct list_head 
> *item,
> mm = alloc->vma_vm_mm;
> if (!mmget_not_zero(mm))
> goto err_mmget;
> -   if (!down_write_trylock(&mm->mmap_sem))
> -   goto err_down_write_mmap_sem_failed;
> +   if (!down_read_trylock(&mm->mmap_sem))
> +   goto err_down_read_mmap_sem_failed;
> vma = binder_alloc_get_vma(alloc);
>
> list_lru_isolate(lru, item);
> @@ -945,7 +945,7 @@ enum lru_status binder_alloc_free_page(struct list_head 
> *item,
>
> trace_binder_unmap_user_end(alloc, index);
> }
> -   up_write(&mm->mmap_sem);
> +   up_read(&mm->mmap_sem);
> mmput(mm);
>
> trace_binder_unmap_kernel_start(alloc, index);
> @@ -959,7 +959,7 @@ enum lru_status binder_alloc_free_page(struct list_head 
> *item,
> mutex_unlock(&alloc->mutex);
> return LRU_REMOVED_RETRY;
>
> -err_down_write_mmap_sem_failed:
> +err_down_read_mmap_sem_failed:
> mmput_async(mm);
>  err_mmget:
>  err_page_already_freed:
> --
> 2.7.4
>


Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (3)

2019-03-28 Thread Todd Kjos
Sigh. One more try... master with the same patch as an attachment.
(the patch is already queued up in gregkh's 'char-misc-linus' branch).

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
master

On Thu, Mar 28, 2019 at 5:20 PM syzbot
 wrote:
>
> Hello,
>
> syzbot tried to test the proposed patch but build/boot failed:
>
> timed out
>
>
>
>
>
>
> Tested on:
>
> commit: 0532a1b0 virt: vbox: Implement passing requestor info to t..
> git tree:
> git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> char-misc-linus
> kernel config:  https://syzkaller.appspot.com/x/.config?x=8dcdce25ea72bedf
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
>
From d49c95c944c15732ef57f1c876e24838b2ddf34b Mon Sep 17 00:00:00 2001
From: Todd Kjos 
Date: Tue, 19 Mar 2019 09:53:01 -0700
Subject: [PATCH] binder: fix BUG_ON found by selinux-testsuite

The selinux-testsuite found an issue resulting in a BUG_ON()
where a conditional relied on a size_t going negative when
checking the validity of a buffer offset.

Fixes: 7a67a39320df ("binder: add function to copy binder object from buffer")
Reported-by: Paul Moore 
Tested-by: Paul Moore 
Signed-off-by: Todd Kjos 
---
Please add to 5.1 (fixes problem introduced in 5.1-rc1)

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

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8685882da64cd..4b9c7ca492e6d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2057,7 +2057,8 @@ static size_t binder_get_object(struct binder_proc *proc,
 	size_t object_size = 0;
 
 	read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
-	if (read_size < sizeof(*hdr) || !IS_ALIGNED(offset, sizeof(u32)))
+	if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
+	!IS_ALIGNED(offset, sizeof(u32)))
 		return 0;
 	binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
   offset, read_size);
-- 
2.21.0.225.g810b269d1ac-goog



Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (3)

2019-03-28 Thread Todd Kjos
On Thu, Mar 28, 2019 at 12:27 PM syzbot
 wrote:
>
> Hello,
>
> syzbot tried to test the proposed patch but build/boot failed:
>
> patch is already applied
>
>
> Tested on:
>
> commit: 0532a1b0 virt: vbox: Implement passing requestor info to t..
> git tree:
> git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> char-misc-linus
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> patch:  https://syzkaller.appspot.com/x/patch.diff?x=1577678b20
>

Trying again without (redundantly) attaching the patch...

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
char-misc-linus


Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (3)

2019-03-28 Thread Todd Kjos
/tpsmEJ for more information about syzbot.
> syzbot engineers can be reached at syzkal...@googlegroups.com.
>
> syzbot will keep track of this bug report. See:
> https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> syzbot can test patches for this bug, for details see:
> https://goo.gl/tpsmEJ#testing-patches
From d49c95c944c15732ef57f1c876e24838b2ddf34b Mon Sep 17 00:00:00 2001
From: Todd Kjos 
Date: Tue, 19 Mar 2019 09:53:01 -0700
Subject: [PATCH] binder: fix BUG_ON found by selinux-testsuite

The selinux-testsuite found an issue resulting in a BUG_ON()
where a conditional relied on a size_t going negative when
checking the validity of a buffer offset.

Fixes: 7a67a39320df ("binder: add function to copy binder object from buffer")
Reported-by: Paul Moore 
Tested-by: Paul Moore 
Signed-off-by: Todd Kjos 
---
Please add to 5.1 (fixes problem introduced in 5.1-rc1)

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

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8685882da64cd..4b9c7ca492e6d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2057,7 +2057,8 @@ static size_t binder_get_object(struct binder_proc *proc,
 	size_t object_size = 0;
 
 	read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
-	if (read_size < sizeof(*hdr) || !IS_ALIGNED(offset, sizeof(u32)))
+	if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
+	!IS_ALIGNED(offset, sizeof(u32)))
 		return 0;
 	binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
   offset, read_size);
-- 
2.21.0.225.g810b269d1ac-goog



[PATCH] binder: fix BUG_ON found by selinux-testsuite

2019-03-20 Thread Todd Kjos
The selinux-testsuite found an issue resulting in a BUG_ON()
where a conditional relied on a size_t going negative when
checking the validity of a buffer offset.

Fixes: 7a67a39320df ("binder: add function to copy binder object from buffer")
Reported-by: Paul Moore 
Tested-by: Paul Moore 
Signed-off-by: Todd Kjos 
---
Please add to 5.1 (fixes problem introduced in 5.1-rc1)

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

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8685882da64cd..4b9c7ca492e6d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2057,7 +2057,8 @@ static size_t binder_get_object(struct binder_proc *proc,
size_t object_size = 0;
 
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
-   if (read_size < sizeof(*hdr) || !IS_ALIGNED(offset, sizeof(u32)))
+   if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
+   !IS_ALIGNED(offset, sizeof(u32)))
return 0;
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
  offset, read_size);
-- 
2.21.0.225.g810b269d1ac-goog



Re: [PATCH] binder: fix race between munmap() and direct reclaim

2019-03-02 Thread Todd Kjos
On Fri, Mar 1, 2019 at 11:57 PM Greg KH  wrote:
>
> On Fri, Mar 01, 2019 at 03:06:06PM -0800, Todd Kjos wrote:
> > An munmap() on a binder device causes binder_vma_close() to be called
> > which clears the alloc->vma pointer.
> >
> > If direct reclaim causes binder_alloc_free_page() to be called, there
> > is a race where alloc->vma is read into a local vma pointer and then
> > used later after the mm->mmap_sem is acquired. This can result in
> > calling zap_page_range() with an invalid vma which manifests as a
> > use-after-free in zap_page_range().
> >
> > The fix is to check alloc->vma after acquiring the mmap_sem (which we
> > were acquiring anyway) and skip zap_page_range() if it has changed
> > to NULL.
> >
> > Signed-off-by: Todd Kjos 
> > ---
>
> Any specific commit that this fixes?

No, it's been there a long time.

> And should it be marked for stable releases?

It is needed in stable (back to 4.4), but will need to be backported.
Should I post backported versions targeting the specific releases now?
I was thinking we'd wait for this one to land. I think we'll need 1
patch for 4.4/4.9 and a second one for 4.14/4.19 (and some of those
backported patches will have conflicts when merged down to android-4.X
-- I think the 4.14/4.19 version will apply to all the android
branches). Let me know how you want to handle this.

>
> thanks,
>
> greg k-h


[PATCH] binder: fix race between munmap() and direct reclaim

2019-03-01 Thread Todd Kjos
An munmap() on a binder device causes binder_vma_close() to be called
which clears the alloc->vma pointer.

If direct reclaim causes binder_alloc_free_page() to be called, there
is a race where alloc->vma is read into a local vma pointer and then
used later after the mm->mmap_sem is acquired. This can result in
calling zap_page_range() with an invalid vma which manifests as a
use-after-free in zap_page_range().

The fix is to check alloc->vma after acquiring the mmap_sem (which we
were acquiring anyway) and skip zap_page_range() if it has changed
to NULL.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder_alloc.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 6389467670a0b..195f120c4e8c9 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -927,14 +927,13 @@ enum lru_status binder_alloc_free_page(struct list_head 
*item,
 
index = page - alloc->pages;
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
+
+   mm = alloc->vma_vm_mm;
+   if (!mmget_not_zero(mm))
+   goto err_mmget;
+   if (!down_write_trylock(&mm->mmap_sem))
+   goto err_down_write_mmap_sem_failed;
vma = binder_alloc_get_vma(alloc);
-   if (vma) {
-   if (!mmget_not_zero(alloc->vma_vm_mm))
-   goto err_mmget;
-   mm = alloc->vma_vm_mm;
-   if (!down_read_trylock(&mm->mmap_sem))
-   goto err_down_write_mmap_sem_failed;
-   }
 
list_lru_isolate(lru, item);
spin_unlock(lock);
@@ -945,10 +944,9 @@ enum lru_status binder_alloc_free_page(struct list_head 
*item,
zap_page_range(vma, page_addr, PAGE_SIZE);
 
trace_binder_unmap_user_end(alloc, index);
-
-   up_read(&mm->mmap_sem);
-   mmput(mm);
}
+   up_write(&mm->mmap_sem);
+   mmput(mm);
 
trace_binder_unmap_kernel_start(alloc, index);
 
-- 
2.21.0.352.gf09ad66450-goog



Re: [PATCH] binder: reduce mmap_sem write-side lock

2019-02-19 Thread Todd Kjos
On Mon, Feb 18, 2019 at 2:47 AM Minchan Kim  wrote:
>
> On Mon, Feb 18, 2019 at 09:32:08AM +0100, Greg KH wrote:
> > On Mon, Feb 18, 2019 at 05:11:45PM +0900, Minchan Kim wrote:
> > > binder has used write-side mmap_sem semaphore to release memory
> > > mapped at address space of the process. However, right lock to
> > > release pages is down_read, not down_write because page table lock
> > > already protects the race for parallel freeing.
> > >
> > > Please do not use mmap_sem write-side lock which is well known
> > > contented lock.
> > >
> > > Cc: Todd Kjos 
> > > Cc: Martijn Coenen 
> > > Cc: Arve Hjønnevåg 
> > > Cc: Greg Kroah-Hartman 
> > > Signed-off-by: Minchan Kim 

Acked-by: Todd Kjos 

> > > ---
> > >  drivers/android/binder_alloc.c | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > Is this just needed for the recent binder changes that are in
> > linux-next, or for older kernels as well?
>
> It has been there for several years but no need to fix older kernels
> because down_write of mmap_sem is technically not a bug to stop the
> working of binder. Rather than, it's just abuse of the lock so
> it's okay to fix only recent kernel.
>
> Thanks.


[PATCH] binder: fix handling of misaligned binder object

2019-02-14 Thread Todd Kjos
Fixes crash found by syzbot:
kernel BUG at drivers/android/binder_alloc.c:LINE! (2)

Reported-by: syzbot+55de1eb4975dec156...@syzkaller.appspotmail.com
Signed-off-by: Todd Kjos 
---
Applies to linux-next

 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 2dba539eb792c..8685882da64cd 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2057,7 +2057,7 @@ static size_t binder_get_object(struct binder_proc *proc,
size_t object_size = 0;
 
read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
-   if (read_size < sizeof(*hdr))
+   if (read_size < sizeof(*hdr) || !IS_ALIGNED(offset, sizeof(u32)))
return 0;
binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
  offset, read_size);
-- 
2.21.0.rc0.258.g878e2cd30e-goog



Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (2)

2019-02-14 Thread Todd Kjos
Trying again with the correct branch spec...

On Thu, Feb 14, 2019 at 2:34 PM Todd Kjos  wrote:
>
> On Thu, Feb 14, 2019 at 3:35 AM syzbot
>  wrote:
> >
> > syzbot has found a reproducer for the following crash on:
> >
> > HEAD commit:b3418f8bddf4 Add linux-next specific files for 20190214
> > git tree:   linux-next
> > console output: https://syzkaller.appspot.com/x/log.txt?x=161d2048c0
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=8a3a37525a677c71
> > dashboard link: https://syzkaller.appspot.com/bug?extid=55de1eb4975dec156d8f
> > compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> > syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=11cd2f1f40
> >
> > IMPORTANT: if you fix the bug, please add the following tag to the commit:
> > Reported-by: syzbot+55de1eb4975dec156...@syzkaller.appspotmail.com
> >
>
> Testing a fix:
>
#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
master


patch
Description: Binary data


Re: kernel BUG at drivers/android/binder_alloc.c:LINE! (2)

2019-02-14 Thread Todd Kjos
On Thu, Feb 14, 2019 at 3:35 AM syzbot
 wrote:
>
> syzbot has found a reproducer for the following crash on:
>
> HEAD commit:b3418f8bddf4 Add linux-next specific files for 20190214
> git tree:   linux-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=161d2048c0
> kernel config:  https://syzkaller.appspot.com/x/.config?x=8a3a37525a677c71
> dashboard link: https://syzkaller.appspot.com/bug?extid=55de1eb4975dec156d8f
> compiler:   gcc (GCC) 9.0.0 20181231 (experimental)
> syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=11cd2f1f40
>
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+55de1eb4975dec156...@syzkaller.appspotmail.com
>

Testing a fix:

#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
linux-next


patch
Description: Binary data


Re: [PATCH v3 1/7] binder: create userspace-to-binder-buffer copy function

2019-02-14 Thread Todd Kjos
On Thu, Feb 14, 2019 at 1:25 PM Joel Fernandes  wrote:
>
> On Thu, Feb 14, 2019 at 03:53:54PM -0500, Joel Fernandes wrote:
> > On Thu, Feb 14, 2019 at 3:42 PM Todd Kjos  wrote:
> > >
> > > On Thu, Feb 14, 2019 at 11:45 AM Joel Fernandes  wrote:
> > [snip]
> > > > > + * check_buffer() - verify that buffer/offset is safe to access
> > > > > + * @alloc: binder_alloc for this proc
> > > > > + * @buffer: binder buffer to be accessed
> > > > > + * @offset: offset into @buffer data
> > > > > + * @bytes: bytes to access from offset
> > > > > + *
> > > > > + * Check that the @offset/@bytes are within the size of the given
> > > > > + * @buffer and that the buffer is currently active and not freeable.
> > > > > + * Offsets must also be multiples of sizeof(u32). The kernel is
> > > >
> > > > In all callers of binder_alloc_copy_user_to_buffer, the alignment of 
> > > > offsets
> > > > is set to sizeof(void *). Then shouldn't this function check for 
> > > > sizeof(void *)
> > > > alignment instead of u32?
> > >
> > > But there are other callers of check_buffer() later in the series that
> > > don't require pointer-size alignment. u32 alignment is consistent with
> > > the alignment requirements of the binder driver before this change.
> > > The copy functions don't actually need to insist on alignment, but
> > > these binder buffer objects have always used u32 alignment which has
> > > been checked in the driver. If user code misaligned it, then errors
> > > are returned. The alignment checks are really to be consistent with
> > > previous binder driver behavior.
> >
> > Got it, thanks.
>
> One more thing I wanted to ask is, kmap() will now cause global lock
> contention because of using spin_lock due to kmap_high().
>
> Previously the binder driver was made to not use global lock (as you had
> done). Now these paths will start global locking on 32-bit architectures.
> Would that degrade performance?

There was a lot of concern about 32-bit performance both for
lock-contention and the cost of map/unmap operations. Of course,
32-bit systems are also where the primary win is -- namely avoiding
vmalloc space depletion. So there was a several months-long evaluation
period on 32-bit devices by a silicon vendor who did a lot of testing
across a broad set of benchmarks / workloads to verify the performance
costs are acceptable. We also ran tests to try to exhaust the kmap
space with multiple large buffers.

The testing did find that there is some performance degradation for
large buffer transfers, but there are no cases where this
significantly impacted a meaningful user workload.

>
> Are we not using kmap_atomic() in this patch because of any concern that the
> kmap fixmap space is limited and may run out?

We're not using the atomic version here since we can't guarantee that
the loop will be atomic since we are calling copy_from_user(). Later
in the series, other cases do use kmap_atomic().

>
> thanks,
>
>  - Joel
>
>


Re: [PATCH v3 1/7] binder: create userspace-to-binder-buffer copy function

2019-02-14 Thread Todd Kjos
On Thu, Feb 14, 2019 at 11:45 AM Joel Fernandes  wrote:
>
> Hi Todd,
>
> One quick question:
>
> On Fri, Feb 08, 2019 at 10:35:14AM -0800, Todd Kjos wrote:
> > The binder driver uses a vm_area to map the per-process
> > binder buffer space. For 32-bit android devices, this is
> > now taking too much vmalloc space. This patch removes
> > the use of vm_area when copying the transaction data
> > from the sender to the buffer space. Instead of using
> > copy_from_user() for multi-page copies, it now uses
> > binder_alloc_copy_user_to_buffer() which uses kmap()
> > and kunmap() to map each page, and uses copy_from_user()
> > for copying to that page.
> >
> > Signed-off-by: Todd Kjos 
> > ---
> > v2: remove casts as suggested by Dan Carpenter
> >
> >  drivers/android/binder.c   |  29 +++--
> >  drivers/android/binder_alloc.c | 113 +
> >  drivers/android/binder_alloc.h |   8 +++
> >  3 files changed, 143 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 5f6ef5e63b91e..ab0b3eec363bc 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -3078,8 +3078,12 @@ static void binder_transaction(struct binder_proc 
> > *proc,
> > ALIGN(tr->data_size, sizeof(void *)));
> >   offp = off_start;
> >
> > - if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
> > -tr->data.ptr.buffer, tr->data_size)) {
> > + if (binder_alloc_copy_user_to_buffer(
> > + &target_proc->alloc,
> > + t->buffer, 0,
> > + (const void __user *)
> > + (uintptr_t)tr->data.ptr.buffer,
> > + tr->data_size)) {
> >   binder_user_error("%d:%d got transaction with invalid data 
> > ptr\n",
> >   proc->pid, thread->pid);
> >   return_error = BR_FAILED_REPLY;
> > @@ -3087,8 +3091,13 @@ static void binder_transaction(struct binder_proc 
> > *proc,
> >   return_error_line = __LINE__;
> >   goto err_copy_data_failed;
> >   }
> > - if (copy_from_user(offp, (const void __user *)(uintptr_t)
> > -tr->data.ptr.offsets, tr->offsets_size)) {
> > + if (binder_alloc_copy_user_to_buffer(
> > + &target_proc->alloc,
> > + t->buffer,
> > + ALIGN(tr->data_size, sizeof(void *)),
> > + (const void __user *)
> > + (uintptr_t)tr->data.ptr.offsets,
> > + tr->offsets_size)) {
> >   binder_user_error("%d:%d got transaction with invalid offsets 
> > ptr\n",
> >   proc->pid, thread->pid);
> >   return_error = BR_FAILED_REPLY;
> > @@ -3217,6 +3226,8 @@ static void binder_transaction(struct binder_proc 
> > *proc,
> >   struct binder_buffer_object *bp =
> >   to_binder_buffer_object(hdr);
> >   size_t buf_left = sg_buf_end - sg_bufp;
> > + binder_size_t sg_buf_offset = (uintptr_t)sg_bufp -
> > + (uintptr_t)t->buffer->data;
> >
> >   if (bp->length > buf_left) {
> >   binder_user_error("%d:%d got transaction with 
> > too large buffer\n",
> > @@ -3226,9 +3237,13 @@ static void binder_transaction(struct binder_proc 
> > *proc,
> >   return_error_line = __LINE__;
> >   goto err_bad_offset;
> >   }
> > - if (copy_from_user(sg_bufp,
> > -(const void __user *)(uintptr_t)
> > -bp->buffer, bp->length)) {
> > + if (binder_alloc_copy_user_to_buffer(
> > + &target_proc->alloc,
> > + t->buffer,
> > + sg_buf_offset,
> > + (const void __user *)
>

[PATCH] binder: fix sparse issue in binder_alloc_selftest.c

2019-02-13 Thread Todd Kjos
Fixes sparse issues reported by the kbuild test robot running
on https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
char-misc-testing: bde4a19fc04f5 ("binder: use userspace pointer as base
of buffer space")

Error output (drivers/android/binder_alloc_selftest.c):
sparse: warning: incorrect type in assignment (different address spaces)
sparse:expected void *page_addr
sparse:got void [noderef]  *user_data
sparse: error: subtraction of different types can't work

Fixed by adding necessary "__user" tags.

Reported-by: kbuild test robot 
Signed-off-by: Todd Kjos 
---
 drivers/android/binder_alloc_selftest.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/android/binder_alloc_selftest.c 
b/drivers/android/binder_alloc_selftest.c
index f0f4d7d026351..b72708918b06b 100644
--- a/drivers/android/binder_alloc_selftest.c
+++ b/drivers/android/binder_alloc_selftest.c
@@ -102,10 +102,11 @@ static bool check_buffer_pages_allocated(struct 
binder_alloc *alloc,
 struct binder_buffer *buffer,
 size_t size)
 {
-   void *page_addr, *end;
+   void __user *page_addr;
+   void __user *end;
int page_index;
 
-   end = (void *)PAGE_ALIGN((uintptr_t)buffer->user_data + size);
+   end = (void __user *)PAGE_ALIGN((uintptr_t)buffer->user_data + size);
page_addr = buffer->user_data;
for (; page_addr < end; page_addr += PAGE_SIZE) {
page_index = (page_addr - alloc->buffer) / PAGE_SIZE;
-- 
2.20.1.791.gb4d0f1c61a-goog



Re: [PATCH] staging: android: vsoc: Remove VSOC_WAIT_FOR_INCOMING_INTERRUPT

2019-02-11 Thread Todd Kjos
+Alistair Strachan

On Mon, Feb 11, 2019 at 9:11 AM Greg KH  wrote:
>
> On Mon, Feb 11, 2019 at 10:15:18PM +0530, Souptick Joarder wrote:
> > On Mon, Feb 11, 2019 at 9:27 PM Greg KH  wrote:
> > >
> > > On Mon, Feb 11, 2019 at 09:21:19PM +0530, Souptick Joarder wrote:
> > > > On Mon, Feb 11, 2019 at 9:10 PM Greg KH  
> > > > wrote:
> > > > >
> > > > > On Mon, Feb 11, 2019 at 08:56:02PM +0530, Souptick Joarder wrote:
> > > > > > As mentioned in TODO list, Removed VSOC_WAIT_FOR_INCOMING_INTERRUPT
> > > > > > ioctl. This functionality has been superseded by the futex and is
> > > > > > there for legacy reasons.
> > > > > >
> > > > > > Signed-off-by: Souptick Joarder 
> > > > > > ---
> > > > > >  drivers/staging/android/uapi/vsoc_shm.h | 7 ---
> > > > > >  drivers/staging/android/vsoc.c  | 5 -
> > > > > >  2 files changed, 12 deletions(-)
> > > > >
> > > > > So userspace is all fixed up now and this ioctl can be dropped?  Any
> > > > > pointers to the userspace commit that did this?
> > > >
> > > > I am not sure about user space part.
> > >
> > > Then we can not just delete the ioctl :)
> >
> > Agree, but where to verify the user space commit ?
> > Any pointer to the source code path ?
>
> Please work with the android developers to solve this.  It should be in
> AOSP "somewhere" :(
>
> good luck,
>
> greg k-h


Re: [PATCH v3 0/7] binder: eliminate use of vmalloc space for binder buffers

2019-02-11 Thread Todd Kjos
On Mon, Feb 11, 2019 at 8:57 AM Christoph Hellwig  wrote:
>
> On Fri, Feb 08, 2019 at 10:35:13AM -0800, Todd Kjos wrote:
> > Binder buffers have always been mapped into kernel space
> > via map_kernel_range_noflush() to allow the binder driver
> > to modify the buffer before posting to userspace for
> > processing.
> >
> > In recent Android releases, the number of long-running
> > binder processes has increased to the point that for
> > 32-bit systems, there is a risk of running out of
> > vmalloc space.
> >
> > This patch set removes the persistent mapping of the
> > binder buffers into kernel space. Instead, the binder
> > driver creates temporary mappings with kmap() or
> > kmap_atomic() to copy to or from the buffer only when
> > necessary.
>
> Is there any good reason to actually map the user memory to kernel
> space instead of just using copy_{to,from}_user?

Yes, the mappings are needed for cases where we are accessing binder
buffers of the target while in sender context. For example, we copy
the message from the sender to the target with 1 copy while in the
sender's context. For this we use copy_from_user(), but use these
temporary mappings for the destination (target process).

-Todd


[PATCH v3 2/7] binder: add functions to copy to/from binder buffers

2019-02-08 Thread Todd Kjos
Avoid vm_area when copying to or from binder buffers.
Instead, new copy functions are added that copy from
kernel space to binder buffer space. These use
kmap_atomic() and kunmap_atomic() to create temporary
mappings and then memcpy() is used to copy within
that page.

Also, kmap_atomic() / kunmap_atomic() use the appropriate
cache flushing to support VIVT cache architectures.
Allow binder to build if CPU_CACHE_VIVT is defined.

Several uses of the new functions are added here. More
to follow in subsequent patches.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 119 +
 drivers/android/binder_alloc.c |  59 
 drivers/android/binder_alloc.h |  12 
 4 files changed, 147 insertions(+), 45 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 4c190f8d1f4c6..6fdf2abe4598a 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 && !CPU_CACHE_VIVT
+   depends on MMU
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 ab0b3eec363bc..74d0c1ff874e2 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2244,14 +2244,22 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
off_end = (void *)off_start + buffer->offsets_size;
for (offp = off_start; offp < off_end; offp++) {
struct binder_object_header *hdr;
-   size_t object_size = binder_validate_object(buffer, *offp);
-
+   size_t object_size;
+   binder_size_t object_offset;
+   binder_size_t buffer_offset = (uintptr_t)offp -
+   (uintptr_t)buffer->data;
+
+   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ buffer, buffer_offset,
+ sizeof(object_offset));
+   object_size = binder_validate_object(buffer, object_offset);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
-  debug_id, (u64)*offp, buffer->data_size);
+  debug_id, (u64)object_offset, buffer->data_size);
continue;
}
-   hdr = (struct binder_object_header *)(buffer->data + *offp);
+   hdr = (struct binder_object_header *)
+   (buffer->data + object_offset);
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
@@ -2359,8 +2367,20 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
continue;
}
fd_array = (u32 *)(parent_buffer + 
(uintptr_t)fda->parent_offset);
-   for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
-   binder_deferred_fd_close(fd_array[fd_index]);
+   for (fd_index = 0; fd_index < fda->num_fds;
+fd_index++) {
+   u32 fd;
+   binder_size_t offset =
+   (uintptr_t)&fd_array[fd_index] -
+   (uintptr_t)buffer->data;
+
+   binder_alloc_copy_from_buffer(&proc->alloc,
+ &fd,
+ buffer,
+ offset,
+ sizeof(fd));
+   binder_deferred_fd_close(fd);
+   }
} break;
default:
pr_err("transaction release %d bad object type %x\n",
@@ -2496,7 +2516,7 @@ static int binder_translate_handle(struct 
flat_binder_object *fp,
return ret;
 }
 
-static int binder_translate_fd(u32 *fdp,
+static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
   struct binder_transaction *t,
   struct binder_thread *thread,
   struct binder_transaction *in_reply_to)
@@ -2507,7 +2527,6 @@ static int binder_translate_fd(u32 *fdp,
struct file *file;
int ret = 0;
bool target_allows_fd;
-   int fd = *fdp;
 

[PATCH v3 7/7] binder: use userspace pointer as base of buffer space

2019-02-08 Thread Todd Kjos
Now that alloc->buffer points to the userspace vm_area
rename buffer->data to buffer->user_data and rename
local pointers that hold user addresses. Also use the
"__user" tag to annotate all user pointers so sparse
can flag cases where user pointer vaues  are copied to
kernel pointers. Refactor code to use offsets instead
of user pointers.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter
v3: fix build-break when CONFIG_ANDROID_BINDER_IPC_SELFTEST enabled

 drivers/android/binder.c| 118 ++--
 drivers/android/binder_alloc.c  |  87 -
 drivers/android/binder_alloc.h  |   6 +-
 drivers/android/binder_alloc_selftest.c |   4 +-
 drivers/android/binder_trace.h  |   2 +-
 5 files changed, 118 insertions(+), 99 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index b3d609b5935a6..25491eceb7503 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2278,33 +2278,30 @@ static void binder_deferred_fd_close(int fd)
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
  struct binder_buffer *buffer,
- binder_size_t *failed_at)
+ binder_size_t failed_at,
+ bool is_failure)
 {
-   binder_size_t *offp, *off_start, *off_end;
int debug_id = buffer->debug_id;
-   binder_size_t off_start_offset;
+   binder_size_t off_start_offset, buffer_offset, off_end_offset;
 
binder_debug(BINDER_DEBUG_TRANSACTION,
-"%d buffer release %d, size %zd-%zd, failed at %pK\n",
+"%d buffer release %d, size %zd-%zd, failed at %llx\n",
 proc->pid, buffer->debug_id,
-buffer->data_size, buffer->offsets_size, failed_at);
+buffer->data_size, buffer->offsets_size,
+(unsigned long long)failed_at);
 
if (buffer->target_node)
binder_dec_node(buffer->target_node, 1, 0);
 
off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
-   off_start = (binder_size_t *)(buffer->data + off_start_offset);
-   if (failed_at)
-   off_end = failed_at;
-   else
-   off_end = (void *)off_start + buffer->offsets_size;
-   for (offp = off_start; offp < off_end; offp++) {
+   off_end_offset = is_failure ? failed_at :
+   off_start_offset + buffer->offsets_size;
+   for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+buffer_offset += sizeof(binder_size_t)) {
struct binder_object_header *hdr;
size_t object_size;
struct binder_object object;
binder_size_t object_offset;
-   binder_size_t buffer_offset = (uintptr_t)offp -
-   (uintptr_t)buffer->data;
 
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
  buffer, buffer_offset,
@@ -2380,9 +2377,10 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
struct binder_object ptr_object;
-   u32 *fd_array;
+   binder_size_t fda_offset;
size_t fd_index;
binder_size_t fd_buf_size;
+   binder_size_t num_valid;
 
if (proc->tsk != current->group_leader) {
/*
@@ -2393,12 +2391,14 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
continue;
}
 
+   num_valid = (buffer_offset - off_start_offset) /
+   sizeof(binder_size_t);
fda = to_binder_fd_array_object(hdr);
parent = binder_validate_ptr(proc, buffer, &ptr_object,
 fda->parent,
 off_start_offset,
 NULL,
-offp - off_start);
+num_valid);
if (!parent) {
pr_err("transaction release %d bad parent 
offset\n",
   debug_id);
@@ -2417,14 +2417,21 @@ static void binder_transaction_buffer_release(struct 
binder_

[PATCH v3 6/7] binder: remove user_buffer_offset

2019-02-08 Thread Todd Kjos
Remove user_buffer_offset since there is no kernel
buffer pointer anymore.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/binder.c   | 39 ++
 drivers/android/binder_alloc.c | 16 ++
 drivers/android/binder_alloc.h | 23 
 3 files changed, 13 insertions(+), 65 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 98163bf5f35c7..b3d609b5935a6 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2380,7 +2380,6 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
struct binder_object ptr_object;
-   uintptr_t parent_buffer;
u32 *fd_array;
size_t fd_index;
binder_size_t fd_buf_size;
@@ -2405,14 +2404,6 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id);
continue;
}
-   /*
-* Since the parent was already fixed up, convert it
-* back to kernel address space to access it
-*/
-   parent_buffer = parent->buffer -
-   binder_alloc_get_user_buffer_offset(
-   &proc->alloc);
-
fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
pr_err("transaction release %d invalid number 
of fds (%lld)\n",
@@ -2426,7 +2417,8 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id, (u64)fda->num_fds);
continue;
}
-   fd_array = (u32 *)(parent_buffer + 
(uintptr_t)fda->parent_offset);
+   fd_array = (u32 *)(uintptr_t)
+   (parent->buffer + fda->parent_offset);
for (fd_index = 0; fd_index < fda->num_fds;
 fd_index++) {
u32 fd;
@@ -2646,7 +2638,6 @@ static int binder_translate_fd_array(struct 
binder_fd_array_object *fda,
 struct binder_transaction *in_reply_to)
 {
binder_size_t fdi, fd_buf_size;
-   uintptr_t parent_buffer;
u32 *fd_array;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2664,13 +2655,7 @@ static int binder_translate_fd_array(struct 
binder_fd_array_object *fda,
  proc->pid, thread->pid, (u64)fda->num_fds);
return -EINVAL;
}
-   /*
-* Since the parent was already fixed up, convert it
-* back to the kernel address space to access it
-*/
-   parent_buffer = parent->buffer -
-   binder_alloc_get_user_buffer_offset(&target_proc->alloc);
-   fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
+   fd_array = (u32 *)(uintptr_t)(parent->buffer + fda->parent_offset);
if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
binder_user_error("%d:%d parent offset not aligned 
correctly.\n",
  proc->pid, thread->pid);
@@ -2703,7 +2688,6 @@ static int binder_fixup_parent(struct binder_transaction 
*t,
   binder_size_t last_fixup_min_off)
 {
struct binder_buffer_object *parent;
-   u8 *parent_buffer;
struct binder_buffer *b = t->buffer;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2739,11 +2723,8 @@ static int binder_fixup_parent(struct binder_transaction 
*t,
  proc->pid, thread->pid);
return -EINVAL;
}
-   parent_buffer = (u8 *)((uintptr_t)parent->buffer -
-   binder_alloc_get_user_buffer_offset(
-   &target_proc->alloc));
buffer_offset = bp->parent_offset +
-   (uintptr_t)parent_buffer - (uintptr_t)b->data;
+   (uintptr_t)parent->buffer - (uintptr_t)b->data;
binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
&bp->buffer, sizeof(bp->buffer));
 
@@ -3159,10 +3140,8 @@ static void binder_transaction(struct binder_proc *proc,

[PATCH v3 3/7] binder: add function to copy binder object from buffer

2019-02-08 Thread Todd Kjos
When creating or tearing down a transaction, the binder driver
examines objects in the buffer and takes appropriate action.
To do this without needing to dereference pointers into the
buffer, the local copies of the objects are needed. This patch
introduces a function to validate and copy binder objects
from the buffer to a local structure.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/binder.c | 75 +++-
 1 file changed, 58 insertions(+), 17 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 74d0c1ff874e2..8063b405e4fa1 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -628,6 +628,26 @@ struct binder_transaction {
spinlock_t lock;
 };
 
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+   union {
+   struct binder_object_header hdr;
+   struct flat_binder_object fbo;
+   struct binder_fd_object fdo;
+   struct binder_buffer_object bbo;
+   struct binder_fd_array_object fdao;
+   };
+};
+
 /**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc: struct binder_proc to acquire
@@ -2017,26 +2037,33 @@ static void binder_cleanup_transaction(struct 
binder_transaction *t,
 }
 
 /**
- * binder_validate_object() - checks for a valid metadata object in a buffer.
+ * binder_get_object() - gets object and checks for valid metadata
+ * @proc:  binder_proc owning the buffer
  * @buffer:binder_buffer that we're parsing.
- * @offset:offset in the buffer at which to validate an object.
+ * @offset:offset in the @buffer at which to validate an object.
+ * @object:struct binder_object to read into
  *
  * Return: If there's a valid metadata object at @offset in @buffer, the
- * size of that object. Otherwise, it returns zero.
+ * size of that object. Otherwise, it returns zero. The object
+ * is read into the struct binder_object pointed to by @object.
  */
-static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
+static size_t binder_get_object(struct binder_proc *proc,
+   struct binder_buffer *buffer,
+   unsigned long offset,
+   struct binder_object *object)
 {
-   /* Check if we can read a header first */
+   size_t read_size;
struct binder_object_header *hdr;
size_t object_size = 0;
 
-   if (buffer->data_size < sizeof(*hdr) ||
-   offset > buffer->data_size - sizeof(*hdr) ||
-   !IS_ALIGNED(offset, sizeof(u32)))
+   read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
+   if (read_size < sizeof(*hdr))
return 0;
+   binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+ offset, read_size);
 
-   /* Ok, now see if we can read a complete object. */
-   hdr = (struct binder_object_header *)(buffer->data + offset);
+   /* Ok, now see if we read a complete object. */
+   hdr = &object->hdr;
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER:
@@ -2245,6 +2272,7 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
for (offp = off_start; offp < off_end; offp++) {
struct binder_object_header *hdr;
size_t object_size;
+   struct binder_object object;
binder_size_t object_offset;
binder_size_t buffer_offset = (uintptr_t)offp -
(uintptr_t)buffer->data;
@@ -2252,14 +2280,14 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
  buffer, buffer_offset,
  sizeof(object_offset));
-   object_size = binder_validate_object(buffer, object_offset);
+   object_size = binder_get_object(proc, buffer,
+   object_offset, &object);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
   debug_id, (u64)object_offset, buffer->data_size);
continue;
}
-   hdr = (struct binder_object_header *)
-   (buffer->data +

[PATCH v3 5/7] binder: remove kernel vm_area for buffer space

2019-02-08 Thread Todd Kjos
Remove the kernel's vm_area and the code that maps
buffer pages into it.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder_alloc.c | 40 ++
 1 file changed, 2 insertions(+), 38 deletions(-)

diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 2eebff4be83e0..d4cbe4b3947a6 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -265,16 +265,6 @@ static int binder_update_page_range(struct binder_alloc 
*alloc, int allocate,
page->alloc = alloc;
INIT_LIST_HEAD(&page->lru);
 
-   ret = map_kernel_range_noflush((unsigned long)page_addr,
-  PAGE_SIZE, PAGE_KERNEL,
-  &page->page_ptr);
-   flush_cache_vmap((unsigned long)page_addr,
-   (unsigned long)page_addr + PAGE_SIZE);
-   if (ret != 1) {
-   pr_err("%d: binder_alloc_buf failed to map page at %pK 
in kernel\n",
-  alloc->pid, page_addr);
-   goto err_map_kernel_failed;
-   }
user_page_addr =
(uintptr_t)page_addr + alloc->user_buffer_offset;
ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr);
@@ -314,8 +304,6 @@ static int binder_update_page_range(struct binder_alloc 
*alloc, int allocate,
continue;
 
 err_vm_insert_page_failed:
-   unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-err_map_kernel_failed:
__free_page(page->page_ptr);
page->page_ptr = NULL;
 err_alloc_page_failed:
@@ -695,7 +683,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
  struct vm_area_struct *vma)
 {
int ret;
-   struct vm_struct *area;
const char *failure_string;
struct binder_buffer *buffer;
 
@@ -706,28 +693,10 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
goto err_already_mapped;
}
 
-   area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC);
-   if (area == NULL) {
-   ret = -ENOMEM;
-   failure_string = "get_vm_area";
-   goto err_get_vm_area_failed;
-   }
-   alloc->buffer = area->addr;
-   alloc->user_buffer_offset =
-   vma->vm_start - (uintptr_t)alloc->buffer;
+   alloc->buffer = (void *)vma->vm_start;
+   alloc->user_buffer_offset = 0;
mutex_unlock(&binder_alloc_mmap_lock);
 
-#ifdef CONFIG_CPU_CACHE_VIPT
-   if (cache_is_vipt_aliasing()) {
-   while (CACHE_COLOUR(
-   (vma->vm_start ^ (uint32_t)alloc->buffer))) {
-   pr_info("%s: %d %lx-%lx maps %pK bad alignment\n",
-   __func__, alloc->pid, vma->vm_start,
-   vma->vm_end, alloc->buffer);
-   vma->vm_start += PAGE_SIZE;
-   }
-   }
-#endif
alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
   sizeof(alloc->pages[0]),
   GFP_KERNEL);
@@ -760,9 +729,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
alloc->pages = NULL;
 err_alloc_pages_failed:
mutex_lock(&binder_alloc_mmap_lock);
-   vfree(alloc->buffer);
alloc->buffer = NULL;
-err_get_vm_area_failed:
 err_already_mapped:
mutex_unlock(&binder_alloc_mmap_lock);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
@@ -821,12 +788,10 @@ void binder_alloc_deferred_release(struct binder_alloc 
*alloc)
 "%s: %d: page %d at %pK %s\n",
 __func__, alloc->pid, i, page_addr,
 on_lru ? "on lru" : "active");
-   unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
__free_page(alloc->pages[i].page_ptr);
page_count++;
}
kfree(alloc->pages);
-   vfree(alloc->buffer);
}
mutex_unlock(&alloc->mutex);
if (alloc->vma_vm_mm)
@@ -988,7 +953,6 @@ enum lru_status binder_alloc_free_page(struct list_head 
*item,
 
trace_binder_unmap_kernel_start(alloc, index);
 
-   unmap_kernel_range(page_addr, PAGE_SIZE);
__free_page(page->page_ptr);
page->page_ptr = NULL;
 
-- 
2.20.1.791.gb4d0f1c61a-goog



[PATCH v3 4/7] binder: avoid kernel vm_area for buffer fixups

2019-02-08 Thread Todd Kjos
Refactor the functions to validate and fixup struct
binder_buffer pointer objects to avoid using vm_area
pointers. Instead copy to/from kernel space using
binder_alloc_copy_to_buffer() and
binder_alloc_copy_from_buffer(). The following
functions were refactored:

refactor binder_validate_ptr()
binder_validate_fixup()
binder_fixup_parent()

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 146 ++-
 1 file changed, 97 insertions(+), 49 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8063b405e4fa1..98163bf5f35c7 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2092,10 +2092,13 @@ static size_t binder_get_object(struct binder_proc 
*proc,
 
 /**
  * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer.
+ * @proc:  binder_proc owning the buffer
  * @b: binder_buffer containing the object
+ * @object:struct binder_object to read into
  * @index: index in offset array at which the binder_buffer_object is
  * located
- * @start: points to the start of the offset array
+ * @start_offset: points to the start of the offset array
+ * @object_offsetp: offset of @object read from @b
  * @num_valid: the number of valid offsets in the offset array
  *
  * Return: If @index is within the valid range of the offset array
@@ -2106,34 +2109,46 @@ static size_t binder_get_object(struct binder_proc 
*proc,
  * Note that the offset found in index @index itself is not
  * verified; this function assumes that @num_valid elements
  * from @start were previously verified to have valid offsets.
+ * If @object_offsetp is non-NULL, then the offset within
+ * @b is written to it.
  */
-static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer 
*b,
-   binder_size_t index,
-   binder_size_t *start,
-   binder_size_t num_valid)
+static struct binder_buffer_object *binder_validate_ptr(
+   struct binder_proc *proc,
+   struct binder_buffer *b,
+   struct binder_object *object,
+   binder_size_t index,
+   binder_size_t start_offset,
+   binder_size_t *object_offsetp,
+   binder_size_t num_valid)
 {
-   struct binder_buffer_object *buffer_obj;
-   binder_size_t *offp;
+   size_t object_size;
+   binder_size_t object_offset;
+   unsigned long buffer_offset;
 
if (index >= num_valid)
return NULL;
 
-   offp = start + index;
-   buffer_obj = (struct binder_buffer_object *)(b->data + *offp);
-   if (buffer_obj->hdr.type != BINDER_TYPE_PTR)
+   buffer_offset = start_offset + sizeof(binder_size_t) * index;
+   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ b, buffer_offset, sizeof(object_offset));
+   object_size = binder_get_object(proc, b, object_offset, object);
+   if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
+   if (object_offsetp)
+   *object_offsetp = object_offset;
 
-   return buffer_obj;
+   return &object->bbo;
 }
 
 /**
  * binder_validate_fixup() - validates pointer/fd fixups happen in order.
+ * @proc:  binder_proc owning the buffer
  * @b: transaction buffer
- * @objects_start  start of objects buffer
- * @buffer:binder_buffer_object in which to fix up
- * @offset:start offset in @buffer to fix up
- * @last_obj:  last binder_buffer_object that we fixed up in
- * @last_min_offset:   minimum fixup offset in @last_obj
+ * @objects_start_offset: offset to start of objects buffer
+ * @buffer_obj_offset: offset to binder_buffer_object in which to fix up
+ * @fixup_offset:  start offset in @buffer to fix up
+ * @last_obj_offset:   offset to last binder_buffer_object that we fixed
+ * @last_min_offset:   minimum fixup offset in object at @last_obj_offset
  *
  * Return: %true if a fixup in buffer @buffer at offset @offset is
  * allowed.
@@ -2164,28 +2179,41 @@ static struct binder_buffer_object 
*binder_validate_ptr(struct binder_buffer *b,
  *   C (parent = A, offset = 16)
  * D (parent = B, offset = 0) // B is not A or any of A's parents
  */
-static bool binder_validate_fixup(struct binder_buffer *b,
- binder_size_t *objects_start,
- 

[PATCH v3 1/7] binder: create userspace-to-binder-buffer copy function

2019-02-08 Thread Todd Kjos
The binder driver uses a vm_area to map the per-process
binder buffer space. For 32-bit android devices, this is
now taking too much vmalloc space. This patch removes
the use of vm_area when copying the transaction data
from the sender to the buffer space. Instead of using
copy_from_user() for multi-page copies, it now uses
binder_alloc_copy_user_to_buffer() which uses kmap()
and kunmap() to map each page, and uses copy_from_user()
for copying to that page.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/binder.c   |  29 +++--
 drivers/android/binder_alloc.c | 113 +
 drivers/android/binder_alloc.h |   8 +++
 3 files changed, 143 insertions(+), 7 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5f6ef5e63b91e..ab0b3eec363bc 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3078,8 +3078,12 @@ static void binder_transaction(struct binder_proc *proc,
  ALIGN(tr->data_size, sizeof(void *)));
offp = off_start;
 
-   if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
-  tr->data.ptr.buffer, tr->data_size)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer, 0,
+   (const void __user *)
+   (uintptr_t)tr->data.ptr.buffer,
+   tr->data_size)) {
binder_user_error("%d:%d got transaction with invalid data 
ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3087,8 +3091,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_copy_data_failed;
}
-   if (copy_from_user(offp, (const void __user *)(uintptr_t)
-  tr->data.ptr.offsets, tr->offsets_size)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer,
+   ALIGN(tr->data_size, sizeof(void *)),
+   (const void __user *)
+   (uintptr_t)tr->data.ptr.offsets,
+   tr->offsets_size)) {
binder_user_error("%d:%d got transaction with invalid offsets 
ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3217,6 +3226,8 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_buffer_object *bp =
to_binder_buffer_object(hdr);
size_t buf_left = sg_buf_end - sg_bufp;
+   binder_size_t sg_buf_offset = (uintptr_t)sg_bufp -
+   (uintptr_t)t->buffer->data;
 
if (bp->length > buf_left) {
binder_user_error("%d:%d got transaction with 
too large buffer\n",
@@ -3226,9 +3237,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
-   if (copy_from_user(sg_bufp,
-  (const void __user *)(uintptr_t)
-  bp->buffer, bp->length)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer,
+   sg_buf_offset,
+   (const void __user *)
+   (uintptr_t)bp->buffer,
+   bp->length)) {
binder_user_error("%d:%d got transaction with 
invalid offsets ptr\n",
  proc->pid, thread->pid);
return_error_param = -EFAULT;
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 022cd80e80cc3..94c0d85c4e75b 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -29,6 +29,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "binder_alloc.h"
 #include "binder_trace.h"
 
@@ -1053,3 +1055,114 @@ int binder_alloc_shrinker_init(void)
}
return ret;
 }
+
+/**
+ * check_buffer() - verify that buffer/offset is safe 

[PATCH v3 0/7] binder: eliminate use of vmalloc space for binder buffers

2019-02-08 Thread Todd Kjos
Binder buffers have always been mapped into kernel space
via map_kernel_range_noflush() to allow the binder driver
to modify the buffer before posting to userspace for
processing.

In recent Android releases, the number of long-running
binder processes has increased to the point that for
32-bit systems, there is a risk of running out of
vmalloc space.

This patch set removes the persistent mapping of the
binder buffers into kernel space. Instead, the binder
driver creates temporary mappings with kmap() or
kmap_atomic() to copy to or from the buffer only when
necessary.

Todd Kjos (7):
binder: create userspace-to-binder-buffer copy function
binder: add functions to copy to/from binder buffers
binder: add function to copy binder object from buffer
binder: avoid kernel vm_area for buffer fixups
binder: remove kernel vm_area for buffer space
binder: remove user_buffer_offset
binder: use userspace pointer as base of buffer space

v2: remove casts as suggested by Dan Carpenter
v3: fix build-break when CONFIG_ANDROID_BINDER_IPC_SELFTEST enabled

 drivers/android/Kconfig |   2 +-
 drivers/android/binder.c| 460 
++
 drivers/android/binder_alloc.c  | 299 
+--
 drivers/android/binder_alloc.h  |  47 
 drivers/android/binder_alloc_selftest.c |   4 +-
 drivers/android/binder_trace.h  |   2 +-
 6 files changed, 536 insertions(+), 278 deletions(-)


Re: [PATCH v2 0/7] binder: eliminate use of vmalloc space for binder buffers

2019-02-08 Thread Todd Kjos
On Fri, Feb 8, 2019 at 3:26 AM Greg KH  wrote:
>
> On Wed, Jan 30, 2019 at 02:46:48PM -0800, Todd Kjos wrote:
> > Binder buffers have always been mapped into kernel space
> > via map_kernel_range_noflush() to allow the binder driver
> > to modify the buffer before posting to userspace for
> > processing.
> >
> > In recent Android releases, the number of long-running
> > binder processes has increased to the point that for
> > 32-bit systems, there is a risk of running out of
> > vmalloc space.
> >
> > This patch set removes the persistent mapping of the
> > binder buffers into kernel space. Instead, the binder
> > driver creates temporary mappings with kmap() or
> > kmap_atomic() to copy to or from the buffer only when
> > necessary.
>
> This patch series blows up when I apply it to my char-misc-next branch:
>
> drivers/android/binder_alloc_selftest.c: In function 
> ‘check_buffer_pages_allocated’:
> drivers/android/binder_alloc_selftest.c:108:44: error: ‘struct binder_buffer’ 
> has no member named ‘data’
>   end = (void *)PAGE_ALIGN((uintptr_t)buffer->data + size);
> ^~
> Did you forget to enable CONFIG_ANDROID_BINDER_IPC_SELFTEST when doing your
> builds?

I did forget. Thanks for catching this. I'll repost with the fix.

-Todd

>
> thanks,
>
> greg k-h


Re: [PATCH v1] binderfs: remove separate device_initcall()

2019-02-05 Thread Todd Kjos
On Wed, Jan 30, 2019 at 4:25 PM Christian Brauner  wrote:
>
> binderfs should not have a separate device_initcall(). When a kernel is
> compiled with CONFIG_ANDROID_BINDERFS register the filesystem alongside
> CONFIG_ANDROID_IPC. This use-case is especially sensible when users specify
> CONFIG_ANDROID_IPC=y, CONFIG_ANDROID_BINDERFS=y and
> ANDROID_BINDER_DEVICES="".
> When CONFIG_ANDROID_BINDERFS=n then this always succeeds so there's no
> regression potential for legacy workloads.
>
> Signed-off-by: Christian Brauner 

Acked-by: Todd Kjos 

>
> ---
> /* Changelog */
> - ensure that device_name is set to NULL so kfree() doesn't freak out
> ---
>  drivers/android/binder.c  | 7 ++-
>  drivers/android/binder_internal.h | 9 +
>  drivers/android/binderfs.c| 4 +---
>  3 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 57cf259de600..4d2b2ad1ee0e 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -5854,9 +5854,10 @@ static int __init init_binder_device(const char *name)
>  static int __init binder_init(void)
>  {
> int ret;
> -   char *device_name, *device_names, *device_tmp;
> +   char *device_name, *device_tmp;
> struct binder_device *device;
> struct hlist_node *tmp;
> +   char *device_names = NULL;
>
> ret = binder_alloc_shrinker_init();
> if (ret)
> @@ -5917,6 +5918,10 @@ static int __init binder_init(void)
> }
> }
>
> +   ret = init_binderfs();
> +   if (ret)
> +   goto err_init_binder_device_failed;
> +
> return ret;
>
>  err_init_binder_device_failed:
> diff --git a/drivers/android/binder_internal.h 
> b/drivers/android/binder_internal.h
> index 7fb97f503ef2..045b3e42d98b 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -46,4 +46,13 @@ static inline bool is_binderfs_device(const struct inode 
> *inode)
>  }
>  #endif
>
> +#ifdef CONFIG_ANDROID_BINDERFS
> +extern int __init init_binderfs(void);
> +#else
> +static inline int __init init_binderfs(void)
> +{
> +   return 0;
> +}
> +#endif
> +
>  #endif /* _LINUX_BINDER_INTERNAL_H */
> diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c
> index 7a550104a722..e773f45d19d9 100644
> --- a/drivers/android/binderfs.c
> +++ b/drivers/android/binderfs.c
> @@ -550,7 +550,7 @@ static struct file_system_type binder_fs_type = {
> .fs_flags   = FS_USERNS_MOUNT,
>  };
>
> -static int __init init_binderfs(void)
> +int __init init_binderfs(void)
>  {
> int ret;
>
> @@ -568,5 +568,3 @@ static int __init init_binderfs(void)
>
> return ret;
>  }
> -
> -device_initcall(init_binderfs);
> --
> 2.20.1
>


[PATCH v2 7/7] binder: use userspace pointer as base of buffer space

2019-01-30 Thread Todd Kjos
Now that alloc->buffer points to the userspace vm_area
rename buffer->data to buffer->user_data and rename
local pointers that hold user addresses. Also use the
"__user" tag to annotate all user pointers so sparse
can flag cases where user pointer vaues  are copied to
kernel pointers. Refactor code to use offsets instead
of user pointers.

Signed-off-by: Todd Kjos 
---
v2: removed casts as suggested by Dan Carpenter

 drivers/android/binder.c   | 118 +++--
 drivers/android/binder_alloc.c |  87 
 drivers/android/binder_alloc.h |   6 +-
 drivers/android/binder_trace.h |   2 +-
 4 files changed, 116 insertions(+), 97 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index b3d609b5935a..25491eceb750 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2278,33 +2278,30 @@ static void binder_deferred_fd_close(int fd)
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
  struct binder_buffer *buffer,
- binder_size_t *failed_at)
+ binder_size_t failed_at,
+ bool is_failure)
 {
-   binder_size_t *offp, *off_start, *off_end;
int debug_id = buffer->debug_id;
-   binder_size_t off_start_offset;
+   binder_size_t off_start_offset, buffer_offset, off_end_offset;
 
binder_debug(BINDER_DEBUG_TRANSACTION,
-"%d buffer release %d, size %zd-%zd, failed at %pK\n",
+"%d buffer release %d, size %zd-%zd, failed at %llx\n",
 proc->pid, buffer->debug_id,
-buffer->data_size, buffer->offsets_size, failed_at);
+buffer->data_size, buffer->offsets_size,
+(unsigned long long)failed_at);
 
if (buffer->target_node)
binder_dec_node(buffer->target_node, 1, 0);
 
off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
-   off_start = (binder_size_t *)(buffer->data + off_start_offset);
-   if (failed_at)
-   off_end = failed_at;
-   else
-   off_end = (void *)off_start + buffer->offsets_size;
-   for (offp = off_start; offp < off_end; offp++) {
+   off_end_offset = is_failure ? failed_at :
+   off_start_offset + buffer->offsets_size;
+   for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+buffer_offset += sizeof(binder_size_t)) {
struct binder_object_header *hdr;
size_t object_size;
struct binder_object object;
binder_size_t object_offset;
-   binder_size_t buffer_offset = (uintptr_t)offp -
-   (uintptr_t)buffer->data;
 
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
  buffer, buffer_offset,
@@ -2380,9 +2377,10 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
struct binder_object ptr_object;
-   u32 *fd_array;
+   binder_size_t fda_offset;
size_t fd_index;
binder_size_t fd_buf_size;
+   binder_size_t num_valid;
 
if (proc->tsk != current->group_leader) {
/*
@@ -2393,12 +2391,14 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
continue;
}
 
+   num_valid = (buffer_offset - off_start_offset) /
+   sizeof(binder_size_t);
fda = to_binder_fd_array_object(hdr);
parent = binder_validate_ptr(proc, buffer, &ptr_object,
 fda->parent,
 off_start_offset,
 NULL,
-offp - off_start);
+num_valid);
if (!parent) {
pr_err("transaction release %d bad parent 
offset\n",
   debug_id);
@@ -2417,14 +2417,21 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id, (u64)fda->num_fds);
continue;

[PATCH v2 6/7] binder: remove user_buffer_offset

2019-01-30 Thread Todd Kjos
Remove user_buffer_offset since there is no kernel
buffer pointer anymore.

Signed-off-by: Todd Kjos 
---
v2: removed casts as suggested by Dan Carpenter

 drivers/android/binder.c   | 39 ++
 drivers/android/binder_alloc.c | 16 ++
 drivers/android/binder_alloc.h | 23 
 3 files changed, 13 insertions(+), 65 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 98163bf5f35c..b3d609b5935a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2380,7 +2380,6 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
struct binder_object ptr_object;
-   uintptr_t parent_buffer;
u32 *fd_array;
size_t fd_index;
binder_size_t fd_buf_size;
@@ -2405,14 +2404,6 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id);
continue;
}
-   /*
-* Since the parent was already fixed up, convert it
-* back to kernel address space to access it
-*/
-   parent_buffer = parent->buffer -
-   binder_alloc_get_user_buffer_offset(
-   &proc->alloc);
-
fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
pr_err("transaction release %d invalid number 
of fds (%lld)\n",
@@ -2426,7 +2417,8 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id, (u64)fda->num_fds);
continue;
}
-   fd_array = (u32 *)(parent_buffer + 
(uintptr_t)fda->parent_offset);
+   fd_array = (u32 *)(uintptr_t)
+   (parent->buffer + fda->parent_offset);
for (fd_index = 0; fd_index < fda->num_fds;
 fd_index++) {
u32 fd;
@@ -2646,7 +2638,6 @@ static int binder_translate_fd_array(struct 
binder_fd_array_object *fda,
 struct binder_transaction *in_reply_to)
 {
binder_size_t fdi, fd_buf_size;
-   uintptr_t parent_buffer;
u32 *fd_array;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2664,13 +2655,7 @@ static int binder_translate_fd_array(struct 
binder_fd_array_object *fda,
  proc->pid, thread->pid, (u64)fda->num_fds);
return -EINVAL;
}
-   /*
-* Since the parent was already fixed up, convert it
-* back to the kernel address space to access it
-*/
-   parent_buffer = parent->buffer -
-   binder_alloc_get_user_buffer_offset(&target_proc->alloc);
-   fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
+   fd_array = (u32 *)(uintptr_t)(parent->buffer + fda->parent_offset);
if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
binder_user_error("%d:%d parent offset not aligned 
correctly.\n",
  proc->pid, thread->pid);
@@ -2703,7 +2688,6 @@ static int binder_fixup_parent(struct binder_transaction 
*t,
   binder_size_t last_fixup_min_off)
 {
struct binder_buffer_object *parent;
-   u8 *parent_buffer;
struct binder_buffer *b = t->buffer;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2739,11 +2723,8 @@ static int binder_fixup_parent(struct binder_transaction 
*t,
  proc->pid, thread->pid);
return -EINVAL;
}
-   parent_buffer = (u8 *)((uintptr_t)parent->buffer -
-   binder_alloc_get_user_buffer_offset(
-   &target_proc->alloc));
buffer_offset = bp->parent_offset +
-   (uintptr_t)parent_buffer - (uintptr_t)b->data;
+   (uintptr_t)parent->buffer - (uintptr_t)b->data;
binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
&bp->buffer, sizeof(bp->buffer));
 
@@ -3159,10 +3140,8 @@ static void binder_transaction(struct binder_proc *proc,

[PATCH v2 0/7] binder: eliminate use of vmalloc space for binder buffers

2019-01-30 Thread Todd Kjos
Binder buffers have always been mapped into kernel space
via map_kernel_range_noflush() to allow the binder driver
to modify the buffer before posting to userspace for
processing.

In recent Android releases, the number of long-running
binder processes has increased to the point that for
32-bit systems, there is a risk of running out of
vmalloc space.

This patch set removes the persistent mapping of the
binder buffers into kernel space. Instead, the binder
driver creates temporary mappings with kmap() or
kmap_atomic() to copy to or from the buffer only when
necessary.

Todd Kjos (7):
binder: create userspace-to-binder-buffer copy function
binder: add functions to copy to/from binder buffers
binder: add function to copy binder object from buffer
binder: avoid kernel vm_area for buffer fixups
binder: remove kernel vm_area for buffer space
binder: remove user_buffer_offset
binder: use userspace pointer as base of buffer space

v2: remove casts as suggested by Dan Carpenter

 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 460 
+---
 drivers/android/binder_alloc.c | 299 
+-
 drivers/android/binder_alloc.h |  47 +-
 drivers/android/binder_trace.h |   2 +-
 5 files changed, 534 insertions(+), 276 deletions(-)



[PATCH v2 1/7] binder: create userspace-to-binder-buffer copy function

2019-01-30 Thread Todd Kjos
The binder driver uses a vm_area to map the per-process
binder buffer space. For 32-bit android devices, this is
now taking too much vmalloc space. This patch removes
the use of vm_area when copying the transaction data
from the sender to the buffer space. Instead of using
copy_from_user() for multi-page copies, it now uses
binder_alloc_copy_user_to_buffer() which uses kmap()
and kunmap() to map each page, and uses copy_from_user()
for copying to that page.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/binder.c   |  29 +++--
 drivers/android/binder_alloc.c | 113 +
 drivers/android/binder_alloc.h |   8 +++
 3 files changed, 143 insertions(+), 7 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5f6ef5e63b91..ab0b3eec363b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3078,8 +3078,12 @@ static void binder_transaction(struct binder_proc *proc,
  ALIGN(tr->data_size, sizeof(void *)));
offp = off_start;
 
-   if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
-  tr->data.ptr.buffer, tr->data_size)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer, 0,
+   (const void __user *)
+   (uintptr_t)tr->data.ptr.buffer,
+   tr->data_size)) {
binder_user_error("%d:%d got transaction with invalid data 
ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3087,8 +3091,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_copy_data_failed;
}
-   if (copy_from_user(offp, (const void __user *)(uintptr_t)
-  tr->data.ptr.offsets, tr->offsets_size)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer,
+   ALIGN(tr->data_size, sizeof(void *)),
+   (const void __user *)
+   (uintptr_t)tr->data.ptr.offsets,
+   tr->offsets_size)) {
binder_user_error("%d:%d got transaction with invalid offsets 
ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3217,6 +3226,8 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_buffer_object *bp =
to_binder_buffer_object(hdr);
size_t buf_left = sg_buf_end - sg_bufp;
+   binder_size_t sg_buf_offset = (uintptr_t)sg_bufp -
+   (uintptr_t)t->buffer->data;
 
if (bp->length > buf_left) {
binder_user_error("%d:%d got transaction with 
too large buffer\n",
@@ -3226,9 +3237,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
-   if (copy_from_user(sg_bufp,
-  (const void __user *)(uintptr_t)
-  bp->buffer, bp->length)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer,
+   sg_buf_offset,
+   (const void __user *)
+   (uintptr_t)bp->buffer,
+   bp->length)) {
binder_user_error("%d:%d got transaction with 
invalid offsets ptr\n",
  proc->pid, thread->pid);
return_error_param = -EFAULT;
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 022cd80e80cc..94c0d85c4e75 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -29,6 +29,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "binder_alloc.h"
 #include "binder_trace.h"
 
@@ -1053,3 +1055,114 @@ int binder_alloc_shrinker_init(void)
}
return ret;
 }
+
+/**
+ * check_buffer() - verify that buffer/offset is safe to access
+ * 

[PATCH v2 2/7] binder: add functions to copy to/from binder buffers

2019-01-30 Thread Todd Kjos
Avoid vm_area when copying to or from binder buffers.
Instead, new copy functions are added that copy from
kernel space to binder buffer space. These use
kmap_atomic() and kunmap_atomic() to create temporary
mappings and then memcpy() is used to copy within
that page.

Also, kmap_atomic() / kunmap_atomic() use the appropriate
cache flushing to support VIVT cache architectures.
Allow binder to build if CPU_CACHE_VIVT is defined.

Several uses of the new functions are added here. More
to follow in subsequent patches.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 119 +
 drivers/android/binder_alloc.c |  59 
 drivers/android/binder_alloc.h |  12 
 4 files changed, 147 insertions(+), 45 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 4c190f8d1f4c..6fdf2abe4598 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 && !CPU_CACHE_VIVT
+   depends on MMU
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 ab0b3eec363b..74d0c1ff874e 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2244,14 +2244,22 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
off_end = (void *)off_start + buffer->offsets_size;
for (offp = off_start; offp < off_end; offp++) {
struct binder_object_header *hdr;
-   size_t object_size = binder_validate_object(buffer, *offp);
-
+   size_t object_size;
+   binder_size_t object_offset;
+   binder_size_t buffer_offset = (uintptr_t)offp -
+   (uintptr_t)buffer->data;
+
+   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ buffer, buffer_offset,
+ sizeof(object_offset));
+   object_size = binder_validate_object(buffer, object_offset);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
-  debug_id, (u64)*offp, buffer->data_size);
+  debug_id, (u64)object_offset, buffer->data_size);
continue;
}
-   hdr = (struct binder_object_header *)(buffer->data + *offp);
+   hdr = (struct binder_object_header *)
+   (buffer->data + object_offset);
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
@@ -2359,8 +2367,20 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
continue;
}
fd_array = (u32 *)(parent_buffer + 
(uintptr_t)fda->parent_offset);
-   for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
-   binder_deferred_fd_close(fd_array[fd_index]);
+   for (fd_index = 0; fd_index < fda->num_fds;
+fd_index++) {
+   u32 fd;
+   binder_size_t offset =
+   (uintptr_t)&fd_array[fd_index] -
+   (uintptr_t)buffer->data;
+
+   binder_alloc_copy_from_buffer(&proc->alloc,
+ &fd,
+ buffer,
+ offset,
+ sizeof(fd));
+   binder_deferred_fd_close(fd);
+   }
} break;
default:
pr_err("transaction release %d bad object type %x\n",
@@ -2496,7 +2516,7 @@ static int binder_translate_handle(struct 
flat_binder_object *fp,
return ret;
 }
 
-static int binder_translate_fd(u32 *fdp,
+static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
   struct binder_transaction *t,
   struct binder_thread *thread,
   struct binder_transaction *in_reply_to)
@@ -2507,7 +2527,6 @@ static int binder_translate_fd(u32 *fdp,
struct file *file;
int ret = 0;
bool target_allows_fd;
-   int fd = *fdp;
 

[PATCH v2 3/7] binder: add function to copy binder object from buffer

2019-01-30 Thread Todd Kjos
When creating or tearing down a transaction, the binder driver
examines objects in the buffer and takes appropriate action.
To do this without needing to dereference pointers into the
buffer, the local copies of the objects are needed. This patch
introduces a function to validate and copy binder objects
from the buffer to a local structure.

Signed-off-by: Todd Kjos 
---
v2: remove casts as suggested by Dan Carpenter

 drivers/android/binder.c | 75 +++-
 1 file changed, 58 insertions(+), 17 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 74d0c1ff874e..8063b405e4fa 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -628,6 +628,26 @@ struct binder_transaction {
spinlock_t lock;
 };
 
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+   union {
+   struct binder_object_header hdr;
+   struct flat_binder_object fbo;
+   struct binder_fd_object fdo;
+   struct binder_buffer_object bbo;
+   struct binder_fd_array_object fdao;
+   };
+};
+
 /**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc: struct binder_proc to acquire
@@ -2017,26 +2037,33 @@ static void binder_cleanup_transaction(struct 
binder_transaction *t,
 }
 
 /**
- * binder_validate_object() - checks for a valid metadata object in a buffer.
+ * binder_get_object() - gets object and checks for valid metadata
+ * @proc:  binder_proc owning the buffer
  * @buffer:binder_buffer that we're parsing.
- * @offset:offset in the buffer at which to validate an object.
+ * @offset:offset in the @buffer at which to validate an object.
+ * @object:struct binder_object to read into
  *
  * Return: If there's a valid metadata object at @offset in @buffer, the
- * size of that object. Otherwise, it returns zero.
+ * size of that object. Otherwise, it returns zero. The object
+ * is read into the struct binder_object pointed to by @object.
  */
-static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
+static size_t binder_get_object(struct binder_proc *proc,
+   struct binder_buffer *buffer,
+   unsigned long offset,
+   struct binder_object *object)
 {
-   /* Check if we can read a header first */
+   size_t read_size;
struct binder_object_header *hdr;
size_t object_size = 0;
 
-   if (buffer->data_size < sizeof(*hdr) ||
-   offset > buffer->data_size - sizeof(*hdr) ||
-   !IS_ALIGNED(offset, sizeof(u32)))
+   read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
+   if (read_size < sizeof(*hdr))
return 0;
+   binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+ offset, read_size);
 
-   /* Ok, now see if we can read a complete object. */
-   hdr = (struct binder_object_header *)(buffer->data + offset);
+   /* Ok, now see if we read a complete object. */
+   hdr = &object->hdr;
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER:
@@ -2245,6 +2272,7 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
for (offp = off_start; offp < off_end; offp++) {
struct binder_object_header *hdr;
size_t object_size;
+   struct binder_object object;
binder_size_t object_offset;
binder_size_t buffer_offset = (uintptr_t)offp -
(uintptr_t)buffer->data;
@@ -2252,14 +2280,14 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
  buffer, buffer_offset,
  sizeof(object_offset));
-   object_size = binder_validate_object(buffer, object_offset);
+   object_size = binder_get_object(proc, buffer,
+   object_offset, &object);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
   debug_id, (u64)object_offset, buffer->data_size);
continue;
}
-   hdr = (struct binder_object_header *)
-   (buffer->data + object_offset);
+  

[PATCH v2 5/7] binder: remove kernel vm_area for buffer space

2019-01-30 Thread Todd Kjos
Remove the kernel's vm_area and the code that maps
buffer pages into it.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder_alloc.c | 40 ++
 1 file changed, 2 insertions(+), 38 deletions(-)

diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 2eebff4be83e..d4cbe4b3947a 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -265,16 +265,6 @@ static int binder_update_page_range(struct binder_alloc 
*alloc, int allocate,
page->alloc = alloc;
INIT_LIST_HEAD(&page->lru);
 
-   ret = map_kernel_range_noflush((unsigned long)page_addr,
-  PAGE_SIZE, PAGE_KERNEL,
-  &page->page_ptr);
-   flush_cache_vmap((unsigned long)page_addr,
-   (unsigned long)page_addr + PAGE_SIZE);
-   if (ret != 1) {
-   pr_err("%d: binder_alloc_buf failed to map page at %pK 
in kernel\n",
-  alloc->pid, page_addr);
-   goto err_map_kernel_failed;
-   }
user_page_addr =
(uintptr_t)page_addr + alloc->user_buffer_offset;
ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr);
@@ -314,8 +304,6 @@ static int binder_update_page_range(struct binder_alloc 
*alloc, int allocate,
continue;
 
 err_vm_insert_page_failed:
-   unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-err_map_kernel_failed:
__free_page(page->page_ptr);
page->page_ptr = NULL;
 err_alloc_page_failed:
@@ -695,7 +683,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
  struct vm_area_struct *vma)
 {
int ret;
-   struct vm_struct *area;
const char *failure_string;
struct binder_buffer *buffer;
 
@@ -706,28 +693,10 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
goto err_already_mapped;
}
 
-   area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC);
-   if (area == NULL) {
-   ret = -ENOMEM;
-   failure_string = "get_vm_area";
-   goto err_get_vm_area_failed;
-   }
-   alloc->buffer = area->addr;
-   alloc->user_buffer_offset =
-   vma->vm_start - (uintptr_t)alloc->buffer;
+   alloc->buffer = (void *)vma->vm_start;
+   alloc->user_buffer_offset = 0;
mutex_unlock(&binder_alloc_mmap_lock);
 
-#ifdef CONFIG_CPU_CACHE_VIPT
-   if (cache_is_vipt_aliasing()) {
-   while (CACHE_COLOUR(
-   (vma->vm_start ^ (uint32_t)alloc->buffer))) {
-   pr_info("%s: %d %lx-%lx maps %pK bad alignment\n",
-   __func__, alloc->pid, vma->vm_start,
-   vma->vm_end, alloc->buffer);
-   vma->vm_start += PAGE_SIZE;
-   }
-   }
-#endif
alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
   sizeof(alloc->pages[0]),
   GFP_KERNEL);
@@ -760,9 +729,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
alloc->pages = NULL;
 err_alloc_pages_failed:
mutex_lock(&binder_alloc_mmap_lock);
-   vfree(alloc->buffer);
alloc->buffer = NULL;
-err_get_vm_area_failed:
 err_already_mapped:
mutex_unlock(&binder_alloc_mmap_lock);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
@@ -821,12 +788,10 @@ void binder_alloc_deferred_release(struct binder_alloc 
*alloc)
 "%s: %d: page %d at %pK %s\n",
 __func__, alloc->pid, i, page_addr,
 on_lru ? "on lru" : "active");
-   unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
__free_page(alloc->pages[i].page_ptr);
page_count++;
}
kfree(alloc->pages);
-   vfree(alloc->buffer);
}
mutex_unlock(&alloc->mutex);
if (alloc->vma_vm_mm)
@@ -988,7 +953,6 @@ enum lru_status binder_alloc_free_page(struct list_head 
*item,
 
trace_binder_unmap_kernel_start(alloc, index);
 
-   unmap_kernel_range(page_addr, PAGE_SIZE);
__free_page(page->page_ptr);
page->page_ptr = NULL;
 
-- 
2.20.1.495.gaa96b0ce6b-goog



[PATCH v2 4/7] binder: avoid kernel vm_area for buffer fixups

2019-01-30 Thread Todd Kjos
Refactor the functions to validate and fixup struct
binder_buffer pointer objects to avoid using vm_area
pointers. Instead copy to/from kernel space using
binder_alloc_copy_to_buffer() and
binder_alloc_copy_from_buffer(). The following
functions were refactored:

binder_validate_ptr()
binder_validate_fixup()
binder_fixup_parent()

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 146 ++-
 1 file changed, 97 insertions(+), 49 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 8063b405e4fa..98163bf5f35c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2092,10 +2092,13 @@ static size_t binder_get_object(struct binder_proc 
*proc,
 
 /**
  * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer.
+ * @proc:  binder_proc owning the buffer
  * @b: binder_buffer containing the object
+ * @object:struct binder_object to read into
  * @index: index in offset array at which the binder_buffer_object is
  * located
- * @start: points to the start of the offset array
+ * @start_offset: points to the start of the offset array
+ * @object_offsetp: offset of @object read from @b
  * @num_valid: the number of valid offsets in the offset array
  *
  * Return: If @index is within the valid range of the offset array
@@ -2106,34 +2109,46 @@ static size_t binder_get_object(struct binder_proc 
*proc,
  * Note that the offset found in index @index itself is not
  * verified; this function assumes that @num_valid elements
  * from @start were previously verified to have valid offsets.
+ * If @object_offsetp is non-NULL, then the offset within
+ * @b is written to it.
  */
-static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer 
*b,
-   binder_size_t index,
-   binder_size_t *start,
-   binder_size_t num_valid)
+static struct binder_buffer_object *binder_validate_ptr(
+   struct binder_proc *proc,
+   struct binder_buffer *b,
+   struct binder_object *object,
+   binder_size_t index,
+   binder_size_t start_offset,
+   binder_size_t *object_offsetp,
+   binder_size_t num_valid)
 {
-   struct binder_buffer_object *buffer_obj;
-   binder_size_t *offp;
+   size_t object_size;
+   binder_size_t object_offset;
+   unsigned long buffer_offset;
 
if (index >= num_valid)
return NULL;
 
-   offp = start + index;
-   buffer_obj = (struct binder_buffer_object *)(b->data + *offp);
-   if (buffer_obj->hdr.type != BINDER_TYPE_PTR)
+   buffer_offset = start_offset + sizeof(binder_size_t) * index;
+   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ b, buffer_offset, sizeof(object_offset));
+   object_size = binder_get_object(proc, b, object_offset, object);
+   if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
+   if (object_offsetp)
+   *object_offsetp = object_offset;
 
-   return buffer_obj;
+   return &object->bbo;
 }
 
 /**
  * binder_validate_fixup() - validates pointer/fd fixups happen in order.
+ * @proc:  binder_proc owning the buffer
  * @b: transaction buffer
- * @objects_start  start of objects buffer
- * @buffer:binder_buffer_object in which to fix up
- * @offset:start offset in @buffer to fix up
- * @last_obj:  last binder_buffer_object that we fixed up in
- * @last_min_offset:   minimum fixup offset in @last_obj
+ * @objects_start_offset: offset to start of objects buffer
+ * @buffer_obj_offset: offset to binder_buffer_object in which to fix up
+ * @fixup_offset:  start offset in @buffer to fix up
+ * @last_obj_offset:   offset to last binder_buffer_object that we fixed
+ * @last_min_offset:   minimum fixup offset in object at @last_obj_offset
  *
  * Return: %true if a fixup in buffer @buffer at offset @offset is
  * allowed.
@@ -2164,28 +2179,41 @@ static struct binder_buffer_object 
*binder_validate_ptr(struct binder_buffer *b,
  *   C (parent = A, offset = 16)
  * D (parent = B, offset = 0) // B is not A or any of A's parents
  */
-static bool binder_validate_fixup(struct binder_buffer *b,
- binder_size_t *objects_start,
- struct bi

Re: [PATCH 1/7] binder: create userspace-to-binder-buffer copy function

2019-01-29 Thread Todd Kjos
On Tue, Jan 29, 2019 at 12:12 AM Dan Carpenter  wrote:
>
> On Mon, Jan 28, 2019 at 04:49:28PM -0800, Todd Kjos wrote:
> > +/**
> > + * binder_alloc_copy_user_to_buffer() - copy src user to tgt user
> > + * @alloc: binder_alloc for this proc
> > + * @buffer: binder buffer to be accessed
> > + * @buffer_offset: offset into @buffer data
> > + * @from: userspace pointer to source buffer
> > + * @bytes: bytes to copy
> > + *
> > + * Copy bytes from source userspace to target buffer.
> > + *
> > + * Return: bytes remaining to be copied
> > + */
> > +unsigned long
> > +binder_alloc_copy_user_to_buffer(struct binder_alloc *alloc,
> > +  struct binder_buffer *buffer,
> > +  binder_size_t buffer_offset,
> > +  const void __user *from,
> > +  size_t bytes)
> > +{
> > + if (!check_buffer(alloc, buffer, buffer_offset, bytes))
> > + return bytes;
> > +
> > + while (bytes) {
> > + unsigned long size;
> > + unsigned long ret;
> > + struct page *page;
> > + pgoff_t pgoff;
> > + void *kptr;
> > +
> > + page = binder_alloc_get_page(alloc, buffer,
> > +  buffer_offset, &pgoff);
> > + size = min(bytes, (size_t)(PAGE_SIZE - pgoff));
>
> This code has so much more casting than necessary.  To me casting says
> that we haven't got the types correct or something.  I've just pulled
> this function out as an example really, but none of the casts here are
> required...  This could just be:
>
> size = min(bytes, PAGE_SIZE - pgoff);

Dan,

Thanks for the feedback.

The one above: "size = min(bytes, PAGE_SIZE - pgoff);", results in
32-bit compile warnings:

./include/linux/kernel.h:846:29: warning: comparison of distinct
pointer types lacks a cast
   (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
[...]
drivers/android/binder_alloc.c:1157:10: note: in expansion of macro ‘min’
   size = min(bytes, PAGE_SIZE - pgoff);

so, I took your suggestion:

  size = min_t(size_t, bytes, PAGE_SIZE - pgoff);

>
> Btw, if you really need to do a cast inside a min() (you don't in this
> cast) then use min_t().
>
> > + kptr = (void *)((uintptr_t)kmap(page) + pgoff);
>
> This would be a lot cleaner as:
>
> kptr = kmap(page) + pgoff;

It definitely is cleaner, but the clean version is doing arithmetic on
a void pointer which is generally not considered good practice (but is
supported by gcc). Is this acceptable in the kernel? I don't see any
statement on it in Documentation/process/coding-style.rst.

If so, I agree a bunch of these casts can go as you suggest.

-Todd

[...]

>
> regards,
> dan carpenter
>


[PATCH 5/7] binder: remove kernel vm_area for buffer space

2019-01-28 Thread Todd Kjos
Remove the kernel's vm_area and the code that maps
buffer pages into it.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder_alloc.c | 40 ++
 1 file changed, 2 insertions(+), 38 deletions(-)

diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index be2a6077e6c5c..dde8977c49ea0 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -265,16 +265,6 @@ static int binder_update_page_range(struct binder_alloc 
*alloc, int allocate,
page->alloc = alloc;
INIT_LIST_HEAD(&page->lru);
 
-   ret = map_kernel_range_noflush((unsigned long)page_addr,
-  PAGE_SIZE, PAGE_KERNEL,
-  &page->page_ptr);
-   flush_cache_vmap((unsigned long)page_addr,
-   (unsigned long)page_addr + PAGE_SIZE);
-   if (ret != 1) {
-   pr_err("%d: binder_alloc_buf failed to map page at %pK 
in kernel\n",
-  alloc->pid, page_addr);
-   goto err_map_kernel_failed;
-   }
user_page_addr =
(uintptr_t)page_addr + alloc->user_buffer_offset;
ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr);
@@ -314,8 +304,6 @@ static int binder_update_page_range(struct binder_alloc 
*alloc, int allocate,
continue;
 
 err_vm_insert_page_failed:
-   unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-err_map_kernel_failed:
__free_page(page->page_ptr);
page->page_ptr = NULL;
 err_alloc_page_failed:
@@ -695,7 +683,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
  struct vm_area_struct *vma)
 {
int ret;
-   struct vm_struct *area;
const char *failure_string;
struct binder_buffer *buffer;
 
@@ -706,28 +693,10 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
goto err_already_mapped;
}
 
-   area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC);
-   if (area == NULL) {
-   ret = -ENOMEM;
-   failure_string = "get_vm_area";
-   goto err_get_vm_area_failed;
-   }
-   alloc->buffer = area->addr;
-   alloc->user_buffer_offset =
-   vma->vm_start - (uintptr_t)alloc->buffer;
+   alloc->buffer = (void *)vma->vm_start;
+   alloc->user_buffer_offset = 0;
mutex_unlock(&binder_alloc_mmap_lock);
 
-#ifdef CONFIG_CPU_CACHE_VIPT
-   if (cache_is_vipt_aliasing()) {
-   while (CACHE_COLOUR(
-   (vma->vm_start ^ (uint32_t)alloc->buffer))) {
-   pr_info("%s: %d %lx-%lx maps %pK bad alignment\n",
-   __func__, alloc->pid, vma->vm_start,
-   vma->vm_end, alloc->buffer);
-   vma->vm_start += PAGE_SIZE;
-   }
-   }
-#endif
alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
   sizeof(alloc->pages[0]),
   GFP_KERNEL);
@@ -760,9 +729,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
alloc->pages = NULL;
 err_alloc_pages_failed:
mutex_lock(&binder_alloc_mmap_lock);
-   vfree(alloc->buffer);
alloc->buffer = NULL;
-err_get_vm_area_failed:
 err_already_mapped:
mutex_unlock(&binder_alloc_mmap_lock);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
@@ -821,12 +788,10 @@ void binder_alloc_deferred_release(struct binder_alloc 
*alloc)
 "%s: %d: page %d at %pK %s\n",
 __func__, alloc->pid, i, page_addr,
 on_lru ? "on lru" : "active");
-   unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
__free_page(alloc->pages[i].page_ptr);
page_count++;
}
kfree(alloc->pages);
-   vfree(alloc->buffer);
}
mutex_unlock(&alloc->mutex);
if (alloc->vma_vm_mm)
@@ -988,7 +953,6 @@ enum lru_status binder_alloc_free_page(struct list_head 
*item,
 
trace_binder_unmap_kernel_start(alloc, index);
 
-   unmap_kernel_range(page_addr, PAGE_SIZE);
__free_page(page->page_ptr);
page->page_ptr = NULL;
 
-- 
2.20.1.495.gaa96b0ce6b-goog



[PATCH 4/7] binder: avoid kernel vm_area for buffer fixups

2019-01-28 Thread Todd Kjos
Refactor the functions to validate and fixup struct
binder_buffer pointer objects to avoid using vm_area
pointers. Instead copy to/from kernel space using
binder_alloc_copy_to_buffer() and
binder_alloc_copy_from_buffer(). The following
functions were refactored:

binder_validate_ptr()
binder_validate_fixup()
binder_fixup_parent()

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 146 ++-
 1 file changed, 97 insertions(+), 49 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1563b9b60a0a3..197b7bdc38eef 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2092,10 +2092,13 @@ static size_t binder_get_object(struct binder_proc 
*proc,
 
 /**
  * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer.
+ * @proc:  binder_proc owning the buffer
  * @b: binder_buffer containing the object
+ * @object:struct binder_object to read into
  * @index: index in offset array at which the binder_buffer_object is
  * located
- * @start: points to the start of the offset array
+ * @start_offset: points to the start of the offset array
+ * @object_offsetp: offset of @object read from @b
  * @num_valid: the number of valid offsets in the offset array
  *
  * Return: If @index is within the valid range of the offset array
@@ -2106,34 +2109,46 @@ static size_t binder_get_object(struct binder_proc 
*proc,
  * Note that the offset found in index @index itself is not
  * verified; this function assumes that @num_valid elements
  * from @start were previously verified to have valid offsets.
+ * If @object_offsetp is non-NULL, then the offset within
+ * @b is written to it.
  */
-static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer 
*b,
-   binder_size_t index,
-   binder_size_t *start,
-   binder_size_t num_valid)
+static struct binder_buffer_object *binder_validate_ptr(
+   struct binder_proc *proc,
+   struct binder_buffer *b,
+   struct binder_object *object,
+   binder_size_t index,
+   binder_size_t start_offset,
+   binder_size_t *object_offsetp,
+   binder_size_t num_valid)
 {
-   struct binder_buffer_object *buffer_obj;
-   binder_size_t *offp;
+   size_t object_size;
+   binder_size_t object_offset;
+   unsigned long buffer_offset;
 
if (index >= num_valid)
return NULL;
 
-   offp = start + index;
-   buffer_obj = (struct binder_buffer_object *)(b->data + *offp);
-   if (buffer_obj->hdr.type != BINDER_TYPE_PTR)
+   buffer_offset = start_offset + sizeof(binder_size_t) * index;
+   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ b, buffer_offset, sizeof(object_offset));
+   object_size = binder_get_object(proc, b, object_offset, object);
+   if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
return NULL;
+   if (object_offsetp)
+   *object_offsetp = object_offset;
 
-   return buffer_obj;
+   return &object->bbo;
 }
 
 /**
  * binder_validate_fixup() - validates pointer/fd fixups happen in order.
+ * @proc:  binder_proc owning the buffer
  * @b: transaction buffer
- * @objects_start  start of objects buffer
- * @buffer:binder_buffer_object in which to fix up
- * @offset:start offset in @buffer to fix up
- * @last_obj:  last binder_buffer_object that we fixed up in
- * @last_min_offset:   minimum fixup offset in @last_obj
+ * @objects_start_offset: offset to start of objects buffer
+ * @buffer_obj_offset: offset to binder_buffer_object in which to fix up
+ * @fixup_offset:  start offset in @buffer to fix up
+ * @last_obj_offset:   offset to last binder_buffer_object that we fixed
+ * @last_min_offset:   minimum fixup offset in object at @last_obj_offset
  *
  * Return: %true if a fixup in buffer @buffer at offset @offset is
  * allowed.
@@ -2164,28 +2179,41 @@ static struct binder_buffer_object 
*binder_validate_ptr(struct binder_buffer *b,
  *   C (parent = A, offset = 16)
  * D (parent = B, offset = 0) // B is not A or any of A's parents
  */
-static bool binder_validate_fixup(struct binder_buffer *b,
- binder_size_t *objects_start,
- 

[PATCH 6/7] binder: remove user_buffer_offset

2019-01-28 Thread Todd Kjos
Remove user_buffer_offset since there is no kernel
buffer pointer anymore.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c   | 38 +++---
 drivers/android/binder_alloc.c | 16 ++
 drivers/android/binder_alloc.h | 23 
 3 files changed, 13 insertions(+), 64 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 197b7bdc38eef..07b92bbb7360e 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2380,7 +2380,6 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
struct binder_object ptr_object;
-   uintptr_t parent_buffer;
u32 *fd_array;
size_t fd_index;
binder_size_t fd_buf_size;
@@ -2405,14 +2404,6 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id);
continue;
}
-   /*
-* Since the parent was already fixed up, convert it
-* back to kernel address space to access it
-*/
-   parent_buffer = parent->buffer -
-   binder_alloc_get_user_buffer_offset(
-   &proc->alloc);
-
fd_buf_size = sizeof(u32) * fda->num_fds;
if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
pr_err("transaction release %d invalid number 
of fds (%lld)\n",
@@ -2426,7 +2417,8 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id, (u64)fda->num_fds);
continue;
}
-   fd_array = (u32 *)(parent_buffer + 
(uintptr_t)fda->parent_offset);
+   fd_array = (u32 *)(uintptr_t)
+   (parent->buffer + fda->parent_offset);
for (fd_index = 0; fd_index < fda->num_fds;
 fd_index++) {
u32 fd;
@@ -2646,7 +2638,6 @@ static int binder_translate_fd_array(struct 
binder_fd_array_object *fda,
 struct binder_transaction *in_reply_to)
 {
binder_size_t fdi, fd_buf_size;
-   uintptr_t parent_buffer;
u32 *fd_array;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2664,13 +2655,7 @@ static int binder_translate_fd_array(struct 
binder_fd_array_object *fda,
  proc->pid, thread->pid, (u64)fda->num_fds);
return -EINVAL;
}
-   /*
-* Since the parent was already fixed up, convert it
-* back to the kernel address space to access it
-*/
-   parent_buffer = parent->buffer -
-   binder_alloc_get_user_buffer_offset(&target_proc->alloc);
-   fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
+   fd_array = (u32 *)(uintptr_t)(parent->buffer + fda->parent_offset);
if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
binder_user_error("%d:%d parent offset not aligned 
correctly.\n",
  proc->pid, thread->pid);
@@ -2703,7 +2688,6 @@ static int binder_fixup_parent(struct binder_transaction 
*t,
   binder_size_t last_fixup_min_off)
 {
struct binder_buffer_object *parent;
-   u8 *parent_buffer;
struct binder_buffer *b = t->buffer;
struct binder_proc *proc = thread->proc;
struct binder_proc *target_proc = t->to_proc;
@@ -2739,11 +2723,8 @@ static int binder_fixup_parent(struct binder_transaction 
*t,
  proc->pid, thread->pid);
return -EINVAL;
}
-   parent_buffer = (u8 *)((uintptr_t)parent->buffer -
-   binder_alloc_get_user_buffer_offset(
-   &target_proc->alloc));
buffer_offset = bp->parent_offset +
-   (uintptr_t)parent_buffer - (uintptr_t)b->data;
+   (uintptr_t)parent->buffer - (uintptr_t)b->data;
binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
&bp->buffer, sizeof(bp->buffer));
 
@@ -3159,10 +3140,8 @@ static void binder_transaction(struct binder_proc *proc,
ALIGN(tr->offsets_size, sizeof(

[PATCH 3/7] binder: add function to copy binder object from buffer

2019-01-28 Thread Todd Kjos
When creating or tearing down a transaction, the binder driver
examines objects in the buffer and takes appropriate action.
To do this without needing to dereference pointers into the
buffer, the local copies of the objects are needed. This patch
introduces a function to validate and copy binder objects
from the buffer to a local structure.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c | 75 +++-
 1 file changed, 58 insertions(+), 17 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 74d0c1ff874e2..1563b9b60a0a3 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -628,6 +628,26 @@ struct binder_transaction {
spinlock_t lock;
 };
 
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+   union {
+   struct binder_object_header hdr;
+   struct flat_binder_object fbo;
+   struct binder_fd_object fdo;
+   struct binder_buffer_object bbo;
+   struct binder_fd_array_object fdao;
+   };
+};
+
 /**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc: struct binder_proc to acquire
@@ -2017,26 +2037,33 @@ static void binder_cleanup_transaction(struct 
binder_transaction *t,
 }
 
 /**
- * binder_validate_object() - checks for a valid metadata object in a buffer.
+ * binder_get_object() - gets object and checks for valid metadata
+ * @proc:  binder_proc owning the buffer
  * @buffer:binder_buffer that we're parsing.
- * @offset:offset in the buffer at which to validate an object.
+ * @offset:offset in the @buffer at which to validate an object.
+ * @object:struct binder_object to read into
  *
  * Return: If there's a valid metadata object at @offset in @buffer, the
- * size of that object. Otherwise, it returns zero.
+ * size of that object. Otherwise, it returns zero. The object
+ * is read into the struct binder_object pointed to by @object.
  */
-static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset)
+static size_t binder_get_object(struct binder_proc *proc,
+   struct binder_buffer *buffer,
+   unsigned long offset,
+   struct binder_object *object)
 {
-   /* Check if we can read a header first */
+   size_t read_size;
struct binder_object_header *hdr;
size_t object_size = 0;
 
-   if (buffer->data_size < sizeof(*hdr) ||
-   offset > buffer->data_size - sizeof(*hdr) ||
-   !IS_ALIGNED(offset, sizeof(u32)))
+   read_size = min(sizeof(*object), (size_t)(buffer->data_size - offset));
+   if (read_size < sizeof(*hdr))
return 0;
+   binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+ offset, read_size);
 
-   /* Ok, now see if we can read a complete object. */
-   hdr = (struct binder_object_header *)(buffer->data + offset);
+   /* Ok, now see if we read a complete object. */
+   hdr = &object->hdr;
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER:
@@ -2245,6 +2272,7 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
for (offp = off_start; offp < off_end; offp++) {
struct binder_object_header *hdr;
size_t object_size;
+   struct binder_object object;
binder_size_t object_offset;
binder_size_t buffer_offset = (uintptr_t)offp -
(uintptr_t)buffer->data;
@@ -2252,14 +2280,14 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
  buffer, buffer_offset,
  sizeof(object_offset));
-   object_size = binder_validate_object(buffer, object_offset);
+   object_size = binder_get_object(proc, buffer,
+   object_offset, &object);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
   debug_id, (u64)object_offset, buffer->data_size);
continue;
}
-   hdr = (struct binder_object_header *)
-   (buffer->data + object_offset);
+   hdr = &object.hdr;
 

[PATCH 7/7] binder: use userspace pointer as base of buffer space

2019-01-28 Thread Todd Kjos
Now that alloc->buffer points to the userspace vm_area
rename buffer->data to buffer->user_data and rename
local pointers that hold user addresses. Also use the
"__user" tag to annotate all user pointers so sparse
can flag cases where user pointer vaues  are copied to
kernel pointers. Refactor code to use offsets instead
of user pointers.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c   | 120 +++--
 drivers/android/binder_alloc.c |  89 
 drivers/android/binder_alloc.h |   6 +-
 drivers/android/binder_trace.h |   2 +-
 4 files changed, 119 insertions(+), 98 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 07b92bbb7360e..ec5b98699de4d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2278,33 +2278,30 @@ static void binder_deferred_fd_close(int fd)
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
  struct binder_buffer *buffer,
- binder_size_t *failed_at)
+ binder_size_t failed_at,
+ bool is_failure)
 {
-   binder_size_t *offp, *off_start, *off_end;
int debug_id = buffer->debug_id;
-   binder_size_t off_start_offset;
+   binder_size_t off_start_offset, buffer_offset, off_end_offset;
 
binder_debug(BINDER_DEBUG_TRANSACTION,
-"%d buffer release %d, size %zd-%zd, failed at %pK\n",
+"%d buffer release %d, size %zd-%zd, failed at %llx\n",
 proc->pid, buffer->debug_id,
-buffer->data_size, buffer->offsets_size, failed_at);
+buffer->data_size, buffer->offsets_size,
+(unsigned long long)failed_at);
 
if (buffer->target_node)
binder_dec_node(buffer->target_node, 1, 0);
 
off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
-   off_start = (binder_size_t *)(buffer->data + off_start_offset);
-   if (failed_at)
-   off_end = failed_at;
-   else
-   off_end = (void *)off_start + buffer->offsets_size;
-   for (offp = off_start; offp < off_end; offp++) {
+   off_end_offset = is_failure ? failed_at :
+   off_start_offset + buffer->offsets_size;
+   for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+buffer_offset += sizeof(binder_size_t)) {
struct binder_object_header *hdr;
size_t object_size;
struct binder_object object;
binder_size_t object_offset;
-   binder_size_t buffer_offset = (uintptr_t)offp -
-   (uintptr_t)buffer->data;
 
binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
  buffer, buffer_offset,
@@ -2380,9 +2377,10 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
struct binder_fd_array_object *fda;
struct binder_buffer_object *parent;
struct binder_object ptr_object;
-   u32 *fd_array;
+   binder_size_t fda_offset;
size_t fd_index;
binder_size_t fd_buf_size;
+   binder_size_t num_valid;
 
if (proc->tsk != current->group_leader) {
/*
@@ -2393,12 +2391,14 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
continue;
}
 
+   num_valid = (buffer_offset - off_start_offset) /
+   sizeof(binder_size_t);
fda = to_binder_fd_array_object(hdr);
parent = binder_validate_ptr(proc, buffer, &ptr_object,
 fda->parent,
 off_start_offset,
 NULL,
-offp - off_start);
+num_valid);
if (!parent) {
pr_err("transaction release %d bad parent 
offset\n",
   debug_id);
@@ -2417,14 +2417,21 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
   debug_id, (u64)fda->num_fds);
continue;
}
-   fd_array = (u32 *)(uintptr_t)
-   

[PATCH 1/7] binder: create userspace-to-binder-buffer copy function

2019-01-28 Thread Todd Kjos
The binder driver uses a vm_area to map the per-process
binder buffer space. For 32-bit android devices, this is
now taking too much vmalloc space. This patch removes
the use of vm_area when copying the transaction data
from the sender to the buffer space. Instead of using
copy_from_user() for multi-page copies, it now uses
binder_alloc_copy_user_to_buffer() which uses kmap()
and kunmap() to map each page, and uses copy_from_user()
for copying to that page.

Signed-off-by: Todd Kjos 
---
 drivers/android/binder.c   |  29 +++--
 drivers/android/binder_alloc.c | 114 +
 drivers/android/binder_alloc.h |   8 +++
 3 files changed, 144 insertions(+), 7 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5f6ef5e63b91e..ab0b3eec363bc 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3078,8 +3078,12 @@ static void binder_transaction(struct binder_proc *proc,
  ALIGN(tr->data_size, sizeof(void *)));
offp = off_start;
 
-   if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
-  tr->data.ptr.buffer, tr->data_size)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer, 0,
+   (const void __user *)
+   (uintptr_t)tr->data.ptr.buffer,
+   tr->data_size)) {
binder_user_error("%d:%d got transaction with invalid data 
ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3087,8 +3091,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_copy_data_failed;
}
-   if (copy_from_user(offp, (const void __user *)(uintptr_t)
-  tr->data.ptr.offsets, tr->offsets_size)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer,
+   ALIGN(tr->data_size, sizeof(void *)),
+   (const void __user *)
+   (uintptr_t)tr->data.ptr.offsets,
+   tr->offsets_size)) {
binder_user_error("%d:%d got transaction with invalid offsets 
ptr\n",
proc->pid, thread->pid);
return_error = BR_FAILED_REPLY;
@@ -3217,6 +3226,8 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_buffer_object *bp =
to_binder_buffer_object(hdr);
size_t buf_left = sg_buf_end - sg_bufp;
+   binder_size_t sg_buf_offset = (uintptr_t)sg_bufp -
+   (uintptr_t)t->buffer->data;
 
if (bp->length > buf_left) {
binder_user_error("%d:%d got transaction with 
too large buffer\n",
@@ -3226,9 +3237,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_bad_offset;
}
-   if (copy_from_user(sg_bufp,
-  (const void __user *)(uintptr_t)
-  bp->buffer, bp->length)) {
+   if (binder_alloc_copy_user_to_buffer(
+   &target_proc->alloc,
+   t->buffer,
+   sg_buf_offset,
+   (const void __user *)
+   (uintptr_t)bp->buffer,
+   bp->length)) {
binder_user_error("%d:%d got transaction with 
invalid offsets ptr\n",
  proc->pid, thread->pid);
return_error_param = -EFAULT;
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 022cd80e80cc3..255fa71911e5e 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -29,6 +29,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "binder_alloc.h"
 #include "binder_trace.h"
 
@@ -1053,3 +1055,115 @@ int binder_alloc_shrinker_init(void)
}
return ret;
 }
+
+/**
+ * check_buffer() - verify that buffer/offset is safe to access
+ * @alloc: binder_alloc for this proc
+ * @buffer:

[PATCH 2/7] binder: add functions to copy to/from binder buffers

2019-01-28 Thread Todd Kjos
Avoid vm_area when copying to or from binder buffers.
Instead, new copy functions are added that copy from
kernel space to binder buffer space. These use
kmap_atomic() and kunmap_atomic() to create temporary
mappings and then memcpy() is used to copy within
that page.

Also, kmap_atomic() / kunmap_atomic() use the appropriate
cache flushing to support VIVT cache architectures.
Allow binder to build if CPU_CACHE_VIVT is defined.

Several uses of the new functions are added here. More
to follow in subsequent patches.

Signed-off-by: Todd Kjos 
---
 drivers/android/Kconfig|   2 +-
 drivers/android/binder.c   | 119 +
 drivers/android/binder_alloc.c |  59 
 drivers/android/binder_alloc.h |  12 
 4 files changed, 147 insertions(+), 45 deletions(-)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 4c190f8d1f4c6..6fdf2abe4598a 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 && !CPU_CACHE_VIVT
+   depends on MMU
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 ab0b3eec363bc..74d0c1ff874e2 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2244,14 +2244,22 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
off_end = (void *)off_start + buffer->offsets_size;
for (offp = off_start; offp < off_end; offp++) {
struct binder_object_header *hdr;
-   size_t object_size = binder_validate_object(buffer, *offp);
-
+   size_t object_size;
+   binder_size_t object_offset;
+   binder_size_t buffer_offset = (uintptr_t)offp -
+   (uintptr_t)buffer->data;
+
+   binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
+ buffer, buffer_offset,
+ sizeof(object_offset));
+   object_size = binder_validate_object(buffer, object_offset);
if (object_size == 0) {
pr_err("transaction release %d bad object at offset 
%lld, size %zd\n",
-  debug_id, (u64)*offp, buffer->data_size);
+  debug_id, (u64)object_offset, buffer->data_size);
continue;
}
-   hdr = (struct binder_object_header *)(buffer->data + *offp);
+   hdr = (struct binder_object_header *)
+   (buffer->data + object_offset);
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
@@ -2359,8 +2367,20 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
continue;
}
fd_array = (u32 *)(parent_buffer + 
(uintptr_t)fda->parent_offset);
-   for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
-   binder_deferred_fd_close(fd_array[fd_index]);
+   for (fd_index = 0; fd_index < fda->num_fds;
+fd_index++) {
+   u32 fd;
+   binder_size_t offset =
+   (uintptr_t)&fd_array[fd_index] -
+   (uintptr_t)buffer->data;
+
+   binder_alloc_copy_from_buffer(&proc->alloc,
+ &fd,
+ buffer,
+ offset,
+ sizeof(fd));
+   binder_deferred_fd_close(fd);
+   }
} break;
default:
pr_err("transaction release %d bad object type %x\n",
@@ -2496,7 +2516,7 @@ static int binder_translate_handle(struct 
flat_binder_object *fp,
return ret;
 }
 
-static int binder_translate_fd(u32 *fdp,
+static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
   struct binder_transaction *t,
   struct binder_thread *thread,
   struct binder_transaction *in_reply_to)
@@ -2507,7 +2527,6 @@ static int binder_translate_fd(u32 *fdp,
struct file *file;
int ret = 0;
bool target_allows_fd;
-   int fd = *fdp;
 
if (in_reply_to)
target_al

  1   2   3   >