From 3e4f00ba01840aa99832f6571d6600729bb9a7ee Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Mon, 27 Jul 2020 22:32:06 +0300 Subject: [PATCH] Add sysctl to disable disk-based swap --- ...dd-sysctl-to-disable-disk-based-swap.patch | 168 ++++++++++++++++++ kernel.spec | 16 +- 2 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 0001-mm-add-sysctl-to-disable-disk-based-swap.patch diff --git a/0001-mm-add-sysctl-to-disable-disk-based-swap.patch b/0001-mm-add-sysctl-to-disable-disk-based-swap.patch new file mode 100644 index 0000000..c1618d3 --- /dev/null +++ b/0001-mm-add-sysctl-to-disable-disk-based-swap.patch @@ -0,0 +1,168 @@ +From 739b745efb929453f41472e111760be6f8be6a3a Mon Sep 17 00:00:00 2001 +From: Mikhail Novosyolov +Date: Sat, 1 Aug 2020 12:43:53 +0300 +Subject: [PATCH] mm: add sysctl to disable disk-based swap + +Sometimes it is needed to disallow using disk-based swaps, for example, +when it is required to ensure that any secret information is not left on disk. + +When something is written to disk, it can be restored in most cases +unless being overwritten. When memory data is stored on disk, we cannot be +sure that it will be overwritten and so cannot be sure that secret information +is deleted securely. + +CONFIG_INIT_ON_FREE_DEFAULT_ON=y makes the kernel overwrite everything that is +deleted from memory, but it does not ensure that regions of the disk with swap +are overwritten. Currently there is no way to ensure wiping swap on disk. + +In such conditions it makes sense to disallow usage of disk-based swap. +This patch adds sysctl vm.disk_based_swap, by default is is 1, which means that +disk-based swap (both swap files and swap partitions) can be used. +If = 0, than only zram swap is allowed, zram is not a disk-based swap +(but note that zram can offload parts of it to disk, CONFIG_ZRAM_WRITEBACK, +it is not controlled by this sysctl). + +This patch is based on patches from Chromium OS Linux kernel [1, 2, 3, 4] +Patch [5] is taken as an example of adding a sysctl. + +[1] https://gitlab.freedesktop.org/seanpaul/dpu-staging/commit/0b992f2dbb044896c3584e10bd5b97cf41e2ec6d +[2] https://chromium.googlesource.com/chromiumos/third_party/kernel/+/880b2d77404682761ae2e19297f1183fd434b0ec%5E%21/ +[3] https://chromium.googlesource.com/chromiumos/third_party/kernel/+blame/refs/heads/chromeos-5.4/mm/swapfile.c +[4] https://chromium.googlesource.com/chromiumos/third_party/kernel/+blame/refs/heads/chromeos-5.4/kernel/sysctl.c +[5] https://patchwork.kernel.org/patch/10858771/ + +Author of [2] in Chromium OS kernel: +Co-authored-by: Will Drewry + +Signed-off-by: Mikhail Novosyolov +--- + Documentation/admin-guide/sysctl/vm.rst | 8 ++++++++ + include/linux/mm.h | 2 ++ + init/Kconfig | 11 +++++++++++ + kernel/sysctl.c | 9 +++++++++ + mm/swapfile.c | 16 ++++++++++++++++ + 5 files changed, 46 insertions(+) + +diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst +index 64aeee1009ca..9d60154695f6 100644 +--- a/Documentation/admin-guide/sysctl/vm.rst ++++ b/Documentation/admin-guide/sysctl/vm.rst +@@ -35,6 +35,7 @@ Currently, these files are in /proc/sys/vm: + - dirty_ratio + - dirtytime_expire_seconds + - dirty_writeback_centisecs ++- disk_based_swap + - drop_caches + - extfrag_threshold + - hugetlb_shm_group +@@ -209,6 +210,13 @@ out to disk. This tunable expresses the interval between those wakeups, in + + Setting this to zero disables periodic writeback altogether. + ++disk_based_swap ++=============== ++ ++Disables (0) or enables (1) usage of disk-based swap, both swap files and ++swap partitions. When disabled, only zram swap can be used, and disk-based ++swap is prohibited then. ++ + + drop_caches + =========== +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 3285dae06c03..f8b9522da07d 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2901,5 +2901,7 @@ static inline int pages_identical(struct page *page1, struct page *page2) + return !memcmp_pages(page1, page2); + } + ++extern int sysctl_disk_based_swap; ++ + #endif /* __KERNEL__ */ + #endif /* _LINUX_MM_H */ +diff --git a/init/Kconfig b/init/Kconfig +index 87e4f2ac7c5e..4187799a9d13 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -280,6 +280,17 @@ config SWAP + used to provide more virtual memory than the actual RAM present + in your computer. If unsure say Y. + ++config DISK_BASED_SWAP_DEFAULT_ON ++ bool "Allow disk-based swap" ++ depends on SWAP ++ default y ++ help ++ If true, disk-based swap (either a file or a partition) is allowed, ++ otherwise only zram swap is allowed. ++ sysctl vm.disk_based_swap = [ 1 | 0 ] ++ Note that zram writeback feature is not controlled by this sysctl. ++ If unsure say Y. ++ + config SYSVIPC + bool "System V IPC" + ---help--- +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 70665934d53e..5f2e4613e655 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -1405,6 +1405,15 @@ static struct ctl_table vm_table[] = { + .proc_handler = dirtytime_interval_handler, + .extra1 = SYSCTL_ZERO, + }, ++ { ++ .procname = "disk_based_swap", ++ .data = &sysctl_disk_based_swap, ++ .maxlen = sizeof(sysctl_disk_based_swap), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_ONE, ++ }, + { + .procname = "swappiness", + .data = &vm_swappiness, +diff --git a/mm/swapfile.c b/mm/swapfile.c +index 891a3ef48651..ef79f4d03809 100644 +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -2871,12 +2871,26 @@ static struct swap_info_struct *alloc_swap_info(void) + return p; + } + ++#ifdef CONFIG_DISK_BASED_SWAP_DEFAULT_ON ++int sysctl_disk_based_swap __read_mostly = 1; ++#else ++int sysctl_disk_based_swap __read_mostly = 0; ++#endif ++ + static int claim_swapfile(struct swap_info_struct *p, struct inode *inode) + { + int error; + + if (S_ISBLK(inode->i_mode)) { ++ char name[BDEVNAME_SIZE]; + p->bdev = bdgrab(I_BDEV(inode)); ++ bdevname(p->bdev, name); ++ // If sysctl vm.disk_based_swap = false, prohibit any swaps but zram ++ if (strncmp(name, "zram", strlen("zram")) && !sysctl_disk_based_swap) { ++ bdput(p->bdev); ++ p->bdev = NULL; ++ return -EINVAL; ++ } + error = blkdev_get(p->bdev, + FMODE_READ | FMODE_WRITE | FMODE_EXCL, p); + if (error < 0) { +@@ -2889,6 +2903,8 @@ static int claim_swapfile(struct swap_info_struct *p, struct inode *inode) + return error; + p->flags |= SWP_BLKDEV; + } else if (S_ISREG(inode->i_mode)) { ++ if (!sysctl_disk_based_swap) ++ return -EINVAL; + p->bdev = inode->i_sb->s_bdev; + } + +-- +2.17.1 + diff --git a/kernel.spec b/kernel.spec index ae7c481..e85c7f1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -24,7 +24,7 @@ %define sublevel 40 # Release number. Increase this before a rebuild. -%define rpmrel 6 +%define rpmrel 7 %define fullrpmrel %{rpmrel} %define rpmtag %{disttag} @@ -280,6 +280,8 @@ Patch302: 0001-sign-file-full-functionality-with-modern-LibreSSL.patch # For buildability with new binutils # https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/commit/?id=0ada120c883d Patch303: perf-5.4.20-binutil-libs-2.34.patch +# Add sysctl to disable disk-based swap +Patch304: 0001-mm-add-sysctl-to-disable-disk-based-swap.patch # Disable AutoReq AutoReq: 0 @@ -1051,6 +1053,18 @@ sed -i '/CONFIG_SECURITY_ALTHA/d' .config echo 'CONFIG_SECURITY_ALTHA=y' >> %{build_dir}/.config.append %endif +# Disable disk-based swap (swap files and partitions) on certified systems by default +# because we cannot guarantee that data stored in swap is erased from disk securely. +# Our patch, based on Chromium OS kernel, allows to use only zram if CONFIG_DISK_BASED_SWAP_DEFAULT_ON=y. +# sysctl vm.disk_based_swap = 1 to allow disk-based swap, = 0 to disable it. +# Note that CONFIG_ZRAM_WRITEBACK is still on. +sed -i '/CONFIG_DISK_BASED_SWAP_DEFAULT_ON/d' .config +%if %{with nickel} +echo 'CONFIG_DISK_BASED_SWAP_DEFAULT_ON=n' >> %{build_dir}/.config.append +%else +echo 'CONFIG_DISK_BASED_SWAP_DEFAULT_ON=y' >> %{build_dir}/.config.append +%endif + cat %{build_dir}/.config.append >> .config # Store the config file in the appropriate directory.