Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust_binder: introduce TransactionInfo

Rust Binder exposes information about transactions that are sent in
various ways: printing to the kernel log, tracepoints, files in
binderfs, and the upcoming netlink support. Currently all these
mechanisms use disparate ways of obtaining the same information, so
let's introduce a single Info struct that collects all the required
information in a single place, so that all of these different mechanisms
can operate in a more uniform way.

For now, the new info struct is only used to replace a few things:
* The BinderTransactionDataSg struct that is passed as an argument to
several methods is removed as the information is moved into the new
info struct and passed down that way.
* The oneway spam detection fields on Transaction and Allocation can be
removed, as the information can be returned to the caller via the
mutable info struct instead.
But several other uses of the info struct are planned in follow-up
patches.

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20260306-transaction-info-v1-1-fda58fca558b@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alice Ryhl and committed by
Greg Kroah-Hartman
5326a18e a8a37957

+168 -135
-3
drivers/android/binder/allocation.rs
··· 56 56 pub(crate) process: Arc<Process>, 57 57 allocation_info: Option<AllocationInfo>, 58 58 free_on_drop: bool, 59 - pub(crate) oneway_spam_detected: bool, 60 59 #[allow(dead_code)] 61 60 pub(crate) debug_id: usize, 62 61 } ··· 67 68 offset: usize, 68 69 size: usize, 69 70 ptr: usize, 70 - oneway_spam_detected: bool, 71 71 ) -> Self { 72 72 Self { 73 73 process, ··· 74 76 size, 75 77 ptr, 76 78 debug_id, 77 - oneway_spam_detected, 78 79 allocation_info: None, 79 80 free_on_drop: true, 80 81 }
+1 -9
drivers/android/binder/error.rs
··· 13 13 /// errno. 14 14 pub(crate) struct BinderError { 15 15 pub(crate) reply: u32, 16 - source: Option<Error>, 16 + pub(crate) source: Option<Error>, 17 17 } 18 18 19 19 impl BinderError { ··· 40 40 41 41 pub(crate) fn is_dead(&self) -> bool { 42 42 self.reply == BR_DEAD_REPLY 43 - } 44 - 45 - pub(crate) fn as_errno(&self) -> kernel::ffi::c_int { 46 - self.source.unwrap_or(EINVAL).to_errno() 47 - } 48 - 49 - pub(crate) fn should_pr_warn(&self) -> bool { 50 - self.source.is_some() 51 43 } 52 44 } 53 45
+7 -8
drivers/android/binder/process.rs
··· 48 48 range_alloc::{RangeAllocator, ReserveNew, ReserveNewArgs}, 49 49 stats::BinderStats, 50 50 thread::{PushWorkRes, Thread}, 51 + transaction::TransactionInfo, 51 52 BinderfsProcFile, DArc, DLArc, DTRWrap, DeliverToRead, 52 53 }; 53 54 ··· 1004 1003 self: &Arc<Self>, 1005 1004 debug_id: usize, 1006 1005 size: usize, 1007 - is_oneway: bool, 1008 - from_pid: i32, 1006 + info: &mut TransactionInfo, 1009 1007 ) -> BinderResult<NewAllocation> { 1010 1008 use kernel::page::PAGE_SIZE; 1011 1009 1012 1010 let mut reserve_new_args = ReserveNewArgs { 1013 1011 debug_id, 1014 1012 size, 1015 - is_oneway, 1016 - pid: from_pid, 1013 + is_oneway: info.is_oneway(), 1014 + pid: info.from_pid, 1017 1015 ..ReserveNewArgs::default() 1018 1016 }; 1019 1017 ··· 1028 1028 reserve_new_args = alloc_request.make_alloc()?; 1029 1029 }; 1030 1030 1031 + info.oneway_spam_suspect = new_alloc.oneway_spam_detected; 1031 1032 let res = Allocation::new( 1032 1033 self.clone(), 1033 1034 debug_id, 1034 1035 new_alloc.offset, 1035 1036 size, 1036 1037 addr + new_alloc.offset, 1037 - new_alloc.oneway_spam_detected, 1038 1038 ); 1039 1039 1040 1040 // This allocation will be marked as in use until the `Allocation` is used to free it. ··· 1066 1066 let mapping = inner.mapping.as_mut()?; 1067 1067 let offset = ptr.checked_sub(mapping.address)?; 1068 1068 let (size, debug_id, odata) = mapping.alloc.reserve_existing(offset).ok()?; 1069 - let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr, false); 1069 + let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr); 1070 1070 if let Some(data) = odata { 1071 1071 alloc.set_info(data); 1072 1072 } ··· 1414 1414 .alloc 1415 1415 .take_for_each(|offset, size, debug_id, odata| { 1416 1416 let ptr = offset + address; 1417 - let mut alloc = 1418 - Allocation::new(self.clone(), debug_id, offset, size, ptr, false); 1417 + let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr); 1419 1418 if let Some(data) = odata { 1420 1419 alloc.set_info(data); 1421 1420 }
+107 -83
drivers/android/binder/thread.rs
··· 19 19 sync::poll::{PollCondVar, PollTable}, 20 20 sync::{aref::ARef, Arc, SpinLock}, 21 21 task::Task, 22 - uaccess::UserSlice, 22 + uaccess::{UserPtr, UserSlice, UserSliceReader}, 23 23 uapi, 24 24 }; 25 25 ··· 30 30 process::{GetWorkOrRegister, Process}, 31 31 ptr_align, 32 32 stats::GLOBAL_STATS, 33 - transaction::Transaction, 33 + transaction::{Transaction, TransactionInfo}, 34 34 BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverCode, DeliverToRead, 35 35 }; 36 36 ··· 951 951 pub(crate) fn copy_transaction_data( 952 952 &self, 953 953 to_process: Arc<Process>, 954 - tr: &BinderTransactionDataSg, 954 + info: &mut TransactionInfo, 955 955 debug_id: usize, 956 956 allow_fds: bool, 957 957 txn_security_ctx_offset: Option<&mut usize>, 958 958 ) -> BinderResult<NewAllocation> { 959 - let trd = &tr.transaction_data; 960 - let is_oneway = trd.flags & TF_ONE_WAY != 0; 961 959 let mut secctx = if let Some(offset) = txn_security_ctx_offset { 962 960 let secid = self.process.cred.get_secid(); 963 961 let ctx = match security::SecurityCtx::from_secid(secid) { ··· 970 972 None 971 973 }; 972 974 973 - let data_size = trd.data_size.try_into().map_err(|_| EINVAL)?; 975 + let data_size = info.data_size; 974 976 let aligned_data_size = ptr_align(data_size).ok_or(EINVAL)?; 975 - let offsets_size: usize = trd.offsets_size.try_into().map_err(|_| EINVAL)?; 976 - let buffers_size: usize = tr.buffers_size.try_into().map_err(|_| EINVAL)?; 977 + let offsets_size = info.offsets_size; 978 + let buffers_size = info.buffers_size; 977 979 let aligned_secctx_size = match secctx.as_ref() { 978 980 Some((_offset, ctx)) => ptr_align(ctx.len()).ok_or(EINVAL)?, 979 981 None => 0, ··· 996 998 size_of::<u64>(), 997 999 ); 998 1000 let secctx_off = aligned_data_size + offsets_size + buffers_size; 999 - let mut alloc = 1000 - match to_process.buffer_alloc(debug_id, len, is_oneway, self.process.task.pid()) { 1001 - Ok(alloc) => alloc, 1002 - Err(err) => { 1003 - pr_warn!( 1004 - "Failed to allocate buffer. len:{}, is_oneway:{}", 1005 - len, 1006 - is_oneway 1007 - ); 1008 - return Err(err); 1009 - } 1010 - }; 1001 + let mut alloc = match to_process.buffer_alloc(debug_id, len, info) { 1002 + Ok(alloc) => alloc, 1003 + Err(err) => { 1004 + pr_warn!( 1005 + "Failed to allocate buffer. len:{}, is_oneway:{}", 1006 + len, 1007 + info.is_oneway(), 1008 + ); 1009 + return Err(err); 1010 + } 1011 + }; 1011 1012 1012 - // SAFETY: This accesses a union field, but it's okay because the field's type is valid for 1013 - // all bit-patterns. 1014 - let trd_data_ptr = unsafe { &trd.data.ptr }; 1015 - let mut buffer_reader = 1016 - UserSlice::new(UserPtr::from_addr(trd_data_ptr.buffer as _), data_size).reader(); 1013 + let mut buffer_reader = UserSlice::new(info.data_ptr, data_size).reader(); 1017 1014 let mut end_of_previous_object = 0; 1018 1015 let mut sg_state = None; 1019 1016 1020 1017 // Copy offsets if there are any. 1021 1018 if offsets_size > 0 { 1022 - let mut offsets_reader = 1023 - UserSlice::new(UserPtr::from_addr(trd_data_ptr.offsets as _), offsets_size) 1024 - .reader(); 1019 + let mut offsets_reader = UserSlice::new(info.offsets_ptr, offsets_size).reader(); 1025 1020 1026 1021 let offsets_start = aligned_data_size; 1027 1022 let offsets_end = aligned_data_size + offsets_size; ··· 1189 1198 } 1190 1199 } 1191 1200 1192 - fn transaction<T>(self: &Arc<Self>, tr: &BinderTransactionDataSg, inner: T) 1193 - where 1194 - T: FnOnce(&Arc<Self>, &BinderTransactionDataSg) -> BinderResult, 1195 - { 1196 - if let Err(err) = inner(self, tr) { 1197 - if err.should_pr_warn() { 1198 - let mut ee = self.inner.lock().extended_error; 1199 - ee.command = err.reply; 1200 - ee.param = err.as_errno(); 1201 - pr_warn!( 1202 - "Transaction failed: {:?} my_pid:{}", 1203 - err, 1204 - self.process.pid_in_current_ns() 1205 - ); 1201 + // No inlining avoids allocating stack space for `BinderTransactionData` for the entire 1202 + // duration of `transaction()`. 1203 + #[inline(never)] 1204 + fn read_transaction_info( 1205 + &self, 1206 + cmd: u32, 1207 + reader: &mut UserSliceReader, 1208 + info: &mut TransactionInfo, 1209 + ) -> Result<()> { 1210 + let td = match cmd { 1211 + BC_TRANSACTION | BC_REPLY => { 1212 + reader.read::<BinderTransactionData>()?.with_buffers_size(0) 1213 + } 1214 + BC_TRANSACTION_SG | BC_REPLY_SG => reader.read::<BinderTransactionDataSg>()?, 1215 + _ => return Err(EINVAL), 1216 + }; 1217 + 1218 + // SAFETY: Above `read` call initializes all bytes, so this union read is ok. 1219 + let trd_data_ptr = unsafe { &td.transaction_data.data.ptr }; 1220 + 1221 + info.is_reply = matches!(cmd, BC_REPLY | BC_REPLY_SG); 1222 + info.from_pid = self.process.task.pid(); 1223 + info.from_tid = self.id; 1224 + info.code = td.transaction_data.code; 1225 + info.flags = td.transaction_data.flags; 1226 + info.data_ptr = UserPtr::from_addr(trd_data_ptr.buffer as usize); 1227 + info.data_size = td.transaction_data.data_size as usize; 1228 + info.offsets_ptr = UserPtr::from_addr(trd_data_ptr.offsets as usize); 1229 + info.offsets_size = td.transaction_data.offsets_size as usize; 1230 + info.buffers_size = td.buffers_size as usize; 1231 + // SAFETY: Above `read` call initializes all bytes, so this union read is ok. 1232 + info.target_handle = unsafe { td.transaction_data.target.handle }; 1233 + Ok(()) 1234 + } 1235 + 1236 + #[inline(never)] 1237 + fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Result<()> { 1238 + let mut info = TransactionInfo::zeroed(); 1239 + self.read_transaction_info(cmd, reader, &mut info)?; 1240 + 1241 + let ret = if info.is_reply { 1242 + self.reply_inner(&mut info) 1243 + } else if info.is_oneway() { 1244 + self.oneway_transaction_inner(&mut info) 1245 + } else { 1246 + self.transaction_inner(&mut info) 1247 + }; 1248 + 1249 + if let Err(err) = ret { 1250 + if err.reply != BR_TRANSACTION_COMPLETE { 1251 + info.reply = err.reply; 1206 1252 } 1207 1253 1208 1254 self.push_return_work(err.reply); 1255 + if let Some(source) = &err.source { 1256 + info.errno = source.to_errno(); 1257 + info.reply = err.reply; 1258 + 1259 + { 1260 + let mut ee = self.inner.lock().extended_error; 1261 + ee.command = err.reply; 1262 + ee.param = source.to_errno(); 1263 + } 1264 + 1265 + pr_warn!( 1266 + "{}:{} transaction to {} failed: {source:?}", 1267 + info.from_pid, 1268 + info.from_tid, 1269 + info.to_pid 1270 + ); 1271 + } 1209 1272 } 1273 + 1274 + Ok(()) 1210 1275 } 1211 1276 1212 - fn transaction_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult { 1213 - // SAFETY: Handle's type has no invalid bit patterns. 1214 - let handle = unsafe { tr.transaction_data.target.handle }; 1215 - let node_ref = self.process.get_transaction_node(handle)?; 1277 + fn transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult { 1278 + let node_ref = self.process.get_transaction_node(info.target_handle)?; 1279 + info.to_pid = node_ref.node.owner.task.pid(); 1216 1280 security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?; 1217 1281 // TODO: We need to ensure that there isn't a pending transaction in the work queue. How 1218 1282 // could this happen? 1219 1283 let top = self.top_of_transaction_stack()?; 1220 1284 let list_completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?; 1221 1285 let completion = list_completion.clone_arc(); 1222 - let transaction = Transaction::new(node_ref, top, self, tr)?; 1286 + let transaction = Transaction::new(node_ref, top, self, info)?; 1223 1287 1224 1288 // Check that the transaction stack hasn't changed while the lock was released, then update 1225 1289 // it with the new transaction. ··· 1290 1244 inner.push_work_deferred(list_completion); 1291 1245 } 1292 1246 1293 - if let Err(e) = transaction.submit() { 1247 + if let Err(e) = transaction.submit(info) { 1294 1248 completion.skip(); 1295 1249 // Define `transaction` first to drop it after `inner`. 1296 1250 let transaction; ··· 1303 1257 } 1304 1258 } 1305 1259 1306 - fn reply_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult { 1260 + fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult { 1307 1261 let orig = self.inner.lock().pop_transaction_to_reply(self)?; 1308 1262 if !orig.from.is_current_transaction(&orig) { 1309 1263 return Err(EINVAL.into()); 1310 1264 } 1265 + 1266 + info.to_tid = orig.from.id; 1267 + info.to_pid = orig.from.process.task.pid(); 1311 1268 1312 1269 // We need to complete the transaction even if we cannot complete building the reply. 1313 1270 let out = (|| -> BinderResult<_> { 1314 1271 let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?; 1315 1272 let process = orig.from.process.clone(); 1316 1273 let allow_fds = orig.flags & TF_ACCEPT_FDS != 0; 1317 - let reply = Transaction::new_reply(self, process, tr, allow_fds)?; 1274 + let reply = Transaction::new_reply(self, process, info, allow_fds)?; 1318 1275 self.inner.lock().push_work(completion); 1319 1276 orig.from.deliver_reply(Ok(reply), &orig); 1320 1277 Ok(()) ··· 1338 1289 out 1339 1290 } 1340 1291 1341 - fn oneway_transaction_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult { 1342 - // SAFETY: The `handle` field is valid for all possible byte values, so reading from the 1343 - // union is okay. 1344 - let handle = unsafe { tr.transaction_data.target.handle }; 1345 - let node_ref = self.process.get_transaction_node(handle)?; 1292 + fn oneway_transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult { 1293 + let node_ref = self.process.get_transaction_node(info.target_handle)?; 1294 + info.to_pid = node_ref.node.owner.task.pid(); 1346 1295 security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?; 1347 - let transaction = Transaction::new(node_ref, None, self, tr)?; 1348 - let code = if self.process.is_oneway_spam_detection_enabled() 1349 - && transaction.oneway_spam_detected 1350 - { 1296 + let transaction = Transaction::new(node_ref, None, self, info)?; 1297 + let code = if self.process.is_oneway_spam_detection_enabled() && info.oneway_spam_suspect { 1351 1298 BR_ONEWAY_SPAM_SUSPECT 1352 1299 } else { 1353 1300 BR_TRANSACTION_COMPLETE ··· 1351 1306 let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code))?; 1352 1307 let completion = list_completion.clone_arc(); 1353 1308 self.inner.lock().push_work(list_completion); 1354 - match transaction.submit() { 1309 + match transaction.submit(info) { 1355 1310 Ok(()) => Ok(()), 1356 1311 Err(err) => { 1357 1312 completion.skip(); ··· 1372 1327 GLOBAL_STATS.inc_bc(cmd); 1373 1328 self.process.stats.inc_bc(cmd); 1374 1329 match cmd { 1375 - BC_TRANSACTION => { 1376 - let tr = reader.read::<BinderTransactionData>()?.with_buffers_size(0); 1377 - if tr.transaction_data.flags & TF_ONE_WAY != 0 { 1378 - self.transaction(&tr, Self::oneway_transaction_inner); 1379 - } else { 1380 - self.transaction(&tr, Self::transaction_inner); 1381 - } 1382 - } 1383 - BC_TRANSACTION_SG => { 1384 - let tr = reader.read::<BinderTransactionDataSg>()?; 1385 - if tr.transaction_data.flags & TF_ONE_WAY != 0 { 1386 - self.transaction(&tr, Self::oneway_transaction_inner); 1387 - } else { 1388 - self.transaction(&tr, Self::transaction_inner); 1389 - } 1390 - } 1391 - BC_REPLY => { 1392 - let tr = reader.read::<BinderTransactionData>()?.with_buffers_size(0); 1393 - self.transaction(&tr, Self::reply_inner) 1394 - } 1395 - BC_REPLY_SG => { 1396 - let tr = reader.read::<BinderTransactionDataSg>()?; 1397 - self.transaction(&tr, Self::reply_inner) 1330 + BC_TRANSACTION | BC_TRANSACTION_SG | BC_REPLY | BC_REPLY_SG => { 1331 + self.transaction(cmd, &mut reader)?; 1398 1332 } 1399 1333 BC_FREE_BUFFER => { 1400 1334 let buffer = self.process.buffer_get(reader.read()?);
+52 -31
drivers/android/binder/transaction.rs
··· 8 8 seq_print, 9 9 sync::atomic::{ordering::Relaxed, Atomic}, 10 10 sync::{Arc, SpinLock}, 11 - task::Kuid, 11 + task::{Kuid, Pid}, 12 12 time::{Instant, Monotonic}, 13 13 types::ScopeGuard, 14 14 }; ··· 23 23 thread::{PushWorkRes, Thread}, 24 24 BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead, 25 25 }; 26 + 27 + #[derive(Zeroable)] 28 + pub(crate) struct TransactionInfo { 29 + pub(crate) from_pid: Pid, 30 + pub(crate) from_tid: Pid, 31 + pub(crate) to_pid: Pid, 32 + pub(crate) to_tid: Pid, 33 + pub(crate) code: u32, 34 + pub(crate) flags: u32, 35 + pub(crate) data_ptr: UserPtr, 36 + pub(crate) data_size: usize, 37 + pub(crate) offsets_ptr: UserPtr, 38 + pub(crate) offsets_size: usize, 39 + pub(crate) buffers_size: usize, 40 + pub(crate) target_handle: u32, 41 + pub(crate) errno: i32, 42 + pub(crate) reply: u32, 43 + pub(crate) oneway_spam_suspect: bool, 44 + pub(crate) is_reply: bool, 45 + } 46 + 47 + impl TransactionInfo { 48 + #[inline] 49 + pub(crate) fn is_oneway(&self) -> bool { 50 + self.flags & TF_ONE_WAY != 0 51 + } 52 + } 26 53 27 54 use core::mem::offset_of; 28 55 use kernel::bindings::rb_transaction_layout; ··· 79 52 data_address: usize, 80 53 sender_euid: Kuid, 81 54 txn_security_ctx_off: Option<usize>, 82 - pub(crate) oneway_spam_detected: bool, 83 55 start_time: Instant<Monotonic>, 84 56 } 85 57 ··· 91 65 node_ref: NodeRef, 92 66 from_parent: Option<DArc<Transaction>>, 93 67 from: &Arc<Thread>, 94 - tr: &BinderTransactionDataSg, 68 + info: &mut TransactionInfo, 95 69 ) -> BinderResult<DLArc<Self>> { 96 70 let debug_id = super::next_debug_id(); 97 - let trd = &tr.transaction_data; 98 71 let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0; 99 72 let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0; 100 73 let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None }; 101 74 let to = node_ref.node.owner.clone(); 102 75 let mut alloc = match from.copy_transaction_data( 103 76 to.clone(), 104 - tr, 77 + info, 105 78 debug_id, 106 79 allow_fds, 107 80 txn_security_ctx_off.as_mut(), ··· 113 88 return Err(err); 114 89 } 115 90 }; 116 - let oneway_spam_detected = alloc.oneway_spam_detected; 117 - if trd.flags & TF_ONE_WAY != 0 { 91 + if info.is_oneway() { 118 92 if from_parent.is_some() { 119 93 pr_warn!("Oneway transaction should not be in a transaction stack."); 120 94 return Err(EINVAL.into()); 121 95 } 122 96 alloc.set_info_oneway_node(node_ref.node.clone()); 123 97 } 124 - if trd.flags & TF_CLEAR_BUF != 0 { 98 + if info.flags & TF_CLEAR_BUF != 0 { 125 99 alloc.set_info_clear_on_drop(); 126 100 } 127 101 let target_node = node_ref.node.clone(); ··· 134 110 sender_euid: Kuid::current_euid(), 135 111 from: from.clone(), 136 112 to, 137 - code: trd.code, 138 - flags: trd.flags, 139 - data_size: trd.data_size as _, 140 - offsets_size: trd.offsets_size as _, 113 + code: info.code, 114 + flags: info.flags, 115 + data_size: info.data_size, 116 + offsets_size: info.offsets_size, 141 117 data_address, 142 118 allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"), 143 119 is_outstanding: Atomic::new(false), 144 120 txn_security_ctx_off, 145 - oneway_spam_detected, 146 121 start_time: Instant::now(), 147 122 }))?) 148 123 } ··· 149 126 pub(crate) fn new_reply( 150 127 from: &Arc<Thread>, 151 128 to: Arc<Process>, 152 - tr: &BinderTransactionDataSg, 129 + info: &mut TransactionInfo, 153 130 allow_fds: bool, 154 131 ) -> BinderResult<DLArc<Self>> { 155 132 let debug_id = super::next_debug_id(); 156 - let trd = &tr.transaction_data; 157 - let mut alloc = match from.copy_transaction_data(to.clone(), tr, debug_id, allow_fds, None) 158 - { 159 - Ok(alloc) => alloc, 160 - Err(err) => { 161 - pr_warn!("Failure in copy_transaction_data: {:?}", err); 162 - return Err(err); 163 - } 164 - }; 165 - let oneway_spam_detected = alloc.oneway_spam_detected; 166 - if trd.flags & TF_CLEAR_BUF != 0 { 133 + let mut alloc = 134 + match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) { 135 + Ok(alloc) => alloc, 136 + Err(err) => { 137 + pr_warn!("Failure in copy_transaction_data: {:?}", err); 138 + return Err(err); 139 + } 140 + }; 141 + if info.flags & TF_CLEAR_BUF != 0 { 167 142 alloc.set_info_clear_on_drop(); 168 143 } 169 144 Ok(DTRWrap::arc_pin_init(pin_init!(Transaction { ··· 171 150 sender_euid: Kuid::current_euid(), 172 151 from: from.clone(), 173 152 to, 174 - code: trd.code, 175 - flags: trd.flags, 176 - data_size: trd.data_size as _, 177 - offsets_size: trd.offsets_size as _, 153 + code: info.code, 154 + flags: info.flags, 155 + data_size: info.data_size, 156 + offsets_size: info.offsets_size, 178 157 data_address: alloc.ptr, 179 158 allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"), 180 159 is_outstanding: Atomic::new(false), 181 160 txn_security_ctx_off: None, 182 - oneway_spam_detected, 183 161 start_time: Instant::now(), 184 162 }))?) 185 163 } ··· 268 248 /// stack, otherwise uses the destination process. 269 249 /// 270 250 /// Not used for replies. 271 - pub(crate) fn submit(self: DLArc<Self>) -> BinderResult { 251 + pub(crate) fn submit(self: DLArc<Self>, info: &mut TransactionInfo) -> BinderResult { 272 252 // Defined before `process_inner` so that the destructor runs after releasing the lock. 273 253 let mut _t_outdated; 274 254 ··· 318 298 } 319 299 320 300 let res = if let Some(thread) = self.find_target_thread() { 301 + info.to_tid = thread.id; 321 302 crate::trace::trace_transaction(false, &self, Some(&thread.task)); 322 303 match thread.push_work(self) { 323 304 PushWorkRes::Ok => Ok(()),
+1 -1
rust/kernel/uaccess.rs
··· 19 19 /// 20 20 /// This is the Rust equivalent to C pointers tagged with `__user`. 21 21 #[repr(transparent)] 22 - #[derive(Copy, Clone)] 22 + #[derive(Copy, Clone, Zeroable)] 23 23 pub struct UserPtr(*mut c_void); 24 24 25 25 impl UserPtr {