1 /*
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 
17 use nix::ioctl_readwrite;
18 use std::io;
19 
20 // Constants/values from uapi/linux/fsverity.h
21 const FS_VERITY_METADATA_TYPE_MERKLE_TREE: u64 = 1;
22 const FS_VERITY_METADATA_TYPE_SIGNATURE: u64 = 3;
23 const FS_IOCTL_MAGIC: u8 = b'f';
24 const FS_IOCTL_READ_VERITY_METADATA: u8 = 135;
25 
26 #[repr(C)]
27 pub struct fsverity_read_metadata_arg {
28     metadata_type: u64,
29     offset: u64,
30     length: u64,
31     buf_ptr: u64,
32     __reserved: u64,
33 }
34 
35 ioctl_readwrite!(
36     read_verity_metadata,
37     FS_IOCTL_MAGIC,
38     FS_IOCTL_READ_VERITY_METADATA,
39     fsverity_read_metadata_arg
40 );
41 
42 fn read_metadata(fd: i32, metadata_type: u64, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
43     let mut arg = fsverity_read_metadata_arg {
44         metadata_type,
45         offset,
46         length: buf.len() as u64,
47         buf_ptr: buf.as_mut_ptr() as u64,
48         __reserved: 0,
49     };
50     Ok(unsafe { read_verity_metadata(fd, &mut arg) }.map_err(|e| {
51         if let nix::Error::Sys(errno) = e {
52             io::Error::from_raw_os_error(errno as i32)
53         } else {
54             // Document of nix::sys::ioctl indicates the macro-generated function always returns an
55             // nix::errno::Errno, which can be converted nix::Error::Sys above. As the result, this
56             // branch is unreachable.
57             unreachable!();
58         }
59     })? as usize)
60 }
61 
62 /// Read the raw Merkle tree from the fd, if it exists. The API semantics is similar to a regular
63 /// pread(2), and may not return full requested buffer.
64 pub fn read_merkle_tree(fd: i32, offset: u64, buf: &mut [u8]) -> io::Result<usize> {
65     read_metadata(fd, FS_VERITY_METADATA_TYPE_MERKLE_TREE, offset, buf)
66 }
67 
68 /// Read the fs-verity signature from the fd (if exists). The returned signature should be complete.
69 pub fn read_signature(fd: i32, buf: &mut [u8]) -> io::Result<usize> {
70     read_metadata(fd, FS_VERITY_METADATA_TYPE_SIGNATURE, 0 /* offset */, buf)
71 }
72