kernel-5.15/0001-mm-add-sysctl-to-disable-disk-based-swap.patch
Mikhail Novosyolov b60bba1a6f add TODO to patch
2020-08-06 14:34:46 +03:00

170 lines
5.9 KiB
Diff

From 739b745efb929453f41472e111760be6f8be6a3a Mon Sep 17 00:00:00 2001
From: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
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.
TODO: print a message why swap was blocked.
[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 <wad@chromium.org>
Signed-off-by: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
---
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 (!sysctl_disk_based_swap && strncmp(name, "zram", strlen("zram"))) {
+ 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