| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * kexec.c - kexec_load system call |
|---|
| 3 | 4 | * Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This source code is licensed under the GNU General Public License, |
|---|
| 6 | | - * Version 2. See the file COPYING for more details. |
|---|
| 7 | 5 | */ |
|---|
| 8 | 6 | |
|---|
| 9 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 112 | 110 | unsigned long i; |
|---|
| 113 | 111 | int ret; |
|---|
| 114 | 112 | |
|---|
| 113 | + /* |
|---|
| 114 | + * Because we write directly to the reserved memory region when loading |
|---|
| 115 | + * crash kernels we need a serialization here to prevent multiple crash |
|---|
| 116 | + * kernels from attempting to load simultaneously. |
|---|
| 117 | + */ |
|---|
| 118 | + if (!kexec_trylock()) |
|---|
| 119 | + return -EBUSY; |
|---|
| 120 | + |
|---|
| 115 | 121 | if (flags & KEXEC_ON_CRASH) { |
|---|
| 116 | 122 | dest_image = &kexec_crash_image; |
|---|
| 117 | 123 | if (kexec_crash_image) |
|---|
| .. | .. |
|---|
| 123 | 129 | if (nr_segments == 0) { |
|---|
| 124 | 130 | /* Uninstall image */ |
|---|
| 125 | 131 | kimage_free(xchg(dest_image, NULL)); |
|---|
| 126 | | - return 0; |
|---|
| 132 | + ret = 0; |
|---|
| 133 | + goto out_unlock; |
|---|
| 127 | 134 | } |
|---|
| 128 | 135 | if (flags & KEXEC_ON_CRASH) { |
|---|
| 129 | 136 | /* |
|---|
| .. | .. |
|---|
| 136 | 143 | |
|---|
| 137 | 144 | ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags); |
|---|
| 138 | 145 | if (ret) |
|---|
| 139 | | - return ret; |
|---|
| 146 | + goto out_unlock; |
|---|
| 140 | 147 | |
|---|
| 141 | 148 | if (flags & KEXEC_PRESERVE_CONTEXT) |
|---|
| 142 | 149 | image->preserve_context = 1; |
|---|
| .. | .. |
|---|
| 161 | 168 | |
|---|
| 162 | 169 | kimage_terminate(image); |
|---|
| 163 | 170 | |
|---|
| 171 | + ret = machine_kexec_post_load(image); |
|---|
| 172 | + if (ret) |
|---|
| 173 | + goto out; |
|---|
| 174 | + |
|---|
| 164 | 175 | /* Install the new kernel and uninstall the old */ |
|---|
| 165 | 176 | image = xchg(dest_image, image); |
|---|
| 166 | 177 | |
|---|
| .. | .. |
|---|
| 169 | 180 | arch_kexec_protect_crashkres(); |
|---|
| 170 | 181 | |
|---|
| 171 | 182 | kimage_free(image); |
|---|
| 183 | +out_unlock: |
|---|
| 184 | + kexec_unlock(); |
|---|
| 172 | 185 | return ret; |
|---|
| 173 | 186 | } |
|---|
| 174 | 187 | |
|---|
| .. | .. |
|---|
| 203 | 216 | return -EPERM; |
|---|
| 204 | 217 | |
|---|
| 205 | 218 | /* Permit LSMs and IMA to fail the kexec */ |
|---|
| 206 | | - result = security_kernel_load_data(LOADING_KEXEC_IMAGE); |
|---|
| 219 | + result = security_kernel_load_data(LOADING_KEXEC_IMAGE, false); |
|---|
| 207 | 220 | if (result < 0) |
|---|
| 221 | + return result; |
|---|
| 222 | + |
|---|
| 223 | + /* |
|---|
| 224 | + * kexec can be used to circumvent module loading restrictions, so |
|---|
| 225 | + * prevent loading in that case |
|---|
| 226 | + */ |
|---|
| 227 | + result = security_locked_down(LOCKDOWN_KEXEC); |
|---|
| 228 | + if (result) |
|---|
| 208 | 229 | return result; |
|---|
| 209 | 230 | |
|---|
| 210 | 231 | /* |
|---|
| .. | .. |
|---|
| 237 | 258 | ((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT)) |
|---|
| 238 | 259 | return -EINVAL; |
|---|
| 239 | 260 | |
|---|
| 240 | | - /* Because we write directly to the reserved memory |
|---|
| 241 | | - * region when loading crash kernels we need a mutex here to |
|---|
| 242 | | - * prevent multiple crash kernels from attempting to load |
|---|
| 243 | | - * simultaneously, and to prevent a crash kernel from loading |
|---|
| 244 | | - * over the top of a in use crash kernel. |
|---|
| 245 | | - * |
|---|
| 246 | | - * KISS: always take the mutex. |
|---|
| 247 | | - */ |
|---|
| 248 | | - if (!mutex_trylock(&kexec_mutex)) |
|---|
| 249 | | - return -EBUSY; |
|---|
| 250 | | - |
|---|
| 251 | 261 | result = do_kexec_load(entry, nr_segments, segments, flags); |
|---|
| 252 | | - |
|---|
| 253 | | - mutex_unlock(&kexec_mutex); |
|---|
| 254 | 262 | |
|---|
| 255 | 263 | return result; |
|---|
| 256 | 264 | } |
|---|
| .. | .. |
|---|
| 291 | 299 | return -EFAULT; |
|---|
| 292 | 300 | } |
|---|
| 293 | 301 | |
|---|
| 294 | | - /* Because we write directly to the reserved memory |
|---|
| 295 | | - * region when loading crash kernels we need a mutex here to |
|---|
| 296 | | - * prevent multiple crash kernels from attempting to load |
|---|
| 297 | | - * simultaneously, and to prevent a crash kernel from loading |
|---|
| 298 | | - * over the top of a in use crash kernel. |
|---|
| 299 | | - * |
|---|
| 300 | | - * KISS: always take the mutex. |
|---|
| 301 | | - */ |
|---|
| 302 | | - if (!mutex_trylock(&kexec_mutex)) |
|---|
| 303 | | - return -EBUSY; |
|---|
| 304 | | - |
|---|
| 305 | 302 | result = do_kexec_load(entry, nr_segments, ksegments, flags); |
|---|
| 306 | | - |
|---|
| 307 | | - mutex_unlock(&kexec_mutex); |
|---|
| 308 | 303 | |
|---|
| 309 | 304 | return result; |
|---|
| 310 | 305 | } |
|---|