diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2016-01-14 20:59:14 -0500 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2016-02-21 09:06:14 -0500 |
commit | b804defe4297157a9ff45863769efe9a01953398 (patch) | |
tree | 562c479b3b93e922ac99a0afe94d09015e3cf11d /kernel/kexec_file.c | |
parent | c6af8efe97d87fa308eb1bbd0cf4feb820a4d622 (diff) |
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>
Diffstat (limited to 'kernel/kexec_file.c')
-rw-r--r-- | kernel/kexec_file.c | 73 |
1 files changed, 9 insertions, 64 deletions
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 007b791f676d..b696c3f3708f 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kexec.h> | 18 | #include <linux/kexec.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
21 | #include <linux/fs.h> | ||
21 | #include <crypto/hash.h> | 22 | #include <crypto/hash.h> |
22 | #include <crypto/sha.h> | 23 | #include <crypto/sha.h> |
23 | #include <linux/syscalls.h> | 24 | #include <linux/syscalls.h> |
@@ -33,65 +34,6 @@ size_t __weak kexec_purgatory_size = 0; | |||
33 | 34 | ||
34 | static int kexec_calculate_store_digests(struct kimage *image); | 35 | static int kexec_calculate_store_digests(struct kimage *image); |
35 | 36 | ||
36 | static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len) | ||
37 | { | ||
38 | struct fd f = fdget(fd); | ||
39 | int ret; | ||
40 | struct kstat stat; | ||
41 | loff_t pos; | ||
42 | ssize_t bytes = 0; | ||
43 | |||
44 | if (!f.file) | ||
45 | return -EBADF; | ||
46 | |||
47 | ret = vfs_getattr(&f.file->f_path, &stat); | ||
48 | if (ret) | ||
49 | goto out; | ||
50 | |||
51 | if (stat.size > INT_MAX) { | ||
52 | ret = -EFBIG; | ||
53 | goto out; | ||
54 | } | ||
55 | |||
56 | /* Don't hand 0 to vmalloc, it whines. */ | ||
57 | if (stat.size == 0) { | ||
58 | ret = -EINVAL; | ||
59 | goto out; | ||
60 | } | ||
61 | |||
62 | *buf = vmalloc(stat.size); | ||
63 | if (!*buf) { | ||
64 | ret = -ENOMEM; | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | pos = 0; | ||
69 | while (pos < stat.size) { | ||
70 | bytes = kernel_read(f.file, pos, (char *)(*buf) + pos, | ||
71 | stat.size - pos); | ||
72 | if (bytes < 0) { | ||
73 | vfree(*buf); | ||
74 | ret = bytes; | ||
75 | goto out; | ||
76 | } | ||
77 | |||
78 | if (bytes == 0) | ||
79 | break; | ||
80 | pos += bytes; | ||
81 | } | ||
82 | |||
83 | if (pos != stat.size) { | ||
84 | ret = -EBADF; | ||
85 | vfree(*buf); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | *buf_len = pos; | ||
90 | out: | ||
91 | fdput(f); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | /* Architectures can provide this probe function */ | 37 | /* Architectures can provide this probe function */ |
96 | int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf, | 38 | int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf, |
97 | unsigned long buf_len) | 39 | unsigned long buf_len) |
@@ -182,16 +124,17 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, | |||
182 | { | 124 | { |
183 | int ret = 0; | 125 | int ret = 0; |
184 | void *ldata; | 126 | void *ldata; |
127 | loff_t size; | ||
185 | 128 | ||
186 | ret = copy_file_from_fd(kernel_fd, &image->kernel_buf, | 129 | ret = kernel_read_file_from_fd(kernel_fd, &image->kernel_buf, |
187 | &image->kernel_buf_len); | 130 | &size, INT_MAX, READING_KEXEC_IMAGE); |
188 | if (ret) | 131 | if (ret) |
189 | return ret; | 132 | return ret; |
133 | image->kernel_buf_len = size; | ||
190 | 134 | ||
191 | /* Call arch image probe handlers */ | 135 | /* Call arch image probe handlers */ |
192 | ret = arch_kexec_kernel_image_probe(image, image->kernel_buf, | 136 | ret = arch_kexec_kernel_image_probe(image, image->kernel_buf, |
193 | image->kernel_buf_len); | 137 | image->kernel_buf_len); |
194 | |||
195 | if (ret) | 138 | if (ret) |
196 | goto out; | 139 | goto out; |
197 | 140 | ||
@@ -206,10 +149,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, | |||
206 | #endif | 149 | #endif |
207 | /* It is possible that there no initramfs is being loaded */ | 150 | /* It is possible that there no initramfs is being loaded */ |
208 | if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { | 151 | if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { |
209 | ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, | 152 | ret = kernel_read_file_from_fd(initrd_fd, &image->initrd_buf, |
210 | &image->initrd_buf_len); | 153 | &size, INT_MAX, |
154 | READING_KEXEC_INITRAMFS); | ||
211 | if (ret) | 155 | if (ret) |
212 | goto out; | 156 | goto out; |
157 | image->initrd_buf_len = size; | ||
213 | } | 158 | } |
214 | 159 | ||
215 | if (cmdline_len) { | 160 | if (cmdline_len) { |