1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 use kernel::{ 6 alloc::kvec::KVVec, 7 error::code::*, 8 prelude::*, 9 security, 10 str::{CStr, CString}, 11 sync::{Arc, Mutex}, 12 task::Kuid, 13 }; 14 15 use crate::{error::BinderError, node::NodeRef, process::Process}; 16 17 kernel::sync::global_lock! { 18 // SAFETY: We call `init` in the module initializer, so it's initialized before first use. 19 pub(crate) unsafe(uninit) static CONTEXTS: Mutex<ContextList> = ContextList { 20 contexts: KVVec::new(), 21 }; 22 } 23 24 pub(crate) struct ContextList { 25 contexts: KVVec<Arc<Context>>, 26 } 27 28 pub(crate) fn get_all_contexts() -> Result<KVVec<Arc<Context>>> { 29 let lock = CONTEXTS.lock(); 30 let mut ctxs = KVVec::with_capacity(lock.contexts.len(), GFP_KERNEL)?; 31 for ctx in lock.contexts.iter() { 32 ctxs.push(ctx.clone(), GFP_KERNEL)?; 33 } 34 Ok(ctxs) 35 } 36 37 /// This struct keeps track of the processes using this context, and which process is the context 38 /// manager. 39 struct Manager { 40 node: Option<NodeRef>, 41 uid: Option<Kuid>, 42 all_procs: KVVec<Arc<Process>>, 43 } 44 45 /// There is one context per binder file (/dev/binder, /dev/hwbinder, etc) 46 #[pin_data] 47 pub(crate) struct Context { 48 #[pin] 49 manager: Mutex<Manager>, 50 pub(crate) name: CString, 51 } 52 53 impl Context { 54 pub(crate) fn new(name: &CStr) -> Result<Arc<Self>> { 55 let name = CString::try_from(name)?; 56 let ctx = Arc::pin_init( 57 try_pin_init!(Context { 58 name, 59 manager <- kernel::new_mutex!(Manager { 60 all_procs: KVVec::new(), 61 node: None, 62 uid: None, 63 }, "Context::manager"), 64 }), 65 GFP_KERNEL, 66 )?; 67 68 CONTEXTS.lock().contexts.push(ctx.clone(), GFP_KERNEL)?; 69 70 Ok(ctx) 71 } 72 73 /// Called when the file for this context is unlinked. 74 /// 75 /// No-op if called twice. 76 pub(crate) fn deregister(self: &Arc<Self>) { 77 // Safe removal using retain 78 CONTEXTS.lock().contexts.retain(|c| !Arc::ptr_eq(c, self)); 79 } 80 81 pub(crate) fn register_process(self: &Arc<Self>, proc: Arc<Process>) -> Result { 82 if !Arc::ptr_eq(self, &proc.ctx) { 83 pr_err!("Context::register_process called on the wrong context."); 84 return Err(EINVAL); 85 } 86 self.manager.lock().all_procs.push(proc, GFP_KERNEL)?; 87 Ok(()) 88 } 89 90 pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Arc<Process>) { 91 if !Arc::ptr_eq(self, &proc.ctx) { 92 pr_err!("Context::deregister_process called on the wrong context."); 93 return; 94 } 95 let mut manager = self.manager.lock(); 96 manager.all_procs.retain(|p| !Arc::ptr_eq(p, proc)); 97 } 98 99 pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result { 100 let mut manager = self.manager.lock(); 101 if manager.node.is_some() { 102 pr_warn!("BINDER_SET_CONTEXT_MGR already set"); 103 return Err(EBUSY); 104 } 105 security::binder_set_context_mgr(&node_ref.node.owner.cred)?; 106 107 // If the context manager has been set before, ensure that we use the same euid. 108 let caller_uid = Kuid::current_euid(); 109 if let Some(ref uid) = manager.uid { 110 if *uid != caller_uid { 111 return Err(EPERM); 112 } 113 } 114 115 manager.node = Some(node_ref); 116 manager.uid = Some(caller_uid); 117 Ok(()) 118 } 119 120 pub(crate) fn unset_manager_node(&self) { 121 let node_ref = self.manager.lock().node.take(); 122 drop(node_ref); 123 } 124 125 pub(crate) fn get_manager_node(&self, strong: bool) -> Result<NodeRef, BinderError> { 126 self.manager 127 .lock() 128 .node 129 .as_ref() 130 .ok_or_else(BinderError::new_dead)? 131 .clone(strong) 132 .map_err(BinderError::from) 133 } 134 135 pub(crate) fn for_each_proc<F>(&self, mut func: F) 136 where 137 F: FnMut(&Process), 138 { 139 let lock = self.manager.lock(); 140 for proc in &lock.all_procs { 141 func(&proc); 142 } 143 } 144 145 pub(crate) fn get_all_procs(&self) -> Result<KVVec<Arc<Process>>> { 146 let lock = self.manager.lock(); 147 let mut procs = KVVec::with_capacity(lock.all_procs.len(), GFP_KERNEL)?; 148 for proc in lock.all_procs.iter() { 149 procs.push(Arc::clone(proc), GFP_KERNEL)?; 150 } 151 Ok(procs) 152 } 153 154 pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result<KVVec<Arc<Process>>> { 155 let lock = self.manager.lock(); 156 let mut matching_procs = KVVec::new(); 157 for proc in lock.all_procs.iter() { 158 if proc.task.pid() == pid { 159 matching_procs.push(Arc::clone(proc), GFP_KERNEL)?; 160 } 161 } 162 Ok(matching_procs) 163 } 164 } 165