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
read_metadata(fd: i32, metadata_type: u64, offset: u64, buf: &mut [u8]) -> io::Result<usize>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.
read_merkle_tree(fd: i32, offset: u64, buf: &mut [u8]) -> io::Result<usize>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.
read_signature(fd: i32, buf: &mut [u8]) -> io::Result<usize>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