blob: c3d43676af2f39abeb22dd02597e7ea16cc94ed8 [file] [log] [blame]
Lorenz Brun1d801752020-04-02 09:24:51 +02001From 695a880f7d1bf86090dae3c32e3dc67c30917267 Mon Sep 17 00:00:00 2001
2From: David Howells <dhowells@redhat.com>
3Date: Fri, 5 Jul 2019 11:10:10 +0100
4Subject: [PATCH 2/4] watch_queue: Introduce a non-repeating system-unique
5 superblock ID
6
7Introduce an (effectively) non-repeating system-unique superblock ID that
8can be used to determine that two object are in the same superblock without
9risking reuse of the ID in the meantime (as is possible with device IDs).
10
11The ID is time-based to make it harder to use it as a covert communications
12channel.
13
14In future patches, this ID will be used to tag superblock notification
15messages. It will also be made queryable.
16
17Signed-off-by: David Howells <dhowells@redhat.com>
18---
19 fs/internal.h | 1 +
20 fs/super.c | 24 ++++++++++++++++++++++++
21 include/linux/fs.h | 3 +++
22 3 files changed, 28 insertions(+)
23
24diff --git a/fs/internal.h b/fs/internal.h
25index f3f280b952a3..a0d90f23593c 100644
26--- a/fs/internal.h
27+++ b/fs/internal.h
28@@ -109,6 +109,7 @@ extern int reconfigure_super(struct fs_context *);
29 extern bool trylock_super(struct super_block *sb);
30 extern struct super_block *user_get_super(dev_t);
31 extern bool mount_capable(struct fs_context *);
32+extern void vfs_generate_unique_id(u64 *);
33
34 /*
35 * open.c
36diff --git a/fs/super.c b/fs/super.c
37index cd352530eca9..ececa5695fd1 100644
38--- a/fs/super.c
39+++ b/fs/super.c
40@@ -44,6 +44,8 @@ static int thaw_super_locked(struct super_block *sb);
41
42 static LIST_HEAD(super_blocks);
43 static DEFINE_SPINLOCK(sb_lock);
44+static u64 vfs_last_identifier;
45+static u64 vfs_identifier_offset;
46
47 static char *sb_writers_name[SB_FREEZE_LEVELS] = {
48 "sb_writers",
49@@ -273,6 +275,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
50 goto fail;
51 if (list_lru_init_memcg(&s->s_inode_lru, &s->s_shrink))
52 goto fail;
53+ vfs_generate_unique_id(&s->s_unique_id);
54 return s;
55
56 fail:
57@@ -1867,3 +1870,24 @@ int thaw_super(struct super_block *sb)
58 return thaw_super_locked(sb);
59 }
60 EXPORT_SYMBOL(thaw_super);
61+
62+/*
63+ * Generate a unique identifier for a superblock or mount object.
64+ */
65+void vfs_generate_unique_id(u64 *_id)
66+{
67+ u64 id = ktime_to_ns(ktime_get());
68+
69+ spin_lock(&sb_lock);
70+
71+ id += vfs_identifier_offset;
72+ if (id <= vfs_last_identifier) {
73+ id = vfs_last_identifier + 1;
74+ vfs_identifier_offset = vfs_last_identifier - id;
75+ }
76+
77+ vfs_last_identifier = id;
78+ spin_unlock(&sb_lock);
79+
80+ *_id = id;
81+}
82diff --git a/include/linux/fs.h b/include/linux/fs.h
83index abedbffe2c9e..fb0db8474141 100644
84--- a/include/linux/fs.h
85+++ b/include/linux/fs.h
86@@ -1549,6 +1549,9 @@ struct super_block {
87
88 spinlock_t s_inode_wblist_lock;
89 struct list_head s_inodes_wb; /* writeback inodes */
90+
91+ /* Superblock event notifications */
92+ u64 s_unique_id;
93 } __randomize_layout;
94
95 /* Helper functions so that in most cases filesystems will
96--
972.20.1
98