From patchwork Fri Jan 24 22:55:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: steven chen X-Patchwork-Id: 13950014 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3317D1E98ED; Fri, 24 Jan 2025 22:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737759358; cv=none; b=Id0H9TYkknAkSPU02l/n27jt2/W3E7JwkpplIxy6QekNXORgBkTj0dlzI8w0a10MsivZdQb79cwQa83paIsJBgBjMMAhyEOGS7x+Inm0XcJNMvD4bJj9Ot02H9n9eXhfY2/kTSnEofzv0STFvBoCFPdSJvG5GwwkTpsIAUqV6b8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737759358; c=relaxed/simple; bh=t4XqqrYhwscr6FS7U4bhL3N2YVK27fxTi1qasHS8jzw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FLMDEGl/G+S9BcJ+wefBSAMsmozxe1jgk9XZrQm34lIGATvt0LgG9fx0XHLqhUbIDYg3aRa2OI9ZF4nYj2YYiCU7MGXqDhFP1KYJV0yPn7TSIb1EwIBoYwTvoxNZ9NKCsm9DPqYCpZD16sZeC3GfAHl5YbTycrHY/qquId3yc8c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=jghbD9HJ; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="jghbD9HJ" Received: from localhost.localdomain (unknown [167.220.59.4]) by linux.microsoft.com (Postfix) with ESMTPSA id 9A8E1210D0D4; Fri, 24 Jan 2025 14:55:56 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 9A8E1210D0D4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1737759356; bh=l74eF+4+r695BFOwyov/kRxEW4Z5jvFKpT/pUDEgh3Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jghbD9HJu2oe58ohStE3w987J3WX+/gkRdWwpCd4JLYg7z6r1Qf3HZ9mk4JndUR9W CtUCBpr101c9MQyJEReYtW+jX7yPKjJDpKmMH31MMZ7uK52RkOZ0kQia+DMYnjLeFk bc1Bw3SbP1WlwcoqStVL8VJp3SoaaWG7mu49EAjI= From: steven chen To: zohar@linux.ibm.com, stefanb@linux.ibm.com, roberto.sassu@huaweicloud.com, petr@tesarici.cz, eric.snowberg@oracle.com, paul@paul-moore.com, code@tyhicks.com, nramas@linux.microsoft.com, James.Bottomley@HansenPartnership.com, madvenka@linux.microsoft.com Cc: linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, chenste@linux.microsoft.com Subject: [PATCH v6 2/7] kexec: define functions to map and unmap segments Date: Fri, 24 Jan 2025 14:55:42 -0800 Message-Id: <20250124225547.22684-3-chenste@linux.microsoft.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250124225547.22684-1-chenste@linux.microsoft.com> References: <20250124225547.22684-1-chenste@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Author: Tushar Sugandhi Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Signed-off-by: Tushar Sugandhi Signed-off-by: steven chen --- 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); +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;