summaryrefslogtreecommitdiff
path: root/drivers/android/binder/transaction.rs
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/android/binder/transaction.rs')
-rw-r--r--drivers/android/binder/transaction.rs96
1 files changed, 58 insertions, 38 deletions
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 50bd1cee0f1a..b5434a2ae819 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -8,7 +8,7 @@ use kernel::{
seq_file::SeqFile,
seq_print,
sync::{Arc, SpinLock},
- task::Kuid,
+ task::{Kuid, Pid},
time::{Instant, Monotonic},
types::ScopeGuard,
};
@@ -24,6 +24,34 @@ use crate::{
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
};
+#[derive(Zeroable)]
+pub(crate) struct TransactionInfo {
+ pub(crate) from_pid: Pid,
+ pub(crate) from_tid: Pid,
+ pub(crate) to_pid: Pid,
+ pub(crate) to_tid: Pid,
+ pub(crate) code: u32,
+ pub(crate) flags: u32,
+ pub(crate) data_ptr: UserPtr,
+ pub(crate) data_size: usize,
+ pub(crate) offsets_ptr: UserPtr,
+ pub(crate) offsets_size: usize,
+ pub(crate) buffers_size: usize,
+ pub(crate) target_handle: u32,
+ pub(crate) errno: i32,
+ pub(crate) reply: u32,
+ pub(crate) oneway_spam_suspect: bool,
+ pub(crate) is_reply: bool,
+ pub(crate) debug_id: usize,
+}
+
+impl TransactionInfo {
+ #[inline]
+ pub(crate) fn is_oneway(&self) -> bool {
+ self.flags & TF_ONE_WAY != 0
+ }
+}
+
#[pin_data(PinnedDrop)]
pub(crate) struct Transaction {
pub(crate) debug_id: usize,
@@ -41,7 +69,6 @@ pub(crate) struct Transaction {
data_address: usize,
sender_euid: Kuid,
txn_security_ctx_off: Option<usize>,
- pub(crate) oneway_spam_detected: bool,
start_time: Instant<Monotonic>,
}
@@ -54,18 +81,16 @@ impl Transaction {
node_ref: NodeRef,
from_parent: Option<DArc<Transaction>>,
from: &Arc<Thread>,
- tr: &BinderTransactionDataSg,
+ info: &mut TransactionInfo,
) -> BinderResult<DLArc<Self>> {
- let debug_id = super::next_debug_id();
- let trd = &tr.transaction_data;
let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
let to = node_ref.node.owner.clone();
let mut alloc = match from.copy_transaction_data(
to.clone(),
- tr,
- debug_id,
+ info,
+ info.debug_id,
allow_fds,
txn_security_ctx_off.as_mut(),
) {
@@ -77,15 +102,14 @@ impl Transaction {
return Err(err);
}
};
- let oneway_spam_detected = alloc.oneway_spam_detected;
- if trd.flags & TF_ONE_WAY != 0 {
+ if info.is_oneway() {
if from_parent.is_some() {
pr_warn!("Oneway transaction should not be in a transaction stack.");
return Err(EINVAL.into());
}
alloc.set_info_oneway_node(node_ref.node.clone());
}
- if trd.flags & TF_CLEAR_BUF != 0 {
+ if info.flags & TF_CLEAR_BUF != 0 {
alloc.set_info_clear_on_drop();
}
let target_node = node_ref.node.clone();
@@ -93,21 +117,20 @@ impl Transaction {
let data_address = alloc.ptr;
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
- debug_id,
+ debug_id: info.debug_id,
target_node: Some(target_node),
from_parent,
sender_euid: from.process.task.euid(),
from: from.clone(),
to,
- code: trd.code,
- flags: trd.flags,
- data_size: trd.data_size as _,
- offsets_size: trd.offsets_size as _,
+ code: info.code,
+ flags: info.flags,
+ data_size: info.data_size,
+ offsets_size: info.offsets_size,
data_address,
allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"),
is_outstanding: AtomicBool::new(false),
txn_security_ctx_off,
- oneway_spam_detected,
start_time: Instant::now(),
}))?)
}
@@ -115,39 +138,35 @@ impl Transaction {
pub(crate) fn new_reply(
from: &Arc<Thread>,
to: Arc<Process>,
- tr: &BinderTransactionDataSg,
+ info: &mut TransactionInfo,
allow_fds: bool,
) -> BinderResult<DLArc<Self>> {
- let debug_id = super::next_debug_id();
- let trd = &tr.transaction_data;
- let mut alloc = match from.copy_transaction_data(to.clone(), tr, debug_id, allow_fds, None)
- {
- Ok(alloc) => alloc,
- Err(err) => {
- pr_warn!("Failure in copy_transaction_data: {:?}", err);
- return Err(err);
- }
- };
- let oneway_spam_detected = alloc.oneway_spam_detected;
- if trd.flags & TF_CLEAR_BUF != 0 {
+ let mut alloc =
+ match from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None) {
+ Ok(alloc) => alloc,
+ Err(err) => {
+ pr_warn!("Failure in copy_transaction_data: {:?}", err);
+ return Err(err);
+ }
+ };
+ if info.flags & TF_CLEAR_BUF != 0 {
alloc.set_info_clear_on_drop();
}
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
- debug_id,
+ debug_id: info.debug_id,
target_node: None,
from_parent: None,
sender_euid: from.process.task.euid(),
from: from.clone(),
to,
- code: trd.code,
- flags: trd.flags,
- data_size: trd.data_size as _,
- offsets_size: trd.offsets_size as _,
+ code: info.code,
+ flags: info.flags,
+ data_size: info.data_size,
+ offsets_size: info.offsets_size,
data_address: alloc.ptr,
allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"),
is_outstanding: AtomicBool::new(false),
txn_security_ctx_off: None,
- oneway_spam_detected,
start_time: Instant::now(),
}))?)
}
@@ -237,7 +256,7 @@ impl Transaction {
/// stack, otherwise uses the destination process.
///
/// Not used for replies.
- pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
+ pub(crate) fn submit(self: DLArc<Self>, info: &mut TransactionInfo) -> BinderResult {
// Defined before `process_inner` so that the destructor runs after releasing the lock.
let _t_outdated;
let _oneway_node;
@@ -295,6 +314,7 @@ impl Transaction {
}
let res = if let Some(thread) = self.find_target_thread() {
+ info.to_tid = thread.id;
match thread.push_work(self) {
PushWorkRes::Ok => Ok(()),
PushWorkRes::FailedDead(me) => Err((BinderError::new_dead(), me)),
@@ -359,7 +379,7 @@ impl DeliverToRead for Transaction {
let send_failed_reply = ScopeGuard::new(|| {
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
let reply = Err(BR_FAILED_REPLY);
- self.from.deliver_reply(reply, &self);
+ self.from.deliver_reply(reply, &self, None);
}
self.drop_outstanding_txn();
});
@@ -441,7 +461,7 @@ impl DeliverToRead for Transaction {
// If this is not a reply or oneway transaction, then send a dead reply.
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
let reply = Err(BR_DEAD_REPLY);
- self.from.deliver_reply(reply, &self);
+ self.from.deliver_reply(reply, &self, None);
}
self.drop_outstanding_txn();