1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Ioctl to read verity metadata 4 * 5 * Copyright 2021 Google LLC 6 */ 7 8 #include "fsverity_private.h" 9 10 #include <linux/backing-dev.h> 11 #include <linux/export.h> 12 #include <linux/highmem.h> 13 #include <linux/sched/signal.h> 14 #include <linux/uaccess.h> 15 16 static int fsverity_read_merkle_tree(struct inode *inode, 17 const struct fsverity_info *vi, 18 void __user *buf, u64 offset, int length) 19 { 20 const struct fsverity_operations *vops = inode->i_sb->s_vop; 21 u64 end_offset; 22 unsigned int offs_in_page; 23 pgoff_t index, last_index; 24 int retval = 0; 25 int err = 0; 26 27 end_offset = min(offset + length, vi->tree_params.tree_size); 28 if (offset >= end_offset) 29 return 0; 30 offs_in_page = offset_in_page(offset); 31 index = offset >> PAGE_SHIFT; 32 last_index = (end_offset - 1) >> PAGE_SHIFT; 33 34 /* 35 * Kick off readahead for the range we are going to read to ensure a 36 * single large sequential read instead of lots of small ones. 37 */ 38 if (inode->i_sb->s_vop->readahead_merkle_tree) { 39 filemap_invalidate_lock_shared(inode->i_mapping); 40 inode->i_sb->s_vop->readahead_merkle_tree( 41 inode, index, last_index - index + 1); 42 filemap_invalidate_unlock_shared(inode->i_mapping); 43 } 44 45 /* 46 * Iterate through each Merkle tree page in the requested range and copy 47 * the requested portion to userspace. Note that the Merkle tree block 48 * size isn't important here, as we are returning a byte stream; i.e., 49 * we can just work with pages even if the tree block size != PAGE_SIZE. 50 */ 51 for (; index <= last_index; index++) { 52 unsigned int bytes_to_copy = min_t(u64, end_offset - offset, 53 PAGE_SIZE - offs_in_page); 54 struct page *page; 55 const void *virt; 56 57 page = vops->read_merkle_tree_page(inode, index); 58 if (IS_ERR(page)) { 59 err = PTR_ERR(page); 60 fsverity_err(inode, 61 "Error %d reading Merkle tree page %lu", 62 err, index); 63 break; 64 } 65 66 virt = kmap_local_page(page); 67 if (copy_to_user(buf, virt + offs_in_page, bytes_to_copy)) { 68 kunmap_local(virt); 69 put_page(page); 70 err = -EFAULT; 71 break; 72 } 73 kunmap_local(virt); 74 put_page(page); 75 76 retval += bytes_to_copy; 77 buf += bytes_to_copy; 78 offset += bytes_to_copy; 79 80 if (fatal_signal_pending(current)) { 81 err = -EINTR; 82 break; 83 } 84 cond_resched(); 85 offs_in_page = 0; 86 } 87 return retval ? retval : err; 88 } 89 90 /* Copy the requested portion of the buffer to userspace. */ 91 static int fsverity_read_buffer(void __user *dst, u64 offset, int length, 92 const void *src, size_t src_length) 93 { 94 if (offset >= src_length) 95 return 0; 96 src += offset; 97 src_length -= offset; 98 99 length = min_t(size_t, length, src_length); 100 101 if (copy_to_user(dst, src, length)) 102 return -EFAULT; 103 104 return length; 105 } 106 107 static int fsverity_read_descriptor(struct inode *inode, 108 void __user *buf, u64 offset, int length) 109 { 110 struct fsverity_descriptor *desc; 111 size_t desc_size; 112 int res; 113 114 res = fsverity_get_descriptor(inode, &desc); 115 if (res) 116 return res; 117 118 /* don't include the builtin signature */ 119 desc_size = offsetof(struct fsverity_descriptor, signature); 120 desc->sig_size = 0; 121 122 res = fsverity_read_buffer(buf, offset, length, desc, desc_size); 123 124 kfree(desc); 125 return res; 126 } 127 128 static int fsverity_read_signature(struct inode *inode, 129 void __user *buf, u64 offset, int length) 130 { 131 struct fsverity_descriptor *desc; 132 int res; 133 134 res = fsverity_get_descriptor(inode, &desc); 135 if (res) 136 return res; 137 138 if (desc->sig_size == 0) { 139 res = -ENODATA; 140 goto out; 141 } 142 143 /* 144 * Include only the builtin signature. fsverity_get_descriptor() 145 * already verified that sig_size is in-bounds. 146 */ 147 res = fsverity_read_buffer(buf, offset, length, desc->signature, 148 le32_to_cpu(desc->sig_size)); 149 out: 150 kfree(desc); 151 return res; 152 } 153 154 /** 155 * fsverity_ioctl_read_metadata() - read verity metadata from a file 156 * @filp: file to read the metadata from 157 * @uarg: user pointer to fsverity_read_metadata_arg 158 * 159 * Return: length read on success, 0 on EOF, -errno on failure 160 */ 161 int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg) 162 { 163 struct inode *inode = file_inode(filp); 164 const struct fsverity_info *vi; 165 struct fsverity_read_metadata_arg arg; 166 int length; 167 void __user *buf; 168 169 vi = fsverity_get_info(inode); 170 if (!vi) 171 return -ENODATA; /* not a verity file */ 172 /* 173 * Note that we don't have to explicitly check that the file is open for 174 * reading, since verity files can only be opened for reading. 175 */ 176 177 if (copy_from_user(&arg, uarg, sizeof(arg))) 178 return -EFAULT; 179 180 if (arg.__reserved) 181 return -EINVAL; 182 183 /* offset + length must not overflow. */ 184 if (arg.offset + arg.length < arg.offset) 185 return -EINVAL; 186 187 /* Ensure that the return value will fit in INT_MAX. */ 188 length = min_t(u64, arg.length, INT_MAX); 189 190 buf = u64_to_user_ptr(arg.buf_ptr); 191 192 switch (arg.metadata_type) { 193 case FS_VERITY_METADATA_TYPE_MERKLE_TREE: 194 return fsverity_read_merkle_tree(inode, vi, buf, arg.offset, 195 length); 196 case FS_VERITY_METADATA_TYPE_DESCRIPTOR: 197 return fsverity_read_descriptor(inode, buf, arg.offset, length); 198 case FS_VERITY_METADATA_TYPE_SIGNATURE: 199 return fsverity_read_signature(inode, buf, arg.offset, length); 200 default: 201 return -EINVAL; 202 } 203 } 204 EXPORT_SYMBOL_GPL(fsverity_ioctl_read_metadata); 205