lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1656934895-12334-3-git-send-email-carlo.bai@linux.alibaba.com>
Date:   Mon,  4 Jul 2022 19:41:35 +0800
From:   Kaihao Bai <carlo.bai@...ux.alibaba.com>
To:     ebiederm@...ssion.com
Cc:     kexec@...ts.infradead.org, linux-kernel@...r.kernel.org,
        baolin.wang@...ux.alibaba.com, carlo.bai@...ux.alibaba.com
Subject: [PATCH 2/2] kexec: release reserved memory ranges to RAM if crashk_low_res defined

If reserving low memory range for crashkenrel, the range could not free
to System RAM all the time. However, the high memory range corresponding
to crashk_res can free to RAM through /sys/kernel/kexec_crash_size. If I
write a smaller size to /sys/kernel/kexec_crash_size,  the exceeded part
of  the new size would be released.

To support releasing the low memory range,  we should determine whether
the new size is greater than the accumulated size. If not, the reserved
high memory range will be released firstly. If the new size is smaller
than the size of low memory range, we continue to release the reserved
low memory range after completely releasing the high memory range.

Signed-off-by: Kaihao Bai <carlo.bai@...ux.alibaba.com>
---
 kernel/kexec_core.c | 75 +++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 56 insertions(+), 19 deletions(-)

diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 137f6eb..e89c171 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1031,12 +1031,42 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
 		free_reserved_page(boot_pfn_to_page(addr >> PAGE_SHIFT));
 }
 
+static int __crash_shrink_memory(struct resource *crashkernel,
+				 unsigned long start, unsigned long end)
+{
+	int ret = 0;
+	struct resource *ram_res;
+
+	ram_res = kzalloc(sizeof(*ram_res), GFP_KERNEL);
+	if (!ram_res) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	crash_free_reserved_phys_range(end, crashkernel->end);
+
+	if ((start == end) && (crashkernel->parent != NULL))
+		release_resource(crashkernel);
+
+	ram_res->start = end;
+	ram_res->end = crashk_res.end;
+	ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
+	ram_res->name = "System RAM";
+
+	crashkernel->end = end - 1;
+
+	insert_resource(&iomem_resource, ram_res);
+
+	return ret;
+}
+
 int crash_shrink_memory(unsigned long new_size)
 {
 	int ret = 0;
 	unsigned long start, end;
+	unsigned long low_start, low_end;
 	unsigned long old_size;
-	struct resource *ram_res;
+	unsigned long low_old_size;
 
 	mutex_lock(&kexec_mutex);
 
@@ -1047,33 +1077,40 @@ int crash_shrink_memory(unsigned long new_size)
 	start = crashk_res.start;
 	end = crashk_res.end;
 	old_size = (end == 0) ? 0 : end - start + 1;
+	low_start = crashk_low_res.start;
+	low_end = crashk_low_res.end;
+	low_old_size = (low_end == 0) ? 0 : low_end - low_start + 1;
+	old_size += low_old_size;
+
 	if (new_size >= old_size) {
 		ret = (new_size == old_size) ? 0 : -EINVAL;
 		goto unlock;
 	}
+	if (start != end) {
+		start = roundup(start, KEXEC_CRASH_MEM_ALIGN);
 
-	ram_res = kzalloc(sizeof(*ram_res), GFP_KERNEL);
-	if (!ram_res) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
-
-	start = roundup(start, KEXEC_CRASH_MEM_ALIGN);
-	end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN);
-
-	crash_free_reserved_phys_range(end, crashk_res.end);
+		/*
+		 * If the new_size is smaller than the reserved lower memory
+		 * range of crashkernel, it releases all higher memory range.
+		 * Otherwise it releases part of higher range.
+		 */
+		end = (new_size <= low_old_size) ?
+			roundup(start, KEXEC_CRASH_MEM_ALIGN) :
+			roundup(start + new_size - low_old_size,
+				KEXEC_CRASH_MEM_ALIGN);
 
-	if ((start == end) && (crashk_res.parent != NULL))
-		release_resource(&crashk_res);
+		ret = __crash_shrink_memory(&crashk_res, start, end);
 
-	ram_res->start = end;
-	ram_res->end = crashk_res.end;
-	ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
-	ram_res->name = "System RAM";
+		if (ret)
+			goto unlock;
+	}
 
-	crashk_res.end = end - 1;
+	if (new_size < low_old_size) {
+		low_start = roundup(low_start, KEXEC_CRASH_MEM_ALIGN);
+		low_end = roundup(low_start + new_size, KEXEC_CRASH_MEM_ALIGN);
 
-	insert_resource(&iomem_resource, ram_res);
+		ret = __crash_shrink_memory(&crashk_low_res, low_start, low_end);
+	}
 
 unlock:
 	mutex_unlock(&kexec_mutex);
-- 
1.8.3.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ