blob: 01b82095d0b3554a0ad3fc19e3cdb38da4601f24 [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 Hsieh6e78d3c2022-08-26 10:21:37 -070030use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
Victor Hsieh559b9272021-11-08 15:15:14 -080031use 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
34use crate::fsverity;
35use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
Victor Hsiehf7fc3d32021-11-22 10:20:33 -080036 BnVirtFdService, FsStat::FsStat, IVirtFdService, MAX_REQUESTING_DATA,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070037};
Inseob Kimc0886c22021-12-13 17:41:24 +090038use authfs_fsverity_metadata::{
39 get_fsverity_metadata_path, parse_fsverity_metadata, FSVerityMetadata,
40};
Alan Stokes0e82b502022-08-08 14:44:48 +010041use binder::{
42 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
43};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070044
Victor Hsiehf393a722021-12-08 13:04:27 -080045/// Bitflags of forbidden file mode, e.g. setuid, setgid and sticky bit.
46const FORBIDDEN_MODES: Mode = Mode::from_bits_truncate(!0o777);
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070047
48/// Configuration of a file descriptor to be served/exposed/shared.
49pub enum FdConfig {
50 /// A read-only file to serve by this server. The file is supposed to be verifiable with the
51 /// associated fs-verity metadata.
52 Readonly {
53 /// The file to read from. fs-verity metadata can be retrieved from this file's FD.
54 file: File,
55
Inseob Kimc0886c22021-12-13 17:41:24 +090056 // Alternative metadata storing merkle tree and signature.
57 alt_metadata: Option<Box<FSVerityMetadata>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070058 },
59
60 /// A readable/writable file to serve by this server. This backing file should just be a
61 /// regular file and does not have any specific property.
62 ReadWrite(File),
Victor Hsieh45636232021-10-15 17:52:51 -070063
Victor Hsieh559b9272021-11-08 15:15:14 -080064 /// A read-only directory to serve by this server.
Victor Hsiehbf944d72022-03-07 23:46:43 +000065 InputDir(OwnedFd),
Victor Hsieh559b9272021-11-08 15:15:14 -080066
Victor Hsieh45636232021-10-15 17:52:51 -070067 /// A writable directory to serve by this server.
Victor Hsiehbf944d72022-03-07 23:46:43 +000068 OutputDir(OwnedFd),
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070069}
70
71pub struct FdService {
Victor Hsieh45636232021-10-15 17:52:51 -070072 /// A pool of opened files and directories, which can be looked up by the FD number.
Victor Hsiehbf944d72022-03-07 23:46:43 +000073 fd_pool: Arc<RwLock<BTreeMap<i32, FdConfig>>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070074}
75
76impl FdService {
77 pub fn new_binder(fd_pool: BTreeMap<i32, FdConfig>) -> Strong<dyn IVirtFdService> {
Victor Hsieh45636232021-10-15 17:52:51 -070078 BnVirtFdService::new_binder(
Victor Hsiehbf944d72022-03-07 23:46:43 +000079 FdService { fd_pool: Arc::new(RwLock::new(fd_pool)) },
Victor Hsieh45636232021-10-15 17:52:51 -070080 BinderFeatures::default(),
81 )
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070082 }
83
Victor Hsieh45636232021-10-15 17:52:51 -070084 /// Handles the requesting file `id` with `handle_fn` if it is in the FD pool. This function
85 /// returns whatever `handle_fn` returns.
86 fn handle_fd<F, R>(&self, id: i32, handle_fn: F) -> BinderResult<R>
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070087 where
88 F: FnOnce(&FdConfig) -> BinderResult<R>,
89 {
Victor Hsiehbf944d72022-03-07 23:46:43 +000090 let fd_pool = self.fd_pool.read().unwrap();
Victor Hsieh45636232021-10-15 17:52:51 -070091 let fd_config = fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
92 handle_fn(fd_config)
93 }
94
95 /// Inserts a new FD and corresponding `FdConfig` created by `create_fn` to the FD pool, then
96 /// returns the new FD number.
97 fn insert_new_fd<F>(&self, fd: i32, create_fn: F) -> BinderResult<i32>
98 where
99 F: FnOnce(&mut FdConfig) -> BinderResult<(i32, FdConfig)>,
100 {
Victor Hsiehbf944d72022-03-07 23:46:43 +0000101 let mut fd_pool = self.fd_pool.write().unwrap();
Chris Wailes641fc4a2021-12-01 15:03:21 -0800102 let fd_config = fd_pool.get_mut(&fd).ok_or_else(|| new_errno_error(Errno::EBADF))?;
103 let (new_fd, new_fd_config) = create_fn(fd_config)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700104 if let btree_map::Entry::Vacant(entry) = fd_pool.entry(new_fd) {
105 entry.insert(new_fd_config);
106 Ok(new_fd)
107 } else {
Andrew Walbrandcf9d582022-08-03 11:25:24 +0000108 Err(Status::new_exception_str(
Victor Hsieh45636232021-10-15 17:52:51 -0700109 ExceptionCode::ILLEGAL_STATE,
Andrew Walbrandcf9d582022-08-03 11:25:24 +0000110 Some(format!(
111 "The newly created FD {} is already in the pool unexpectedly",
112 new_fd
113 )),
Victor Hsieh45636232021-10-15 17:52:51 -0700114 ))
115 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700116 }
117}
118
119impl Interface for FdService {}
120
121impl IVirtFdService for FdService {
122 fn readFile(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
123 let size: usize = validate_and_cast_size(size)?;
124 let offset: u64 = validate_and_cast_offset(offset)?;
125
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700126 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700127 FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
128 read_into_buf(file, size, offset).map_err(|e| {
129 error!("readFile: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700130 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700131 })
132 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800133 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700134 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700135 }
136
137 fn readFsverityMerkleTree(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
138 let size: usize = validate_and_cast_size(size)?;
139 let offset: u64 = validate_and_cast_offset(offset)?;
140
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700141 self.handle_fd(id, |config| match config {
Inseob Kimc0886c22021-12-13 17:41:24 +0900142 FdConfig::Readonly { file, alt_metadata, .. } => {
143 let mut buf = vec![0; size];
144
145 let s = if let Some(metadata) = &alt_metadata {
146 metadata.read_merkle_tree(offset, &mut buf).map_err(|e| {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700147 error!("readFsverityMerkleTree: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700148 new_errno_error(Errno::EIO)
Inseob Kimc0886c22021-12-13 17:41:24 +0900149 })?
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700150 } else {
Inseob Kimc0886c22021-12-13 17:41:24 +0900151 fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf).map_err(|e| {
152 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
153 new_errno_error(Errno::EIO)
154 })?
155 };
156 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
157 buf.truncate(s);
158 Ok(buf)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700159 }
160 FdConfig::ReadWrite(_file) => {
161 // For a writable file, Merkle tree is not expected to be served since Auth FS
162 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
163 // use.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700164 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700165 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800166 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700167 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700168 }
169
170 fn readFsveritySignature(&self, id: i32) -> BinderResult<Vec<u8>> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700171 self.handle_fd(id, |config| match config {
Inseob Kimc0886c22021-12-13 17:41:24 +0900172 FdConfig::Readonly { file, alt_metadata, .. } => {
173 if let Some(metadata) = &alt_metadata {
174 if let Some(signature) = &metadata.signature {
175 Ok(signature.clone())
176 } else {
Andrew Walbrandcf9d582022-08-03 11:25:24 +0000177 Err(Status::new_service_specific_error_str(
178 -1,
179 Some("metadata doesn't contain a signature"),
Inseob Kimc0886c22021-12-13 17:41:24 +0900180 ))
181 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700182 } else {
183 let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
184 let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
185 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700186 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700187 })?;
188 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
189 buf.truncate(s);
190 Ok(buf)
191 }
192 }
193 FdConfig::ReadWrite(_file) => {
194 // There is no signature for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700195 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700196 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800197 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700198 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700199 }
200
201 fn writeFile(&self, id: i32, buf: &[u8], offset: i64) -> BinderResult<i32> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700202 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700203 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
204 FdConfig::ReadWrite(file) => {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700205 let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700206 // Check buffer size just to make `as i32` safe below.
207 if buf.len() > i32::MAX as usize {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700208 return Err(new_errno_error(Errno::EOVERFLOW));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700209 }
210 Ok(file.write_at(buf, offset).map_err(|e| {
211 error!("writeFile: write error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700212 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700213 })? as i32)
214 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800215 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700216 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700217 }
218
219 fn resize(&self, id: i32, size: i64) -> BinderResult<()> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700220 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700221 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
222 FdConfig::ReadWrite(file) => {
223 if size < 0 {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700224 return Err(new_errno_error(Errno::EINVAL));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700225 }
226 file.set_len(size as u64).map_err(|e| {
227 error!("resize: set_len error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700228 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700229 })
230 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800231 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700232 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700233 }
234
235 fn getFileSize(&self, id: i32) -> BinderResult<i64> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700236 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700237 FdConfig::Readonly { file, .. } => {
238 let size = file
239 .metadata()
240 .map_err(|e| {
241 error!("getFileSize error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700242 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700243 })?
244 .len();
245 Ok(size.try_into().map_err(|e| {
246 error!("getFileSize: File too large: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700247 new_errno_error(Errno::EFBIG)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700248 })?)
249 }
250 FdConfig::ReadWrite(_file) => {
251 // Content and metadata of a writable file needs to be tracked by authfs, since
252 // fd_server isn't considered trusted. So there is no point to support getFileSize
253 // for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700254 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700255 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800256 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
257 })
258 }
259
Victor Hsiehdd99b462021-12-02 17:36:15 -0800260 fn openFileInDirectory(&self, dir_fd: i32, file_path: &str) -> BinderResult<i32> {
Victor Hsieh559b9272021-11-08 15:15:14 -0800261 let path_buf = PathBuf::from(file_path);
262 // Checks if the path is a simple, related path.
263 if path_buf.components().any(|c| !matches!(c, Component::Normal(_))) {
264 return Err(new_errno_error(Errno::EINVAL));
265 }
266
Victor Hsiehdd99b462021-12-02 17:36:15 -0800267 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800268 FdConfig::InputDir(dir) => {
Victor Hsieh6e78d3c2022-08-26 10:21:37 -0700269 let file = open_readonly_at(dir.as_fd(), &path_buf).map_err(new_errno_error)?;
Victor Hsieh559b9272021-11-08 15:15:14 -0800270
Inseob Kimc0886c22021-12-13 17:41:24 +0900271 let metadata_path_buf = get_fsverity_metadata_path(&path_buf);
Victor Hsieh6e78d3c2022-08-26 10:21:37 -0700272 let metadata = open_readonly_at(dir.as_fd(), &metadata_path_buf)
Inseob Kimc0886c22021-12-13 17:41:24 +0900273 .ok()
274 .and_then(|f| parse_fsverity_metadata(f).ok());
275
276 Ok((file.as_raw_fd(), FdConfig::Readonly { file, alt_metadata: metadata }))
Victor Hsieh559b9272021-11-08 15:15:14 -0800277 }
278 FdConfig::OutputDir(_) => {
279 Err(new_errno_error(Errno::ENOSYS)) // TODO: Implement when needed
280 }
281 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsieh45636232021-10-15 17:52:51 -0700282 })
283 }
284
Victor Hsiehf393a722021-12-08 13:04:27 -0800285 fn createFileInDirectory(&self, dir_fd: i32, basename: &str, mode: i32) -> BinderResult<i32> {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800286 validate_basename(basename)?;
287
288 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800289 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
Victor Hsieh45636232021-10-15 17:52:51 -0700290 FdConfig::OutputDir(dir) => {
Victor Hsiehf393a722021-12-08 13:04:27 -0800291 let mode = validate_file_mode(mode)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700292 let new_fd = openat(
293 dir.as_raw_fd(),
294 basename,
Victor Hsieh928d5032022-02-15 00:06:20 +0000295 // This function is supposed to be only called when FUSE/authfs thinks the file
296 // does not exist. However, if the file does exist from the view of fd_server
297 // (where the execution context is considered untrusted), we prefer to honor
298 // authfs and still allow the create to success. Therefore, always use O_TRUNC.
Victor Hsieh45636232021-10-15 17:52:51 -0700299 OFlag::O_CREAT | OFlag::O_RDWR | OFlag::O_TRUNC,
Victor Hsiehf393a722021-12-08 13:04:27 -0800300 mode,
Victor Hsieh45636232021-10-15 17:52:51 -0700301 )
302 .map_err(new_errno_error)?;
303 // SAFETY: new_fd is just created and not an error.
304 let new_file = unsafe { File::from_raw_fd(new_fd) };
305 Ok((new_fd, FdConfig::ReadWrite(new_file)))
306 }
307 _ => Err(new_errno_error(Errno::ENOTDIR)),
308 })
309 }
310
Victor Hsiehf393a722021-12-08 13:04:27 -0800311 fn createDirectoryInDirectory(
312 &self,
313 dir_fd: i32,
314 basename: &str,
315 mode: i32,
316 ) -> BinderResult<i32> {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800317 validate_basename(basename)?;
318
Victor Hsieh45636232021-10-15 17:52:51 -0700319 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800320 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
Victor Hsieh45636232021-10-15 17:52:51 -0700321 FdConfig::OutputDir(_) => {
Victor Hsiehf393a722021-12-08 13:04:27 -0800322 let mode = validate_file_mode(mode)?;
323 mkdirat(dir_fd, basename, mode).map_err(new_errno_error)?;
Victor Hsiehbf944d72022-03-07 23:46:43 +0000324 let new_dir_fd =
325 openat(dir_fd, basename, OFlag::O_DIRECTORY | OFlag::O_RDONLY, Mode::empty())
326 .map_err(new_errno_error)?;
327 // SAFETY: new_dir_fd is just created and not an error.
328 let fd_owner = unsafe { OwnedFd::from_raw_fd(new_dir_fd) };
329 Ok((new_dir_fd, FdConfig::OutputDir(fd_owner)))
Victor Hsieh45636232021-10-15 17:52:51 -0700330 }
331 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700332 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700333 }
Victor Hsiehf7fc3d32021-11-22 10:20:33 -0800334
Victor Hsiehdd99b462021-12-02 17:36:15 -0800335 fn deleteFile(&self, dir_fd: i32, basename: &str) -> BinderResult<()> {
336 validate_basename(basename)?;
337
338 self.handle_fd(dir_fd, |config| match config {
Victor Hsiehbf944d72022-03-07 23:46:43 +0000339 FdConfig::OutputDir(_) => {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800340 unlinkat(Some(dir_fd), basename, UnlinkatFlags::NoRemoveDir)
341 .map_err(new_errno_error)?;
342 Ok(())
343 }
344 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
345 _ => Err(new_errno_error(Errno::ENOTDIR)),
346 })
347 }
348
349 fn deleteDirectory(&self, dir_fd: i32, basename: &str) -> BinderResult<()> {
350 validate_basename(basename)?;
351
352 self.handle_fd(dir_fd, |config| match config {
Victor Hsiehbf944d72022-03-07 23:46:43 +0000353 FdConfig::OutputDir(_) => {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800354 unlinkat(Some(dir_fd), basename, UnlinkatFlags::RemoveDir)
355 .map_err(new_errno_error)?;
356 Ok(())
357 }
358 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
359 _ => Err(new_errno_error(Errno::ENOTDIR)),
360 })
361 }
362
Victor Hsiehf393a722021-12-08 13:04:27 -0800363 fn chmod(&self, fd: i32, mode: i32) -> BinderResult<()> {
364 self.handle_fd(fd, |config| match config {
365 FdConfig::ReadWrite(_) | FdConfig::OutputDir(_) => {
366 let mode = validate_file_mode(mode)?;
367 fchmod(fd, mode).map_err(new_errno_error)
368 }
369 _ => Err(new_errno_error(Errno::EACCES)),
370 })
371 }
372
Victor Hsiehf7fc3d32021-11-22 10:20:33 -0800373 fn statfs(&self) -> BinderResult<FsStat> {
374 let st = statvfs("/data").map_err(new_errno_error)?;
375 try_into_fs_stat(st).map_err(|_e| new_errno_error(Errno::EINVAL))
376 }
377}
378
379fn try_into_fs_stat(st: Statvfs) -> Result<FsStat, std::num::TryFromIntError> {
380 Ok(FsStat {
381 blockSize: st.block_size().try_into()?,
382 fragmentSize: st.fragment_size().try_into()?,
383 blockNumbers: st.blocks().try_into()?,
384 blockAvailable: st.blocks_available().try_into()?,
385 inodesAvailable: st.files_available().try_into()?,
386 maxFilename: st.name_max().try_into()?,
387 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700388}
389
390fn read_into_buf(file: &File, max_size: usize, offset: u64) -> io::Result<Vec<u8>> {
391 let remaining = file.metadata()?.len().saturating_sub(offset);
392 let buf_size = min(remaining, max_size as u64) as usize;
393 let mut buf = vec![0; buf_size];
394 file.read_exact_at(&mut buf, offset)?;
395 Ok(buf)
396}
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700397
398fn new_errno_error(errno: Errno) -> Status {
Andrew Walbrandcf9d582022-08-03 11:25:24 +0000399 Status::new_service_specific_error_str(errno as i32, Some(errno.desc()))
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700400}
Victor Hsieh559b9272021-11-08 15:15:14 -0800401
Victor Hsieh6e78d3c2022-08-26 10:21:37 -0700402fn open_readonly_at(dir_fd: BorrowedFd, path: &Path) -> nix::Result<File> {
403 let new_fd = openat(dir_fd.as_raw_fd(), path, OFlag::O_RDONLY, Mode::empty())?;
Victor Hsieh559b9272021-11-08 15:15:14 -0800404 // SAFETY: new_fd is just created successfully and not owned.
405 let new_file = unsafe { File::from_raw_fd(new_fd) };
406 Ok(new_file)
407}
Victor Hsiehdd99b462021-12-02 17:36:15 -0800408
Victor Hsiehf393a722021-12-08 13:04:27 -0800409fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
410 offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
411}
412
413fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
414 if size > MAX_REQUESTING_DATA {
415 Err(new_errno_error(Errno::EFBIG))
416 } else {
417 size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
418 }
419}
420
Victor Hsiehdd99b462021-12-02 17:36:15 -0800421fn validate_basename(name: &str) -> BinderResult<()> {
422 if name.contains(MAIN_SEPARATOR) {
423 Err(new_errno_error(Errno::EINVAL))
424 } else {
425 Ok(())
426 }
427}
Victor Hsiehf393a722021-12-08 13:04:27 -0800428
429fn validate_file_mode(mode: i32) -> BinderResult<Mode> {
430 let mode = Mode::from_bits(mode as mode_t).ok_or_else(|| new_errno_error(Errno::EINVAL))?;
431 if mode.intersects(FORBIDDEN_MODES) {
432 Err(new_errno_error(Errno::EPERM))
433 } else {
434 Ok(mode)
435 }
436}