linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] binder: print warnings when detecting oneway spamming.
@ 2020-08-20  7:51 Martijn Coenen
  2020-08-20 10:41 ` kernel test robot
  0 siblings, 1 reply; 3+ messages in thread
From: Martijn Coenen @ 2020-08-20  7:51 UTC (permalink / raw)
  To: gregkh, tkjos, arve, joel, christian, hridya, surenb
  Cc: linux-kernel, devel, maco, Martijn Coenen

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 <maco@android.com>
---
 drivers/android/binder.c       |  2 +-
 drivers/android/binder_alloc.c | 49 +++++++++++++++++++++++++++++++---
 drivers/android/binder_alloc.h |  5 +++-
 3 files changed, 51 insertions(+), 5 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
+	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->offsets_size = offsets_size;
 	buffer->async_transaction = is_async;
 	buffer->extra_buffers_size = extra_buffers_size;
+	buffer->pid = pid;
 	if (is_async) {
 		alloc->free_async_space -= size + sizeof(struct binder_buffer);
 		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
 			     "%d: binder_alloc_buf size %zd async free %zd\n",
 			      alloc->pid, size, alloc->free_async_space);
+		if (alloc->free_async_space < alloc->buffer_size / 10) {
+			// Start detecting spammers once we reach 80% of async space used
+			debug_low_async_space_locked(alloc, pid);
+		}
 	}
 	return buffer;
 
@@ -508,6 +549,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
  * @offsets_size:       user specified buffer offset
  * @extra_buffers_size: size of extra space for meta-data (eg, security context)
  * @is_async:           buffer for async transaction
+ * @pid:				pid to attribute allocation to (used for debugging)
  *
  * Allocate a new buffer given the requested sizes. Returns
  * the kernel version of the buffer pointer. The size allocated
@@ -520,13 +562,14 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
 					   size_t data_size,
 					   size_t offsets_size,
 					   size_t extra_buffers_size,
-					   int is_async)
+					   int is_async,
+					   int pid)
 {
 	struct binder_buffer *buffer;
 
 	mutex_lock(&alloc->mutex);
 	buffer = binder_alloc_new_buf_locked(alloc, data_size, offsets_size,
-					     extra_buffers_size, is_async);
+					     extra_buffers_size, is_async, pid);
 	mutex_unlock(&alloc->mutex);
 	return buffer;
 }
diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
index db9c1b984695..55d8b4106766 100644
--- a/drivers/android/binder_alloc.h
+++ b/drivers/android/binder_alloc.h
@@ -32,6 +32,7 @@ struct binder_transaction;
  * @offsets_size:       size of array of offsets
  * @extra_buffers_size: size of space for other objects (like sg lists)
  * @user_data:          user pointer to base of buffer space
+ * @pid:                pid to attribute the buffer to (caller)
  *
  * Bookkeeping structure for binder transaction buffers
  */
@@ -51,6 +52,7 @@ struct binder_buffer {
 	size_t offsets_size;
 	size_t extra_buffers_size;
 	void __user *user_data;
+	int    pid;
 };
 
 /**
@@ -117,7 +119,8 @@ extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
 						  size_t data_size,
 						  size_t offsets_size,
 						  size_t extra_buffers_size,
-						  int is_async);
+						  int is_async,
+						  int pid);
 extern void binder_alloc_init(struct binder_alloc *alloc);
 extern int binder_alloc_shrinker_init(void);
 extern void binder_alloc_vma_close(struct binder_alloc *alloc);
-- 
2.28.0.220.ged08abb693-goog


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] binder: print warnings when detecting oneway spamming.
  2020-08-20  7:51 [PATCH] binder: print warnings when detecting oneway spamming Martijn Coenen
@ 2020-08-20 10:41 ` kernel test robot
  2020-08-20 11:47   ` Martijn Coenen
  0 siblings, 1 reply; 3+ messages in thread
From: kernel test robot @ 2020-08-20 10:41 UTC (permalink / raw)
  To: Martijn Coenen, gregkh, tkjos, arve, joel, christian, hridya, surenb
  Cc: kbuild-all, clang-built-linux, linux-kernel, devel, maco

[-- Attachment #1: Type: text/plain, Size: 3533 bytes --]

Hi Martijn,

I love your patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]
[also build test ERROR on v5.9-rc1 next-20200820]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Martijn-Coenen/binder-print-warnings-when-detecting-oneway-spamming/20200820-155358
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git bc752d2f345bf55d71b3422a6a24890ea03168dc
config: s390-randconfig-r002-20200818 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 4deda57106f7c9b982a49cb907c33e3966c8de7f)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install s390 cross compiling tool for clang build
        # apt-get install binutils-s390x-linux-gnu
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=s390 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/android/binder_alloc_selftest.c:122:61: error: too few arguments to function call, expected 6, have 5
                   buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0);
                                ~~~~~~~~~~~~~~~~~~~~                         ^
   drivers/android/binder_alloc.h:118:30: note: 'binder_alloc_new_buf' declared here
   extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
                                ^
   1 error generated.

# https://github.com/0day-ci/linux/commit/9d0b269f4468d6793f6fd76a410fdde39dbf6ac2
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Martijn-Coenen/binder-print-warnings-when-detecting-oneway-spamming/20200820-155358
git checkout 9d0b269f4468d6793f6fd76a410fdde39dbf6ac2
vim +122 drivers/android/binder_alloc_selftest.c

4175e2b46fd4b9 Sherry Yang 2017-08-23  114  
4175e2b46fd4b9 Sherry Yang 2017-08-23  115  static void binder_selftest_alloc_buf(struct binder_alloc *alloc,
4175e2b46fd4b9 Sherry Yang 2017-08-23  116  				      struct binder_buffer *buffers[],
4175e2b46fd4b9 Sherry Yang 2017-08-23  117  				      size_t *sizes, int *seq)
4175e2b46fd4b9 Sherry Yang 2017-08-23  118  {
4175e2b46fd4b9 Sherry Yang 2017-08-23  119  	int i;
4175e2b46fd4b9 Sherry Yang 2017-08-23  120  
4175e2b46fd4b9 Sherry Yang 2017-08-23  121  	for (i = 0; i < BUFFER_NUM; i++) {
4175e2b46fd4b9 Sherry Yang 2017-08-23 @122  		buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0);
4175e2b46fd4b9 Sherry Yang 2017-08-23  123  		if (IS_ERR(buffers[i]) ||
4175e2b46fd4b9 Sherry Yang 2017-08-23  124  		    !check_buffer_pages_allocated(alloc, buffers[i],
4175e2b46fd4b9 Sherry Yang 2017-08-23  125  						  sizes[i])) {
4175e2b46fd4b9 Sherry Yang 2017-08-23  126  			pr_err_size_seq(sizes, seq);
4175e2b46fd4b9 Sherry Yang 2017-08-23  127  			binder_selftest_failures++;
4175e2b46fd4b9 Sherry Yang 2017-08-23  128  		}
4175e2b46fd4b9 Sherry Yang 2017-08-23  129  	}
4175e2b46fd4b9 Sherry Yang 2017-08-23  130  }
4175e2b46fd4b9 Sherry Yang 2017-08-23  131  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 19968 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] binder: print warnings when detecting oneway spamming.
  2020-08-20 10:41 ` kernel test robot
@ 2020-08-20 11:47   ` Martijn Coenen
  0 siblings, 0 replies; 3+ messages in thread
From: Martijn Coenen @ 2020-08-20 11:47 UTC (permalink / raw)
  To: kernel test robot
  Cc: Greg KH, Todd Kjos, Arve Hjønnevåg, Joel Fernandes,
	Christian Brauner, Hridya Valsaraju, Suren Baghdasaryan,
	kbuild-all, clang-built-linux, LKML, open list:ANDROID DRIVERS,
	Martijn Coenen

On Thu, Aug 20, 2020 at 12:41 PM kernel test robot <lkp@intel.com> wrote:
>
> Hi Martijn,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on staging/staging-testing]
> [also build test ERROR on v5.9-rc1 next-20200820]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url:    https://github.com/0day-ci/linux/commits/Martijn-Coenen/binder-print-warnings-when-detecting-oneway-spamming/20200820-155358
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git bc752d2f345bf55d71b3422a6a24890ea03168dc
> config: s390-randconfig-r002-20200818 (attached as .config)
> compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 4deda57106f7c9b982a49cb907c33e3966c8de7f)
> reproduce (this is a W=1 build):
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # install s390 cross compiling tool for clang build
>         # apt-get install binutils-s390x-linux-gnu
>         # save the attached .config to linux build tree
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=s390
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
> >> drivers/android/binder_alloc_selftest.c:122:61: error: too few arguments to function call, expected 6, have 5
>                    buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0);

missed this call-site, will send v2.

Martijn
>                                 ~~~~~~~~~~~~~~~~~~~~                         ^
>    drivers/android/binder_alloc.h:118:30: note: 'binder_alloc_new_buf' declared here
>    extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
>                                 ^
>    1 error generated.
>
> # https://github.com/0day-ci/linux/commit/9d0b269f4468d6793f6fd76a410fdde39dbf6ac2
> git remote add linux-review https://github.com/0day-ci/linux
> git fetch --no-tags linux-review Martijn-Coenen/binder-print-warnings-when-detecting-oneway-spamming/20200820-155358
> git checkout 9d0b269f4468d6793f6fd76a410fdde39dbf6ac2
> vim +122 drivers/android/binder_alloc_selftest.c
>
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  114
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  115  static void binder_selftest_alloc_buf(struct binder_alloc *alloc,
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  116                                    struct binder_buffer *buffers[],
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  117                                    size_t *sizes, int *seq)
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  118  {
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  119      int i;
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  120
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  121      for (i = 0; i < BUFFER_NUM; i++) {
> 4175e2b46fd4b9 Sherry Yang 2017-08-23 @122              buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0);
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  123              if (IS_ERR(buffers[i]) ||
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  124                  !check_buffer_pages_allocated(alloc, buffers[i],
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  125                                                sizes[i])) {
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  126                      pr_err_size_seq(sizes, seq);
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  127                      binder_selftest_failures++;
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  128              }
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  129      }
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  130  }
> 4175e2b46fd4b9 Sherry Yang 2017-08-23  131
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-08-20 11:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-20  7:51 [PATCH] binder: print warnings when detecting oneway spamming Martijn Coenen
2020-08-20 10:41 ` kernel test robot
2020-08-20 11:47   ` Martijn Coenen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).