blob: 125b991cd3a7412c706fbf1c1c26d5c707fdc166 [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 Hsiehf393a722021-12-08 13:04:27 -080020 dir::Dir, errno::Errno, fcntl::openat, fcntl::OFlag, sys::stat::fchmod, sys::stat::mkdirat,
21 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 Hsieh45636232021-10-15 17:52:51 -070032use std::sync::{Arc, Mutex};
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};
38use authfs_aidl_interface::binder::{
Victor Hsieh45636232021-10-15 17:52:51 -070039 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070040};
Inseob Kimc0886c22021-12-13 17:41:24 +090041use authfs_fsverity_metadata::{
42 get_fsverity_metadata_path, parse_fsverity_metadata, FSVerityMetadata,
43};
Victor Hsieh45636232021-10-15 17:52:51 -070044use binder_common::{new_binder_exception, new_binder_service_specific_error};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070045
Victor Hsiehf393a722021-12-08 13:04:27 -080046/// Bitflags of forbidden file mode, e.g. setuid, setgid and sticky bit.
47const FORBIDDEN_MODES: Mode = Mode::from_bits_truncate(!0o777);
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070048
49/// Configuration of a file descriptor to be served/exposed/shared.
50pub enum FdConfig {
51 /// A read-only file to serve by this server. The file is supposed to be verifiable with the
52 /// associated fs-verity metadata.
53 Readonly {
54 /// The file to read from. fs-verity metadata can be retrieved from this file's FD.
55 file: File,
56
Inseob Kimc0886c22021-12-13 17:41:24 +090057 // Alternative metadata storing merkle tree and signature.
58 alt_metadata: Option<Box<FSVerityMetadata>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070059 },
60
61 /// A readable/writable file to serve by this server. This backing file should just be a
62 /// regular file and does not have any specific property.
63 ReadWrite(File),
Victor Hsieh45636232021-10-15 17:52:51 -070064
Victor Hsieh559b9272021-11-08 15:15:14 -080065 /// A read-only directory to serve by this server.
66 InputDir(Dir),
67
Victor Hsieh45636232021-10-15 17:52:51 -070068 /// A writable directory to serve by this server.
69 OutputDir(Dir),
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070070}
71
72pub struct FdService {
Victor Hsieh45636232021-10-15 17:52:51 -070073 /// A pool of opened files and directories, which can be looked up by the FD number.
74 fd_pool: Arc<Mutex<BTreeMap<i32, FdConfig>>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070075}
76
77impl FdService {
78 pub fn new_binder(fd_pool: BTreeMap<i32, FdConfig>) -> Strong<dyn IVirtFdService> {
Victor Hsieh45636232021-10-15 17:52:51 -070079 BnVirtFdService::new_binder(
80 FdService { fd_pool: Arc::new(Mutex::new(fd_pool)) },
81 BinderFeatures::default(),
82 )
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070083 }
84
Victor Hsieh45636232021-10-15 17:52:51 -070085 /// Handles the requesting file `id` with `handle_fn` if it is in the FD pool. This function
86 /// returns whatever `handle_fn` returns.
87 fn handle_fd<F, R>(&self, id: i32, handle_fn: F) -> BinderResult<R>
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070088 where
89 F: FnOnce(&FdConfig) -> BinderResult<R>,
90 {
Victor Hsieh45636232021-10-15 17:52:51 -070091 let fd_pool = self.fd_pool.lock().unwrap();
92 let fd_config = fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
93 handle_fn(fd_config)
94 }
95
96 /// Inserts a new FD and corresponding `FdConfig` created by `create_fn` to the FD pool, then
97 /// returns the new FD number.
98 fn insert_new_fd<F>(&self, fd: i32, create_fn: F) -> BinderResult<i32>
99 where
100 F: FnOnce(&mut FdConfig) -> BinderResult<(i32, FdConfig)>,
101 {
102 let mut fd_pool = self.fd_pool.lock().unwrap();
Chris Wailes641fc4a2021-12-01 15:03:21 -0800103 let fd_config = fd_pool.get_mut(&fd).ok_or_else(|| new_errno_error(Errno::EBADF))?;
104 let (new_fd, new_fd_config) = create_fn(fd_config)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700105 if let btree_map::Entry::Vacant(entry) = fd_pool.entry(new_fd) {
106 entry.insert(new_fd_config);
107 Ok(new_fd)
108 } else {
109 Err(new_binder_exception(
110 ExceptionCode::ILLEGAL_STATE,
111 format!("The newly created FD {} is already in the pool unexpectedly", new_fd),
112 ))
113 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700114 }
115}
116
117impl Interface for FdService {}
118
119impl IVirtFdService for FdService {
120 fn readFile(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
121 let size: usize = validate_and_cast_size(size)?;
122 let offset: u64 = validate_and_cast_offset(offset)?;
123
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700124 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700125 FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
126 read_into_buf(file, size, offset).map_err(|e| {
127 error!("readFile: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700128 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700129 })
130 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800131 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700132 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700133 }
134
135 fn readFsverityMerkleTree(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
136 let size: usize = validate_and_cast_size(size)?;
137 let offset: u64 = validate_and_cast_offset(offset)?;
138
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700139 self.handle_fd(id, |config| match config {
Inseob Kimc0886c22021-12-13 17:41:24 +0900140 FdConfig::Readonly { file, alt_metadata, .. } => {
141 let mut buf = vec![0; size];
142
143 let s = if let Some(metadata) = &alt_metadata {
144 metadata.read_merkle_tree(offset, &mut buf).map_err(|e| {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700145 error!("readFsverityMerkleTree: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700146 new_errno_error(Errno::EIO)
Inseob Kimc0886c22021-12-13 17:41:24 +0900147 })?
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700148 } else {
Inseob Kimc0886c22021-12-13 17:41:24 +0900149 fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf).map_err(|e| {
150 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
151 new_errno_error(Errno::EIO)
152 })?
153 };
154 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
155 buf.truncate(s);
156 Ok(buf)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700157 }
158 FdConfig::ReadWrite(_file) => {
159 // For a writable file, Merkle tree is not expected to be served since Auth FS
160 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
161 // use.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700162 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700163 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800164 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700165 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700166 }
167
168 fn readFsveritySignature(&self, id: i32) -> BinderResult<Vec<u8>> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700169 self.handle_fd(id, |config| match config {
Inseob Kimc0886c22021-12-13 17:41:24 +0900170 FdConfig::Readonly { file, alt_metadata, .. } => {
171 if let Some(metadata) = &alt_metadata {
172 if let Some(signature) = &metadata.signature {
173 Ok(signature.clone())
174 } else {
175 Err(new_binder_exception(
176 ExceptionCode::SERVICE_SPECIFIC,
177 "metadata doesn't contain a signature".to_string(),
178 ))
179 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700180 } else {
181 let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
182 let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
183 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700184 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700185 })?;
186 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
187 buf.truncate(s);
188 Ok(buf)
189 }
190 }
191 FdConfig::ReadWrite(_file) => {
192 // There is no signature for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700193 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700194 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800195 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700196 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700197 }
198
199 fn writeFile(&self, id: i32, buf: &[u8], offset: i64) -> BinderResult<i32> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700200 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700201 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
202 FdConfig::ReadWrite(file) => {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700203 let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700204 // Check buffer size just to make `as i32` safe below.
205 if buf.len() > i32::MAX as usize {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700206 return Err(new_errno_error(Errno::EOVERFLOW));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700207 }
208 Ok(file.write_at(buf, offset).map_err(|e| {
209 error!("writeFile: write error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700210 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700211 })? as i32)
212 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800213 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700214 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700215 }
216
217 fn resize(&self, id: i32, size: i64) -> BinderResult<()> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700218 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700219 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
220 FdConfig::ReadWrite(file) => {
221 if size < 0 {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700222 return Err(new_errno_error(Errno::EINVAL));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700223 }
224 file.set_len(size as u64).map_err(|e| {
225 error!("resize: set_len error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700226 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700227 })
228 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800229 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700230 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700231 }
232
233 fn getFileSize(&self, id: i32) -> BinderResult<i64> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700234 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700235 FdConfig::Readonly { file, .. } => {
236 let size = file
237 .metadata()
238 .map_err(|e| {
239 error!("getFileSize error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700240 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700241 })?
242 .len();
243 Ok(size.try_into().map_err(|e| {
244 error!("getFileSize: File too large: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700245 new_errno_error(Errno::EFBIG)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700246 })?)
247 }
248 FdConfig::ReadWrite(_file) => {
249 // Content and metadata of a writable file needs to be tracked by authfs, since
250 // fd_server isn't considered trusted. So there is no point to support getFileSize
251 // for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700252 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700253 }
Victor Hsieh559b9272021-11-08 15:15:14 -0800254 FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
255 })
256 }
257
Victor Hsiehdd99b462021-12-02 17:36:15 -0800258 fn openFileInDirectory(&self, dir_fd: i32, file_path: &str) -> BinderResult<i32> {
Victor Hsieh559b9272021-11-08 15:15:14 -0800259 let path_buf = PathBuf::from(file_path);
260 // Checks if the path is a simple, related path.
261 if path_buf.components().any(|c| !matches!(c, Component::Normal(_))) {
262 return Err(new_errno_error(Errno::EINVAL));
263 }
264
Victor Hsiehdd99b462021-12-02 17:36:15 -0800265 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800266 FdConfig::InputDir(dir) => {
267 let file = open_readonly_at(dir.as_raw_fd(), &path_buf).map_err(new_errno_error)?;
268
Inseob Kimc0886c22021-12-13 17:41:24 +0900269 let metadata_path_buf = get_fsverity_metadata_path(&path_buf);
270 let metadata = open_readonly_at(dir.as_raw_fd(), &metadata_path_buf)
271 .ok()
272 .and_then(|f| parse_fsverity_metadata(f).ok());
273
274 Ok((file.as_raw_fd(), FdConfig::Readonly { file, alt_metadata: metadata }))
Victor Hsieh559b9272021-11-08 15:15:14 -0800275 }
276 FdConfig::OutputDir(_) => {
277 Err(new_errno_error(Errno::ENOSYS)) // TODO: Implement when needed
278 }
279 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsieh45636232021-10-15 17:52:51 -0700280 })
281 }
282
Victor Hsiehf393a722021-12-08 13:04:27 -0800283 fn createFileInDirectory(&self, dir_fd: i32, basename: &str, mode: i32) -> BinderResult<i32> {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800284 validate_basename(basename)?;
285
286 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800287 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
Victor Hsieh45636232021-10-15 17:52:51 -0700288 FdConfig::OutputDir(dir) => {
Victor Hsiehf393a722021-12-08 13:04:27 -0800289 let mode = validate_file_mode(mode)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700290 let new_fd = openat(
291 dir.as_raw_fd(),
292 basename,
293 // TODO(205172873): handle the case when the file already exist, e.g. truncate
294 // or fail, and possibly allow the client to specify. For now, always truncate.
295 OFlag::O_CREAT | OFlag::O_RDWR | OFlag::O_TRUNC,
Victor Hsiehf393a722021-12-08 13:04:27 -0800296 mode,
Victor Hsieh45636232021-10-15 17:52:51 -0700297 )
298 .map_err(new_errno_error)?;
299 // SAFETY: new_fd is just created and not an error.
300 let new_file = unsafe { File::from_raw_fd(new_fd) };
301 Ok((new_fd, FdConfig::ReadWrite(new_file)))
302 }
303 _ => Err(new_errno_error(Errno::ENOTDIR)),
304 })
305 }
306
Victor Hsiehf393a722021-12-08 13:04:27 -0800307 fn createDirectoryInDirectory(
308 &self,
309 dir_fd: i32,
310 basename: &str,
311 mode: i32,
312 ) -> BinderResult<i32> {
Victor Hsiehdd99b462021-12-02 17:36:15 -0800313 validate_basename(basename)?;
314
Victor Hsieh45636232021-10-15 17:52:51 -0700315 self.insert_new_fd(dir_fd, |config| match config {
Victor Hsieh559b9272021-11-08 15:15:14 -0800316 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
Victor Hsieh45636232021-10-15 17:52:51 -0700317 FdConfig::OutputDir(_) => {
Victor Hsiehf393a722021-12-08 13:04:27 -0800318 let mode = validate_file_mode(mode)?;
319 mkdirat(dir_fd, basename, mode).map_err(new_errno_error)?;
Victor Hsieh45636232021-10-15 17:52:51 -0700320 let new_dir = Dir::openat(
321 dir_fd,
322 basename,
323 OFlag::O_DIRECTORY | OFlag::O_RDONLY,
324 Mode::empty(),
325 )
326 .map_err(new_errno_error)?;
327 Ok((new_dir.as_raw_fd(), FdConfig::OutputDir(new_dir)))
328 }
329 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700330 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700331 }
Victor Hsiehf7fc3d32021-11-22 10:20:33 -0800332
Victor Hsiehdd99b462021-12-02 17:36:15 -0800333 fn deleteFile(&self, dir_fd: i32, basename: &str) -> BinderResult<()> {
334 validate_basename(basename)?;
335
336 self.handle_fd(dir_fd, |config| match config {
337 FdConfig::OutputDir(_dir) => {
338 unlinkat(Some(dir_fd), basename, UnlinkatFlags::NoRemoveDir)
339 .map_err(new_errno_error)?;
340 Ok(())
341 }
342 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
343 _ => Err(new_errno_error(Errno::ENOTDIR)),
344 })
345 }
346
347 fn deleteDirectory(&self, dir_fd: i32, basename: &str) -> BinderResult<()> {
348 validate_basename(basename)?;
349
350 self.handle_fd(dir_fd, |config| match config {
351 FdConfig::OutputDir(_dir) => {
352 unlinkat(Some(dir_fd), basename, UnlinkatFlags::RemoveDir)
353 .map_err(new_errno_error)?;
354 Ok(())
355 }
356 FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
357 _ => Err(new_errno_error(Errno::ENOTDIR)),
358 })
359 }
360
Victor Hsiehf393a722021-12-08 13:04:27 -0800361 fn chmod(&self, fd: i32, mode: i32) -> BinderResult<()> {
362 self.handle_fd(fd, |config| match config {
363 FdConfig::ReadWrite(_) | FdConfig::OutputDir(_) => {
364 let mode = validate_file_mode(mode)?;
365 fchmod(fd, mode).map_err(new_errno_error)
366 }
367 _ => Err(new_errno_error(Errno::EACCES)),
368 })
369 }
370
Victor Hsiehf7fc3d32021-11-22 10:20:33 -0800371 fn statfs(&self) -> BinderResult<FsStat> {
372 let st = statvfs("/data").map_err(new_errno_error)?;
373 try_into_fs_stat(st).map_err(|_e| new_errno_error(Errno::EINVAL))
374 }
375}
376
377fn try_into_fs_stat(st: Statvfs) -> Result<FsStat, std::num::TryFromIntError> {
378 Ok(FsStat {
379 blockSize: st.block_size().try_into()?,
380 fragmentSize: st.fragment_size().try_into()?,
381 blockNumbers: st.blocks().try_into()?,
382 blockAvailable: st.blocks_available().try_into()?,
383 inodesAvailable: st.files_available().try_into()?,
384 maxFilename: st.name_max().try_into()?,
385 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700386}
387
388fn read_into_buf(file: &File, max_size: usize, offset: u64) -> io::Result<Vec<u8>> {
389 let remaining = file.metadata()?.len().saturating_sub(offset);
390 let buf_size = min(remaining, max_size as u64) as usize;
391 let mut buf = vec![0; buf_size];
392 file.read_exact_at(&mut buf, offset)?;
393 Ok(buf)
394}
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700395
396fn new_errno_error(errno: Errno) -> Status {
397 new_binder_service_specific_error(errno as i32, errno.desc())
398}
Victor Hsieh559b9272021-11-08 15:15:14 -0800399
400fn open_readonly_at(dir_fd: RawFd, path: &Path) -> nix::Result<File> {
401 let new_fd = openat(dir_fd, path, OFlag::O_RDONLY, Mode::empty())?;
402 // SAFETY: new_fd is just created successfully and not owned.
403 let new_file = unsafe { File::from_raw_fd(new_fd) };
404 Ok(new_file)
405}
Victor Hsiehdd99b462021-12-02 17:36:15 -0800406
Victor Hsiehf393a722021-12-08 13:04:27 -0800407fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
408 offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
409}
410
411fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
412 if size > MAX_REQUESTING_DATA {
413 Err(new_errno_error(Errno::EFBIG))
414 } else {
415 size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
416 }
417}
418
Victor Hsiehdd99b462021-12-02 17:36:15 -0800419fn validate_basename(name: &str) -> BinderResult<()> {
420 if name.contains(MAIN_SEPARATOR) {
421 Err(new_errno_error(Errno::EINVAL))
422 } else {
423 Ok(())
424 }
425}
Victor Hsiehf393a722021-12-08 13:04:27 -0800426
427fn validate_file_mode(mode: i32) -> BinderResult<Mode> {
428 let mode = Mode::from_bits(mode as mode_t).ok_or_else(|| new_errno_error(Errno::EINVAL))?;
429 if mode.intersects(FORBIDDEN_MODES) {
430 Err(new_errno_error(Errno::EPERM))
431 } else {
432 Ok(mode)
433 }
434}