Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/android/binder/context.rs
29520 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
// Copyright (C) 2025 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
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_list_arc_safe! {
59
impl ListArcSafe<0> for Context { untracked; }
60
}
61
kernel::list::impl_list_item! {
62
impl ListItem<0> for Context {
63
using ListLinks { self.links };
64
}
65
}
66
67
impl 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
}
181
182