1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Based on arch/arm/mm/mmap.c 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2012 ARM Ltd. 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #include <linux/elf.h> 9*4882a593Smuzhiyun #include <linux/fs.h> 10*4882a593Smuzhiyun #include <linux/memblock.h> 11*4882a593Smuzhiyun #include <linux/mm.h> 12*4882a593Smuzhiyun #include <linux/mman.h> 13*4882a593Smuzhiyun #include <linux/export.h> 14*4882a593Smuzhiyun #include <linux/shm.h> 15*4882a593Smuzhiyun #include <linux/sched/signal.h> 16*4882a593Smuzhiyun #include <linux/sched/mm.h> 17*4882a593Smuzhiyun #include <linux/io.h> 18*4882a593Smuzhiyun #include <linux/personality.h> 19*4882a593Smuzhiyun #include <linux/random.h> 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun #include <asm/cputype.h> 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun /* 24*4882a593Smuzhiyun * You really shouldn't be using read() or write() on /dev/mem. This might go 25*4882a593Smuzhiyun * away in the future. 26*4882a593Smuzhiyun */ valid_phys_addr_range(phys_addr_t addr,size_t size)27*4882a593Smuzhiyunint valid_phys_addr_range(phys_addr_t addr, size_t size) 28*4882a593Smuzhiyun { 29*4882a593Smuzhiyun /* 30*4882a593Smuzhiyun * Check whether addr is covered by a memory region without the 31*4882a593Smuzhiyun * MEMBLOCK_NOMAP attribute, and whether that region covers the 32*4882a593Smuzhiyun * entire range. In theory, this could lead to false negatives 33*4882a593Smuzhiyun * if the range is covered by distinct but adjacent memory regions 34*4882a593Smuzhiyun * that only differ in other attributes. However, few of such 35*4882a593Smuzhiyun * attributes have been defined, and it is debatable whether it 36*4882a593Smuzhiyun * follows that /dev/mem read() calls should be able traverse 37*4882a593Smuzhiyun * such boundaries. 38*4882a593Smuzhiyun */ 39*4882a593Smuzhiyun return memblock_is_region_memory(addr, size) && 40*4882a593Smuzhiyun memblock_is_map_memory(addr); 41*4882a593Smuzhiyun } 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun /* 44*4882a593Smuzhiyun * Do not allow /dev/mem mappings beyond the supported physical range. 45*4882a593Smuzhiyun */ valid_mmap_phys_addr_range(unsigned long pfn,size_t size)46*4882a593Smuzhiyunint valid_mmap_phys_addr_range(unsigned long pfn, size_t size) 47*4882a593Smuzhiyun { 48*4882a593Smuzhiyun return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK); 49*4882a593Smuzhiyun } 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun #ifdef CONFIG_STRICT_DEVMEM 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun #include <linux/ioport.h> 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun /* 56*4882a593Smuzhiyun * devmem_is_allowed() checks to see if /dev/mem access to a certain address 57*4882a593Smuzhiyun * is valid. The argument is a physical page number. We mimic x86 here by 58*4882a593Smuzhiyun * disallowing access to system RAM as well as device-exclusive MMIO regions. 59*4882a593Smuzhiyun * This effectively disable read()/write() on /dev/mem. 60*4882a593Smuzhiyun */ devmem_is_allowed(unsigned long pfn)61*4882a593Smuzhiyunint devmem_is_allowed(unsigned long pfn) 62*4882a593Smuzhiyun { 63*4882a593Smuzhiyun if (iomem_is_exclusive(pfn << PAGE_SHIFT)) 64*4882a593Smuzhiyun return 0; 65*4882a593Smuzhiyun if (!page_is_ram(pfn)) 66*4882a593Smuzhiyun return 1; 67*4882a593Smuzhiyun return 0; 68*4882a593Smuzhiyun } 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun #endif 71