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