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
set_manager_node(&self, node_ref: NodeRef) -> Result99 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
unset_manager_node(&self)120 pub(crate) fn unset_manager_node(&self) {
121 let node_ref = self.manager.lock().node.take();
122 drop(node_ref);
123 }
124
get_manager_node(&self, strong: bool) -> Result<NodeRef, BinderError>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
for_each_proc<F>(&self, mut func: F) where F: FnMut(&Process),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
get_all_procs(&self) -> Result<KVVec<Arc<Process>>>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
get_procs_with_pid(&self, pid: i32) -> Result<KVVec<Arc<Process>>>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