[PATCH 04/17] watch_queue: Introduce a non-repeating system-unique superblock ID [ver #17]

David Howells
2020-02-21T18:02:26Z

Introduce an (effectively) non-repeating system-unique superblock ID that
can be used to determine that two object are in the same superblock without
risking reuse of the ID in the meantime (as is possible with device IDs).

The ID is time-based to make it harder to use it as a covert communications
channel.

In future patches, this ID will be used to tag superblock notification
messages. It will also be made queryable.

Signed-off-by: David Howells <dhowells@redhat.com>
---

fs/super.c | 24 ++++++++++++++++++++++++
include/linux/fs.h | 3 +++
2 files changed, 27 insertions(+)

diff --git a/fs/super.c b/fs/super.c
index cd352530eca9..a63073e6127e 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -44,6 +44,8 @@ static int thaw_super_locked(struct super_block *sb);

static LIST_HEAD(super_blocks);
static DEFINE_SPINLOCK(sb_lock);
+static u64 sb_last_identifier;
+static u64 sb_identifier_offset;

static char *sb_writers_name[SB_FREEZE_LEVELS] = {
"sb_writers",
@@ -188,6 +190,27 @@ static void destroy_unused_super(struct super_block *s)
destroy_super_work(&s->destroy_work);
}

+/*
+ * Generate a unique identifier for a superblock.
+ */
+static void generate_super_id(struct super_block *s)
+{
+ u64 id = ktime_to_ns(ktime_get());
+
+ spin_lock(&sb_lock);
+
+ id += sb_identifier_offset;
+ if (id <= sb_last_identifier) {
+ id = sb_last_identifier + 1;
+ sb_identifier_offset = sb_last_identifier - id;
+ }
+
+ sb_last_identifier = id;
+ spin_unlock(&sb_lock);
+
+ s->s_unique_id = id;
+}
+
/**
* alloc_super - create new superblock
* @type: filesystem type superblock should belong to
@@ -273,6 +296,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
goto fail;
if (list_lru_init_memcg(&s->s_inode_lru, &s->s_shrink))
goto fail;
+ generate_super_id(s);
return s;

fail:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3cd4fe6b845e..9de6bfe41016 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1548,6 +1548,9 @@ struct super_block {

spinlock_t s_inode_wblist_lock;
struct list_head s_inodes_wb; /* writeback inodes */
+
+ /* Superblock event notifications */
+ u64 s_unique_id;
} __randomize_layout;

/* Helper functions so that in most cases filesystems will