xref: /linux/drivers/android/binder/context.rs (revision cb4eb6771c0f8fd1c52a8f6fdec7762fb087380a)
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