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