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