On Mon, 2019-04-29 at 14:47 -0700, Prakhar Srivastava wrote: > From: Prakhar Srivastava <prsriva02@xxxxxxxxx> > > prepend the kernel file name to kexec_cmdline > before measuring the buffer. > kexec doesn't really know or care about IMA. Other than the IMA call, itself, nothing should be added to kexec files. As mentioned in 1/4, the IMA hook would be named something like ima_kexec_cmdline(). Mimi > 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;