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
get_all_contexts() -> Result<KVVec<Arc<Context>>>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 {
new(name: &CStr) -> Result<Arc<Self>>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.
deregister(self: &Arc<Self>)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
register_process(self: &Arc<Self>, proc: Arc<Process>) -> Result81 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
deregister_process(self: &Arc<Self>, proc: &Arc<Process>)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 // Shrink the vector if it has significant unused capacity to avoid memory waste,
99 // but use a conservative strategy to prevent shrink-then-regrow oscillation.
100 // Only shrink when length drops below 1/4 of capacity, and shrink to twice the length.
101 let len = manager.all_procs.len();
102 let cap = manager.all_procs.capacity();
103 if len < cap / 4 {
104 // Shrink to twice the current length. Ignore allocation failures since this
105 // is just an optimization; the vector remains valid even if shrinking fails.
106 let _ = manager.all_procs.shrink_to(len * 2, GFP_KERNEL);
107 }
108 }
109
set_manager_node(&self, node_ref: NodeRef) -> Result110 pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result {
111 let mut manager = self.manager.lock();
112 if manager.node.is_some() {
113 pr_warn!("BINDER_SET_CONTEXT_MGR already set");
114 return Err(EBUSY);
115 }
116 security::binder_set_context_mgr(&node_ref.node.owner.cred)?;
117
118 // If the context manager has been set before, ensure that we use the same euid.
119 let caller_uid = Kuid::current_euid();
120 if let Some(ref uid) = manager.uid {
121 if *uid != caller_uid {
122 return Err(EPERM);
123 }
124 }
125
126 manager.node = Some(node_ref);
127 manager.uid = Some(caller_uid);
128 Ok(())
129 }
130
unset_manager_node(&self)131 pub(crate) fn unset_manager_node(&self) {
132 let node_ref = self.manager.lock().node.take();
133 drop(node_ref);
134 }
135
get_manager_node(&self, strong: bool) -> Result<NodeRef, BinderError>136 pub(crate) fn get_manager_node(&self, strong: bool) -> Result<NodeRef, BinderError> {
137 self.manager
138 .lock()
139 .node
140 .as_ref()
141 .ok_or_else(BinderError::new_dead)?
142 .clone(strong)
143 .map_err(BinderError::from)
144 }
145
for_each_proc<F>(&self, mut func: F) where F: FnMut(&Process),146 pub(crate) fn for_each_proc<F>(&self, mut func: F)
147 where
148 F: FnMut(&Process),
149 {
150 let lock = self.manager.lock();
151 for proc in &lock.all_procs {
152 func(proc);
153 }
154 }
155
get_all_procs(&self) -> Result<KVVec<Arc<Process>>>156 pub(crate) fn get_all_procs(&self) -> Result<KVVec<Arc<Process>>> {
157 let lock = self.manager.lock();
158 let mut procs = KVVec::with_capacity(lock.all_procs.len(), GFP_KERNEL)?;
159 for proc in lock.all_procs.iter() {
160 procs.push(Arc::clone(proc), GFP_KERNEL)?;
161 }
162 Ok(procs)
163 }
164
get_procs_with_pid(&self, pid: i32) -> Result<KVVec<Arc<Process>>>165 pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result<KVVec<Arc<Process>>> {
166 let lock = self.manager.lock();
167 let mut matching_procs = KVVec::new();
168 for proc in lock.all_procs.iter() {
169 if proc.task.pid() == pid {
170 matching_procs.push(Arc::clone(proc), GFP_KERNEL)?;
171 }
172 }
173 Ok(matching_procs)
174 }
175 }
176