xref: /linux/security/min_addr.c (revision 2d8ad8719591fa803b0d589ed057fa46f49b7155)
1788084abSEric Paris #include <linux/init.h>
2788084abSEric Paris #include <linux/mm.h>
3788084abSEric Paris #include <linux/security.h>
4788084abSEric Paris #include <linux/sysctl.h>
5788084abSEric Paris 
6788084abSEric Paris /* amount of vm to protect from userspace access by both DAC and the LSM*/
7788084abSEric Paris unsigned long mmap_min_addr;
8788084abSEric Paris /* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
9788084abSEric Paris unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
10788084abSEric Paris /* amount of vm to protect from userspace using the LSM = CONFIG_LSM_MMAP_MIN_ADDR */
11788084abSEric Paris 
12788084abSEric Paris /*
13788084abSEric Paris  * Update mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR)
14788084abSEric Paris  */
15788084abSEric Paris static void update_mmap_min_addr(void)
16788084abSEric Paris {
17788084abSEric Paris #ifdef CONFIG_LSM_MMAP_MIN_ADDR
18788084abSEric Paris 	if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
19788084abSEric Paris 		mmap_min_addr = dac_mmap_min_addr;
20788084abSEric Paris 	else
21788084abSEric Paris 		mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
22788084abSEric Paris #else
23788084abSEric Paris 	mmap_min_addr = dac_mmap_min_addr;
24788084abSEric Paris #endif
25788084abSEric Paris }
26788084abSEric Paris 
27788084abSEric Paris /*
28788084abSEric Paris  * sysctl handler which just sets dac_mmap_min_addr = the new value and then
29788084abSEric Paris  * calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
30788084abSEric Paris  */
318d65af78SAlexey Dobriyan int mmap_min_addr_handler(struct ctl_table *table, int write,
32788084abSEric Paris 			  void __user *buffer, size_t *lenp, loff_t *ppos)
33788084abSEric Paris {
34788084abSEric Paris 	int ret;
35788084abSEric Paris 
36*4ae69e6bSKees Cook 	if (write && !capable(CAP_SYS_RAWIO))
370e1a6ef2SKees Cook 		return -EPERM;
380e1a6ef2SKees Cook 
398d65af78SAlexey Dobriyan 	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
40788084abSEric Paris 
41788084abSEric Paris 	update_mmap_min_addr();
42788084abSEric Paris 
43788084abSEric Paris 	return ret;
44788084abSEric Paris }
45788084abSEric Paris 
46dd880fbeSH Hartley Sweeten static int __init init_mmap_min_addr(void)
47788084abSEric Paris {
48788084abSEric Paris 	update_mmap_min_addr();
49788084abSEric Paris 
50788084abSEric Paris 	return 0;
51788084abSEric Paris }
52788084abSEric Paris pure_initcall(init_mmap_min_addr);
53