Skip to content

Commit 6374034

Browse files
eggonleagregkh
authored andcommitted
binder: introduce transaction reports via netlink
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> Link: https://lore.kernel.org/r/20250727182932.2499194-4-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5cd0645 commit 6374034

File tree

8 files changed

+265
-5
lines changed

8 files changed

+265
-5
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+
#
3+
# Copyright 2025 Google LLC
4+
#
5+
---
6+
name: binder
7+
protocol: genetlink
8+
uapi-header: linux/android/binder_netlink.h
9+
doc: Binder interface over generic netlink
10+
11+
attribute-sets:
12+
-
13+
name: report
14+
doc: |
15+
Attributes included within a transaction failure report. The elements
16+
correspond directly with the specific transaction that failed, along
17+
with the error returned to the sender e.g. BR_DEAD_REPLY.
18+
19+
attributes:
20+
-
21+
name: error
22+
type: u32
23+
doc: The enum binder_driver_return_protocol returned to the sender.
24+
-
25+
name: context
26+
type: string
27+
doc: The binder context where the transaction occurred.
28+
-
29+
name: from_pid
30+
type: u32
31+
doc: The PID of the sender process.
32+
-
33+
name: from_tid
34+
type: u32
35+
doc: The TID of the sender thread.
36+
-
37+
name: to_pid
38+
type: u32
39+
doc: |
40+
The PID of the recipient process. This attribute may not be present
41+
if the target could not be determined.
42+
-
43+
name: to_tid
44+
type: u32
45+
doc: |
46+
The TID of the recipient thread. This attribute may not be present
47+
if the target could not be determined.
48+
-
49+
name: is_reply
50+
type: flag
51+
doc: When present, indicates the failed transaction is a reply.
52+
-
53+
name: flags
54+
type: u32
55+
doc: The bitmask of enum transaction_flags from the transaction.
56+
-
57+
name: code
58+
type: u32
59+
doc: The application-defined code from the transaction.
60+
-
61+
name: data_size
62+
type: u32
63+
doc: The transaction payload size in bytes.
64+
65+
operations:
66+
list:
67+
-
68+
name: report
69+
doc: |
70+
A multicast event sent to userspace subscribers to notify them about
71+
binder transaction failures. The generated report provides the full
72+
details of the specific transaction that failed. The intention is for
73+
programs to monitor these events and react to the failures as needed.
74+
75+
attribute-set: report
76+
mcgrp: report
77+
event:
78+
attributes:
79+
- error
80+
- context
81+
- from_pid
82+
- from_tid
83+
- to_pid
84+
- to_tid
85+
- is_reply
86+
- flags
87+
- code
88+
- data_size
89+
90+
mcast-groups:
91+
list:
92+
-
93+
name: report

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,7 @@ M: Suren Baghdasaryan <surenb@google.com>
17901790
L: linux-kernel@vger.kernel.org
17911791
S: Supported
17921792
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
1793+
F: Documentation/netlink/specs/binder.yaml
17931794
F: drivers/android/
17941795

17951796
ANDROID GOLDFISH PIC DRIVER

drivers/android/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ menu "Android"
44
config ANDROID_BINDER_IPC
55
bool "Android Binder IPC Driver"
66
depends on MMU
7+
depends on NET
78
default n
89
help
910
Binder is used in Android for both communication between processes,

drivers/android/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
ccflags-y += -I$(src) # needed for trace events
33

44
obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
5-
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o
5+
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o binder_netlink.o
66
obj-$(CONFIG_ANDROID_BINDER_ALLOC_KUNIT_TEST) += tests/

drivers/android/binder.c

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474

7575
#include <linux/cacheflush.h>
7676

77+
#include "binder_netlink.h"
7778
#include "binder_internal.h"
7879
#include "binder_trace.h"
7980

@@ -2993,6 +2994,67 @@ static void binder_set_txn_from_error(struct binder_transaction *t, int id,
29932994
binder_thread_dec_tmpref(from);
29942995
}
29952996

2997+
/**
2998+
* binder_netlink_report() - report a transaction failure via netlink
2999+
* @proc: the binder proc sending the transaction
3000+
* @t: the binder transaction that failed
3001+
* @data_size: the user provided data size for the transaction
3002+
* @error: enum binder_driver_return_protocol returned to sender
3003+
*/
3004+
static void binder_netlink_report(struct binder_proc *proc,
3005+
struct binder_transaction *t,
3006+
u32 data_size,
3007+
u32 error)
3008+
{
3009+
const char *context = proc->context->name;
3010+
struct sk_buff *skb;
3011+
void *hdr;
3012+
3013+
if (!genl_has_listeners(&binder_nl_family, &init_net,
3014+
BINDER_NLGRP_REPORT))
3015+
return;
3016+
3017+
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
3018+
if (!skb)
3019+
return;
3020+
3021+
hdr = genlmsg_put(skb, 0, 0, &binder_nl_family, 0, BINDER_CMD_REPORT);
3022+
if (!hdr)
3023+
goto free_skb;
3024+
3025+
if (nla_put_u32(skb, BINDER_A_REPORT_ERROR, error) ||
3026+
nla_put_string(skb, BINDER_A_REPORT_CONTEXT, context) ||
3027+
nla_put_u32(skb, BINDER_A_REPORT_FROM_PID, t->from_pid) ||
3028+
nla_put_u32(skb, BINDER_A_REPORT_FROM_TID, t->from_tid))
3029+
goto cancel_skb;
3030+
3031+
if (t->to_proc &&
3032+
nla_put_u32(skb, BINDER_A_REPORT_TO_PID, t->to_proc->pid))
3033+
goto cancel_skb;
3034+
3035+
if (t->to_thread &&
3036+
nla_put_u32(skb, BINDER_A_REPORT_TO_TID, t->to_thread->pid))
3037+
goto cancel_skb;
3038+
3039+
if (t->is_reply && nla_put_flag(skb, BINDER_A_REPORT_IS_REPLY))
3040+
goto cancel_skb;
3041+
3042+
if (nla_put_u32(skb, BINDER_A_REPORT_FLAGS, t->flags) ||
3043+
nla_put_u32(skb, BINDER_A_REPORT_CODE, t->code) ||
3044+
nla_put_u32(skb, BINDER_A_REPORT_DATA_SIZE, data_size))
3045+
goto cancel_skb;
3046+
3047+
genlmsg_end(skb, hdr);
3048+
genlmsg_multicast(&binder_nl_family, skb, 0, BINDER_NLGRP_REPORT,
3049+
GFP_KERNEL);
3050+
return;
3051+
3052+
cancel_skb:
3053+
genlmsg_cancel(skb, hdr);
3054+
free_skb:
3055+
nlmsg_free(skb);
3056+
}
3057+
29963058
static void binder_transaction(struct binder_proc *proc,
29973059
struct binder_thread *thread,
29983060
struct binder_transaction_data *tr, int reply,
@@ -3679,10 +3741,13 @@ static void binder_transaction(struct binder_proc *proc,
36793741
return_error_line = __LINE__;
36803742
goto err_copy_data_failed;
36813743
}
3682-
if (t->buffer->oneway_spam_suspect)
3744+
if (t->buffer->oneway_spam_suspect) {
36833745
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
3684-
else
3746+
binder_netlink_report(proc, t, tr->data_size,
3747+
BR_ONEWAY_SPAM_SUSPECT);
3748+
} else {
36853749
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
3750+
}
36863751

36873752
if (reply) {
36883753
binder_enqueue_thread_work(thread, tcomplete);
@@ -3730,8 +3795,11 @@ static void binder_transaction(struct binder_proc *proc,
37303795
* process and is put in a pending queue, waiting for the target
37313796
* process to be unfrozen.
37323797
*/
3733-
if (return_error == BR_TRANSACTION_PENDING_FROZEN)
3798+
if (return_error == BR_TRANSACTION_PENDING_FROZEN) {
37343799
tcomplete->type = BINDER_WORK_TRANSACTION_PENDING;
3800+
binder_netlink_report(proc, t, tr->data_size,
3801+
return_error);
3802+
}
37353803
binder_enqueue_thread_work(thread, tcomplete);
37363804
if (return_error &&
37373805
return_error != BR_TRANSACTION_PENDING_FROZEN)
@@ -3789,6 +3857,8 @@ static void binder_transaction(struct binder_proc *proc,
37893857
binder_dec_node(target_node, 1, 0);
37903858
binder_dec_node_tmpref(target_node);
37913859
}
3860+
3861+
binder_netlink_report(proc, t, tr->data_size, return_error);
37923862
kfree(t);
37933863
binder_stats_deleted(BINDER_STAT_TRANSACTION);
37943864
err_alloc_t_failed:
@@ -7059,12 +7129,19 @@ static int __init binder_init(void)
70597129
}
70607130
}
70617131

7062-
ret = init_binderfs();
7132+
ret = genl_register_family(&binder_nl_family);
70637133
if (ret)
70647134
goto err_init_binder_device_failed;
70657135

7136+
ret = init_binderfs();
7137+
if (ret)
7138+
goto err_init_binderfs_failed;
7139+
70667140
return ret;
70677141

7142+
err_init_binderfs_failed:
7143+
genl_unregister_family(&binder_nl_family);
7144+
70687145
err_init_binder_device_failed:
70697146
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
70707147
misc_deregister(&device->miscdev);

drivers/android/binder_netlink.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2+
/* Do not edit directly, auto-generated from: */
3+
/* Documentation/netlink/specs/binder.yaml */
4+
/* YNL-GEN kernel source */
5+
6+
#include <net/netlink.h>
7+
#include <net/genetlink.h>
8+
9+
#include "binder_netlink.h"
10+
11+
#include <uapi/linux/android/binder_netlink.h>
12+
13+
/* Ops table for binder */
14+
static const struct genl_split_ops binder_nl_ops[] = {
15+
};
16+
17+
static const struct genl_multicast_group binder_nl_mcgrps[] = {
18+
[BINDER_NLGRP_REPORT] = { "report", },
19+
};
20+
21+
struct genl_family binder_nl_family __ro_after_init = {
22+
.name = BINDER_FAMILY_NAME,
23+
.version = BINDER_FAMILY_VERSION,
24+
.netnsok = true,
25+
.parallel_ops = true,
26+
.module = THIS_MODULE,
27+
.split_ops = binder_nl_ops,
28+
.n_split_ops = ARRAY_SIZE(binder_nl_ops),
29+
.mcgrps = binder_nl_mcgrps,
30+
.n_mcgrps = ARRAY_SIZE(binder_nl_mcgrps),
31+
};

drivers/android/binder_netlink.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
2+
/* Do not edit directly, auto-generated from: */
3+
/* Documentation/netlink/specs/binder.yaml */
4+
/* YNL-GEN kernel header */
5+
6+
#ifndef _LINUX_BINDER_GEN_H
7+
#define _LINUX_BINDER_GEN_H
8+
9+
#include <net/netlink.h>
10+
#include <net/genetlink.h>
11+
12+
#include <uapi/linux/android/binder_netlink.h>
13+
14+
enum {
15+
BINDER_NLGRP_REPORT,
16+
};
17+
18+
extern struct genl_family binder_nl_family;
19+
20+
#endif /* _LINUX_BINDER_GEN_H */
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
2+
/* Do not edit directly, auto-generated from: */
3+
/* Documentation/netlink/specs/binder.yaml */
4+
/* YNL-GEN uapi header */
5+
6+
#ifndef _UAPI_LINUX_ANDROID_BINDER_NETLINK_H
7+
#define _UAPI_LINUX_ANDROID_BINDER_NETLINK_H
8+
9+
#define BINDER_FAMILY_NAME "binder"
10+
#define BINDER_FAMILY_VERSION 1
11+
12+
enum {
13+
BINDER_A_REPORT_ERROR = 1,
14+
BINDER_A_REPORT_CONTEXT,
15+
BINDER_A_REPORT_FROM_PID,
16+
BINDER_A_REPORT_FROM_TID,
17+
BINDER_A_REPORT_TO_PID,
18+
BINDER_A_REPORT_TO_TID,
19+
BINDER_A_REPORT_IS_REPLY,
20+
BINDER_A_REPORT_FLAGS,
21+
BINDER_A_REPORT_CODE,
22+
BINDER_A_REPORT_DATA_SIZE,
23+
24+
__BINDER_A_REPORT_MAX,
25+
BINDER_A_REPORT_MAX = (__BINDER_A_REPORT_MAX - 1)
26+
};
27+
28+
enum {
29+
BINDER_CMD_REPORT = 1,
30+
31+
__BINDER_CMD_MAX,
32+
BINDER_CMD_MAX = (__BINDER_CMD_MAX - 1)
33+
};
34+
35+
#define BINDER_MCGRP_REPORT "report"
36+
37+
#endif /* _UAPI_LINUX_ANDROID_BINDER_NETLINK_H */

0 commit comments

Comments
 (0)