blob: 0c41eacc30504a37f7fd10c1dcd040146936595b [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::{
20 dir::Dir, errno::Errno, fcntl::openat, fcntl::OFlag, sys::stat::mkdirat, sys::stat::Mode,
21};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070022use std::cmp::min;
Victor Hsieh45636232021-10-15 17:52:51 -070023use std::collections::{btree_map, BTreeMap};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070024use std::convert::TryInto;
25use std::fs::File;
26use std::io;
27use std::os::unix::fs::FileExt;
Victor Hsieh45636232021-10-15 17:52:51 -070028use std::os::unix::io::{AsRawFd, FromRawFd};
29use std::path::MAIN_SEPARATOR;
30use std::sync::{Arc, Mutex};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070031
32use crate::fsverity;
33use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070034 BnVirtFdService, IVirtFdService, MAX_REQUESTING_DATA,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070035};
36use authfs_aidl_interface::binder::{
Victor Hsieh45636232021-10-15 17:52:51 -070037 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070038};
Victor Hsieh45636232021-10-15 17:52:51 -070039use binder_common::{new_binder_exception, new_binder_service_specific_error};
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070040
41fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070042 offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070043}
44
45fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
46 if size > MAX_REQUESTING_DATA {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070047 Err(new_errno_error(Errno::EFBIG))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070048 } else {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070049 size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070050 }
51}
52
53/// Configuration of a file descriptor to be served/exposed/shared.
54pub enum FdConfig {
55 /// A read-only file to serve by this server. The file is supposed to be verifiable with the
56 /// associated fs-verity metadata.
57 Readonly {
58 /// The file to read from. fs-verity metadata can be retrieved from this file's FD.
59 file: File,
60
61 /// Alternative Merkle tree stored in another file.
62 alt_merkle_tree: Option<File>,
63
64 /// Alternative signature stored in another file.
65 alt_signature: Option<File>,
66 },
67
68 /// A readable/writable file to serve by this server. This backing file should just be a
69 /// regular file and does not have any specific property.
70 ReadWrite(File),
Victor Hsieh45636232021-10-15 17:52:51 -070071
72 /// A writable directory to serve by this server.
73 OutputDir(Dir),
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070074}
75
76pub struct FdService {
Victor Hsieh45636232021-10-15 17:52:51 -070077 /// A pool of opened files and directories, which can be looked up by the FD number.
78 fd_pool: Arc<Mutex<BTreeMap<i32, FdConfig>>>,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070079}
80
81impl FdService {
82 pub fn new_binder(fd_pool: BTreeMap<i32, FdConfig>) -> Strong<dyn IVirtFdService> {
Victor Hsieh45636232021-10-15 17:52:51 -070083 BnVirtFdService::new_binder(
84 FdService { fd_pool: Arc::new(Mutex::new(fd_pool)) },
85 BinderFeatures::default(),
86 )
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070087 }
88
Victor Hsieh45636232021-10-15 17:52:51 -070089 /// Handles the requesting file `id` with `handle_fn` if it is in the FD pool. This function
90 /// returns whatever `handle_fn` returns.
91 fn handle_fd<F, R>(&self, id: i32, handle_fn: F) -> BinderResult<R>
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070092 where
93 F: FnOnce(&FdConfig) -> BinderResult<R>,
94 {
Victor Hsieh45636232021-10-15 17:52:51 -070095 let fd_pool = self.fd_pool.lock().unwrap();
96 let fd_config = fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
97 handle_fn(fd_config)
98 }
99
100 /// Inserts a new FD and corresponding `FdConfig` created by `create_fn` to the FD pool, then
101 /// returns the new FD number.
102 fn insert_new_fd<F>(&self, fd: i32, create_fn: F) -> BinderResult<i32>
103 where
104 F: FnOnce(&mut FdConfig) -> BinderResult<(i32, FdConfig)>,
105 {
106 let mut fd_pool = self.fd_pool.lock().unwrap();
107 let mut fd_config = fd_pool.get_mut(&fd).ok_or_else(|| new_errno_error(Errno::EBADF))?;
108 let (new_fd, new_fd_config) = create_fn(&mut fd_config)?;
109 if let btree_map::Entry::Vacant(entry) = fd_pool.entry(new_fd) {
110 entry.insert(new_fd_config);
111 Ok(new_fd)
112 } else {
113 Err(new_binder_exception(
114 ExceptionCode::ILLEGAL_STATE,
115 format!("The newly created FD {} is already in the pool unexpectedly", new_fd),
116 ))
117 }
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700118 }
119}
120
121impl Interface for FdService {}
122
123impl IVirtFdService for FdService {
124 fn readFile(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
125 let size: usize = validate_and_cast_size(size)?;
126 let offset: u64 = validate_and_cast_offset(offset)?;
127
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700128 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700129 FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
130 read_into_buf(file, size, offset).map_err(|e| {
131 error!("readFile: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700132 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700133 })
134 }
Victor Hsieh45636232021-10-15 17:52:51 -0700135 FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700136 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700137 }
138
139 fn readFsverityMerkleTree(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
140 let size: usize = validate_and_cast_size(size)?;
141 let offset: u64 = validate_and_cast_offset(offset)?;
142
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700143 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700144 FdConfig::Readonly { file, alt_merkle_tree, .. } => {
145 if let Some(tree_file) = &alt_merkle_tree {
146 read_into_buf(tree_file, size, offset).map_err(|e| {
147 error!("readFsverityMerkleTree: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700148 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700149 })
150 } else {
151 let mut buf = vec![0; size];
152 let s = fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf)
153 .map_err(|e| {
154 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700155 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700156 })?;
157 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
158 buf.truncate(s);
159 Ok(buf)
160 }
161 }
162 FdConfig::ReadWrite(_file) => {
163 // For a writable file, Merkle tree is not expected to be served since Auth FS
164 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
165 // use.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700166 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700167 }
Victor Hsieh45636232021-10-15 17:52:51 -0700168 FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700169 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700170 }
171
172 fn readFsveritySignature(&self, id: i32) -> BinderResult<Vec<u8>> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700173 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700174 FdConfig::Readonly { file, alt_signature, .. } => {
175 if let Some(sig_file) = &alt_signature {
176 // Supposedly big enough buffer size to store signature.
177 let size = MAX_REQUESTING_DATA as usize;
178 let offset = 0;
179 read_into_buf(sig_file, size, offset).map_err(|e| {
180 error!("readFsveritySignature: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700181 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700182 })
183 } else {
184 let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
185 let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
186 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700187 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700188 })?;
189 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
190 buf.truncate(s);
191 Ok(buf)
192 }
193 }
194 FdConfig::ReadWrite(_file) => {
195 // There is no signature for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700196 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700197 }
Victor Hsieh45636232021-10-15 17:52:51 -0700198 FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700199 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700200 }
201
202 fn writeFile(&self, id: i32, buf: &[u8], offset: i64) -> BinderResult<i32> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700203 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700204 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
205 FdConfig::ReadWrite(file) => {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700206 let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700207 // Check buffer size just to make `as i32` safe below.
208 if buf.len() > i32::MAX as usize {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700209 return Err(new_errno_error(Errno::EOVERFLOW));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700210 }
211 Ok(file.write_at(buf, offset).map_err(|e| {
212 error!("writeFile: write error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700213 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700214 })? as i32)
215 }
Victor Hsieh45636232021-10-15 17:52:51 -0700216 FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700217 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700218 }
219
220 fn resize(&self, id: i32, size: i64) -> BinderResult<()> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700221 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700222 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
223 FdConfig::ReadWrite(file) => {
224 if size < 0 {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700225 return Err(new_errno_error(Errno::EINVAL));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700226 }
227 file.set_len(size as u64).map_err(|e| {
228 error!("resize: set_len error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700229 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700230 })
231 }
Victor Hsieh45636232021-10-15 17:52:51 -0700232 FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700233 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700234 }
235
236 fn getFileSize(&self, id: i32) -> BinderResult<i64> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700237 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700238 FdConfig::Readonly { file, .. } => {
239 let size = file
240 .metadata()
241 .map_err(|e| {
242 error!("getFileSize error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700243 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700244 })?
245 .len();
246 Ok(size.try_into().map_err(|e| {
247 error!("getFileSize: File too large: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700248 new_errno_error(Errno::EFBIG)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700249 })?)
250 }
251 FdConfig::ReadWrite(_file) => {
252 // Content and metadata of a writable file needs to be tracked by authfs, since
253 // fd_server isn't considered trusted. So there is no point to support getFileSize
254 // for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700255 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700256 }
Victor Hsieh45636232021-10-15 17:52:51 -0700257 FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
258 })
259 }
260
261 fn createFileInDirectory(&self, fd: i32, basename: &str) -> BinderResult<i32> {
262 if basename.contains(MAIN_SEPARATOR) {
263 return Err(new_errno_error(Errno::EINVAL));
264 }
265 self.insert_new_fd(fd, |config| match config {
266 FdConfig::OutputDir(dir) => {
267 let new_fd = openat(
268 dir.as_raw_fd(),
269 basename,
270 // TODO(205172873): handle the case when the file already exist, e.g. truncate
271 // or fail, and possibly allow the client to specify. For now, always truncate.
272 OFlag::O_CREAT | OFlag::O_RDWR | OFlag::O_TRUNC,
273 Mode::S_IRUSR | Mode::S_IWUSR,
274 )
275 .map_err(new_errno_error)?;
276 // SAFETY: new_fd is just created and not an error.
277 let new_file = unsafe { File::from_raw_fd(new_fd) };
278 Ok((new_fd, FdConfig::ReadWrite(new_file)))
279 }
280 _ => Err(new_errno_error(Errno::ENOTDIR)),
281 })
282 }
283
284 fn createDirectoryInDirectory(&self, dir_fd: i32, basename: &str) -> BinderResult<i32> {
285 if basename.contains(MAIN_SEPARATOR) {
286 return Err(new_errno_error(Errno::EINVAL));
287 }
288 self.insert_new_fd(dir_fd, |config| match config {
289 FdConfig::OutputDir(_) => {
290 mkdirat(dir_fd, basename, Mode::S_IRWXU).map_err(new_errno_error)?;
291 let new_dir = Dir::openat(
292 dir_fd,
293 basename,
294 OFlag::O_DIRECTORY | OFlag::O_RDONLY,
295 Mode::empty(),
296 )
297 .map_err(new_errno_error)?;
298 Ok((new_dir.as_raw_fd(), FdConfig::OutputDir(new_dir)))
299 }
300 _ => Err(new_errno_error(Errno::ENOTDIR)),
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700301 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700302 }
303}
304
305fn read_into_buf(file: &File, max_size: usize, offset: u64) -> io::Result<Vec<u8>> {
306 let remaining = file.metadata()?.len().saturating_sub(offset);
307 let buf_size = min(remaining, max_size as u64) as usize;
308 let mut buf = vec![0; buf_size];
309 file.read_exact_at(&mut buf, offset)?;
310 Ok(buf)
311}
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700312
313fn new_errno_error(errno: Errno) -> Status {
314 new_binder_service_specific_error(errno as i32, errno.desc())
315}