fs: Fix enable_verity() impl

The fsverity_enable_arg struct contains optional pointers to additional
data.  Check for them and try to copy them in if necessary.  This
requires a corresponding kernel change where the fuse driver also
reads the struct and copies the relevant data from the userspace
application.

Steps to test this change:

// Create a test file
head -c 1000000 /dev/urandom > file

// Generate a new certificate and private key:
openssl req -newkey rsa:4096 -nodes -keyout key.pem -x509 -out cert.pem

// Convert the certificate from PEM to DER format:
openssl x509 -in cert.pem -out cert.der -outform der

// Load the certificate into the fs-verity keyring.  This step MUST be
// done on the host kernel.
keyctl padd asymmetric '' %keyring:.fs-verity < cert.der

// Now set up fs-verity on the test file:
fsverity sign file file.sig --key=key.pem --cert=cert.pem \
    --salt 12345678
fsverity enable file --signature=file.sig --salt 12345678

BUG=b:141632062
TEST=See above

Change-Id: Ied7106cfbd2919f1f0c7f605166769d4916925b0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3141298
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
This commit is contained in:
Chirantan Ekbote 2021-09-03 18:51:57 +09:00 committed by Commit Bot
parent e1663eeae4
commit e3364b743a

View file

@ -134,11 +134,11 @@ struct fsverity_enable_arg {
_version: u32,
_hash_algorithm: u32,
_block_size: u32,
_salt_size: u32,
_salt_ptr: u64,
_sig_size: u32,
salt_size: u32,
salt_ptr: u64,
sig_size: u32,
__reserved1: u32,
_sig_ptr: u64,
sig_ptr: u64,
__reserved2: [u64; 11],
}
unsafe impl DataInit for fsverity_enable_arg {}
@ -1117,7 +1117,7 @@ impl PassthroughFs {
&self,
inode: Inode,
handle: Handle,
r: R,
mut r: R,
) -> io::Result<IoctlReply> {
let inode_data = self.find_inode(inode)?;
@ -1169,7 +1169,35 @@ impl PassthroughFs {
data
};
let arg = fsverity_enable_arg::from_reader(r)?;
let mut arg = fsverity_enable_arg::from_reader(&mut r)?;
let mut salt;
if arg.salt_size > 0 {
if arg.salt_size > self.max_buffer_size() {
return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
libc::ENOMEM,
))));
}
salt = vec![0; arg.salt_size as usize];
r.read_exact(&mut salt)?;
arg.salt_ptr = salt.as_ptr() as usize as u64;
} else {
arg.salt_ptr = 0;
}
let mut sig;
if arg.sig_size > 0 {
if arg.sig_size > self.max_buffer_size() {
return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
libc::ENOMEM,
))));
}
sig = vec![0; arg.sig_size as usize];
r.read_exact(&mut sig)?;
arg.sig_ptr = sig.as_ptr() as usize as u64;
} else {
arg.sig_ptr = 0;
}
// Safe because this doesn't modify any memory and we check the return value.
let res = unsafe { ioctl_with_ptr(&*data, FS_IOC_ENABLE_VERITY(), &arg) };