Skip to content

Commit 7801b21

Browse files
ambr-eCQ Bot
authored andcommitted
[starnix] Give credentials to binder and UDS remote ends
The remote ends of remote-binder take the credentials of the inside-Starnix remote binder process. When a Unix domain socket is created, it takes (by default) the credentials of its creator. These credentials will be used when transferring file descriptors across: any access done through these fds will use the socket/binder credentials. Bug: 404739824 Change-Id: Iae5317d270ccaef3ef10f2efb2f455643bc209c4 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1336524 Reviewed-by: Wez <[email protected]> Commit-Queue: Ambre Williams <[email protected]>
1 parent ded857a commit 7801b21

File tree

6 files changed

+127
-67
lines changed

6 files changed

+127
-67
lines changed

src/starnix/kernel/fs/fuchsia/remote.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::fs::fuchsia::sync_file::{SyncFence, SyncFile, SyncPoint, Timeline};
88
use crate::mm::memory::MemoryObject;
99
use crate::mm::{ProtectionFlags, VMEX_RESOURCE};
1010
use crate::security;
11-
use crate::task::{CurrentTask, EncryptionKeyId, Kernel};
11+
use crate::task::{CurrentTask, EncryptionKeyId, FullCredentials, Kernel};
1212
use crate::vfs::buffers::{InputBuffer, OutputBuffer, with_iovec_segments};
1313
use crate::vfs::fsverity::FsVerityState;
1414
use crate::vfs::socket::{Socket, SocketFile, ZxioBackedSocket};
@@ -356,7 +356,8 @@ pub fn new_remote_file<L>(
356356
where
357357
L: LockEqualOrBefore<FileOpsCore>,
358358
{
359-
let (attrs, ops) = remote_file_attrs_and_ops(handle)?;
359+
let remote_creds = current_task.full_current_creds();
360+
let (attrs, ops) = remote_file_attrs_and_ops(handle, remote_creds)?;
360361
let mut rights = fio::Flags::empty();
361362
if flags.can_read() {
362363
rights |= fio::PERM_READABLE;
@@ -374,13 +375,17 @@ where
374375
// Create a FileOps from a zx::Handle.
375376
//
376377
// The handle must satisfy the same requirements as `new_remote_file`.
377-
pub fn new_remote_file_ops(handle: zx::Handle) -> Result<Box<dyn FileOps>, Errno> {
378-
let (_, ops) = remote_file_attrs_and_ops(handle)?;
378+
pub fn new_remote_file_ops(
379+
handle: zx::Handle,
380+
creds: FullCredentials,
381+
) -> Result<Box<dyn FileOps>, Errno> {
382+
let (_, ops) = remote_file_attrs_and_ops(handle, creds)?;
379383
Ok(ops)
380384
}
381385

382386
fn remote_file_attrs_and_ops(
383387
mut handle: zx::Handle,
388+
remote_creds: FullCredentials,
384389
) -> Result<(zxio_node_attr, Box<dyn FileOps>), Errno> {
385390
let handle_type =
386391
handle.basic_info().map_err(|status| from_status_like_fdio!(status))?.object_type;
@@ -391,7 +396,8 @@ fn remote_file_attrs_and_ops(
391396
let queryable = funknown::QueryableSynchronousProxy::new(channel);
392397
if let Ok(name) = queryable.query(zx::MonotonicInstant::INFINITE) {
393398
if name == fbinder::UnixDomainSocketMarker::PROTOCOL_NAME.as_bytes() {
394-
let socket_ops = RemoteUnixDomainSocket::new(queryable.into_channel())?;
399+
let socket_ops =
400+
RemoteUnixDomainSocket::new(queryable.into_channel(), remote_creds)?;
395401
let socket = Socket::new_with_ops(Box::new(socket_ops))?;
396402
let file_ops = SocketFile::new(socket);
397403
let attr = zxio_node_attr {

src/starnix/kernel/fs/fuchsia/remote_unix_domain_socket.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
use crate::fs::fuchsia::{OpenFlags, new_remote_file};
66
use crate::task::{
7-
CurrentTask, EventHandler, SignalHandler, SignalHandlerInner, WaitCanceler, Waiter,
7+
CurrentTask, EventHandler, FullCredentials, SignalHandler, SignalHandlerInner, WaitCanceler,
8+
Waiter,
89
};
910
use crate::vfs::buffers::{InputBuffer, OutputBuffer};
1011
use crate::vfs::socket::{
@@ -29,10 +30,11 @@ static WRITABLE_SIGNAL: zx::Signals =
2930
pub struct RemoteUnixDomainSocket {
3031
client: fbinder::UnixDomainSocketSynchronousProxy,
3132
event: zx::EventPair,
33+
remote_creds: FullCredentials,
3234
}
3335

3436
impl RemoteUnixDomainSocket {
35-
pub fn new(channel: zx::Channel) -> Result<Self, Errno> {
37+
pub fn new(channel: zx::Channel, remote_creds: FullCredentials) -> Result<Self, Errno> {
3638
let client = fbinder::UnixDomainSocketSynchronousProxy::from_channel(channel);
3739
let response = client
3840
.get_event(
@@ -42,7 +44,7 @@ impl RemoteUnixDomainSocket {
4244
.map_err(|_| errno!(ECONNREFUSED))?
4345
.map_err(|e: i32| from_status_like_fdio!(zx::Status::from_raw(e)))?;
4446
let event = response.event.ok_or_else(|| errno!(ECONNREFUSED))?;
45-
Ok(Self { client, event })
47+
Ok(Self { client, event, remote_creds })
4648
}
4749

4850
fn get_signals_from_events(events: FdEvents) -> zx::Signals {
@@ -66,6 +68,14 @@ impl RemoteUnixDomainSocket {
6668
}
6769
events
6870
}
71+
72+
/// Perform an action using the credentials of the remote task.
73+
fn with_remote_creds<F, R>(&self, current_task: &CurrentTask, f: F) -> Result<R, Errno>
74+
where
75+
F: FnOnce() -> Result<R, Errno>,
76+
{
77+
current_task.override_creds(|temp_creds| *temp_creds = self.remote_creds.clone(), f)
78+
}
6979
}
7080

7181
impl SocketOps for RemoteUnixDomainSocket {
@@ -145,9 +155,19 @@ impl SocketOps for RemoteUnixDomainSocket {
145155

146156
let mut file_handles: Vec<FileHandle> = vec![];
147157
if let Some(handles) = response.handles {
148-
for handle in handles {
149-
file_handles.push(new_remote_file(locked, current_task, handle, OpenFlags::RDWR)?);
150-
}
158+
// Use the remote task's credentials to create the remote_file object. This ensures
159+
// that the SID associated to the fd is set to the correct value.
160+
self.with_remote_creds(current_task, || {
161+
for handle in handles {
162+
file_handles.push(new_remote_file(
163+
locked,
164+
current_task,
165+
handle,
166+
OpenFlags::RDWR,
167+
)?);
168+
}
169+
Ok(())
170+
})?;
151171
}
152172
let ancillary_data = vec![AncillaryData::Unix(UnixControlData::Rights(file_handles))];
153173

@@ -173,12 +193,16 @@ impl SocketOps for RemoteUnixDomainSocket {
173193
for data in ancillary_data {
174194
match data {
175195
AncillaryData::Unix(UnixControlData::Rights(file_handles)) => {
176-
for file_handle in file_handles {
177-
let Some(handle) = file_handle.to_handle(current_task)? else {
178-
return error!(EINVAL);
179-
};
180-
handles.push(handle);
181-
}
196+
// Access the served files with the credentials of the remote end.
197+
self.with_remote_creds(current_task, || {
198+
for file_handle in file_handles {
199+
let Some(handle) = file_handle.to_handle(current_task)? else {
200+
return error!(EINVAL);
201+
};
202+
handles.push(handle);
203+
}
204+
Ok(())
205+
})?;
182206
}
183207
_ => return error!(EINVAL),
184208
}

src/starnix/kernel/task/current_task.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ impl CurrentTask {
283283
/// actions performed by the task.
284284
pub fn current_creds(&self) -> Credentials {
285285
match self.overridden_creds.borrow().as_ref() {
286-
Some(x) => x.creds.clone(),
286+
Some(full_creds) => full_creds.creds.clone(),
287287
None => self.real_creds(),
288288
}
289289
}
@@ -298,6 +298,17 @@ impl CurrentTask {
298298
}
299299
}
300300

301+
/// Returns the current subjective credentials of the task, including the security state.
302+
pub fn full_current_creds(&self) -> FullCredentials {
303+
match self.overridden_creds.borrow().as_ref() {
304+
Some(full_creds) => full_creds.clone(),
305+
None => FullCredentials {
306+
creds: self.real_creds(),
307+
security_state: self.security_state.clone(),
308+
},
309+
}
310+
}
311+
301312
pub fn current_fscred(&self) -> FsCred {
302313
self.with_current_creds(|creds| creds.as_fscred())
303314
}

src/starnix/kernel/vfs/file_object.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::mm::{DesiredAddress, MappingName, MappingOptions, MemoryAccessorExt,
77
use crate::power::OnWakeOps;
88
use crate::security;
99
use crate::task::{
10-
CurrentTask, CurrentTaskAndLocked, EncryptionKeyId, EventHandler, FullCredentials, Task,
11-
ThreadGroupKey, WaitCallback, WaitCanceler, Waiter, register_delayed_release,
10+
CurrentTask, CurrentTaskAndLocked, EncryptionKeyId, EventHandler, Task, ThreadGroupKey,
11+
WaitCallback, WaitCanceler, Waiter, register_delayed_release,
1212
};
1313
use crate::vfs::buffers::{InputBuffer, OutputBuffer};
1414
use crate::vfs::file_server::serve_file;
@@ -425,7 +425,7 @@ pub trait FileOps: Send + Sync + AsAny + 'static {
425425
file: &FileObject,
426426
current_task: &CurrentTask,
427427
) -> Result<Option<zx::Handle>, Errno> {
428-
serve_file(current_task, file, FullCredentials::for_kernel())
428+
serve_file(current_task, file, current_task.full_current_creds())
429429
.map(|c| Some(c.0.into_handle()))
430430
}
431431

src/starnix/modules/binderfs/binder.rs

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use starnix_core::mm::{
1717
};
1818
use starnix_core::mutable_state::Guard;
1919
use starnix_core::task::{
20-
CurrentTask, CurrentTaskAndLocked, EventHandler, Kernel, SchedulerState, SimpleWaiter, Task,
21-
ThreadGroupKey, WaitCanceler, WaitQueue, Waiter,
20+
CurrentTask, CurrentTaskAndLocked, EventHandler, FullCredentials, Kernel, SchedulerState,
21+
SimpleWaiter, Task, ThreadGroupKey, WaitCanceler, WaitQueue, Waiter,
2222
};
2323
use starnix_core::vfs::buffers::{InputBuffer, OutputBuffer, VecInputBuffer};
2424
use starnix_core::vfs::pseudo::simple_file::BytesFile;
@@ -3229,6 +3229,7 @@ fn get_resource_accessor<'a>(
32293229
struct RemoteResourceAccessor {
32303230
process: zx::Process,
32313231
process_accessor: fbinder::ProcessAccessorSynchronousProxy,
3232+
remote_creds: FullCredentials,
32323233
}
32333234

32343235
impl RemoteResourceAccessor {
@@ -3242,6 +3243,13 @@ impl RemoteResourceAccessor {
32423243
.map_err(|_| errno!(ENOENT))?;
32433244
result.map_err(|e| errno_from_code!(e.into_primitive() as i16))
32443245
}
3246+
3247+
fn with_remote_creds<F, T>(&self, current_task: &CurrentTask, f: F) -> Result<T, Errno>
3248+
where
3249+
F: FnOnce() -> Result<T, Errno>,
3250+
{
3251+
current_task.override_creds(|temp_creds| *temp_creds = self.remote_creds.clone(), f)
3252+
}
32453253
}
32463254

32473255
impl std::fmt::Debug for RemoteResourceAccessor {
@@ -3406,28 +3414,30 @@ impl ResourceAccessor for RemoteResourceAccessor {
34063414
let num_fds = fds.len();
34073415
let mut files = Vec::with_capacity(num_fds);
34083416

3409-
for chunk in fds.chunks(fbinder::MAX_REQUEST_COUNT as usize) {
3410-
let response = self.run_file_request(fbinder::FileRequest {
3411-
get_requests: Some(chunk.into_iter().map(|fd| fd.raw()).collect()),
3412-
..Default::default()
3413-
})?;
3414-
for fbinder::FileHandle { file, flags, .. } in
3415-
response.get_responses.into_iter().flatten()
3416-
{
3417-
let Some(flags) = flags else {
3418-
log_warn!("Incorrect response to file request. Missing flags.");
3419-
return error!(ENOENT);
3420-
};
3421-
let file = if let Some(file) = file {
3422-
new_remote_file(locked, current_task, file, flags.into_fidl())?
3423-
} else {
3424-
new_null_file(locked, current_task, flags.into_fidl())
3425-
};
3426-
files.push((file, FdFlags::empty()));
3417+
self.with_remote_creds(current_task, || {
3418+
for chunk in fds.chunks(fbinder::MAX_REQUEST_COUNT as usize) {
3419+
let response = self.run_file_request(fbinder::FileRequest {
3420+
get_requests: Some(chunk.into_iter().map(|fd| fd.raw()).collect()),
3421+
..Default::default()
3422+
})?;
3423+
for fbinder::FileHandle { file, flags, .. } in
3424+
response.get_responses.into_iter().flatten()
3425+
{
3426+
let Some(flags) = flags else {
3427+
log_warn!("Incorrect response to file request. Missing flags.");
3428+
return error!(ENOENT);
3429+
};
3430+
let file = if let Some(file) = file {
3431+
new_remote_file(locked, current_task, file, flags.into_fidl())?
3432+
} else {
3433+
new_null_file(locked, current_task, flags.into_fidl())
3434+
};
3435+
files.push((file, FdFlags::empty()));
3436+
}
34273437
}
3428-
}
34293438

3430-
if files.len() != num_fds { error!(ENOENT) } else { Ok(files) }
3439+
if files.len() != num_fds { error!(ENOENT) } else { Ok(files) }
3440+
})
34313441
}
34323442

34333443
fn add_files_with_flags(
@@ -3441,27 +3451,30 @@ impl ResourceAccessor for RemoteResourceAccessor {
34413451
let num_files = files.len();
34423452
let mut fds = Vec::with_capacity(num_files);
34433453

3444-
for chunk in files.chunks(fbinder::MAX_REQUEST_COUNT as usize) {
3445-
let mut handles = Vec::with_capacity(chunk.len());
3446-
for (file, _) in chunk.into_iter() {
3447-
handles.push(fbinder::FileHandle {
3448-
file: file.to_handle(current_task)?,
3449-
flags: Some(file.flags().into_fidl()),
3450-
..fbinder::FileHandle::default()
3451-
});
3452-
}
3453-
let response = self.run_file_request(fbinder::FileRequest {
3454-
add_requests: Some(handles),
3455-
..Default::default()
3456-
})?;
3457-
for fd in response.add_responses.into_iter().flatten().map(|fd| FdNumber::from_raw(fd))
3458-
{
3459-
add_action(fd);
3460-
fds.push(fd);
3454+
self.with_remote_creds(current_task, || {
3455+
for chunk in files.chunks(fbinder::MAX_REQUEST_COUNT as usize) {
3456+
let mut handles = Vec::with_capacity(chunk.len());
3457+
for (file, _) in chunk.into_iter() {
3458+
handles.push(fbinder::FileHandle {
3459+
file: file.to_handle(current_task)?,
3460+
flags: Some(file.flags().into_fidl()),
3461+
..fbinder::FileHandle::default()
3462+
});
3463+
}
3464+
let response = self.run_file_request(fbinder::FileRequest {
3465+
add_requests: Some(handles),
3466+
..Default::default()
3467+
})?;
3468+
for fd in
3469+
response.add_responses.into_iter().flatten().map(|fd| FdNumber::from_raw(fd))
3470+
{
3471+
add_action(fd);
3472+
fds.push(fd);
3473+
}
34613474
}
3462-
}
34633475

3464-
if fds.len() != num_files { error!(ENOENT) } else { Ok(fds) }
3476+
if fds.len() != num_files { error!(ENOENT) } else { Ok(fds) }
3477+
})
34653478
}
34663479

34673480
fn as_memory_accessor(&self) -> Option<&dyn MemoryAccessor> {
@@ -3678,7 +3691,11 @@ impl BinderDriver {
36783691
fbinder::ProcessAccessorSynchronousProxy::new(process_accessor.into_channel());
36793692
let identifier = this.create_remote_process(
36803693
current_task.thread_group_key.clone(),
3681-
RemoteResourceAccessor { process_accessor, process },
3694+
RemoteResourceAccessor {
3695+
process_accessor,
3696+
process,
3697+
remote_creds: current_task.full_current_creds(),
3698+
},
36823699
);
36833700
Arc::new(RemoteBinderConnection {
36843701
binder_connection: BinderConnection {
@@ -9661,7 +9678,9 @@ pub mod tests {
96619678
let process = fuchsia_runtime::process_self()
96629679
.duplicate(zx::Rights::SAME_RIGHTS)
96639680
.expect("process");
9664-
let remote_binder_task = Arc::new(RemoteResourceAccessor { process_accessor, process });
9681+
let remote_creds = FullCredentials::for_kernel();
9682+
let remote_binder_task =
9683+
Arc::new(RemoteResourceAccessor { process_accessor, process, remote_creds });
96659684
let mut vector = Vec::with_capacity(vector_size);
96669685
for i in 0..vector_size {
96679686
vector.push((i & 255) as u8);

src/starnix/modules/nanohub/socket_tunnel_file.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use starnix_core::device::DeviceOps;
1313
use starnix_core::device::kobject::Device;
1414
use starnix_core::fs::fuchsia::new_remote_file_ops;
1515
use starnix_core::fs_node_impl_not_dir;
16-
use starnix_core::task::CurrentTask;
16+
use starnix_core::task::{CurrentTask, FullCredentials};
1717
use starnix_core::vfs::pseudo::simple_directory::SimpleDirectoryMutator;
1818
use starnix_core::vfs::{FileOps, FsNode, FsNodeOps, FsStr, FsString};
1919
use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked};
@@ -85,8 +85,8 @@ fn connect(socket_label: Arc<FsString>) -> Result<Box<dyn FileOps>, Errno> {
8585
.map_err(|_| errno!(ENOENT))?
8686
.map_err(|_| errno!(ENOENT))?;
8787

88-
// This will only be reached if the status was OK
89-
new_remote_file_ops(tx.into())
88+
// This will only be reached if the status was OK. Credentials are ignored for sockets.
89+
new_remote_file_ops(tx.into(), FullCredentials::for_kernel())
9090
}
9191

9292
impl DeviceOps for SocketTunnelFile {

0 commit comments

Comments
 (0)