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)] 5 use kernel::{ 6 net::netlink::{ 7 Family, 8 GenlMsg, 9 MulticastGroup, 10 NetlinkSkBuff, // 11 }, 12 prelude::*, // 13 }; 14 15 pub static BINDER_NL_FAMILY: Family = Family::const_new( 16 &crate::THIS_MODULE, 17 kernel::uapi::BINDER_FAMILY_NAME, 18 kernel::uapi::BINDER_FAMILY_VERSION, 19 &BINDER_NL_FAMILY_MCGRPS, 20 ); 21 22 static 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. 28 pub struct Report { 29 skb: GenlMsg, 30 } 31 32 impl 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 } 118