diff mbox series

[v7,2/7] kexec: define functions to map and unmap segments

Message ID 20250203232033.64123-3-chenste@linux.microsoft.com (mailing list archive)
State Handled Elsewhere
Headers show
Series ima: kexec: measure events between kexec load and excute | expand

Commit Message

steven chen Feb. 3, 2025, 11:20 p.m. UTC
Currently, the mechanism to map and unmap segments to the kimage
structure is not available to the subsystems outside of kexec.  This
functionality is needed when IMA is allocating the memory segments
during kexec 'load' operation.  Implement functions to map and unmap
segments to kimage.

Implement kimage_map_segment() to enable mapping of IMA buffer source
pages to the kimage structure post kexec 'load'.  This function,
accepting a kimage pointer, an address, and a size, will gather the
source pages within the specified address range, create an array of page
pointers, and map these to a contiguous virtual address range.  The
function returns the start of this range if successful, or NULL if
unsuccessful.

Implement kimage_unmap_segment() for unmapping segments
using vunmap().

From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: steven chen <chenste@linux.microsoft.com>
---
 include/linux/kexec.h |  7 ++++++
 kernel/kexec_core.c   | 54 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

Comments

Mimi Zohar Feb. 7, 2025, 7:15 p.m. UTC | #1
Hi Steven,

On Mon, 2025-02-03 at 15:20 -0800, steven chen wrote:
> Currently, the mechanism to map and unmap segments to the kimage
> structure is not available to the subsystems outside of kexec.  This
> functionality is needed when IMA is allocating the memory segments
> during kexec 'load' operation.  Implement functions to map and unmap
> segments to kimage.
> 
> Implement kimage_map_segment() to enable mapping of IMA buffer source
> pages to the kimage structure post kexec 'load'.  This function,
> accepting a kimage pointer, an address, and a size, will gather the
> source pages within the specified address range, create an array of page
> pointers, and map these to a contiguous virtual address range.  The
> function returns the start of this range if successful, or NULL if
> unsuccessful.
> 
> Implement kimage_unmap_segment() for unmapping segments
> using vunmap().
> 
> From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

I don't recall previously adding my "Reviewed-by" tag.

Eric, I'd appreciate your reviewing this and the subsequent patch "[PATCH v7 3/7]
ima: kexec: skip IMA segment validation after kexec soft reboot" in particular.


> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: steven chen <chenste@linux.microsoft.com>
> ---
>  include/linux/kexec.h |  7 ++++++
>  kernel/kexec_core.c   | 54 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 61 insertions(+)
> 
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index f0e9f8eda7a3..f8413ea5c8c8 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -467,6 +467,9 @@ extern bool kexec_file_dbg_print;
>  #define kexec_dprintk(fmt, arg...) \
>          do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
>  
> +extern void *kimage_map_segment(struct kimage *image,
> +					unsigned long addr, unsigned long size);

scripts/Checkpatch.pl complains about the parenthesis alignment here and elsewhere.

Mimi

> +extern void kimage_unmap_segment(void *buffer);
>  #else /* !CONFIG_KEXEC_CORE */
>  struct pt_regs;
>  struct task_struct;
> @@ -474,6 +477,10 @@ static inline void __crash_kexec(struct pt_regs *regs) { }
>  static inline void crash_kexec(struct pt_regs *regs) { }
>  static inline int kexec_should_crash(struct task_struct *p) { return 0; }
>  static inline int kexec_crash_loaded(void) { return 0; }
> +static inline void *kimage_map_segment(struct kimage *image,
> +					unsigned long addr, unsigned long size)
> +{ return NULL; }
> +static inline void kimage_unmap_segment(void *buffer) { }
>  #define kexec_in_progress false
>  #endif /* CONFIG_KEXEC_CORE */
>
steven chen Feb. 10, 2025, 5:06 p.m. UTC | #2
On 2/7/2025 11:15 AM, Mimi Zohar wrote:
> Hi Steven,
>
> On Mon, 2025-02-03 at 15:20 -0800, steven chen wrote:
>> Currently, the mechanism to map and unmap segments to the kimage
>> structure is not available to the subsystems outside of kexec.  This
>> functionality is needed when IMA is allocating the memory segments
>> during kexec 'load' operation.  Implement functions to map and unmap
>> segments to kimage.
>>
>> Implement kimage_map_segment() to enable mapping of IMA buffer source
>> pages to the kimage structure post kexec 'load'.  This function,
>> accepting a kimage pointer, an address, and a size, will gather the
>> source pages within the specified address range, create an array of page
>> pointers, and map these to a contiguous virtual address range.  The
>> function returns the start of this range if successful, or NULL if
>> unsuccessful.
>>
>> Implement kimage_unmap_segment() for unmapping segments
>> using vunmap().
>>
>> From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
>> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> I don't recall previously adding my "Reviewed-by" tag.
>
> Eric, I'd appreciate your reviewing this and the subsequent patch "[PATCH v7 3/7]
> ima: kexec: skip IMA segment validation after kexec soft reboot" in particular.
Hi Eric, Could you help to review this patch as Mimi mentioned? Thanks!
>
>> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Signed-off-by: steven chen <chenste@linux.microsoft.com>
>> ---
>>   include/linux/kexec.h |  7 ++++++
>>   kernel/kexec_core.c   | 54 +++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 61 insertions(+)
>>
>> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
>> index f0e9f8eda7a3..f8413ea5c8c8 100644
>> --- a/include/linux/kexec.h
>> +++ b/include/linux/kexec.h
>> @@ -467,6 +467,9 @@ extern bool kexec_file_dbg_print;
>>   #define kexec_dprintk(fmt, arg...) \
>>           do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
>>   
>> +extern void *kimage_map_segment(struct kimage *image,
>> +					unsigned long addr, unsigned long size);
> scripts/Checkpatch.pl complains about the parenthesis alignment here and elsewhere.
>
> Mimi
>
>> +extern void kimage_unmap_segment(void *buffer);
>>   #else /* !CONFIG_KEXEC_CORE */
>>   struct pt_regs;
>>   struct task_struct;
>> @@ -474,6 +477,10 @@ static inline void __crash_kexec(struct pt_regs *regs) { }
>>   static inline void crash_kexec(struct pt_regs *regs) { }
>>   static inline int kexec_should_crash(struct task_struct *p) { return 0; }
>>   static inline int kexec_crash_loaded(void) { return 0; }
>> +static inline void *kimage_map_segment(struct kimage *image,
>> +					unsigned long addr, unsigned long size)
>> +{ return NULL; }
>> +static inline void kimage_unmap_segment(void *buffer) { }
>>   #define kexec_in_progress false
>>   #endif /* CONFIG_KEXEC_CORE */
>>   

Thanks, Mimi, I will update in next version
Mimi Zohar Feb. 12, 2025, 1:03 p.m. UTC | #3
On Mon, 2025-02-10 at 09:06 -0800, steven chen wrote:
> On 2/7/2025 11:15 AM, Mimi Zohar wrote:
> > Hi Steven,
> > 
> > On Mon, 2025-02-03 at 15:20 -0800, steven chen wrote:
> > > Currently, the mechanism to map and unmap segments to the kimage
> > > structure is not available to the subsystems outside of kexec.  This
> > > functionality is needed when IMA is allocating the memory segments
> > > during kexec 'load' operation.  Implement functions to map and unmap
> > > segments to kimage.
> > > 
> > > Implement kimage_map_segment() to enable mapping of IMA buffer source
> > > pages to the kimage structure post kexec 'load'.  This function,
> > > accepting a kimage pointer, an address, and a size, will gather the
> > > source pages within the specified address range, create an array of page
> > > pointers, and map these to a contiguous virtual address range.  The
> > > function returns the start of this range if successful, or NULL if
> > > unsuccessful.
> > > 
> > > Implement kimage_unmap_segment() for unmapping segments
> > > using vunmap().
> > > 
> > > From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> > > Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> > > Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> > > Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> > I don't recall previously adding my "Reviewed-by" tag.
> > 
> > Eric, I'd appreciate your reviewing this and the subsequent patch "[PATCH v7 3/7]
> > ima: kexec: skip IMA segment validation after kexec soft reboot" in particular.
> Hi Eric, Could you help to review this patch as Mimi mentioned? Thanks!
> > 
> > > Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>

Steven, since these patches impact kdump, before re-posting the patch set, please
include the following tags before your Signed-off-by tag on the kexec patches.

Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com>                                             
Cc: Vivek Goyal <vgoyal@redhat.com>                                         
Cc: Dave Young <dyoung@redhat.com>   

> > > Signed-off-by: steven chen <chenste@linux.microsoft.com>

thanks,

Mimi
Baoquan He Feb. 18, 2025, 4:24 a.m. UTC | #4
On 02/12/25 at 08:03am, Mimi Zohar wrote:
> On Mon, 2025-02-10 at 09:06 -0800, steven chen wrote:
> > On 2/7/2025 11:15 AM, Mimi Zohar wrote:
> > > Hi Steven,
> > > 
> > > On Mon, 2025-02-03 at 15:20 -0800, steven chen wrote:
> > > > Currently, the mechanism to map and unmap segments to the kimage
> > > > structure is not available to the subsystems outside of kexec.  This
> > > > functionality is needed when IMA is allocating the memory segments
> > > > during kexec 'load' operation.  Implement functions to map and unmap
> > > > segments to kimage.
> > > > 
> > > > Implement kimage_map_segment() to enable mapping of IMA buffer source
> > > > pages to the kimage structure post kexec 'load'.  This function,
> > > > accepting a kimage pointer, an address, and a size, will gather the
> > > > source pages within the specified address range, create an array of page
> > > > pointers, and map these to a contiguous virtual address range.  The
> > > > function returns the start of this range if successful, or NULL if
> > > > unsuccessful.
> > > > 
> > > > Implement kimage_unmap_segment() for unmapping segments
> > > > using vunmap().
> > > > 
> > > > From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> > > > Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> > > > Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> > > > Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> > > I don't recall previously adding my "Reviewed-by" tag.
> > > 
> > > Eric, I'd appreciate your reviewing this and the subsequent patch "[PATCH v7 3/7]
> > > ima: kexec: skip IMA segment validation after kexec soft reboot" in particular.
> > Hi Eric, Could you help to review this patch as Mimi mentioned? Thanks!
> > > 
> > > > Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> 
> Steven, since these patches impact kdump, before re-posting the patch set, please
> include the following tags before your Signed-off-by tag on the kexec patches.

Thanks, Mimi.

Yes, Steven, please add me in CC when reposting. Thanks in advance.

I will check this version to see if there's impact on kexec/kdump
from my side.

And by the way, kdump should not need IMA, it's better be disabled by
default. I will have a look and try disabling it in kdump kernel, while
really appreciate it if any IMA expert can do it.

Thanks
Baoquan
diff mbox series

Patch

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f0e9f8eda7a3..f8413ea5c8c8 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -467,6 +467,9 @@  extern bool kexec_file_dbg_print;
 #define kexec_dprintk(fmt, arg...) \
         do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
 
+extern void *kimage_map_segment(struct kimage *image,
+					unsigned long addr, unsigned long size);
+extern void kimage_unmap_segment(void *buffer);
 #else /* !CONFIG_KEXEC_CORE */
 struct pt_regs;
 struct task_struct;
@@ -474,6 +477,10 @@  static inline void __crash_kexec(struct pt_regs *regs) { }
 static inline void crash_kexec(struct pt_regs *regs) { }
 static inline int kexec_should_crash(struct task_struct *p) { return 0; }
 static inline int kexec_crash_loaded(void) { return 0; }
+static inline void *kimage_map_segment(struct kimage *image,
+					unsigned long addr, unsigned long size)
+{ return NULL; }
+static inline void kimage_unmap_segment(void *buffer) { }
 #define kexec_in_progress false
 #endif /* CONFIG_KEXEC_CORE */
 
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index c0caa14880c3..4029df8f6860 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -867,6 +867,60 @@  int kimage_load_segment(struct kimage *image,
 	return result;
 }
 
+void *kimage_map_segment(struct kimage *image,
+			 unsigned long addr, unsigned long size)
+{
+	unsigned long eaddr = addr + size;
+	unsigned long src_page_addr, dest_page_addr;
+	unsigned int npages;
+	struct page **src_pages;
+	int i;
+	kimage_entry_t *ptr, entry;
+	void *vaddr = NULL;
+
+	/*
+	 * Collect the source pages and map them in a contiguous VA range.
+	 */
+	npages = PFN_UP(eaddr) - PFN_DOWN(addr);
+	src_pages = kmalloc_array(npages, sizeof(*src_pages), GFP_KERNEL);
+	if (!src_pages) {
+		pr_err("Could not allocate ima pages array.\n");
+		return NULL;
+	}
+
+	i = 0;
+	for_each_kimage_entry(image, ptr, entry) {
+		if (entry & IND_DESTINATION)
+			dest_page_addr = entry & PAGE_MASK;
+		else if (entry & IND_SOURCE) {
+			if (dest_page_addr >= addr && dest_page_addr < eaddr) {
+				src_page_addr = entry & PAGE_MASK;
+				src_pages[i++] =
+					virt_to_page(__va(src_page_addr));
+				if (i == npages)
+					break;
+				dest_page_addr += PAGE_SIZE;
+			}
+		}
+	}
+
+	/* Sanity check. */
+	WARN_ON(i < npages);
+
+	vaddr = vmap(src_pages, npages, VM_MAP, PAGE_KERNEL);
+	kfree(src_pages);
+
+	if (!vaddr)
+		pr_err("Could not map ima buffer.\n");
+
+	return vaddr;
+}
+
+void kimage_unmap_segment(void *segment_buffer)
+{
+	vunmap(segment_buffer);
+}
+
 struct kexec_load_limit {
 	/* Mutex protects the limit count. */
 	struct mutex mutex;