blob: 60514f17c4ffe07406989ce3d0bbe9466c9967c6 [file] [log] [blame]
From 7e212ddab9682e39c383baa643250c6fd45afc05 Mon Sep 17 00:00:00 2001
From: Daniil Lunev <dlunev@chromium.org>
Date: Wed, 23 Mar 2022 16:55:36 +1100
Subject: [PATCH] CHROMIUM: loop: Selective prohibit open after fdclear
Security model for CrOS swap requires exclusion of userspace
access to integrity information. Since integrity information
is stored as a dm-integrity metadevice, that means a need
for access exclusion to loop device and underlying file.
While underlying file can be unlinked from userspace, the loop
device is constantly present and requires other mechanisms to
block its userspace "open". A proposed "flag"-based solution for
device mapper part of the story (needed for excluding access to
plain text content of memory) was rejected upstream[1] and there
is no reason to think the stance on loop device would be different.
While switching behaviour on filename pattern is a hack, this is
a minimal diff from upstream to introduce needed behaviour.
More details: http://shortn/_CcsfmxSjSQ
[1] https://lkml.org/lkml/2022/1/24/633
BUG=b:226288069
TEST=http://crrev/c/3544851
Signed-off-by: Daniil Lunev <dlunev@chromium.org>
Change-Id: I80359fe90dd5d5396d7f330e79b51248dba3b85c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3544412
Reviewed-by: Allen Webb <allenwebb@google.com>
Tested-by: Daniil Lunev <dlunev@chromium.org>
Reviewed-by: Brian Geffon <bgeffon@chromium.org>
Commit-Queue: Daniil Lunev <dlunev@chromium.org>
---
drivers/block/loop.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 084f9b8a0ba3..8e831e3f199c 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -52,6 +52,7 @@ struct loop_device {
loff_t lo_offset;
loff_t lo_sizelimit;
int lo_flags;
+ bool block_open_on_autoclear;
char lo_file_name[LO_NAME_SIZE];
struct file * lo_backing_file;
@@ -92,10 +93,20 @@ struct loop_cmd {
#define LOOP_IDLE_WORKER_TIMEOUT (60 * HZ)
#define LOOP_DEFAULT_HW_Q_DEPTH (128)
+static const char kBlockOpenOnAutoclearPrefix[] = "__block_open_on_autoclear__";
+
static DEFINE_IDR(loop_index_idr);
static DEFINE_MUTEX(loop_ctl_mutex);
static DEFINE_MUTEX(loop_validate_mutex);
+static bool should_block_open_on_autoclear(struct file *file)
+{
+ const size_t prefix_len = strlen(kBlockOpenOnAutoclearPrefix);
+ const char *fname = file->f_path.dentry->d_name.name;
+
+ return !strncmp(fname, kBlockOpenOnAutoclearPrefix, prefix_len);
+}
+
/**
* loop_global_lock_killable() - take locks for safe loop_validate_file() test
*
@@ -607,6 +618,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
blk_mq_freeze_queue(lo->lo_queue);
mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
lo->lo_backing_file = file;
+ if (should_block_open_on_autoclear(file))
+ lo->block_open_on_autoclear = true;
lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
mapping_set_gfp_mask(file->f_mapping,
lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
@@ -1068,6 +1081,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO;
lo->lo_device = bdev;
lo->lo_backing_file = file;
+ if (should_block_open_on_autoclear(file))
+ lo->block_open_on_autoclear = true;
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
@@ -1147,6 +1162,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
spin_lock_irq(&lo->lo_lock);
filp = lo->lo_backing_file;
lo->lo_backing_file = NULL;
+ lo->block_open_on_autoclear = false;
spin_unlock_irq(&lo->lo_lock);
lo->lo_device = NULL;
--
2.36.1.255.ge46751e96f-goog