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-next>] [day] [month] [year] [list]
Message-Id: <20241120122858.22190-1-laoar.shao@gmail.com>
Date: Wed, 20 Nov 2024 20:28:58 +0800
From: Yafang Shao <laoar.shao@...il.com>
To: mingo@...hat.com,
	arnd@...db.de,
	gregkh@...uxfoundation.org
Cc: x86@...nel.org,
	linux-kernel@...r.kernel.org,
	Yafang Shao <laoar.shao@...il.com>,
	Ingo Molnar <mingo@...nel.org>
Subject: [PATCH] /dev/mem: Add a new parameter strict_devmem to bypass strict devmem

When CONFIG_STRICT_DEVMEM is enabled, writing to /dev/mem to override
kernel data for debugging purposes is prohibited. This configuration is
always enabled on our production servers. However, there are times when we
need to use the crash utility to modify kernel data to analyze complex
issues.

As suggested by Ingo, we can add a boot time knob of soft-enabling it.
Therefore, a new parameter "strict_devmem=" is added. The reuslt are as
follows,

- Before this change
  crash> wr panic_on_oops 0
  wr: cannot write to /proc/kcore      <<<< failed

- After this change
  - default
    crash> wr panic_on_oops 0
    wr: cannot write to /proc/kcore    <<<< failed

  - strict_devmem=off
    crash> p panic_on_oops
    panic_on_oops = $1 = 1
    crash> wr panic_on_oops 0
    crash> p panic_on_oops
    panic_on_oops = $2 = 0            <<<< succeeded

  - strict_devmem=invalid
    [    0.230052] Invalid option string for strict_devmem: 'invalid'
    crash> wr panic_on_oops 0
    wr: cannot write to /proc/kcore  <<<< failed

Suggested-by: Ingo Molnar <mingo@...nel.org>
Signed-off-by: Yafang Shao <laoar.shao@...il.com>
---
 .../admin-guide/kernel-parameters.txt         | 16 ++++++++++++++
 drivers/char/mem.c                            | 21 +++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 1518343bbe22..7fe0f66d0dfb 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6563,6 +6563,22 @@
 			them frequently to increase the rate of SLB faults
 			on kernel addresses.
 
+	strict_devmem=
+			[KNL] Under CONFIG_STRICT_DEVMEM, whether strict devmem
+			is enabled for this boot. Strict devmem checking is used
+			to protect the userspace (root) access to all of memory,
+			including kernel and userspace memory. Accidental access
+			to this is obviously disastrous, but specific access can
+			be used by people debugging the kernel. Note that with
+			PAT support enabled, even in this case there are
+			restrictions on /dev/mem use due to the cache aliasing
+			requirements.
+		on	If IO_STRICT_DEVMEM=n, the /dev/mem file only allows
+			userspace access to PCI space and the BIOS code and data
+			regions. This is sufficient for dosemu and X and all
+			common users of /dev/mem. (default)
+		off	Disable strict devmem checks.
+
 	sunrpc.min_resvport=
 	sunrpc.max_resvport=
 			[NFS,SUNRPC]
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 169eed162a7f..bfaeefce4709 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -57,16 +57,24 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
 #endif
 
 #ifdef CONFIG_STRICT_DEVMEM
+static DEFINE_STATIC_KEY_FALSE_RO(bypass_strict_devmem);
+
 static inline int page_is_allowed(unsigned long pfn)
 {
+	if (static_branch_unlikely(&bypass_strict_devmem))
+		return 1;
 	return devmem_is_allowed(pfn);
 }
+
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
 	u64 from = ((u64)pfn) << PAGE_SHIFT;
 	u64 to = from + size;
 	u64 cursor = from;
 
+	if (static_branch_unlikely(&bypass_strict_devmem))
+		return 1;
+
 	while (cursor < to) {
 		if (!devmem_is_allowed(pfn))
 			return 0;
@@ -75,6 +83,19 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 	}
 	return 1;
 }
+
+static bool enable_strict_devmem __initdata = true;
+static int __init parse_strict_devmem(char *str)
+{
+	if (kstrtobool(str, &enable_strict_devmem))
+		pr_warn("Invalid option string for strict_devmem: '%s'\n",
+			str);
+	if (enable_strict_devmem == false)
+		static_branch_enable(&bypass_strict_devmem);
+	return 1;
+}
+
+__setup("strict_devmem=", parse_strict_devmem);
 #else
 static inline int page_is_allowed(unsigned long pfn)
 {
-- 
2.43.5


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ