From: Prakhar Srivastava <prsriva02@xxxxxxxxx> prepend the kernel file name to the cmdline args to avoid conflicrts in case of multiple kexec. Pass the new generated buffer to ima for measurmenet. Signed-off-by: Prakhar Srivastava <prsriva02@xxxxxxxxx> --- kernel/kexec_core.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ kernel/kexec_file.c | 14 +++++++++++ 2 files changed, 71 insertions(+) diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index d7140447be75..4667f03d406e 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1213,3 +1213,60 @@ void __weak arch_kexec_protect_crashkres(void) void __weak arch_kexec_unprotect_crashkres(void) {} + +/** + * kexec_cmdline_prepend_img_name - prepare the buffer with cmdline + * that needs to be measured + * @outbuf - out buffer that contains the formated string + * @kernel_fd - the file identifier for the kerenel image + * @cmdline_ptr - ptr to the cmdline buffer + * @cmdline_len - len of the buffer. + * + * This generates a buffer in the format Kerenelfilename::cmdline + * + * On success return 0. + * On failure return -EINVAL. + */ +int kexec_cmdline_prepend_img_name(char **outbuf, int kernel_fd, + const char *cmdline_ptr, + unsigned long cmdline_len) +{ + int ret = -EINVAL; + struct fd f = {}; + int size = 0; + char *buf = NULL; + char delimiter[] = "::"; + + if (!outbuf || !cmdline_ptr) + goto out; + + f = fdget(kernel_fd); + if (!f.file) + goto out; + + size = (f.file->f_path.dentry->d_name.len + cmdline_len - 1+ + ARRAY_SIZE(delimiter)) - 1; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + goto out; + + memcpy(buf, f.file->f_path.dentry->d_name.name, + f.file->f_path.dentry->d_name.len); + memcpy(buf + f.file->f_path.dentry->d_name.len, + delimiter, ARRAY_SIZE(delimiter) - 1); + memcpy(buf + f.file->f_path.dentry->d_name.len + + ARRAY_SIZE(delimiter) - 1, + cmdline_ptr, cmdline_len - 1); + + *outbuf = buf; + ret = size; + + pr_debug("kexec cmdline buff: %s\n", buf); + +out: + if (f.file) + fdput(f); + + return ret; +} diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index f1d0e00a3971..d287e139085c 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -191,6 +191,8 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, int ret = 0; void *ldata; loff_t size; + char *buff_to_measure = NULL; + int buff_to_measure_size = 0; ret = kernel_read_file_from_fd(kernel_fd, &image->kernel_buf, &size, INT_MAX, READING_KEXEC_IMAGE); @@ -241,6 +243,16 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, ret = -EINVAL; goto out; } + + /* IMA measures the cmdline args passed to the next kernel*/ + buff_to_measure_size = + kexec_cmdline_prepend_img_name(&buff_to_measure, + kernel_fd, image->cmdline_buf, image->cmdline_buf_len); + + ima_buffer_check(buff_to_measure, buff_to_measure_size, + "kexec_cmdline"); + + } /* Call arch image load handlers */ @@ -253,7 +265,9 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, image->image_loader_data = ldata; out: + /* In case of error, free up all allocated memory in this function */ + kfree(buff_to_measure); if (ret) kimage_file_post_load_cleanup(image); return ret; -- 2.20.1