blob: 3a3cdb2014c72619b14fea46fc0c187619e7ef99 [file] [log] [blame]
Victor Hsiehb0f5fc82021-10-15 17:24:19 -07001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use anyhow::Result;
18use log::error;
Victor Hsieh45636232021-10-15 17:52:51 -070019use nix::{
Victor Hsiehbf944d72022-03-07 23:46:43 +000020 errno::Errno, fcntl::openat, fcntl::OFlag, sys::stat::fchmod, sys::stat::mkdirat,
Victor Hsiehf393a722021-12-08 13:04:27 -080021 sys::stat::mode_t, sys::stat::Mode, sys::statvfs::statvfs, sys::statvfs::Statvfs,
22 unistd::unlinkat, unistd::UnlinkatFlags,
Victor Hsieh45636232021-10-15 17:52:51 -070023};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070024use std::cmp::min;
Victor Hsieh45636232021-10-15 17:52:51 -070025use std::collections::{btree_map, BTreeMap};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070026use std::convert::TryInto;
27use std::fs::File;
28use std::io;
29use std::os::unix::fs::FileExt;
Victor Hsieh559b9272021-11-08 15:15:14 -080030use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
31use std::path::{Component, Path, PathBuf, MAIN_SEPARATOR};
Victor Hsiehbf944d72022-03-07 23:46:43 +000032use std::sync::{Arc, RwLock};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070033
Victor Hsiehbf944d72022-03-07 23:46:43 +000034use crate::common::OwnedFd;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070035use crate::fsverity;
36use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
Victor Hsiehf7fc3d32021-11-22 10:20:33 -080037 BnVirtFdService, FsStat::FsStat, IVirtFdService, MAX_REQUESTING_DATA,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070038};
39use authfs_aidl_interface::binder::{
Victor Hsieh45636232021-10-15 17:52:51 -070040 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070041};
Inseob Kimc0886c22021-12-13 17:41:24 +090042use authfs_fsverity_metadata::{
43 get_fsverity_metadata_path, parse_fsverity_metadata, FSVerityMetadata,
44};
Victor Hsieh45636232021-10-15 17:52:51 -070045use binder_common::{new_binder_exception, new_binder_service_specific_error};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070046
Victor Hsiehf393a722021-12-08 13:04:27 -080047/// Bitflags of forbidden file mode, e.g. setuid, setgid and sticky bit.
48const FORBIDDEN_MODES: Mode = Mode::from_bits_truncate(!0o777);
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070049
50/// Configuration of a file descriptor to be served/exposed/shared.
51pub enum FdConfig {
52 /// A read-only file to serve by this server. The file is supposed to be verifiable with the
53 /// associated fs-verity metadata.
54 Readonly {
55 /// The file to read from. fs-verity metadata can be retrieved from this file's FD.
56 file: File,
57
Inseob Kimc0886c22021-12-13 17:41:24 +090058 // Alternative metadata storing merkle tree and signature.
59 alt_metadata: Option<Box<FSVerityMetadata>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070060 },
61
62 /// A readable/writable file to serve by this server. This backing file should just be a
63 /// regular file and does not have any specific property.
64 ReadWrite(File),
Victor Hsieh45636232021-10-15 17:52:51 -070065
Victor Hsieh559b9272021-11-08 15:15:14 -080066 /// A read-only directory to serve by this server.
Victor Hsiehbf944d72022-03-07 23:46:43 +000067 InputDir(OwnedFd),
Victor Hsieh559b9272021-11-08 15:15:14 -080068
Victor Hsieh45636232021-10-15 17:52:51 -070069 /// A writable directory to serve by this server.
Victor Hsiehbf944d72022-03-07 23:46:43 +000070 OutputDir(OwnedFd),
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070071}
72
73pub struct FdService {
Victor Hsieh45636232021-10-15 17:52:51 -070074 /// A pool of opened files and directories, which can be looked up by the FD number.
Victor Hsiehbf944d72022-03-07 23:46:43 +000075 fd_pool: Arc<RwLock<BTreeMap<i32, FdConfig>>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070076}
77
78impl FdService {
79 pub fn new_binder(fd_pool: BTreeMap<i32, FdConfig>) -> Strong<dyn IVirtFdService> {
Victor Hsieh45636232021-10-15 17:52:51 -070080 BnVirtFdService::new_binder(
Victor Hsiehbf944d72022-03-07 23:46:43 +000081 FdService { fd_pool: Arc::new(RwLock::new(fd_pool)) },
Victor Hsieh45636232021-10-15 17:52:51 -070082 BinderFeatures::default(),
83 )
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070084 }
85
Victor Hsieh45636232021-10-15 17:52:51 -070086 /// Handles the requesting file `id` with `handle_fn` if it is in the FD pool. This function
87 /// returns whatever `handle_fn` returns.
88 fn handle_fd<F, R>(&self, id: i32, handle_fn: F) -> BinderResult<R>
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070089 where
90 F: FnOnce(&FdConfig) -> BinderResult<R>,
91 {
Victor Hsiehbf944d72022-03-07 23:46:43 +000092 let fd_pool = self.fd_pool.read().unwrap();
Victor Hsieh45636232021-10-15 17:52:51 -070093 let fd_config = fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
94 handle_fn(fd_config)
95 }
96
97 /// Inserts a new FD and corresponding `FdConfig` created by `create_fn` to the FD pool, then
98 /// returns the new FD number.
99 fn insert_new_fd<F>(&self, fd: i32, create_fn: F) -> BinderResult<i32>
100 where
101 F: FnOnce(&mut FdConfig) -> BinderResult<(i32, FdConfig)>,
102 {
Victor Hsiehbf944d72022-03-07 23:46:43 +0000103 let mut fd_pool = self.fd_pool.write().unwrap();
Chris Wailes641fc4a2021-12-01 15:03:21 -0800104 let fd_config = fd_pool.get_mut(&fd).ok_or_else(|| new_errno_error(Errno::EBADF))?;
105 let (new_fd, new_fd_config) = create_fn(fd_config)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700106 if let btree_map::Entry::Vacant(entry) = fd_pool.entry(new_fd) {
107 entry.insert(new_fd_config);
108 Ok(new_fd)
109 } else {
110 Err(new_binder_exception(
111 ExceptionCode::ILLEGAL_STATE,
112 format!("The newly created FD {} is already in the pool unexpectedly", new_fd),
113 ))
114 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700115 }
116}
117
118impl Interface for FdService {}
119
120impl IVirtFdService for FdService {
121 fn readFile(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
122 let size: usize = validate_and_cast_size(size)?;
123 let offset: u64 = validate_and_cast_offset(offset)?;
124
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700125 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700126 FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
127 read_into_buf(file, size, offset).map_err(|e| {
128 error!("readFile: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700129 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700130 })
131 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800132 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700133 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700134 }
135
136 fn readFsverityMerkleTree(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
137 let size: usize = validate_and_cast_size(size)?;
138 let offset: u64 = validate_and_cast_offset(offset)?;
139
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700140 self.handle_fd(id, |config| match config {
Inseob Kimc0886c22021-12-13 17:41:24 +0900141 FdConfig::Readonly { file, alt_metadata, .. } => {
142 let mut buf = vec![0; size];
143
144 let s = if let Some(metadata) = &alt_metadata {
145 metadata.read_merkle_tree(offset, &mut buf).map_err(|e| {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700146 error!("readFsverityMerkleTree: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700147 new_errno_error(Errno::EIO)
Inseob Kimc0886c22021-12-13 17:41:24 +0900148 })?
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700149 } else {
Inseob Kimc0886c22021-12-13 17:41:24 +0900150 fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf).map_err(|e| {
151 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
152 new_errno_error(Errno::EIO)
153 })?
154 };
155 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
156 buf.truncate(s);
157 Ok(buf)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700158 }
159 FdConfig::ReadWrite(_file) => {
160 // For a writable file, Merkle tree is not expected to be served since Auth FS
161 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
162 // use.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700163 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700164 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800165 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700166 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700167 }
168
169 fn readFsveritySignature(&self, id: i32) -> BinderResult<Vec<u8>> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700170 self.handle_fd(id, |config| match config {
Inseob Kimc0886c22021-12-13 17:41:24 +0900171 FdConfig::Readonly { file, alt_metadata, .. } => {
172 if let Some(metadata) = &alt_metadata {
173 if let Some(signature) = &metadata.signature {
174 Ok(signature.clone())
175 } else {
176 Err(new_binder_exception(
177 ExceptionCode::SERVICE_SPECIFIC,
Charisee2e0ded02022-02-26 01:24:50 +0000178 "metadata doesn't contain a signature",
Inseob Kimc0886c22021-12-13 17:41:24 +0900179 ))
180 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700181 } else {
182 let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
183 let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
184 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700185 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700186 })?;
187 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
188 buf.truncate(s);
189 Ok(buf)
190 }
191 }
192 FdConfig::ReadWrite(_file) => {
193 // There is no signature for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700194 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700195 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800196 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700197 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700198 }
199
200 fn writeFile(&self, id: i32, buf: &[u8], offset: i64) -> BinderResult<i32> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700201 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700202 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
203 FdConfig::ReadWrite(file) => {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700204 let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700205 // Check buffer size just to make `as i32` safe below.
206 if buf.len() > i32::MAX as usize {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700207 return Err(new_errno_error(Errno::EOVERFLOW));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700208 }
209 Ok(file.write_at(buf, offset).map_err(|e| {
210 error!("writeFile: write error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700211 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700212 })? as i32)
213 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800214 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700215 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700216 }
217
218 fn resize(&self, id: i32, size: i64) -> BinderResult<()> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700219 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700220 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
221 FdConfig::ReadWrite(file) => {
222 if size < 0 {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700223 return Err(new_errno_error(Errno::EINVAL));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700224 }
225 file.set_len(size as u64).map_err(|e| {
226 error!("resize: set_len error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700227 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700228 })
229 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800230 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700231 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700232 }
233
234 fn getFileSize(&self, id: i32) -> BinderResult<i64> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700235 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700236 FdConfig::Readonly { file, .. } => {
237 let size = file
238 .metadata()
239 .map_err(|e| {
240 error!("getFileSize error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700241 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700242 })?
243 .len();
244 Ok(size.try_into().map_err(|e| {
245 error!("getFileSize: File too large: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700246 new_errno_error(Errno::EFBIG)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700247 })?)
248 }
249 FdConfig::ReadWrite(_file) => {
250 // Content and metadata of a writable file needs to be tracked by authfs, since
251 // fd_server isn't considered trusted. So there is no point to support getFileSize
252 // for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700253 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700254 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800255 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
256 })
257 }
258
Victor Hsiehdd99b462021-12-02 17:36:15 -0800259 fn openFileInDirectory(&self, dir_fd: i32, file_path: &str) -> BinderResult<i32> {
Victor Hsieh559b9272021-11-08 15:15:14 -0800260 let path_buf = PathBuf::from(file_path);
261 // Checks if the path is a simple, related path.
262 if path_buf.components().any(|c| !matches!(c, Component::Normal(_))) {
263 return Err(new_errno_error(Errno::EINVAL));
264 }
265
Victor Hsiehdd99b462021-12-02 17:36:15 -0800266 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800267 FdConfig::InputDir(dir) => {
268 let file = open_readonly_at(dir.as_raw_fd(), &path_buf).map_err(new_errno_error)?;
269
Inseob Kimc0886c22021-12-13 17:41:24 +0900270 let metadata_path_buf = get_fsverity_metadata_path(&path_buf);
271 let metadata = open_readonly_at(dir.as_raw_fd(), &metadata_path_buf)
272 .ok()
273 .and_then(|f| parse_fsverity_metadata(f).ok());
274
275 Ok((file.as_raw_fd(), FdConfig::Readonly { file, alt_metadata: metadata }))
Victor Hsieh559b9272021-11-08 15:15:14 -0800276 }
277 FdConfig::OutputDir(_) => {
278 Err(new_errno_error(Errno::ENOSYS)) // TODO: Implement when needed
279 }
280 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsieh45636232021-10-15 17:52:51 -0700281 })
282 }
283
Victor Hsiehf393a722021-12-08 13:04:27 -0800284 fn createFileInDirectory(&self, dir_fd: i32, basename: &str, mode: i32) -> BinderResult<i32> {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800285 validate_basename(basename)?;
286
287 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800288 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
Victor Hsieh45636232021-10-15 17:52:51 -0700289 FdConfig::OutputDir(dir) => {
Victor Hsiehf393a722021-12-08 13:04:27 -0800290 let mode = validate_file_mode(mode)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700291 let new_fd = openat(
292 dir.as_raw_fd(),
293 basename,
Victor Hsieh928d5032022-02-15 00:06:20 +0000294 // This function is supposed to be only called when FUSE/authfs thinks the file
295 // does not exist. However, if the file does exist from the view of fd_server
296 // (where the execution context is considered untrusted), we prefer to honor
297 // authfs and still allow the create to success. Therefore, always use O_TRUNC.
Victor Hsieh45636232021-10-15 17:52:51 -0700298 OFlag::O_CREAT | OFlag::O_RDWR | OFlag::O_TRUNC,
Victor Hsiehf393a722021-12-08 13:04:27 -0800299 mode,
Victor Hsieh45636232021-10-15 17:52:51 -0700300 )
301 .map_err(new_errno_error)?;
302 // SAFETY: new_fd is just created and not an error.
303 let new_file = unsafe { File::from_raw_fd(new_fd) };
304 Ok((new_fd, FdConfig::ReadWrite(new_file)))
305 }
306 _ => Err(new_errno_error(Errno::ENOTDIR)),
307 })
308 }
309
Victor Hsiehf393a722021-12-08 13:04:27 -0800310 fn createDirectoryInDirectory(
311 &self,
312 dir_fd: i32,
313 basename: &str,
314 mode: i32,
315 ) -> BinderResult<i32> {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800316 validate_basename(basename)?;
317
Victor Hsieh45636232021-10-15 17:52:51 -0700318 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800319 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
Victor Hsieh45636232021-10-15 17:52:51 -0700320 FdConfig::OutputDir(_) => {
Victor Hsiehf393a722021-12-08 13:04:27 -0800321 let mode = validate_file_mode(mode)?;
322 mkdirat(dir_fd, basename, mode).map_err(new_errno_error)?;
Victor Hsiehbf944d72022-03-07 23:46:43 +0000323 let new_dir_fd =
324 openat(dir_fd, basename, OFlag::O_DIRECTORY | OFlag::O_RDONLY, Mode::empty())
325 .map_err(new_errno_error)?;
326 // SAFETY: new_dir_fd is just created and not an error.
327 let fd_owner = unsafe { OwnedFd::from_raw_fd(new_dir_fd) };
328 Ok((new_dir_fd, FdConfig::OutputDir(fd_owner)))
Victor Hsieh45636232021-10-15 17:52:51 -0700329 }
330 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700331 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700332 }
Victor Hsiehf7fc3d32021-11-22 10:20:33 -0800333
Victor Hsiehdd99b462021-12-02 17:36:15 -0800334 fn deleteFile(&self, dir_fd: i32, basename: &str) -> BinderResult<()> {
335 validate_basename(basename)?;
336
337 self.handle_fd(dir_fd, |config| match config {
Victor Hsiehbf944d72022-03-07 23:46:43 +0000338 FdConfig::OutputDir(_) => {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800339 unlinkat(Some(dir_fd), basename, UnlinkatFlags::NoRemoveDir)
340 .map_err(new_errno_error)?;
341 Ok(())
342 }
343 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
344 _ => Err(new_errno_error(Errno::ENOTDIR)),
345 })
346 }
347
348 fn deleteDirectory(&self, dir_fd: i32, basename: &str) -> BinderResult<()> {
349 validate_basename(basename)?;
350
351 self.handle_fd(dir_fd, |config| match config {
Victor Hsiehbf944d72022-03-07 23:46:43 +0000352 FdConfig::OutputDir(_) => {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800353 unlinkat(Some(dir_fd), basename, UnlinkatFlags::RemoveDir)
354 .map_err(new_errno_error)?;
355 Ok(())
356 }
357 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
358 _ => Err(new_errno_error(Errno::ENOTDIR)),
359 })
360 }
361
Victor Hsiehf393a722021-12-08 13:04:27 -0800362 fn chmod(&self, fd: i32, mode: i32) -> BinderResult<()> {
363 self.handle_fd(fd, |config| match config {
364 FdConfig::ReadWrite(_) | FdConfig::OutputDir(_) => {
365 let mode = validate_file_mode(mode)?;
366 fchmod(fd, mode).map_err(new_errno_error)
367 }
368 _ => Err(new_errno_error(Errno::EACCES)),
369 })
370 }
371
Victor Hsiehf7fc3d32021-11-22 10:20:33 -0800372 fn statfs(&self) -> BinderResult<FsStat> {
373 let st = statvfs("/data").map_err(new_errno_error)?;
374 try_into_fs_stat(st).map_err(|_e| new_errno_error(Errno::EINVAL))
375 }
376}
377
378fn try_into_fs_stat(st: Statvfs) -> Result<FsStat, std::num::TryFromIntError> {
379 Ok(FsStat {
380 blockSize: st.block_size().try_into()?,
381 fragmentSize: st.fragment_size().try_into()?,
382 blockNumbers: st.blocks().try_into()?,
383 blockAvailable: st.blocks_available().try_into()?,
384 inodesAvailable: st.files_available().try_into()?,
385 maxFilename: st.name_max().try_into()?,
386 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700387}
388
389fn read_into_buf(file: &File, max_size: usize, offset: u64) -> io::Result<Vec<u8>> {
390 let remaining = file.metadata()?.len().saturating_sub(offset);
391 let buf_size = min(remaining, max_size as u64) as usize;
392 let mut buf = vec![0; buf_size];
393 file.read_exact_at(&mut buf, offset)?;
394 Ok(buf)
395}
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700396
397fn new_errno_error(errno: Errno) -> Status {
398 new_binder_service_specific_error(errno as i32, errno.desc())
399}
Victor Hsieh559b9272021-11-08 15:15:14 -0800400
401fn open_readonly_at(dir_fd: RawFd, path: &Path) -> nix::Result<File> {
402 let new_fd = openat(dir_fd, path, OFlag::O_RDONLY, Mode::empty())?;
403 // SAFETY: new_fd is just created successfully and not owned.
404 let new_file = unsafe { File::from_raw_fd(new_fd) };
405 Ok(new_file)
406}
Victor Hsiehdd99b462021-12-02 17:36:15 -0800407
Victor Hsiehf393a722021-12-08 13:04:27 -0800408fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
409 offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
410}
411
412fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
413 if size > MAX_REQUESTING_DATA {
414 Err(new_errno_error(Errno::EFBIG))
415 } else {
416 size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
417 }
418}
419
Victor Hsiehdd99b462021-12-02 17:36:15 -0800420fn validate_basename(name: &str) -> BinderResult<()> {
421 if name.contains(MAIN_SEPARATOR) {
422 Err(new_errno_error(Errno::EINVAL))
423 } else {
424 Ok(())
425 }
426}
Victor Hsiehf393a722021-12-08 13:04:27 -0800427
428fn validate_file_mode(mode: i32) -> BinderResult<Mode> {
429 let mode = Mode::from_bits(mode as mode_t).ok_or_else(|| new_errno_error(Errno::EINVAL))?;
430 if mode.intersects(FORBIDDEN_MODES) {
431 Err(new_errno_error(Errno::EPERM))
432 } else {
433 Ok(mode)
434 }
435}