Add sysctl to disable disk-based swap

This commit is contained in:
Mikhail Novosyolov 2020-07-27 22:32:06 +03:00
parent ed3d48040b
commit 3e4f00ba01
2 changed files with 183 additions and 1 deletions

View file

@ -0,0 +1,168 @@
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.
[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 (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

View file

@ -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.