diff options
| author | Jani Nikula <jani.nikula@intel.com> | 2026-02-25 13:23:04 +0200 |
|---|---|---|
| committer | Jani Nikula <jani.nikula@intel.com> | 2026-02-25 13:23:04 +0200 |
| commit | f09812b85fa6f41058bcc46e70ac406bf9b0493a (patch) | |
| tree | 3c9b679b33a85434ea937b6e74d3be3b6f9629ff /drivers/android | |
| parent | 24e2e6581d602f75174010b32bf3e96ec39465ab (diff) | |
| parent | 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f (diff) | |
Merge drm/drm-next into drm-intel-next
Sync with v7.0-rc1 which contains a few treewide changes affecting i915.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/android')
| -rw-r--r-- | drivers/android/binder.c | 61 | ||||
| -rw-r--r-- | drivers/android/binder/context.rs | 86 | ||||
| -rw-r--r-- | drivers/android/binder/node.rs | 8 | ||||
| -rw-r--r-- | drivers/android/binder/page_range.rs | 3 | ||||
| -rw-r--r-- | drivers/android/binder/process.rs | 14 | ||||
| -rw-r--r-- | drivers/android/binder/rust_binder.h | 79 | ||||
| -rw-r--r-- | drivers/android/binder/rust_binder_events.h | 30 | ||||
| -rw-r--r-- | drivers/android/binder/rust_binder_main.rs | 32 | ||||
| -rw-r--r-- | drivers/android/binder/rust_binderfs.c | 25 | ||||
| -rw-r--r-- | drivers/android/binder/stats.rs | 8 | ||||
| -rw-r--r-- | drivers/android/binder/thread.rs | 137 | ||||
| -rw-r--r-- | drivers/android/binder/trace.rs | 21 | ||||
| -rw-r--r-- | drivers/android/binder/transaction.rs | 30 | ||||
| -rw-r--r-- | drivers/android/binder_alloc.c | 19 | ||||
| -rw-r--r-- | drivers/android/binderfs.c | 16 |
15 files changed, 374 insertions, 195 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 535fc881c8da..21f91d9f2fbc 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -795,7 +795,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, struct flat_binder_object *fp) { struct binder_node *node; - struct binder_node *new_node = kzalloc(sizeof(*node), GFP_KERNEL); + struct binder_node *new_node = kzalloc_obj(*node); if (!new_node) return NULL; @@ -1469,7 +1469,7 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, ref = binder_get_ref_for_node_olocked(proc, node, NULL); if (!ref) { binder_proc_unlock(proc); - new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); + new_ref = kzalloc_obj(*ref); if (!new_ref) return -ENOMEM; binder_proc_lock(proc); @@ -2009,7 +2009,7 @@ static void binder_deferred_fd_close(int fd) { struct binder_task_work_cb *twcb; - twcb = kzalloc(sizeof(*twcb), GFP_KERNEL); + twcb = kzalloc_obj(*twcb); if (!twcb) return; init_task_work(&twcb->twork, binder_do_fd_close); @@ -2386,7 +2386,7 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset, * of the fd in the target needs to be done from a * target thread. */ - fixup = kzalloc(sizeof(*fixup), GFP_KERNEL); + fixup = kzalloc_obj(*fixup); if (!fixup) { ret = -ENOMEM; goto err_alloc; @@ -2579,7 +2579,7 @@ static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head, static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset, const void __user *sender_uaddr, size_t length) { - struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL); + struct binder_sg_copy *bc = kzalloc_obj(*bc); if (!bc) return -ENOMEM; @@ -2622,7 +2622,7 @@ static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset, static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset, binder_uintptr_t fixup, size_t skip_size) { - struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL); + struct binder_ptr_fixup *pf = kzalloc_obj(*pf); struct binder_ptr_fixup *tmppf; if (!pf) @@ -2991,6 +2991,10 @@ static void binder_set_txn_from_error(struct binder_transaction *t, int id, * @t: the binder transaction that failed * @data_size: the user provided data size for the transaction * @error: enum binder_driver_return_protocol returned to sender + * + * Note that t->buffer is not safe to access here, as it may have been + * released (or not yet allocated). Callers should guarantee all the + * transaction items used here are safe to access. */ static void binder_netlink_report(struct binder_proc *proc, struct binder_transaction *t, @@ -3097,7 +3101,7 @@ static void binder_transaction(struct binder_proc *proc, binder_set_extended_error(&thread->ee, t_debug_id, BR_OK, 0); binder_inner_proc_unlock(proc); - t = kzalloc(sizeof(*t), GFP_KERNEL); + t = kzalloc_obj(*t); if (!t) { binder_txn_error("%d:%d cannot allocate transaction\n", thread->pid, proc->pid); @@ -3316,7 +3320,7 @@ static void binder_transaction(struct binder_proc *proc, e->to_thread = target_thread->pid; e->to_proc = target_proc->pid; - tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); + tcomplete = kzalloc_obj(*tcomplete); if (tcomplete == NULL) { binder_txn_error("%d:%d cannot allocate work for transaction\n", thread->pid, proc->pid); @@ -3780,6 +3784,14 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_proc_or_thread; } } else { + /* + * Make a transaction copy. It is not safe to access 't' after + * binder_proc_transaction() reported a pending frozen. The + * target could thaw and consume the transaction at any point. + * Instead, use a safe 't_copy' for binder_netlink_report(). + */ + struct binder_transaction t_copy = *t; + BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); return_error = binder_proc_transaction(t, target_proc, NULL); @@ -3790,7 +3802,7 @@ static void binder_transaction(struct binder_proc *proc, */ if (return_error == BR_TRANSACTION_PENDING_FROZEN) { tcomplete->type = BINDER_WORK_TRANSACTION_PENDING; - binder_netlink_report(proc, t, tr->data_size, + binder_netlink_report(proc, &t_copy, tr->data_size, return_error); } binder_enqueue_thread_work(thread, tcomplete); @@ -3812,8 +3824,9 @@ static void binder_transaction(struct binder_proc *proc, return; err_dead_proc_or_thread: - binder_txn_error("%d:%d dead process or thread\n", - thread->pid, proc->pid); + binder_txn_error("%d:%d %s process or thread\n", + proc->pid, thread->pid, + return_error == BR_FROZEN_REPLY ? "frozen" : "dead"); return_error_line = __LINE__; binder_dequeue_work(proc, tcomplete); err_translate_failed: @@ -3913,7 +3926,7 @@ binder_request_freeze_notification(struct binder_proc *proc, struct binder_ref_freeze *freeze; struct binder_ref *ref; - freeze = kzalloc(sizeof(*freeze), GFP_KERNEL); + freeze = kzalloc_obj(*freeze); if (!freeze) return -ENOMEM; binder_proc_lock(proc); @@ -4381,7 +4394,7 @@ static int binder_thread_write(struct binder_proc *proc, * Allocate memory for death notification * before taking lock */ - death = kzalloc(sizeof(*death), GFP_KERNEL); + death = kzalloc_obj(*death); if (death == NULL) { WARN_ON(thread->return_error.cmd != BR_OK); @@ -4510,7 +4523,7 @@ static int binder_thread_write(struct binder_proc *proc, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", + "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", proc->pid, thread->pid, (u64)cookie, death); if (death == NULL) { @@ -5280,7 +5293,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) thread = binder_get_thread_ilocked(proc, NULL); binder_inner_proc_unlock(proc); if (!thread) { - new_thread = kzalloc(sizeof(*thread), GFP_KERNEL); + new_thread = kzalloc_obj(*thread); if (new_thread == NULL) return NULL; binder_inner_proc_lock(proc); @@ -5889,9 +5902,8 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } - target_procs = kcalloc(target_procs_count, - sizeof(struct binder_proc *), - GFP_KERNEL); + target_procs = kzalloc_objs(struct binder_proc *, + target_procs_count); if (!target_procs) { mutex_unlock(&binder_procs_lock); @@ -6015,7 +6027,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) { struct binder_proc *proc = filp->private_data; - if (proc->tsk != current->group_leader) + if (!same_thread_group(proc->tsk, current)) return -EINVAL; binder_debug(BINDER_DEBUG_OPEN_CLOSE, @@ -6046,17 +6058,17 @@ static int binder_open(struct inode *nodp, struct file *filp) bool existing_pid = false; binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, - current->group_leader->pid, current->pid); + current->tgid, current->pid); - proc = kzalloc(sizeof(*proc), GFP_KERNEL); + proc = kzalloc_obj(*proc); if (proc == NULL) return -ENOMEM; dbitmap_init(&proc->dmap); spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); - get_task_struct(current->group_leader); - proc->tsk = current->group_leader; + proc->tsk = get_task_struct(current->group_leader); + proc->pid = current->tgid; proc->cred = get_cred(filp->f_cred); INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->freeze_wait); @@ -6075,7 +6087,6 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_alloc_init(&proc->alloc); binder_stats_created(BINDER_STAT_PROC); - proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); INIT_LIST_HEAD(&proc->delivered_freeze); INIT_LIST_HEAD(&proc->waiting_threads); @@ -7053,7 +7064,7 @@ static int __init init_binder_device(const char *name) int ret; struct binder_device *binder_device; - binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL); + binder_device = kzalloc_obj(*binder_device); if (!binder_device) return -ENOMEM; diff --git a/drivers/android/binder/context.rs b/drivers/android/binder/context.rs index 3d135ec03ca7..9cf437c025a2 100644 --- a/drivers/android/binder/context.rs +++ b/drivers/android/binder/context.rs @@ -3,8 +3,8 @@ // Copyright (C) 2025 Google LLC. use kernel::{ - error::Error, - list::{List, ListArc, ListLinks}, + alloc::kvec::KVVec, + error::code::*, prelude::*, security, str::{CStr, CString}, @@ -17,22 +17,19 @@ use crate::{error::BinderError, node::NodeRef, process::Process}; kernel::sync::global_lock! { // SAFETY: We call `init` in the module initializer, so it's initialized before first use. pub(crate) unsafe(uninit) static CONTEXTS: Mutex<ContextList> = ContextList { - list: List::new(), + contexts: KVVec::new(), }; } pub(crate) struct ContextList { - list: List<Context>, + contexts: KVVec<Arc<Context>>, } -pub(crate) fn get_all_contexts() -> Result<KVec<Arc<Context>>> { +pub(crate) fn get_all_contexts() -> Result<KVVec<Arc<Context>>> { let lock = CONTEXTS.lock(); - - let count = lock.list.iter().count(); - - let mut ctxs = KVec::with_capacity(count, GFP_KERNEL)?; - for ctx in &lock.list { - ctxs.push(Arc::from(ctx), GFP_KERNEL)?; + let mut ctxs = KVVec::with_capacity(lock.contexts.len(), GFP_KERNEL)?; + for ctx in lock.contexts.iter() { + ctxs.push(ctx.clone(), GFP_KERNEL)?; } Ok(ctxs) } @@ -42,7 +39,7 @@ pub(crate) fn get_all_contexts() -> Result<KVec<Arc<Context>>> { struct Manager { node: Option<NodeRef>, uid: Option<Kuid>, - all_procs: List<Process>, + all_procs: KVVec<Arc<Process>>, } /// There is one context per binder file (/dev/binder, /dev/hwbinder, etc) @@ -51,28 +48,16 @@ pub(crate) struct Context { #[pin] manager: Mutex<Manager>, pub(crate) name: CString, - #[pin] - links: ListLinks, -} - -kernel::list::impl_list_arc_safe! { - impl ListArcSafe<0> for Context { untracked; } -} -kernel::list::impl_list_item! { - impl ListItem<0> for Context { - using ListLinks { self.links }; - } } impl Context { pub(crate) fn new(name: &CStr) -> Result<Arc<Self>> { let name = CString::try_from(name)?; - let list_ctx = ListArc::pin_init::<Error>( + let ctx = Arc::pin_init( try_pin_init!(Context { name, - links <- ListLinks::new(), manager <- kernel::new_mutex!(Manager { - all_procs: List::new(), + all_procs: KVVec::new(), node: None, uid: None, }, "Context::manager"), @@ -80,8 +65,7 @@ impl Context { GFP_KERNEL, )?; - let ctx = list_ctx.clone_arc(); - CONTEXTS.lock().list.push_back(list_ctx); + CONTEXTS.lock().contexts.push(ctx.clone(), GFP_KERNEL)?; Ok(ctx) } @@ -89,27 +73,27 @@ impl Context { /// Called when the file for this context is unlinked. /// /// No-op if called twice. - pub(crate) fn deregister(&self) { - // SAFETY: We never add the context to any other linked list than this one, so it is either - // in this list, or not in any list. - unsafe { CONTEXTS.lock().list.remove(self) }; + pub(crate) fn deregister(self: &Arc<Self>) { + // Safe removal using retain + CONTEXTS.lock().contexts.retain(|c| !Arc::ptr_eq(c, self)); } - pub(crate) fn register_process(self: &Arc<Self>, proc: ListArc<Process>) { + pub(crate) fn register_process(self: &Arc<Self>, proc: Arc<Process>) -> Result { if !Arc::ptr_eq(self, &proc.ctx) { pr_err!("Context::register_process called on the wrong context."); - return; + return Err(EINVAL); } - self.manager.lock().all_procs.push_back(proc); + self.manager.lock().all_procs.push(proc, GFP_KERNEL)?; + Ok(()) } - pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Process) { + pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Arc<Process>) { if !Arc::ptr_eq(self, &proc.ctx) { pr_err!("Context::deregister_process called on the wrong context."); return; } - // SAFETY: We just checked that this is the right list. - unsafe { self.manager.lock().all_procs.remove(proc) }; + let mut manager = self.manager.lock(); + manager.all_procs.retain(|p| !Arc::ptr_eq(p, proc)); } pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result { @@ -154,27 +138,27 @@ impl Context { { let lock = self.manager.lock(); for proc in &lock.all_procs { - func(&proc); + func(proc); } } - pub(crate) fn get_all_procs(&self) -> Result<KVec<Arc<Process>>> { + pub(crate) fn get_all_procs(&self) -> Result<KVVec<Arc<Process>>> { let lock = self.manager.lock(); - let count = lock.all_procs.iter().count(); - - let mut procs = KVec::with_capacity(count, GFP_KERNEL)?; - for proc in &lock.all_procs { - procs.push(Arc::from(proc), GFP_KERNEL)?; + let mut procs = KVVec::with_capacity(lock.all_procs.len(), GFP_KERNEL)?; + for proc in lock.all_procs.iter() { + procs.push(Arc::clone(proc), GFP_KERNEL)?; } Ok(procs) } - pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result<KVec<Arc<Process>>> { - let orig = self.get_all_procs()?; - let mut backing = KVec::with_capacity(orig.len(), GFP_KERNEL)?; - for proc in orig.into_iter().filter(|proc| proc.task.pid() == pid) { - backing.push(proc, GFP_KERNEL)?; + pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result<KVVec<Arc<Process>>> { + let lock = self.manager.lock(); + let mut matching_procs = KVVec::new(); + for proc in lock.all_procs.iter() { + if proc.task.pid() == pid { + matching_procs.push(Arc::clone(proc), GFP_KERNEL)?; + } } - Ok(backing) + Ok(matching_procs) } } diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs index c26d113ede96..69f757ff7461 100644 --- a/drivers/android/binder/node.rs +++ b/drivers/android/binder/node.rs @@ -178,6 +178,14 @@ struct NodeInner { refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>, } +use kernel::bindings::rb_node_layout; +use mem::offset_of; +pub(crate) const NODE_LAYOUT: rb_node_layout = rb_node_layout { + arc_offset: Arc::<Node>::DATA_OFFSET + offset_of!(DTRWrap<Node>, wrapped), + debug_id: offset_of!(Node, debug_id), + ptr: offset_of!(Node, ptr), +}; + #[pin_data] pub(crate) struct Node { pub(crate) debug_id: usize, diff --git a/drivers/android/binder/page_range.rs b/drivers/android/binder/page_range.rs index 9379038f61f5..fdd97112ef5c 100644 --- a/drivers/android/binder/page_range.rs +++ b/drivers/android/binder/page_range.rs @@ -727,8 +727,5 @@ unsafe extern "C" fn rust_shrink_free_page( drop(mm); drop(page); - // SAFETY: We just unlocked the lru lock, but it should be locked when we return. - unsafe { bindings::spin_lock(&raw mut (*lru).lock) }; - LRU_REMOVED_ENTRY } diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs index 132055b4790f..41de5593197c 100644 --- a/drivers/android/binder/process.rs +++ b/drivers/android/binder/process.rs @@ -28,11 +28,11 @@ use kernel::{ seq_print, sync::poll::PollTable, sync::{ + aref::ARef, lock::{spinlock::SpinLockBackend, Guard}, Arc, ArcBorrow, CondVar, CondVarTimeoutResult, Mutex, SpinLock, UniqueArc, }, task::Task, - types::ARef, uaccess::{UserSlice, UserSliceReader}, uapi, workqueue::{self, Work}, @@ -418,6 +418,13 @@ impl ProcessNodeRefs { } } +use core::mem::offset_of; +use kernel::bindings::rb_process_layout; +pub(crate) const PROCESS_LAYOUT: rb_process_layout = rb_process_layout { + arc_offset: Arc::<Process>::DATA_OFFSET, + task: offset_of!(Process, task), +}; + /// A process using binder. /// /// Strictly speaking, there can be multiple of these per process. There is one for each binder fd @@ -496,7 +503,7 @@ impl workqueue::WorkItem for Process { impl Process { fn new(ctx: Arc<Context>, cred: ARef<Credential>) -> Result<Arc<Self>> { let current = kernel::current!(); - let list_process = ListArc::pin_init::<Error>( + let process = Arc::pin_init::<Error>( try_pin_init!(Process { ctx, cred, @@ -512,8 +519,7 @@ impl Process { GFP_KERNEL, )?; - let process = list_process.clone_arc(); - process.ctx.register_process(list_process); + process.ctx.register_process(process.clone())?; Ok(process) } diff --git a/drivers/android/binder/rust_binder.h b/drivers/android/binder/rust_binder.h index 31806890ed1a..d2284726c025 100644 --- a/drivers/android/binder/rust_binder.h +++ b/drivers/android/binder/rust_binder.h @@ -20,4 +20,83 @@ struct inode; struct dentry *rust_binderfs_create_proc_file(struct inode *nodp, int pid); void rust_binderfs_remove_file(struct dentry *dentry); +/* + * The internal data types in the Rust Binder driver are opaque to C, so we use + * void pointer typedefs for these types. + */ + +typedef void *rust_binder_transaction; +typedef void *rust_binder_process; +typedef void *rust_binder_node; + +struct rb_process_layout { + size_t arc_offset; + size_t task; +}; + +struct rb_transaction_layout { + size_t debug_id; + size_t code; + size_t flags; + size_t from_thread; + size_t to_proc; + size_t target_node; +}; + +struct rb_node_layout { + size_t arc_offset; + size_t debug_id; + size_t ptr; +}; + +struct rust_binder_layout { + struct rb_transaction_layout t; + struct rb_process_layout p; + struct rb_node_layout n; +}; + +extern const struct rust_binder_layout RUST_BINDER_LAYOUT; + +static inline size_t rust_binder_transaction_debug_id(rust_binder_transaction t) +{ + return *(size_t *) (t + RUST_BINDER_LAYOUT.t.debug_id); +} + +static inline u32 rust_binder_transaction_code(rust_binder_transaction t) +{ + return *(u32 *) (t + RUST_BINDER_LAYOUT.t.code); +} + +static inline u32 rust_binder_transaction_flags(rust_binder_transaction t) +{ + return *(u32 *) (t + RUST_BINDER_LAYOUT.t.flags); +} + +// Nullable! +static inline rust_binder_node rust_binder_transaction_target_node(rust_binder_transaction t) +{ + void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.target_node); + + if (p) + p = p + RUST_BINDER_LAYOUT.n.arc_offset; + return p; +} + +static inline rust_binder_process rust_binder_transaction_to_proc(rust_binder_transaction t) +{ + void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.to_proc); + + return p + RUST_BINDER_LAYOUT.p.arc_offset; +} + +static inline struct task_struct *rust_binder_process_task(rust_binder_process t) +{ + return *(struct task_struct **) (t + RUST_BINDER_LAYOUT.p.task); +} + +static inline size_t rust_binder_node_debug_id(rust_binder_node t) +{ + return *(size_t *) (t + RUST_BINDER_LAYOUT.n.debug_id); +} + #endif diff --git a/drivers/android/binder/rust_binder_events.h b/drivers/android/binder/rust_binder_events.h index 2f3efbf9dba6..8ad785c6bd0f 100644 --- a/drivers/android/binder/rust_binder_events.h +++ b/drivers/android/binder/rust_binder_events.h @@ -30,6 +30,36 @@ TRACE_EVENT(rust_binder_ioctl, TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg) ); +TRACE_EVENT(rust_binder_transaction, + TP_PROTO(bool reply, rust_binder_transaction t, struct task_struct *thread), + TP_ARGS(reply, t, thread), + TP_STRUCT__entry( + __field(int, debug_id) + __field(int, target_node) + __field(int, to_proc) + __field(int, to_thread) + __field(int, reply) + __field(unsigned int, code) + __field(unsigned int, flags) + ), + TP_fast_assign( + rust_binder_process to = rust_binder_transaction_to_proc(t); + rust_binder_node target_node = rust_binder_transaction_target_node(t); + + __entry->debug_id = rust_binder_transaction_debug_id(t); + __entry->target_node = target_node ? rust_binder_node_debug_id(target_node) : 0; + __entry->to_proc = rust_binder_process_task(to)->pid; + __entry->to_thread = thread ? thread->pid : 0; + __entry->reply = reply; + __entry->code = rust_binder_transaction_code(t); + __entry->flags = rust_binder_transaction_flags(t); + ), + TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x", + __entry->debug_id, __entry->target_node, + __entry->to_proc, __entry->to_thread, + __entry->reply, __entry->flags, __entry->code) +); + #endif /* _RUST_BINDER_TRACE_H */ /* This part must be outside protection */ diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs index c79a9e742240..aa5f2a75adb4 100644 --- a/drivers/android/binder/rust_binder_main.rs +++ b/drivers/android/binder/rust_binder_main.rs @@ -18,6 +18,7 @@ use kernel::{ prelude::*, seq_file::SeqFile, seq_print, + sync::atomic::{ordering::Relaxed, Atomic}, sync::poll::PollTable, sync::Arc, task::Pid, @@ -28,10 +29,7 @@ use kernel::{ use crate::{context::Context, page_range::Shrinker, process::Process, thread::Thread}; -use core::{ - ptr::NonNull, - sync::atomic::{AtomicBool, AtomicUsize, Ordering}, -}; +use core::ptr::NonNull; mod allocation; mod context; @@ -89,10 +87,18 @@ module! { license: "GPL", } +use kernel::bindings::rust_binder_layout; +#[no_mangle] +static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout { + t: transaction::TRANSACTION_LAYOUT, + p: process::PROCESS_LAYOUT, + n: node::NODE_LAYOUT, +}; + fn next_debug_id() -> usize { - static NEXT_DEBUG_ID: AtomicUsize = AtomicUsize::new(0); + static NEXT_DEBUG_ID: Atomic<usize> = Atomic::new(0); - NEXT_DEBUG_ID.fetch_add(1, Ordering::Relaxed) + NEXT_DEBUG_ID.fetch_add(1, Relaxed) } /// Provides a single place to write Binder return values via the @@ -215,7 +221,7 @@ impl<T: ListArcSafe> DTRWrap<T> { struct DeliverCode { code: u32, - skip: AtomicBool, + skip: Atomic<bool>, } kernel::list::impl_list_arc_safe! { @@ -226,7 +232,7 @@ impl DeliverCode { fn new(code: u32) -> Self { Self { code, - skip: AtomicBool::new(false), + skip: Atomic::new(false), } } @@ -235,7 +241,7 @@ impl DeliverCode { /// This is used instead of removing it from the work list, since `LinkedList::remove` is /// unsafe, whereas this method is not. fn skip(&self) { - self.skip.store(true, Ordering::Relaxed); + self.skip.store(true, Relaxed); } } @@ -245,7 +251,7 @@ impl DeliverToRead for DeliverCode { _thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool> { - if !self.skip.load(Ordering::Relaxed) { + if !self.skip.load(Relaxed) { writer.write_code(self.code)?; } Ok(true) @@ -259,7 +265,7 @@ impl DeliverToRead for DeliverCode { fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> { seq_print!(m, "{}", prefix); - if self.skip.load(Ordering::Relaxed) { + if self.skip.load(Relaxed) { seq_print!(m, "(skipped) "); } if self.code == defs::BR_TRANSACTION_COMPLETE { @@ -288,7 +294,7 @@ impl kernel::Module for BinderModule { pr_warn!("Loaded Rust Binder."); - BINDER_SHRINKER.register(kernel::c_str!("android-binder"))?; + BINDER_SHRINKER.register(c"android-binder")?; // SAFETY: The module is being loaded, so we can initialize binderfs. unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? }; @@ -314,7 +320,7 @@ pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = { owner: THIS_MODULE.as_ptr(), poll: Some(rust_binder_poll), unlocked_ioctl: Some(rust_binder_ioctl), - compat_ioctl: Some(bindings::compat_ptr_ioctl), + compat_ioctl: bindings::compat_ptr_ioctl, mmap: Some(rust_binder_mmap), open: Some(rust_binder_open), release: Some(rust_binder_release), diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c index c69026df775c..ade1c4d92499 100644 --- a/drivers/android/binder/rust_binderfs.c +++ b/drivers/android/binder/rust_binderfs.c @@ -132,8 +132,8 @@ static int binderfs_binder_device_create(struct inode *ref_inode, mutex_lock(&binderfs_minors_mutex); if (++info->device_count <= info->mount_opts.max) minor = ida_alloc_max(&binderfs_minors, - use_reserve ? BINDERFS_MAX_MINOR : - BINDERFS_MAX_MINOR_CAPPED, + use_reserve ? BINDERFS_MAX_MINOR - 1 : + BINDERFS_MAX_MINOR_CAPPED - 1, GFP_KERNEL); else minor = -ENOSPC; @@ -145,7 +145,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode, mutex_unlock(&binderfs_minors_mutex); ret = -ENOMEM; - device = kzalloc(sizeof(*device), GFP_KERNEL); + device = kzalloc_obj(*device); if (!device) goto err; @@ -387,16 +387,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb) bool use_reserve = true; #endif - device = kzalloc(sizeof(*device), GFP_KERNEL); + device = kzalloc_obj(*device); if (!device) return -ENOMEM; - /* If we have already created a binder-control node, return. */ - if (info->control_dentry) { - ret = 0; - goto out; - } - ret = -ENOMEM; inode = new_inode(sb); if (!inode) @@ -405,8 +399,8 @@ static int binderfs_binder_ctl_create(struct super_block *sb) /* Reserve a new minor number for the new device. */ mutex_lock(&binderfs_minors_mutex); minor = ida_alloc_max(&binderfs_minors, - use_reserve ? BINDERFS_MAX_MINOR : - BINDERFS_MAX_MINOR_CAPPED, + use_reserve ? BINDERFS_MAX_MINOR - 1 : + BINDERFS_MAX_MINOR_CAPPED - 1, GFP_KERNEL); mutex_unlock(&binderfs_minors_mutex); if (minor < 0) { @@ -431,7 +425,8 @@ static int binderfs_binder_ctl_create(struct super_block *sb) inode->i_private = device; info->control_dentry = dentry; - d_add(dentry, inode); + d_make_persistent(dentry, inode); + dput(dentry); return 0; @@ -647,7 +642,7 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_op = &binderfs_super_ops; sb->s_time_gran = 1; - sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL); + sb->s_fs_info = kzalloc_obj(struct binderfs_info); if (!sb->s_fs_info) return -ENOMEM; info = sb->s_fs_info; @@ -726,7 +721,7 @@ static int binderfs_init_fs_context(struct fs_context *fc) { struct binderfs_mount_opts *ctx; - ctx = kzalloc(sizeof(struct binderfs_mount_opts), GFP_KERNEL); + ctx = kzalloc_obj(struct binderfs_mount_opts); if (!ctx) return -ENOMEM; diff --git a/drivers/android/binder/stats.rs b/drivers/android/binder/stats.rs index 037002651941..ab75e9561cbf 100644 --- a/drivers/android/binder/stats.rs +++ b/drivers/android/binder/stats.rs @@ -5,7 +5,7 @@ //! Keep track of statistics for binder_logs. use crate::defs::*; -use core::sync::atomic::{AtomicU32, Ordering::Relaxed}; +use kernel::sync::atomic::{ordering::Relaxed, Atomic}; use kernel::{ioctl::_IOC_NR, seq_file::SeqFile, seq_print}; const BC_COUNT: usize = _IOC_NR(BC_REPLY_SG) as usize + 1; @@ -14,14 +14,14 @@ const BR_COUNT: usize = _IOC_NR(BR_TRANSACTION_PENDING_FROZEN) as usize + 1; pub(crate) static GLOBAL_STATS: BinderStats = BinderStats::new(); pub(crate) struct BinderStats { - bc: [AtomicU32; BC_COUNT], - br: [AtomicU32; BR_COUNT], + bc: [Atomic<u32>; BC_COUNT], + br: [Atomic<u32>; BR_COUNT], } impl BinderStats { pub(crate) const fn new() -> Self { #[expect(clippy::declare_interior_mutable_const)] - const ZERO: AtomicU32 = AtomicU32::new(0); + const ZERO: Atomic<u32> = Atomic::new(0); Self { bc: [ZERO; BC_COUNT], diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs index 1a8e6fdc0dc4..0b62d24b2118 100644 --- a/drivers/android/binder/thread.rs +++ b/drivers/android/binder/thread.rs @@ -15,10 +15,10 @@ use kernel::{ security, seq_file::SeqFile, seq_print, + sync::atomic::{ordering::Relaxed, Atomic}, sync::poll::{PollCondVar, PollTable}, - sync::{Arc, SpinLock}, + sync::{aref::ARef, Arc, SpinLock}, task::Task, - types::ARef, uaccess::UserSlice, uapi, }; @@ -34,10 +34,11 @@ use crate::{ BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverCode, DeliverToRead, }; -use core::{ - mem::size_of, - sync::atomic::{AtomicU32, Ordering}, -}; +use core::mem::size_of; + +fn is_aligned(value: usize, to: usize) -> bool { + value % to == 0 +} /// Stores the layout of the scatter-gather entries. This is used during the `translate_objects` /// call and is discarded when it returns. @@ -69,17 +70,24 @@ struct ScatterGatherEntry { } /// This entry specifies that a fixup should happen at `target_offset` of the -/// buffer. If `skip` is nonzero, then the fixup is a `binder_fd_array_object` -/// and is applied later. Otherwise if `skip` is zero, then the size of the -/// fixup is `sizeof::<u64>()` and `pointer_value` is written to the buffer. -struct PointerFixupEntry { - /// The number of bytes to skip, or zero for a `binder_buffer_object` fixup. - skip: usize, - /// The translated pointer to write when `skip` is zero. - pointer_value: u64, - /// The offset at which the value should be written. The offset is relative - /// to the original buffer. - target_offset: usize, +/// buffer. +enum PointerFixupEntry { + /// A fixup for a `binder_buffer_object`. + Fixup { + /// The translated pointer to write. + pointer_value: u64, + /// The offset at which the value should be written. The offset is relative + /// to the original buffer. + target_offset: usize, + }, + /// A skip for a `binder_fd_array_object`. + Skip { + /// The number of bytes to skip. + skip: usize, + /// The offset at which the skip should happen. The offset is relative + /// to the original buffer. + target_offset: usize, + }, } /// Return type of `apply_and_validate_fixup_in_parent`. @@ -273,8 +281,8 @@ const LOOPER_POLL: u32 = 0x40; impl InnerThread { fn new() -> Result<Self> { fn next_err_id() -> u32 { - static EE_ID: AtomicU32 = AtomicU32::new(0); - EE_ID.fetch_add(1, Ordering::Relaxed) + static EE_ID: Atomic<u32> = Atomic::new(0); + EE_ID.fetch_add(1, Relaxed) } Ok(Self { @@ -762,8 +770,7 @@ impl Thread { parent_entry.fixup_min_offset = info.new_min_offset; parent_entry.pointer_fixups.push( - PointerFixupEntry { - skip: 0, + PointerFixupEntry::Fixup { pointer_value: buffer_ptr_in_user_space, target_offset: info.target_offset, }, @@ -789,6 +796,10 @@ impl Thread { let num_fds = usize::try_from(obj.num_fds).map_err(|_| EINVAL)?; let fds_len = num_fds.checked_mul(size_of::<u32>()).ok_or(EINVAL)?; + if !is_aligned(parent_offset, size_of::<u32>()) { + return Err(EINVAL.into()); + } + let info = sg_state.validate_parent_fixup(parent_index, parent_offset, fds_len)?; view.alloc.info_add_fd_reserve(num_fds)?; @@ -803,13 +814,16 @@ impl Thread { } }; + if !is_aligned(parent_entry.sender_uaddr, size_of::<u32>()) { + return Err(EINVAL.into()); + } + parent_entry.fixup_min_offset = info.new_min_offset; parent_entry .pointer_fixups .push( - PointerFixupEntry { + PointerFixupEntry::Skip { skip: fds_len, - pointer_value: 0, target_offset: info.target_offset, }, GFP_KERNEL, @@ -820,6 +834,7 @@ impl Thread { .sender_uaddr .checked_add(parent_offset) .ok_or(EINVAL)?; + let mut fda_bytes = KVec::new(); UserSlice::new(UserPtr::from_addr(fda_uaddr as _), fds_len) .read_all(&mut fda_bytes, GFP_KERNEL)?; @@ -871,17 +886,21 @@ impl Thread { let mut reader = UserSlice::new(UserPtr::from_addr(sg_entry.sender_uaddr), sg_entry.length).reader(); for fixup in &mut sg_entry.pointer_fixups { - let fixup_len = if fixup.skip == 0 { - size_of::<u64>() - } else { - fixup.skip + let (fixup_len, fixup_offset) = match fixup { + PointerFixupEntry::Fixup { target_offset, .. } => { + (size_of::<u64>(), *target_offset) + } + PointerFixupEntry::Skip { + skip, + target_offset, + } => (*skip, *target_offset), }; - let target_offset_end = fixup.target_offset.checked_add(fixup_len).ok_or(EINVAL)?; - if fixup.target_offset < end_of_previous_fixup || offset_end < target_offset_end { + let target_offset_end = fixup_offset.checked_add(fixup_len).ok_or(EINVAL)?; + if fixup_offset < end_of_previous_fixup || offset_end < target_offset_end { pr_warn!( "Fixups oob {} {} {} {}", - fixup.target_offset, + fixup_offset, end_of_previous_fixup, offset_end, target_offset_end @@ -890,13 +909,13 @@ impl Thread { } let copy_off = end_of_previous_fixup; - let copy_len = fixup.target_offset - end_of_previous_fixup; + let copy_len = fixup_offset - end_of_previous_fixup; if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) { pr_warn!("Failed copying into alloc: {:?}", err); return Err(err.into()); } - if fixup.skip == 0 { - let res = alloc.write::<u64>(fixup.target_offset, &fixup.pointer_value); + if let PointerFixupEntry::Fixup { pointer_value, .. } = fixup { + let res = alloc.write::<u64>(fixup_offset, pointer_value); if let Err(err) = res { pr_warn!("Failed copying ptr into alloc: {:?}", err); return Err(err.into()); @@ -949,25 +968,30 @@ impl Thread { let data_size = trd.data_size.try_into().map_err(|_| EINVAL)?; let aligned_data_size = ptr_align(data_size).ok_or(EINVAL)?; - let offsets_size = trd.offsets_size.try_into().map_err(|_| EINVAL)?; - let aligned_offsets_size = ptr_align(offsets_size).ok_or(EINVAL)?; - let buffers_size = tr.buffers_size.try_into().map_err(|_| EINVAL)?; - let aligned_buffers_size = ptr_align(buffers_size).ok_or(EINVAL)?; + let offsets_size: usize = trd.offsets_size.try_into().map_err(|_| EINVAL)?; + let buffers_size: usize = tr.buffers_size.try_into().map_err(|_| EINVAL)?; let aligned_secctx_size = match secctx.as_ref() { Some((_offset, ctx)) => ptr_align(ctx.len()).ok_or(EINVAL)?, None => 0, }; + if !is_aligned(offsets_size, size_of::<u64>()) { + return Err(EINVAL.into()); + } + if !is_aligned(buffers_size, size_of::<u64>()) { + return Err(EINVAL.into()); + } + // This guarantees that at least `sizeof(usize)` bytes will be allocated. let len = usize::max( aligned_data_size - .checked_add(aligned_offsets_size) - .and_then(|sum| sum.checked_add(aligned_buffers_size)) + .checked_add(offsets_size) + .and_then(|sum| sum.checked_add(buffers_size)) .and_then(|sum| sum.checked_add(aligned_secctx_size)) .ok_or(ENOMEM)?, - size_of::<usize>(), + size_of::<u64>(), ); - let secctx_off = aligned_data_size + aligned_offsets_size + aligned_buffers_size; + let secctx_off = aligned_data_size + offsets_size + buffers_size; let mut alloc = match to_process.buffer_alloc(debug_id, len, is_oneway, self.process.task.pid()) { Ok(alloc) => alloc, @@ -999,13 +1023,13 @@ impl Thread { } let offsets_start = aligned_data_size; - let offsets_end = aligned_data_size + aligned_offsets_size; + let offsets_end = aligned_data_size + offsets_size; // This state is used for BINDER_TYPE_PTR objects. let sg_state = sg_state.insert(ScatterGatherState { unused_buffer_space: UnusedBufferSpace { offset: offsets_end, - limit: len, + limit: offsets_end + buffers_size, }, sg_entries: KVec::new(), ancestors: KVec::new(), @@ -1014,12 +1038,16 @@ impl Thread { // Traverse the objects specified. let mut view = AllocationView::new(&mut alloc, data_size); for (index, index_offset) in (offsets_start..offsets_end) - .step_by(size_of::<usize>()) + .step_by(size_of::<u64>()) .enumerate() { - let offset = view.alloc.read(index_offset)?; + let offset: usize = view + .alloc + .read::<u64>(index_offset)? + .try_into() + .map_err(|_| EINVAL)?; - if offset < end_of_previous_object { + if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) { pr_warn!("Got transaction with invalid offset."); return Err(EINVAL.into()); } @@ -1051,7 +1079,7 @@ impl Thread { } // Update the indexes containing objects to clean up. - let offset_after_object = index_offset + size_of::<usize>(); + let offset_after_object = index_offset + size_of::<u64>(); view.alloc .set_info_offsets(offsets_start..offset_after_object); } @@ -1117,6 +1145,7 @@ impl Thread { transaction: &DArc<Transaction>, ) -> bool { if let Ok(transaction) = &reply { + crate::trace::trace_transaction(true, transaction, Some(&self.task)); transaction.set_outstanding(&mut self.process.inner.lock()); } @@ -1537,7 +1566,7 @@ impl Thread { #[pin_data] struct ThreadError { - error_code: AtomicU32, + error_code: Atomic<u32>, #[pin] links_track: AtomicTracker, } @@ -1545,18 +1574,18 @@ struct ThreadError { impl ThreadError { fn try_new() -> Result<DArc<Self>> { DTRWrap::arc_pin_init(pin_init!(Self { - error_code: AtomicU32::new(BR_OK), + error_code: Atomic::new(BR_OK), links_track <- AtomicTracker::new(), })) .map(ListArc::into_arc) } fn set_error_code(&self, code: u32) { - self.error_code.store(code, Ordering::Relaxed); + self.error_code.store(code, Relaxed); } fn is_unused(&self) -> bool { - self.error_code.load(Ordering::Relaxed) == BR_OK + self.error_code.load(Relaxed) == BR_OK } } @@ -1566,8 +1595,8 @@ impl DeliverToRead for ThreadError { _thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool> { - let code = self.error_code.load(Ordering::Relaxed); - self.error_code.store(BR_OK, Ordering::Relaxed); + let code = self.error_code.load(Relaxed); + self.error_code.store(BR_OK, Relaxed); writer.write_code(code)?; Ok(true) } @@ -1583,7 +1612,7 @@ impl DeliverToRead for ThreadError { m, "{}transaction error: {}\n", prefix, - self.error_code.load(Ordering::Relaxed) + self.error_code.load(Relaxed) ); Ok(()) } diff --git a/drivers/android/binder/trace.rs b/drivers/android/binder/trace.rs index af0e4392805e..9839901c7151 100644 --- a/drivers/android/binder/trace.rs +++ b/drivers/android/binder/trace.rs @@ -2,11 +2,21 @@ // Copyright (C) 2025 Google LLC. +use crate::transaction::Transaction; + +use kernel::bindings::{rust_binder_transaction, task_struct}; use kernel::ffi::{c_uint, c_ulong}; +use kernel::task::Task; use kernel::tracepoint::declare_trace; declare_trace! { unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong); + unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct); +} + +#[inline] +fn raw_transaction(t: &Transaction) -> rust_binder_transaction { + t as *const Transaction as rust_binder_transaction } #[inline] @@ -14,3 +24,14 @@ pub(crate) fn trace_ioctl(cmd: u32, arg: usize) { // SAFETY: Always safe to call. unsafe { rust_binder_ioctl(cmd, arg as c_ulong) } } + +#[inline] +pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) { + let thread = match thread { + Some(thread) => thread.as_ptr(), + None => core::ptr::null_mut(), + }; + // SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is + // valid or null. + unsafe { rust_binder_transaction(reply, raw_transaction(t), thread) } +} diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs index 4bd3c0e417eb..75e6f5fbaaae 100644 --- a/drivers/android/binder/transaction.rs +++ b/drivers/android/binder/transaction.rs @@ -2,11 +2,11 @@ // Copyright (C) 2025 Google LLC. -use core::sync::atomic::{AtomicBool, Ordering}; use kernel::{ prelude::*, seq_file::SeqFile, seq_print, + sync::atomic::{ordering::Relaxed, Atomic}, sync::{Arc, SpinLock}, task::Kuid, time::{Instant, Monotonic}, @@ -24,6 +24,17 @@ use crate::{ BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead, }; +use core::mem::offset_of; +use kernel::bindings::rb_transaction_layout; +pub(crate) const TRANSACTION_LAYOUT: rb_transaction_layout = rb_transaction_layout { + debug_id: offset_of!(Transaction, debug_id), + code: offset_of!(Transaction, code), + flags: offset_of!(Transaction, flags), + from_thread: offset_of!(Transaction, from), + to_proc: offset_of!(Transaction, to), + target_node: offset_of!(Transaction, target_node), +}; + #[pin_data(PinnedDrop)] pub(crate) struct Transaction { pub(crate) debug_id: usize, @@ -33,7 +44,7 @@ pub(crate) struct Transaction { pub(crate) to: Arc<Process>, #[pin] allocation: SpinLock<Option<Allocation>>, - is_outstanding: AtomicBool, + is_outstanding: Atomic<bool>, code: u32, pub(crate) flags: u32, data_size: usize, @@ -105,7 +116,7 @@ impl Transaction { offsets_size: trd.offsets_size as _, data_address, allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"), - is_outstanding: AtomicBool::new(false), + is_outstanding: Atomic::new(false), txn_security_ctx_off, oneway_spam_detected, start_time: Instant::now(), @@ -145,7 +156,7 @@ impl Transaction { offsets_size: trd.offsets_size as _, data_address: alloc.ptr, allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"), - is_outstanding: AtomicBool::new(false), + is_outstanding: Atomic::new(false), txn_security_ctx_off: None, oneway_spam_detected, start_time: Instant::now(), @@ -215,8 +226,8 @@ impl Transaction { pub(crate) fn set_outstanding(&self, to_process: &mut ProcessInner) { // No race because this method is only called once. - if !self.is_outstanding.load(Ordering::Relaxed) { - self.is_outstanding.store(true, Ordering::Relaxed); + if !self.is_outstanding.load(Relaxed) { + self.is_outstanding.store(true, Relaxed); to_process.add_outstanding_txn(); } } @@ -227,8 +238,8 @@ impl Transaction { // destructor, which is guaranteed to not race with any other operations on the // transaction. It also cannot race with `set_outstanding`, since submission happens // before delivery. - if self.is_outstanding.load(Ordering::Relaxed) { - self.is_outstanding.store(false, Ordering::Relaxed); + if self.is_outstanding.load(Relaxed) { + self.is_outstanding.store(false, Relaxed); self.to.drop_outstanding_txn(); } } @@ -249,6 +260,7 @@ impl Transaction { if oneway { if let Some(target_node) = self.target_node.clone() { + crate::trace::trace_transaction(false, &self, None); if process_inner.is_frozen.is_frozen() { process_inner.async_recv = true; if self.flags & TF_UPDATE_TXN != 0 { @@ -286,11 +298,13 @@ impl Transaction { } let res = if let Some(thread) = self.find_target_thread() { + crate::trace::trace_transaction(false, &self, Some(&thread.task)); match thread.push_work(self) { PushWorkRes::Ok => Ok(()), PushWorkRes::FailedDead(me) => Err((BinderError::new_dead(), me)), } } else { + crate::trace::trace_transaction(false, &self, None); process_inner.push_work(self) }; drop(process_inner); diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 979c96b74cad..241f16a9b63d 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -81,7 +81,7 @@ static void binder_insert_free_buffer(struct binder_alloc *alloc, new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: add free buffer, size %zd, at %pK\n", + "%d: add free buffer, size %zd, at %p\n", alloc->pid, new_buffer_size, new_buffer); while (*p) { @@ -289,7 +289,7 @@ static struct page *binder_page_alloc(struct binder_alloc *alloc, return NULL; /* allocate and install shrinker metadata under page->private */ - mdata = kzalloc(sizeof(*mdata), GFP_KERNEL); + mdata = kzalloc_obj(*mdata); if (!mdata) { __free_page(page); return NULL; @@ -572,7 +572,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( } binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", + "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", alloc->pid, size, buffer, buffer_size); /* @@ -672,7 +672,7 @@ struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, } /* Preallocate the next buffer */ - next = kzalloc(sizeof(*next), GFP_KERNEL); + next = kzalloc_obj(*next); if (!next) return ERR_PTR(-ENOMEM); @@ -748,7 +748,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, ALIGN(buffer->extra_buffers_size, sizeof(void *)); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_free_buf %pK size %zd buffer_size %zd\n", + "%d: binder_free_buf %p size %zd buffer_size %zd\n", alloc->pid, buffer, size, buffer_size); BUG_ON(buffer->free); @@ -916,16 +916,15 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, alloc->vm_start = vma->vm_start; - alloc->pages = kvcalloc(alloc->buffer_size / PAGE_SIZE, - sizeof(alloc->pages[0]), - GFP_KERNEL); + alloc->pages = kvzalloc_objs(alloc->pages[0], + alloc->buffer_size / PAGE_SIZE); if (!alloc->pages) { ret = -ENOMEM; failure_string = "alloc page array"; goto err_alloc_pages_failed; } - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + buffer = kzalloc_obj(*buffer); if (!buffer) { ret = -ENOMEM; failure_string = "alloc buffer struct"; @@ -1233,7 +1232,7 @@ static struct shrinker *binder_shrinker; VISIBLE_IF_KUNIT void __binder_alloc_init(struct binder_alloc *alloc, struct list_lru *freelist) { - alloc->pid = current->group_leader->pid; + alloc->pid = current->tgid; alloc->mm = current->mm; mmgrab(alloc->mm); mutex_init(&alloc->mutex); diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index b46bcb91072d..361d69f756f5 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -132,8 +132,8 @@ static int binderfs_binder_device_create(struct inode *ref_inode, mutex_lock(&binderfs_minors_mutex); if (++info->device_count <= info->mount_opts.max) minor = ida_alloc_max(&binderfs_minors, - use_reserve ? BINDERFS_MAX_MINOR : - BINDERFS_MAX_MINOR_CAPPED, + use_reserve ? BINDERFS_MAX_MINOR - 1 : + BINDERFS_MAX_MINOR_CAPPED - 1, GFP_KERNEL); else minor = -ENOSPC; @@ -145,7 +145,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode, mutex_unlock(&binderfs_minors_mutex); ret = -ENOMEM; - device = kzalloc(sizeof(*device), GFP_KERNEL); + device = kzalloc_obj(*device); if (!device) goto err; @@ -396,7 +396,7 @@ static int binderfs_binder_ctl_create(struct super_block *sb) bool use_reserve = true; #endif - device = kzalloc(sizeof(*device), GFP_KERNEL); + device = kzalloc_obj(*device); if (!device) return -ENOMEM; @@ -408,8 +408,8 @@ static int binderfs_binder_ctl_create(struct super_block *sb) /* Reserve a new minor number for the new device. */ mutex_lock(&binderfs_minors_mutex); minor = ida_alloc_max(&binderfs_minors, - use_reserve ? BINDERFS_MAX_MINOR : - BINDERFS_MAX_MINOR_CAPPED, + use_reserve ? BINDERFS_MAX_MINOR - 1 : + BINDERFS_MAX_MINOR_CAPPED - 1, GFP_KERNEL); mutex_unlock(&binderfs_minors_mutex); if (minor < 0) { @@ -638,7 +638,7 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_op = &binderfs_super_ops; sb->s_time_gran = 1; - sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL); + sb->s_fs_info = kzalloc_obj(struct binderfs_info); if (!sb->s_fs_info) return -ENOMEM; info = sb->s_fs_info; @@ -717,7 +717,7 @@ static int binderfs_init_fs_context(struct fs_context *fc) { struct binderfs_mount_opts *ctx; - ctx = kzalloc(sizeof(struct binderfs_mount_opts), GFP_KERNEL); + ctx = kzalloc_obj(struct binderfs_mount_opts); if (!ctx) return -ENOMEM; |
