* [PATCH v19 1/5] binder: pre-allocate binder_transaction
2025-07-25 18:37 [PATCH v19 0/5] binder: introduce transaction reports via netlink Carlos Llamas
@ 2025-07-25 18:37 ` Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 2/5] binder: add t->is_async and t->is_reply Carlos Llamas
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Carlos Llamas @ 2025-07-25 18:37 UTC (permalink / raw)
To: Alice Ryhl, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Carlos Llamas, Suren Baghdasaryan
Cc: Tiffany Yang, John Stultz, Shai Barack, Thiébaud Weksteen,
kernel-team, linux-kernel, Jakub Kicinski
Move the allocation of 'struct binder_transaction' to the beginning of
the binder_transaction() function, along with the initialization of all
the members that are known at that time. This minor refactoring helps to
consolidate the usage of transaction information at later points.
This patch is in preparation for binder's generic netlink implementation
and no functional changes are intended.
Signed-off-by: Carlos Llamas <cmllamas@google.com>
---
drivers/android/binder.c | 64 +++++++++++++++++++---------------------
1 file changed, 30 insertions(+), 34 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 262334851aad..6bb1c9076951 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3042,6 +3042,30 @@ static void binder_transaction(struct binder_proc *proc,
binder_set_extended_error(&thread->ee, t_debug_id, BR_OK, 0);
binder_inner_proc_unlock(proc);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (!t) {
+ binder_txn_error("%d:%d cannot allocate transaction\n",
+ thread->pid, proc->pid);
+ return_error = BR_FAILED_REPLY;
+ return_error_param = -ENOMEM;
+ return_error_line = __LINE__;
+ goto err_alloc_t_failed;
+ }
+ INIT_LIST_HEAD(&t->fd_fixups);
+ binder_stats_created(BINDER_STAT_TRANSACTION);
+ spin_lock_init(&t->lock);
+ t->debug_id = t_debug_id;
+ t->start_time = t_start_time;
+ t->from_pid = proc->pid;
+ t->from_tid = thread->pid;
+ t->sender_euid = task_euid(proc->tsk);
+ t->code = tr->code;
+ t->flags = tr->flags;
+ t->priority = task_nice(current);
+ t->work.type = BINDER_WORK_TRANSACTION;
+ if (!reply && !(tr->flags & TF_ONE_WAY))
+ t->from = thread;
+
if (reply) {
binder_inner_proc_lock(proc);
in_reply_to = thread->transaction_stack;
@@ -3228,24 +3252,13 @@ static void binder_transaction(struct binder_proc *proc,
}
binder_inner_proc_unlock(proc);
}
+
+ t->to_proc = target_proc;
+ t->to_thread = target_thread;
if (target_thread)
e->to_thread = target_thread->pid;
e->to_proc = target_proc->pid;
- /* TODO: reuse incoming transaction for reply */
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if (t == NULL) {
- binder_txn_error("%d:%d cannot allocate transaction\n",
- thread->pid, proc->pid);
- return_error = BR_FAILED_REPLY;
- return_error_param = -ENOMEM;
- return_error_line = __LINE__;
- goto err_alloc_t_failed;
- }
- INIT_LIST_HEAD(&t->fd_fixups);
- binder_stats_created(BINDER_STAT_TRANSACTION);
- spin_lock_init(&t->lock);
-
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
if (tcomplete == NULL) {
binder_txn_error("%d:%d cannot allocate work for transaction\n",
@@ -3257,9 +3270,6 @@ static void binder_transaction(struct binder_proc *proc,
}
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
- t->debug_id = t_debug_id;
- t->start_time = t_start_time;
-
if (reply)
binder_debug(BINDER_DEBUG_TRANSACTION,
"%d:%d BC_REPLY %d -> %d:%d, data size %lld-%lld-%lld\n",
@@ -3275,19 +3285,6 @@ static void binder_transaction(struct binder_proc *proc,
(u64)tr->data_size, (u64)tr->offsets_size,
(u64)extra_buffers_size);
- if (!reply && !(tr->flags & TF_ONE_WAY))
- t->from = thread;
- else
- t->from = NULL;
- t->from_pid = proc->pid;
- t->from_tid = thread->pid;
- t->sender_euid = task_euid(proc->tsk);
- t->to_proc = target_proc;
- t->to_thread = target_thread;
- t->code = tr->code;
- t->flags = tr->flags;
- t->priority = task_nice(current);
-
if (target_node && target_node->txn_security_ctx) {
u32 secid;
size_t added_size;
@@ -3684,7 +3681,6 @@ static void binder_transaction(struct binder_proc *proc,
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
else
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
- t->work.type = BINDER_WORK_TRANSACTION;
if (reply) {
binder_enqueue_thread_work(thread, tcomplete);
@@ -3783,9 +3779,6 @@ static void binder_transaction(struct binder_proc *proc,
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:
err_bad_todo_list:
err_bad_call_stack:
err_empty_call_stack:
@@ -3795,6 +3788,9 @@ static void binder_transaction(struct binder_proc *proc,
binder_dec_node(target_node, 1, 0);
binder_dec_node_tmpref(target_node);
}
+ kfree(t);
+ binder_stats_deleted(BINDER_STAT_TRANSACTION);
+err_alloc_t_failed:
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
"%d:%d transaction %s to %d:%d failed %d/%d/%d, code %u size %lld-%lld line %d\n",
--
2.50.1.470.g6ba607880d-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v19 2/5] binder: add t->is_async and t->is_reply
2025-07-25 18:37 [PATCH v19 0/5] binder: introduce transaction reports via netlink Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 1/5] binder: pre-allocate binder_transaction Carlos Llamas
@ 2025-07-25 18:37 ` Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 3/5] binder: introduce transaction reports via netlink Carlos Llamas
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Carlos Llamas @ 2025-07-25 18:37 UTC (permalink / raw)
To: Alice Ryhl, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Carlos Llamas, Suren Baghdasaryan
Cc: Tiffany Yang, John Stultz, Shai Barack, Thiébaud Weksteen,
kernel-team, linux-kernel, Jakub Kicinski
Replace the t->need_reply flag with the more descriptive t->is_async and
and t->is_reply flags. The 'need_reply' flag was only used for debugging
purposes and the new flags can be used to distinguish between the type
of transactions too: sync, async and reply.
For now, only update the logging in print_binder_transaction_ilocked().
However, the new flags can be used in the future to replace the current
patterns and improve readability. e.g.:
- if (!reply && !(tr->flags & TF_ONE_WAY))
+ if (t->is_async)
This patch is in preparation for binder's generic netlink implementation
and no functional changes are intended.
Signed-off-by: Carlos Llamas <cmllamas@google.com>
---
drivers/android/binder.c | 7 ++++---
drivers/android/binder_internal.h | 4 ++--
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 6bb1c9076951..95aa1fae53e2 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3063,6 +3063,8 @@ static void binder_transaction(struct binder_proc *proc,
t->flags = tr->flags;
t->priority = task_nice(current);
t->work.type = BINDER_WORK_TRANSACTION;
+ t->is_async = !reply && (tr->flags & TF_ONE_WAY);
+ t->is_reply = reply;
if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;
@@ -3708,7 +3710,6 @@ static void binder_transaction(struct binder_proc *proc,
* the target replies (or there is an error).
*/
binder_enqueue_deferred_thread_work_ilocked(thread, tcomplete);
- t->need_reply = 1;
t->from_parent = thread->transaction_stack;
thread->transaction_stack = t;
binder_inner_proc_unlock(proc);
@@ -6328,13 +6329,13 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
spin_lock(&t->lock);
to_proc = t->to_proc;
seq_printf(m,
- "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d elapsed %lldms",
+ "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld a%d r%d elapsed %lldms",
prefix, t->debug_id, t,
t->from_pid,
t->from_tid,
to_proc ? to_proc->pid : 0,
t->to_thread ? t->to_thread->pid : 0,
- t->code, t->flags, t->priority, t->need_reply,
+ t->code, t->flags, t->priority, t->is_async, t->is_reply,
ktime_ms_delta(current_time, t->start_time));
spin_unlock(&t->lock);
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index b5d3014fb4dc..1b69bba2c816 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -539,8 +539,8 @@ struct binder_transaction {
struct binder_proc *to_proc;
struct binder_thread *to_thread;
struct binder_transaction *to_parent;
- unsigned need_reply:1;
- /* unsigned is_dead:1; */ /* not used at the moment */
+ unsigned is_async:1;
+ unsigned is_reply:1;
struct binder_buffer *buffer;
unsigned int code;
--
2.50.1.470.g6ba607880d-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v19 3/5] binder: introduce transaction reports via netlink
2025-07-25 18:37 [PATCH v19 0/5] binder: introduce transaction reports via netlink Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 1/5] binder: pre-allocate binder_transaction Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 2/5] binder: add t->is_async and t->is_reply Carlos Llamas
@ 2025-07-25 18:37 ` Carlos Llamas
2025-07-27 18:18 ` Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 4/5] binder: add transaction_report feature entry Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 5/5] binder: add tracepoint for netlink reports Carlos Llamas
4 siblings, 1 reply; 7+ messages in thread
From: Carlos Llamas @ 2025-07-25 18:37 UTC (permalink / raw)
To: Alice Ryhl, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Carlos Llamas, Suren Baghdasaryan, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Donald Hunter, Li Li
Cc: Tiffany Yang, John Stultz, Shai Barack, Thiébaud Weksteen,
kernel-team, linux-kernel, open list:NETWORKING [GENERAL]
From: Li Li <dualli@google.com>
Introduce a generic netlink multicast event to report binder transaction
failures to userspace. This allows subscribers to monitor these events
and take appropriate actions, such as stopping a misbehaving application
that is spamming a service with huge amount of transactions.
The multicast event contains full details of the failed transactions,
including the sender/target PIDs, payload size and specific error code.
This interface is defined using a YAML spec, from which the UAPI and
kernel headers and source are auto-generated.
Signed-off-by: Li Li <dualli@google.com>
Signed-off-by: Carlos Llamas <cmllamas@google.com>
---
Documentation/netlink/specs/binder.yaml | 96 +++++++++++++++++++++
MAINTAINERS | 1 +
drivers/android/Kconfig | 1 +
drivers/android/Makefile | 2 +-
drivers/android/binder.c | 85 +++++++++++++++++-
drivers/android/binder_netlink.c | 32 +++++++
drivers/android/binder_netlink.h | 21 +++++
include/uapi/linux/android/binder_netlink.h | 37 ++++++++
8 files changed, 270 insertions(+), 5 deletions(-)
create mode 100644 Documentation/netlink/specs/binder.yaml
create mode 100644 drivers/android/binder_netlink.c
create mode 100644 drivers/android/binder_netlink.h
create mode 100644 include/uapi/linux/android/binder_netlink.h
diff --git a/Documentation/netlink/specs/binder.yaml b/Documentation/netlink/specs/binder.yaml
new file mode 100644
index 000000000000..a2e54aa42448
--- /dev/null
+++ b/Documentation/netlink/specs/binder.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+#
+# Copyright 2025 Google LLC
+#
+---
+name: binder
+protocol: genetlink
+uapi-header: linux/android/binder_netlink.h
+doc: Binder interface over generic netlink
+
+attribute-sets:
+ -
+ name: report
+ doc: |
+ Attributes included within a transaction failure report. The elements
+ correspond directly with the specific transaction that failed, along
+ with the error returned to the sender e.g. BR_DEAD_REPLY.
+
+ attributes:
+ -
+ name: error
+ type: u32
+ doc: The enum binder_driver_return_protocol returned to the sender.
+ -
+ name: context
+ type: string
+ doc: The binder context where the transaction occurred.
+ -
+ name: from_pid
+ type: u32
+ doc: The PID of the sender process.
+ -
+ name: from_tid
+ type: u32
+ doc: The TID of the sender thread.
+ -
+ name: to_pid
+ type: u32
+ doc: |
+ The PID of the recipient process. This attribute may not be present
+ if the target could not be determined.
+ -
+ name: to_tid
+ type: u32
+ doc: |
+ The TID of the recipient thread. This attribute may not be present
+ if the target could not be determined.
+ -
+ name: is_reply
+ type: flag
+ doc: When present, indicates the failed transaction is a reply.
+ -
+ name: flags
+ type: u32
+ doc: The bitmask of enum transaction_flags from the transaction.
+ -
+ name: code
+ type: u32
+ doc: The application-defined code from the transaction.
+ -
+ name: data_size
+ type: u32
+ doc: The transaction payload size in bytes.
+
+operations:
+ list:
+ -
+ name: report
+ doc: |
+ A multicast event sent to userspace subscribers to notify them about
+ binder transaction failures. The generated report provides the full
+ details of the specific transaction that failed. The intention is for
+ programs to monitor these events and react to the failures as needed.
+
+ attribute-set: report
+ mcgrp: report
+ event:
+ attributes:
+ - error
+ - context
+ - from_pid
+ - from_tid
+ - to_pid
+ - to_tid
+ - is_reply
+ - flags
+ - code
+ - data_size
+
+kernel-family:
+ headers: ["binder_internal.h"]
+
+mcast-groups:
+ list:
+ -
+ name: report
diff --git a/MAINTAINERS b/MAINTAINERS
index f8c8f682edf6..df8f6b31f2f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1769,6 +1769,7 @@ M: Suren Baghdasaryan <surenb@google.com>
L: linux-kernel@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
+F: Documentation/netlink/specs/binder.yaml
F: drivers/android/
ANDROID GOLDFISH PIC DRIVER
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 5b3b8041f827..75af3cf472c8 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -4,6 +4,7 @@ menu "Android"
config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
depends on MMU
+ depends on NET
default n
help
Binder is used in Android for both communication between processes,
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c5d47be0276c..f422f91e026b 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -2,5 +2,5 @@
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) += binder.o binder_alloc.o binder_netlink.o
obj-$(CONFIG_ANDROID_BINDER_ALLOC_KUNIT_TEST) += tests/
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 95aa1fae53e2..0d37eca514f9 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -74,6 +74,7 @@
#include <linux/cacheflush.h>
+#include "binder_netlink.h"
#include "binder_internal.h"
#include "binder_trace.h"
@@ -2993,6 +2994,67 @@ static void binder_set_txn_from_error(struct binder_transaction *t, int id,
binder_thread_dec_tmpref(from);
}
+/**
+ * binder_netlink_report() - report a transaction failure via netlink
+ * @proc: the binder proc sending the transaction
+ * @t: the binder transaction that failed
+ * @data_size: the user provided data size for the transaction
+ * @error: enum binder_driver_return_protocol returned to sender
+ */
+static void binder_netlink_report(struct binder_proc *proc,
+ struct binder_transaction *t,
+ u32 data_size,
+ u32 error)
+{
+ const char *context = proc->context->name;
+ struct sk_buff *skb;
+ void *hdr;
+
+ if (!genl_has_listeners(&binder_nl_family, &init_net,
+ BINDER_NLGRP_REPORT))
+ return;
+
+ skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ hdr = genlmsg_put(skb, 0, 0, &binder_nl_family, 0, BINDER_CMD_REPORT);
+ if (!hdr)
+ goto free_skb;
+
+ if (nla_put_u32(skb, BINDER_A_REPORT_ERROR, error) ||
+ nla_put_string(skb, BINDER_A_REPORT_CONTEXT, context) ||
+ nla_put_u32(skb, BINDER_A_REPORT_FROM_PID, t->from_pid) ||
+ nla_put_u32(skb, BINDER_A_REPORT_FROM_TID, t->from_tid))
+ goto cancel_skb;
+
+ if (t->to_proc &&
+ nla_put_u32(skb, BINDER_A_REPORT_TO_PID, t->to_proc->pid))
+ goto cancel_skb;
+
+ if (t->to_thread &&
+ nla_put_u32(skb, BINDER_A_REPORT_TO_TID, t->to_thread->pid))
+ goto cancel_skb;
+
+ if (t->is_reply && nla_put_flag(skb, BINDER_A_REPORT_IS_REPLY))
+ goto cancel_skb;
+
+ if (nla_put_u32(skb, BINDER_A_REPORT_FLAGS, t->flags) ||
+ nla_put_u32(skb, BINDER_A_REPORT_CODE, t->code) ||
+ nla_put_u32(skb, BINDER_A_REPORT_DATA_SIZE, data_size))
+ goto cancel_skb;
+
+ genlmsg_end(skb, hdr);
+ genlmsg_multicast(&binder_nl_family, skb, 0, BINDER_NLGRP_REPORT,
+ GFP_KERNEL);
+ return;
+
+cancel_skb:
+ genlmsg_cancel(skb, hdr);
+free_skb:
+ nlmsg_free(skb);
+}
+
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply,
@@ -3679,10 +3741,13 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_copy_data_failed;
}
- if (t->buffer->oneway_spam_suspect)
+ if (t->buffer->oneway_spam_suspect) {
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
- else
+ binder_netlink_report(proc, t, tr->data_size,
+ BR_ONEWAY_SPAM_SUSPECT);
+ } else {
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+ }
if (reply) {
binder_enqueue_thread_work(thread, tcomplete);
@@ -3730,8 +3795,11 @@ static void binder_transaction(struct binder_proc *proc,
* process and is put in a pending queue, waiting for the target
* process to be unfrozen.
*/
- if (return_error == BR_TRANSACTION_PENDING_FROZEN)
+ if (return_error == BR_TRANSACTION_PENDING_FROZEN) {
tcomplete->type = BINDER_WORK_TRANSACTION_PENDING;
+ binder_netlink_report(proc, t, tr->data_size,
+ return_error);
+ }
binder_enqueue_thread_work(thread, tcomplete);
if (return_error &&
return_error != BR_TRANSACTION_PENDING_FROZEN)
@@ -3789,6 +3857,8 @@ static void binder_transaction(struct binder_proc *proc,
binder_dec_node(target_node, 1, 0);
binder_dec_node_tmpref(target_node);
}
+
+ binder_netlink_report(proc, t, tr->data_size, return_error);
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
err_alloc_t_failed:
@@ -7067,12 +7137,19 @@ static int __init binder_init(void)
}
}
- ret = init_binderfs();
+ ret = genl_register_family(&binder_nl_family);
if (ret)
goto err_init_binder_device_failed;
+ ret = init_binderfs();
+ if (ret)
+ goto err_init_binderfs_failed;
+
return ret;
+err_init_binderfs_failed:
+ genl_unregister_family(&binder_nl_family);
+
err_init_binder_device_failed:
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
misc_deregister(&device->miscdev);
diff --git a/drivers/android/binder_netlink.c b/drivers/android/binder_netlink.c
new file mode 100644
index 000000000000..f62fbca3143c
--- /dev/null
+++ b/drivers/android/binder_netlink.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/binder.yaml */
+/* YNL-GEN kernel source */
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "binder_netlink.h"
+
+#include <uapi/linux/android/binder_netlink.h>
+#include <binder_internal.h>
+
+/* Ops table for binder */
+static const struct genl_split_ops binder_nl_ops[] = {
+};
+
+static const struct genl_multicast_group binder_nl_mcgrps[] = {
+ [BINDER_NLGRP_REPORT] = { "report", },
+};
+
+struct genl_family binder_nl_family __ro_after_init = {
+ .name = BINDER_FAMILY_NAME,
+ .version = BINDER_FAMILY_VERSION,
+ .netnsok = true,
+ .parallel_ops = true,
+ .module = THIS_MODULE,
+ .split_ops = binder_nl_ops,
+ .n_split_ops = ARRAY_SIZE(binder_nl_ops),
+ .mcgrps = binder_nl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(binder_nl_mcgrps),
+};
diff --git a/drivers/android/binder_netlink.h b/drivers/android/binder_netlink.h
new file mode 100644
index 000000000000..f78b8ec54c53
--- /dev/null
+++ b/drivers/android/binder_netlink.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/binder.yaml */
+/* YNL-GEN kernel header */
+
+#ifndef _LINUX_BINDER_GEN_H
+#define _LINUX_BINDER_GEN_H
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include <uapi/linux/android/binder_netlink.h>
+#include <binder_internal.h>
+
+enum {
+ BINDER_NLGRP_REPORT,
+};
+
+extern struct genl_family binder_nl_family;
+
+#endif /* _LINUX_BINDER_GEN_H */
diff --git a/include/uapi/linux/android/binder_netlink.h b/include/uapi/linux/android/binder_netlink.h
new file mode 100644
index 000000000000..b218f96d6668
--- /dev/null
+++ b/include/uapi/linux/android/binder_netlink.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/binder.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_ANDROID_BINDER_NETLINK_H
+#define _UAPI_LINUX_ANDROID_BINDER_NETLINK_H
+
+#define BINDER_FAMILY_NAME "binder"
+#define BINDER_FAMILY_VERSION 1
+
+enum {
+ BINDER_A_REPORT_ERROR = 1,
+ BINDER_A_REPORT_CONTEXT,
+ BINDER_A_REPORT_FROM_PID,
+ BINDER_A_REPORT_FROM_TID,
+ BINDER_A_REPORT_TO_PID,
+ BINDER_A_REPORT_TO_TID,
+ BINDER_A_REPORT_IS_REPLY,
+ BINDER_A_REPORT_FLAGS,
+ BINDER_A_REPORT_CODE,
+ BINDER_A_REPORT_DATA_SIZE,
+
+ __BINDER_A_REPORT_MAX,
+ BINDER_A_REPORT_MAX = (__BINDER_A_REPORT_MAX - 1)
+};
+
+enum {
+ BINDER_CMD_REPORT = 1,
+
+ __BINDER_CMD_MAX,
+ BINDER_CMD_MAX = (__BINDER_CMD_MAX - 1)
+};
+
+#define BINDER_MCGRP_REPORT "report"
+
+#endif /* _UAPI_LINUX_ANDROID_BINDER_NETLINK_H */
--
2.50.1.470.g6ba607880d-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v19 3/5] binder: introduce transaction reports via netlink
2025-07-25 18:37 ` [PATCH v19 3/5] binder: introduce transaction reports via netlink Carlos Llamas
@ 2025-07-27 18:18 ` Carlos Llamas
0 siblings, 0 replies; 7+ messages in thread
From: Carlos Llamas @ 2025-07-27 18:18 UTC (permalink / raw)
To: Alice Ryhl, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Suren Baghdasaryan, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Li Li
Cc: Tiffany Yang, John Stultz, Shai Barack, Thiébaud Weksteen,
kernel-team, linux-kernel, open list:NETWORKING [GENERAL]
On Fri, Jul 25, 2025 at 06:37:46PM +0000, Carlos Llamas wrote:
> From: Li Li <dualli@google.com>
>
> Introduce a generic netlink multicast event to report binder transaction
> failures to userspace. This allows subscribers to monitor these events
> and take appropriate actions, such as stopping a misbehaving application
> that is spamming a service with huge amount of transactions.
>
> The multicast event contains full details of the failed transactions,
> including the sender/target PIDs, payload size and specific error code.
> This interface is defined using a YAML spec, from which the UAPI and
> kernel headers and source are auto-generated.
>
> Signed-off-by: Li Li <dualli@google.com>
> Signed-off-by: Carlos Llamas <cmllamas@google.com>
> ---
> Documentation/netlink/specs/binder.yaml | 96 +++++++++++++++++++++
> MAINTAINERS | 1 +
> drivers/android/Kconfig | 1 +
> drivers/android/Makefile | 2 +-
> drivers/android/binder.c | 85 +++++++++++++++++-
> drivers/android/binder_netlink.c | 32 +++++++
> drivers/android/binder_netlink.h | 21 +++++
> include/uapi/linux/android/binder_netlink.h | 37 ++++++++
> 8 files changed, 270 insertions(+), 5 deletions(-)
> create mode 100644 Documentation/netlink/specs/binder.yaml
> create mode 100644 drivers/android/binder_netlink.c
> create mode 100644 drivers/android/binder_netlink.h
> create mode 100644 include/uapi/linux/android/binder_netlink.h
>
> diff --git a/Documentation/netlink/specs/binder.yaml b/Documentation/netlink/specs/binder.yaml
> new file mode 100644
> index 000000000000..a2e54aa42448
> --- /dev/null
> +++ b/Documentation/netlink/specs/binder.yaml
> @@ -0,0 +1,96 @@
> +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
> +#
> +# Copyright 2025 Google LLC
> +#
> +---
> +name: binder
> +protocol: genetlink
> +uapi-header: linux/android/binder_netlink.h
> +doc: Binder interface over generic netlink
> +
> +attribute-sets:
> + -
> + name: report
> + doc: |
> + Attributes included within a transaction failure report. The elements
> + correspond directly with the specific transaction that failed, along
> + with the error returned to the sender e.g. BR_DEAD_REPLY.
> +
> + attributes:
> + -
> + name: error
> + type: u32
> + doc: The enum binder_driver_return_protocol returned to the sender.
> + -
> + name: context
> + type: string
> + doc: The binder context where the transaction occurred.
> + -
> + name: from_pid
> + type: u32
> + doc: The PID of the sender process.
> + -
> + name: from_tid
> + type: u32
> + doc: The TID of the sender thread.
> + -
> + name: to_pid
> + type: u32
> + doc: |
> + The PID of the recipient process. This attribute may not be present
> + if the target could not be determined.
> + -
> + name: to_tid
> + type: u32
> + doc: |
> + The TID of the recipient thread. This attribute may not be present
> + if the target could not be determined.
> + -
> + name: is_reply
> + type: flag
> + doc: When present, indicates the failed transaction is a reply.
> + -
> + name: flags
> + type: u32
> + doc: The bitmask of enum transaction_flags from the transaction.
> + -
> + name: code
> + type: u32
> + doc: The application-defined code from the transaction.
> + -
> + name: data_size
> + type: u32
> + doc: The transaction payload size in bytes.
> +
> +operations:
> + list:
> + -
> + name: report
> + doc: |
> + A multicast event sent to userspace subscribers to notify them about
> + binder transaction failures. The generated report provides the full
> + details of the specific transaction that failed. The intention is for
> + programs to monitor these events and react to the failures as needed.
> +
> + attribute-set: report
> + mcgrp: report
> + event:
> + attributes:
> + - error
> + - context
> + - from_pid
> + - from_tid
> + - to_pid
> + - to_tid
> + - is_reply
> + - flags
> + - code
> + - data_size
> +
> +kernel-family:
> + headers: ["binder_internal.h"]
Hmm, it seems this header inclusion was left in from patchset v13, where
the 'struct binder_context' needed to be exposed. Not anymore though, so
I'll send out a new version that drops this part.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v19 4/5] binder: add transaction_report feature entry
2025-07-25 18:37 [PATCH v19 0/5] binder: introduce transaction reports via netlink Carlos Llamas
` (2 preceding siblings ...)
2025-07-25 18:37 ` [PATCH v19 3/5] binder: introduce transaction reports via netlink Carlos Llamas
@ 2025-07-25 18:37 ` Carlos Llamas
2025-07-25 18:37 ` [PATCH v19 5/5] binder: add tracepoint for netlink reports Carlos Llamas
4 siblings, 0 replies; 7+ messages in thread
From: Carlos Llamas @ 2025-07-25 18:37 UTC (permalink / raw)
To: Alice Ryhl, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Carlos Llamas, Suren Baghdasaryan, Shuah Khan, Yu-Ting Tseng,
Li Li, Ba Jing
Cc: Tiffany Yang, John Stultz, Shai Barack, Thiébaud Weksteen,
kernel-team, linux-kernel, Jakub Kicinski,
open list:KERNEL SELFTEST FRAMEWORK
From: Li Li <dualli@google.com>
Add "transaction_report" to the binderfs feature list, to help userspace
determine if the "BINDER_CMD_REPORT" generic netlink api is supported by
the binder driver.
Signed-off-by: Li Li <dualli@google.com>
Signed-off-by: Carlos Llamas <cmllamas@google.com>
---
drivers/android/binderfs.c | 8 ++++++++
.../selftests/filesystems/binderfs/binderfs_test.c | 1 +
2 files changed, 9 insertions(+)
diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c
index 4f827152d18e..f74a7e380261 100644
--- a/drivers/android/binderfs.c
+++ b/drivers/android/binderfs.c
@@ -59,6 +59,7 @@ struct binder_features {
bool oneway_spam_detection;
bool extended_error;
bool freeze_notification;
+ bool transaction_report;
};
static const struct constant_table binderfs_param_stats[] = {
@@ -76,6 +77,7 @@ static struct binder_features binder_features = {
.oneway_spam_detection = true,
.extended_error = true,
.freeze_notification = true,
+ .transaction_report = true,
};
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
@@ -616,6 +618,12 @@ static int init_binder_features(struct super_block *sb)
if (IS_ERR(dentry))
return PTR_ERR(dentry);
+ dentry = binderfs_create_file(dir, "transaction_report",
+ &binder_features_fops,
+ &binder_features.transaction_report);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
return 0;
}
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
index 81db85a5cc16..39a68078a79b 100644
--- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
+++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
@@ -65,6 +65,7 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
"oneway_spam_detection",
"extended_error",
"freeze_notification",
+ "transaction_report",
};
change_mountns(_metadata);
--
2.50.1.470.g6ba607880d-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v19 5/5] binder: add tracepoint for netlink reports
2025-07-25 18:37 [PATCH v19 0/5] binder: introduce transaction reports via netlink Carlos Llamas
` (3 preceding siblings ...)
2025-07-25 18:37 ` [PATCH v19 4/5] binder: add transaction_report feature entry Carlos Llamas
@ 2025-07-25 18:37 ` Carlos Llamas
4 siblings, 0 replies; 7+ messages in thread
From: Carlos Llamas @ 2025-07-25 18:37 UTC (permalink / raw)
To: Alice Ryhl, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Carlos Llamas, Suren Baghdasaryan
Cc: Tiffany Yang, John Stultz, Shai Barack, Thiébaud Weksteen,
kernel-team, linux-kernel, Jakub Kicinski
Add a tracepoint to capture the same details that are being sent through
the generic netlink interface during transaction failures. This provides
a useful debugging tool to observe the events independently from the
netlink listeners.
Signed-off-by: Carlos Llamas <cmllamas@google.com>
---
drivers/android/binder.c | 2 ++
drivers/android/binder_trace.h | 37 ++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 0d37eca514f9..695c1631703b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3014,6 +3014,8 @@ static void binder_netlink_report(struct binder_proc *proc,
BINDER_NLGRP_REPORT))
return;
+ trace_binder_netlink_report(context, t, data_size, error);
+
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb)
return;
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 97a78e5623db..fa5eb61cf580 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -402,6 +402,43 @@ TRACE_EVENT(binder_return,
"unknown")
);
+TRACE_EVENT(binder_netlink_report,
+ TP_PROTO(const char *context,
+ struct binder_transaction *t,
+ u32 data_size,
+ u32 error),
+ TP_ARGS(context, t, data_size, error),
+ TP_STRUCT__entry(
+ __field(const char *, context)
+ __field(u32, error)
+ __field(int, from_pid)
+ __field(int, from_tid)
+ __field(int, to_pid)
+ __field(int, to_tid)
+ __field(bool, is_reply)
+ __field(unsigned int, flags)
+ __field(unsigned int, code)
+ __field(size_t, data_size)
+ ),
+ TP_fast_assign(
+ __entry->context = context;
+ __entry->error = error;
+ __entry->from_pid = t->from_pid;
+ __entry->from_tid = t->from_tid;
+ __entry->to_pid = t->to_proc ? t->to_proc->pid : 0;
+ __entry->to_tid = t->to_thread ? t->to_thread->pid : 0;
+ __entry->is_reply = t->is_reply;
+ __entry->flags = t->flags;
+ __entry->code = t->code;
+ __entry->data_size = data_size;
+ ),
+ TP_printk("from %d:%d to %d:%d context=%s error=%d is_reply=%d flags=0x%x code=0x%x size=%zu",
+ __entry->from_pid, __entry->from_tid,
+ __entry->to_pid, __entry->to_tid,
+ __entry->context, __entry->error, __entry->is_reply,
+ __entry->flags, __entry->code, __entry->data_size)
+);
+
#endif /* _BINDER_TRACE_H */
#undef TRACE_INCLUDE_PATH
--
2.50.1.470.g6ba607880d-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread