Lorenz Brun | 1d80175 | 2020-04-02 09:24:51 +0200 | [diff] [blame] | 1 | From 695a880f7d1bf86090dae3c32e3dc67c30917267 Mon Sep 17 00:00:00 2001 |
| 2 | From: David Howells <dhowells@redhat.com> |
| 3 | Date: Fri, 5 Jul 2019 11:10:10 +0100 |
| 4 | Subject: [PATCH 2/4] watch_queue: Introduce a non-repeating system-unique |
| 5 | superblock ID |
| 6 | |
| 7 | Introduce an (effectively) non-repeating system-unique superblock ID that |
| 8 | can be used to determine that two object are in the same superblock without |
| 9 | risking reuse of the ID in the meantime (as is possible with device IDs). |
| 10 | |
| 11 | The ID is time-based to make it harder to use it as a covert communications |
| 12 | channel. |
| 13 | |
| 14 | In future patches, this ID will be used to tag superblock notification |
| 15 | messages. It will also be made queryable. |
| 16 | |
| 17 | Signed-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 | |
| 24 | diff --git a/fs/internal.h b/fs/internal.h |
| 25 | index 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 |
| 36 | diff --git a/fs/super.c b/fs/super.c |
| 37 | index 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 | +} |
| 82 | diff --git a/include/linux/fs.h b/include/linux/fs.h |
| 83 | index 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 | -- |
| 97 | 2.20.1 |
| 98 | |