Commit 235d074f authored by Huacai Chen's avatar Huacai Chen
Browse files

LoongArch: Support access filter to /dev/mem interface



Accidental access to /dev/mem is obviously disastrous, but specific
access can be used by people debugging the kernel. So select GENERIC_
LIB_DEVMEM_IS_ALLOWED, as well as define ARCH_HAS_VALID_PHYS_ADDR_RANGE
and related helpers, to support access filter to /dev/mem interface.

Signed-off-by: default avatarWeihao Li <liweihao@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent b61a40af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ config LOONGARCH
	select GENERIC_LIB_CMPDI2
	select GENERIC_LIB_LSHRDI3
	select GENERIC_LIB_UCMPDI2
	select GENERIC_LIB_DEVMEM_IS_ALLOWED
	select GENERIC_PCI_IOMAP
	select GENERIC_SCHED_CLOCK
	select GENERIC_SMP_IDLE_THREAD
+4 −0
Original line number Diff line number Diff line
@@ -107,4 +107,8 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t

#include <asm-generic/io.h>

#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);

#endif /* _ASM_IO_H */
+29 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
 */
#include <linux/export.h>
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/mman.h>

@@ -116,3 +118,30 @@ int __virt_addr_valid(volatile void *kaddr)
	return pfn_valid(PFN_DOWN(PHYSADDR(kaddr)));
}
EXPORT_SYMBOL_GPL(__virt_addr_valid);

/*
 * You really shouldn't be using read() or write() on /dev/mem.  This might go
 * away in the future.
 */
int valid_phys_addr_range(phys_addr_t addr, size_t size)
{
	/*
	 * Check whether addr is covered by a memory region without the
	 * MEMBLOCK_NOMAP attribute, and whether that region covers the
	 * entire range. In theory, this could lead to false negatives
	 * if the range is covered by distinct but adjacent memory regions
	 * that only differ in other attributes. However, few of such
	 * attributes have been defined, and it is debatable whether it
	 * follows that /dev/mem read() calls should be able traverse
	 * such boundaries.
	 */
	return memblock_is_region_memory(addr, size) && memblock_is_map_memory(addr);
}

/*
 * Do not allow /dev/mem mappings beyond the supported physical range.
 */
int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
	return !(((pfn << PAGE_SHIFT) + size) & ~(GENMASK_ULL(cpu_pabits, 0)));
}