blob: 48547e7b72e66cbdad1953a0bb7280edb316b312 [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 Hsiehbe8b08d2021-10-29 16:31:24 -070019use nix::errno::Errno;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070020use std::cmp::min;
21use std::collections::BTreeMap;
22use std::convert::TryInto;
23use std::fs::File;
24use std::io;
25use std::os::unix::fs::FileExt;
26use std::os::unix::io::AsRawFd;
27
28use crate::fsverity;
29use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::{
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070030 BnVirtFdService, IVirtFdService, MAX_REQUESTING_DATA,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070031};
32use authfs_aidl_interface::binder::{
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070033 BinderFeatures, Interface, Result as BinderResult, Status, StatusCode, Strong,
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070034};
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070035use binder_common::new_binder_service_specific_error;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070036
37fn validate_and_cast_offset(offset: i64) -> Result<u64, Status> {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070038 offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070039}
40
41fn validate_and_cast_size(size: i32) -> Result<usize, Status> {
42 if size > MAX_REQUESTING_DATA {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070043 Err(new_errno_error(Errno::EFBIG))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070044 } else {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070045 size.try_into().map_err(|_| new_errno_error(Errno::EINVAL))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070046 }
47}
48
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
57 /// Alternative Merkle tree stored in another file.
58 alt_merkle_tree: Option<File>,
59
60 /// Alternative signature stored in another file.
61 alt_signature: Option<File>,
62 },
63
64 /// A readable/writable file to serve by this server. This backing file should just be a
65 /// regular file and does not have any specific property.
66 ReadWrite(File),
67}
68
69pub struct FdService {
70 /// A pool of opened files, may be readonly or read-writable.
71 fd_pool: BTreeMap<i32, FdConfig>,
72}
73
74impl FdService {
75 pub fn new_binder(fd_pool: BTreeMap<i32, FdConfig>) -> Strong<dyn IVirtFdService> {
76 BnVirtFdService::new_binder(FdService { fd_pool }, BinderFeatures::default())
77 }
78
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070079 /// Handles the requesting file `id` with `handler` if it is in the FD pool. This function
80 /// returns whatever the handler returns.
81 fn handle_fd<F, R>(&self, id: i32, handler: F) -> BinderResult<R>
82 where
83 F: FnOnce(&FdConfig) -> BinderResult<R>,
84 {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -070085 let fd_config = self.fd_pool.get(&id).ok_or_else(|| new_errno_error(Errno::EBADF))?;
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070086 handler(fd_config)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070087 }
88}
89
90impl Interface for FdService {}
91
92impl IVirtFdService for FdService {
93 fn readFile(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
94 let size: usize = validate_and_cast_size(size)?;
95 let offset: u64 = validate_and_cast_offset(offset)?;
96
Victor Hsiehc85e4ef2021-10-18 15:28:53 -070097 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -070098 FdConfig::Readonly { file, .. } | FdConfig::ReadWrite(file) => {
99 read_into_buf(file, size, offset).map_err(|e| {
100 error!("readFile: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700101 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700102 })
103 }
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700104 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700105 }
106
107 fn readFsverityMerkleTree(&self, id: i32, offset: i64, size: i32) -> BinderResult<Vec<u8>> {
108 let size: usize = validate_and_cast_size(size)?;
109 let offset: u64 = validate_and_cast_offset(offset)?;
110
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700111 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700112 FdConfig::Readonly { file, alt_merkle_tree, .. } => {
113 if let Some(tree_file) = &alt_merkle_tree {
114 read_into_buf(tree_file, size, offset).map_err(|e| {
115 error!("readFsverityMerkleTree: read error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700116 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700117 })
118 } else {
119 let mut buf = vec![0; size];
120 let s = fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf)
121 .map_err(|e| {
122 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700123 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700124 })?;
125 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
126 buf.truncate(s);
127 Ok(buf)
128 }
129 }
130 FdConfig::ReadWrite(_file) => {
131 // For a writable file, Merkle tree is not expected to be served since Auth FS
132 // doesn't trust it anyway. Auth FS may keep the Merkle tree privately for its own
133 // use.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700134 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700135 }
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700136 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700137 }
138
139 fn readFsveritySignature(&self, id: i32) -> BinderResult<Vec<u8>> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700140 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700141 FdConfig::Readonly { file, alt_signature, .. } => {
142 if let Some(sig_file) = &alt_signature {
143 // Supposedly big enough buffer size to store signature.
144 let size = MAX_REQUESTING_DATA as usize;
145 let offset = 0;
146 read_into_buf(sig_file, size, offset).map_err(|e| {
147 error!("readFsveritySignature: 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; MAX_REQUESTING_DATA as usize];
152 let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
153 error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700154 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700155 })?;
156 debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
157 buf.truncate(s);
158 Ok(buf)
159 }
160 }
161 FdConfig::ReadWrite(_file) => {
162 // There is no signature for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700163 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700164 }
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700165 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700166 }
167
168 fn writeFile(&self, id: i32, buf: &[u8], offset: i64) -> BinderResult<i32> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700169 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700170 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
171 FdConfig::ReadWrite(file) => {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700172 let offset: u64 = offset.try_into().map_err(|_| new_errno_error(Errno::EINVAL))?;
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700173 // Check buffer size just to make `as i32` safe below.
174 if buf.len() > i32::MAX as usize {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700175 return Err(new_errno_error(Errno::EOVERFLOW));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700176 }
177 Ok(file.write_at(buf, offset).map_err(|e| {
178 error!("writeFile: write error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700179 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700180 })? as i32)
181 }
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700182 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700183 }
184
185 fn resize(&self, id: i32, size: i64) -> BinderResult<()> {
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700186 self.handle_fd(id, |config| match config {
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700187 FdConfig::Readonly { .. } => Err(StatusCode::INVALID_OPERATION.into()),
188 FdConfig::ReadWrite(file) => {
189 if size < 0 {
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700190 return Err(new_errno_error(Errno::EINVAL));
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700191 }
192 file.set_len(size as u64).map_err(|e| {
193 error!("resize: set_len error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700194 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700195 })
196 }
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700197 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700198 }
199
200 fn getFileSize(&self, id: i32) -> BinderResult<i64> {
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 { file, .. } => {
203 let size = file
204 .metadata()
205 .map_err(|e| {
206 error!("getFileSize error: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700207 new_errno_error(Errno::EIO)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700208 })?
209 .len();
210 Ok(size.try_into().map_err(|e| {
211 error!("getFileSize: File too large: {}", e);
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700212 new_errno_error(Errno::EFBIG)
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700213 })?)
214 }
215 FdConfig::ReadWrite(_file) => {
216 // Content and metadata of a writable file needs to be tracked by authfs, since
217 // fd_server isn't considered trusted. So there is no point to support getFileSize
218 // for a writable file.
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700219 Err(new_errno_error(Errno::ENOSYS))
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700220 }
Victor Hsiehc85e4ef2021-10-18 15:28:53 -0700221 })
Victor Hsiehb0f5fc82021-10-15 17:24:19 -0700222 }
223}
224
225fn read_into_buf(file: &File, max_size: usize, offset: u64) -> io::Result<Vec<u8>> {
226 let remaining = file.metadata()?.len().saturating_sub(offset);
227 let buf_size = min(remaining, max_size as u64) as usize;
228 let mut buf = vec![0; buf_size];
229 file.read_exact_at(&mut buf, offset)?;
230 Ok(buf)
231}
Victor Hsiehbe8b08d2021-10-29 16:31:24 -0700232
233fn new_errno_error(errno: Errno) -> Status {
234 new_binder_service_specific_error(errno as i32, errno.desc())
235}