Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kexec: replace call to copy_file_from_fd() with kernel version

Replace copy_file_from_fd() with kernel_read_file_from_fd().

Two new identifiers named READING_KEXEC_IMAGE and READING_KEXEC_INITRAMFS
are defined for measuring, appraising or auditing the kexec image and
initramfs.

Changelog v3:
- return -EBADF, not -ENOEXEC
- identifier change
- split patch, moving copy_file_from_fd() to a separate patch
- split patch, moving IMA changes to a separate patch
v0:
- use kstat file size type loff_t, not size_t
- Calculate the file hash from the in memory buffer - Dave Young

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: Kees Cook <keescook@chromium.org>
Acked-by: Luis R. Rodriguez <mcgrof@kernel.org>
Cc: Eric Biederman <ebiederm@xmission.com>
Acked-by: Dave Young <dyoung@redhat.com>

+11 -64
+2
include/linux/fs.h
··· 2579 2579 enum kernel_read_file_id { 2580 2580 READING_FIRMWARE = 1, 2581 2581 READING_MODULE, 2582 + READING_KEXEC_IMAGE, 2583 + READING_KEXEC_INITRAMFS, 2582 2584 READING_MAX_ID 2583 2585 }; 2584 2586
+9 -64
kernel/kexec_file.c
··· 18 18 #include <linux/kexec.h> 19 19 #include <linux/mutex.h> 20 20 #include <linux/list.h> 21 + #include <linux/fs.h> 21 22 #include <crypto/hash.h> 22 23 #include <crypto/sha.h> 23 24 #include <linux/syscalls.h> ··· 33 32 size_t __weak kexec_purgatory_size = 0; 34 33 35 34 static int kexec_calculate_store_digests(struct kimage *image); 36 - 37 - static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len) 38 - { 39 - struct fd f = fdget(fd); 40 - int ret; 41 - struct kstat stat; 42 - loff_t pos; 43 - ssize_t bytes = 0; 44 - 45 - if (!f.file) 46 - return -EBADF; 47 - 48 - ret = vfs_getattr(&f.file->f_path, &stat); 49 - if (ret) 50 - goto out; 51 - 52 - if (stat.size > INT_MAX) { 53 - ret = -EFBIG; 54 - goto out; 55 - } 56 - 57 - /* Don't hand 0 to vmalloc, it whines. */ 58 - if (stat.size == 0) { 59 - ret = -EINVAL; 60 - goto out; 61 - } 62 - 63 - *buf = vmalloc(stat.size); 64 - if (!*buf) { 65 - ret = -ENOMEM; 66 - goto out; 67 - } 68 - 69 - pos = 0; 70 - while (pos < stat.size) { 71 - bytes = kernel_read(f.file, pos, (char *)(*buf) + pos, 72 - stat.size - pos); 73 - if (bytes < 0) { 74 - vfree(*buf); 75 - ret = bytes; 76 - goto out; 77 - } 78 - 79 - if (bytes == 0) 80 - break; 81 - pos += bytes; 82 - } 83 - 84 - if (pos != stat.size) { 85 - ret = -EBADF; 86 - vfree(*buf); 87 - goto out; 88 - } 89 - 90 - *buf_len = pos; 91 - out: 92 - fdput(f); 93 - return ret; 94 - } 95 35 96 36 /* Architectures can provide this probe function */ 97 37 int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf, ··· 124 182 { 125 183 int ret = 0; 126 184 void *ldata; 185 + loff_t size; 127 186 128 - ret = copy_file_from_fd(kernel_fd, &image->kernel_buf, 129 - &image->kernel_buf_len); 187 + ret = kernel_read_file_from_fd(kernel_fd, &image->kernel_buf, 188 + &size, INT_MAX, READING_KEXEC_IMAGE); 130 189 if (ret) 131 190 return ret; 191 + image->kernel_buf_len = size; 132 192 133 193 /* Call arch image probe handlers */ 134 194 ret = arch_kexec_kernel_image_probe(image, image->kernel_buf, 135 195 image->kernel_buf_len); 136 - 137 196 if (ret) 138 197 goto out; 139 198 ··· 149 206 #endif 150 207 /* It is possible that there no initramfs is being loaded */ 151 208 if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { 152 - ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, 153 - &image->initrd_buf_len); 209 + ret = kernel_read_file_from_fd(initrd_fd, &image->initrd_buf, 210 + &size, INT_MAX, 211 + READING_KEXEC_INITRAMFS); 154 212 if (ret) 155 213 goto out; 214 + image->initrd_buf_len = size; 156 215 } 157 216 158 217 if (cmdline_len) {