projects/linux·blob master · refs

117 lines · 4.4 KiB

1// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2/* Based on: Documentation/netlink/specs/binder.yaml */
3
4#![allow(unreachable_pub, clippy::wrong_self_convention)]
5use kernel::{
6 net::netlink::{
7 Family,
8 GenlMsg,
9 MulticastGroup,
10 NetlinkSkBuff, //
11 },
12 prelude::*, //
13};
14
15pub static BINDER_NL_FAMILY: Family = Family::const_new(
16 kernel::module::this_module::<crate::LocalModule>(),
17 kernel::uapi::BINDER_FAMILY_NAME,
18 kernel::uapi::BINDER_FAMILY_VERSION,
19 &BINDER_NL_FAMILY_MCGRPS,
20);
21
22static BINDER_NL_FAMILY_MCGRPS: [MulticastGroup; 1] = [MulticastGroup::const_new(c"report")];
23
24/// A multicast event sent to userspace subscribers to notify them about
25/// binder transaction failures. The generated report provides the full
26/// details of the specific transaction that failed. The intention is for
27/// programs to monitor these events and react to the failures as needed.
28pub struct Report {
29 skb: GenlMsg,
30}
31
32impl Report {
33 /// Create a new multicast message.
34 pub fn new(
35 size: usize,
36 portid: u32,
37 seq: u32,
38 flags: kernel::alloc::Flags,
39 ) -> Result<Self, kernel::alloc::AllocError> {
40 const BINDER_CMD_REPORT: u8 = kernel::uapi::BINDER_CMD_REPORT as u8;
41 let skb = NetlinkSkBuff::new(size, flags)?;
42 let skb = skb.genlmsg_put(portid, seq, &BINDER_NL_FAMILY, BINDER_CMD_REPORT)?;
43 Ok(Self { skb })
44 }
45
46 /// Broadcast this message.
47 pub fn multicast(self, portid: u32, flags: kernel::alloc::Flags) -> Result {
48 self.skb.multicast(&BINDER_NL_FAMILY, portid, 0, flags)
49 }
50
51 /// Check if this message type has listeners.
52 pub fn has_listeners() -> bool {
53 BINDER_NL_FAMILY.has_listeners(0)
54 }
55
56 /// The enum binder_driver_return_protocol returned to the sender.
57 pub fn error(&mut self, val: u32) -> Result {
58 const BINDER_A_REPORT_ERROR: c_int = kernel::uapi::BINDER_A_REPORT_ERROR as c_int;
59 self.skb.put_u32(BINDER_A_REPORT_ERROR, val)
60 }
61
62 /// The binder context where the transaction occurred.
63 pub fn context(&mut self, val: &CStr) -> Result {
64 const BINDER_A_REPORT_CONTEXT: c_int = kernel::uapi::BINDER_A_REPORT_CONTEXT as c_int;
65 self.skb.put_string(BINDER_A_REPORT_CONTEXT, val)
66 }
67
68 /// The PID of the sender process.
69 pub fn from_pid(&mut self, val: u32) -> Result {
70 const BINDER_A_REPORT_FROM_PID: c_int = kernel::uapi::BINDER_A_REPORT_FROM_PID as c_int;
71 self.skb.put_u32(BINDER_A_REPORT_FROM_PID, val)
72 }
73
74 /// The TID of the sender thread.
75 pub fn from_tid(&mut self, val: u32) -> Result {
76 const BINDER_A_REPORT_FROM_TID: c_int = kernel::uapi::BINDER_A_REPORT_FROM_TID as c_int;
77 self.skb.put_u32(BINDER_A_REPORT_FROM_TID, val)
78 }
79
80 /// The PID of the recipient process. This attribute may not be present
81 /// if the target could not be determined.
82 pub fn to_pid(&mut self, val: u32) -> Result {
83 const BINDER_A_REPORT_TO_PID: c_int = kernel::uapi::BINDER_A_REPORT_TO_PID as c_int;
84 self.skb.put_u32(BINDER_A_REPORT_TO_PID, val)
85 }
86
87 /// The TID of the recipient thread. This attribute may not be present
88 /// if the target could not be determined.
89 pub fn to_tid(&mut self, val: u32) -> Result {
90 const BINDER_A_REPORT_TO_TID: c_int = kernel::uapi::BINDER_A_REPORT_TO_TID as c_int;
91 self.skb.put_u32(BINDER_A_REPORT_TO_TID, val)
92 }
93
94 /// When present, indicates the failed transaction is a reply.
95 pub fn is_reply(&mut self) -> Result {
96 const BINDER_A_REPORT_IS_REPLY: c_int = kernel::uapi::BINDER_A_REPORT_IS_REPLY as c_int;
97 self.skb.put_flag(BINDER_A_REPORT_IS_REPLY)
98 }
99
100 /// The bitmask of enum transaction_flags from the transaction.
101 pub fn flags(&mut self, val: u32) -> Result {
102 const BINDER_A_REPORT_FLAGS: c_int = kernel::uapi::BINDER_A_REPORT_FLAGS as c_int;
103 self.skb.put_u32(BINDER_A_REPORT_FLAGS, val)
104 }
105
106 /// The application-defined code from the transaction.
107 pub fn code(&mut self, val: u32) -> Result {
108 const BINDER_A_REPORT_CODE: c_int = kernel::uapi::BINDER_A_REPORT_CODE as c_int;
109 self.skb.put_u32(BINDER_A_REPORT_CODE, val)
110 }
111
112 /// The transaction payload size in bytes.
113 pub fn data_size(&mut self, val: u32) -> Result {
114 const BINDER_A_REPORT_DATA_SIZE: c_int = kernel::uapi::BINDER_A_REPORT_DATA_SIZE as c_int;
115 self.skb.put_u32(BINDER_A_REPORT_DATA_SIZE, val)
116 }
117}