min_addr.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/init.h>
  3. #include <linux/mm.h>
  4. #include <linux/security.h>
  5. #include <linux/sysctl.h>
  6. /* amount of vm to protect from userspace access by both DAC and the LSM*/
  7. unsigned long mmap_min_addr;
  8. /* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
  9. unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
  10. /* amount of vm to protect from userspace using the LSM = CONFIG_LSM_MMAP_MIN_ADDR */
  11. /*
  12. * Update mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR)
  13. */
  14. static void update_mmap_min_addr(void)
  15. {
  16. #ifdef CONFIG_LSM_MMAP_MIN_ADDR
  17. if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
  18. mmap_min_addr = dac_mmap_min_addr;
  19. else
  20. mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
  21. #else
  22. mmap_min_addr = dac_mmap_min_addr;
  23. #endif
  24. }
  25. /*
  26. * sysctl handler which just sets dac_mmap_min_addr = the new value and then
  27. * calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
  28. */
  29. int mmap_min_addr_handler(struct ctl_table *table, int write,
  30. void __user *buffer, size_t *lenp, loff_t *ppos)
  31. {
  32. int ret;
  33. if (write && !capable(CAP_SYS_RAWIO))
  34. return -EPERM;
  35. ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
  36. update_mmap_min_addr();
  37. return ret;
  38. }
  39. static int __init init_mmap_min_addr(void)
  40. {
  41. update_mmap_min_addr();
  42. return 0;
  43. }
  44. pure_initcall(init_mmap_min_addr);