|  | From 695a880f7d1bf86090dae3c32e3dc67c30917267 Mon Sep 17 00:00:00 2001 | 
|  | From: David Howells <dhowells@redhat.com> | 
|  | Date: Fri, 5 Jul 2019 11:10:10 +0100 | 
|  | Subject: [PATCH 2/4] watch_queue: Introduce a non-repeating system-unique | 
|  | superblock ID | 
|  |  | 
|  | 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/internal.h      |  1 + | 
|  | fs/super.c         | 24 ++++++++++++++++++++++++ | 
|  | include/linux/fs.h |  3 +++ | 
|  | 3 files changed, 28 insertions(+) | 
|  |  | 
|  | diff --git a/fs/internal.h b/fs/internal.h | 
|  | index f3f280b952a3..a0d90f23593c 100644 | 
|  | --- a/fs/internal.h | 
|  | +++ b/fs/internal.h | 
|  | @@ -109,6 +109,7 @@ extern int reconfigure_super(struct fs_context *); | 
|  | extern bool trylock_super(struct super_block *sb); | 
|  | extern struct super_block *user_get_super(dev_t); | 
|  | extern bool mount_capable(struct fs_context *); | 
|  | +extern void vfs_generate_unique_id(u64 *); | 
|  |  | 
|  | /* | 
|  | * open.c | 
|  | diff --git a/fs/super.c b/fs/super.c | 
|  | index cd352530eca9..ececa5695fd1 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 vfs_last_identifier; | 
|  | +static u64 vfs_identifier_offset; | 
|  |  | 
|  | static char *sb_writers_name[SB_FREEZE_LEVELS] = { | 
|  | "sb_writers", | 
|  | @@ -273,6 +275,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; | 
|  | +	vfs_generate_unique_id(&s->s_unique_id); | 
|  | return s; | 
|  |  | 
|  | fail: | 
|  | @@ -1867,3 +1870,24 @@ int thaw_super(struct super_block *sb) | 
|  | return thaw_super_locked(sb); | 
|  | } | 
|  | EXPORT_SYMBOL(thaw_super); | 
|  | + | 
|  | +/* | 
|  | + * Generate a unique identifier for a superblock or mount object. | 
|  | + */ | 
|  | +void vfs_generate_unique_id(u64 *_id) | 
|  | +{ | 
|  | +	u64 id = ktime_to_ns(ktime_get()); | 
|  | + | 
|  | +	spin_lock(&sb_lock); | 
|  | + | 
|  | +	id += vfs_identifier_offset; | 
|  | +	if (id <= vfs_last_identifier) { | 
|  | +		id = vfs_last_identifier + 1; | 
|  | +		vfs_identifier_offset = vfs_last_identifier - id; | 
|  | +	} | 
|  | + | 
|  | +	vfs_last_identifier = id; | 
|  | +	spin_unlock(&sb_lock); | 
|  | + | 
|  | +	*_id = id; | 
|  | +} | 
|  | diff --git a/include/linux/fs.h b/include/linux/fs.h | 
|  | index abedbffe2c9e..fb0db8474141 100644 | 
|  | --- a/include/linux/fs.h | 
|  | +++ b/include/linux/fs.h | 
|  | @@ -1549,6 +1549,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 | 
|  | -- | 
|  | 2.20.1 | 
|  |  |