Re: [PATCH 05/19] vfs: Introduce a non-repeating system-unique superblock ID [ver #16]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Feb 18, 2020 at 05:05:35PM +0000, David Howells wrote:
> 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.
> 
> Also make it so that this ID can be fetched by the fsinfo() system call.
> The ID added so that superblock notification messages will also be able to
> be tagged with it.
> 
> Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
> ---
> 
>  fs/fsinfo.c               |    1 +
>  fs/super.c                |   24 ++++++++++++++++++++++++
>  include/linux/fs.h        |    3 +++
>  samples/vfs/test-fsinfo.c |    1 +
>  4 files changed, 29 insertions(+)
> 
> diff --git a/fs/fsinfo.c b/fs/fsinfo.c
> index 55710d6da327..f8e85762fc47 100644
> --- a/fs/fsinfo.c
> +++ b/fs/fsinfo.c
> @@ -92,6 +92,7 @@ static int fsinfo_generic_ids(struct path *path, struct fsinfo_context *ctx)
>  	p->f_fstype	= sb->s_magic;
>  	p->f_dev_major	= MAJOR(sb->s_dev);
>  	p->f_dev_minor	= MINOR(sb->s_dev);
> +	p->f_sb_id	= sb->s_unique_id;

Ahah, this is what the f_sb_id field is for.  I noticed a few patches
ago that it was in a header file but was never set.

I'm losing track of which IDs do what...

* f_fsid is that old int[2] thing that we used for statfs.  It sucks but
  we can't remove it because it's been in statfs since the beginning of
  time.

* f_fs_name is a string coming from s_type, which is the name of the fs
  (e.g. "XFS")?

* f_fstype comes from s_magic, which (for XFS) is 0x58465342.

* f_sb_id is basically an incore u64 cookie that one can use with the
  mount events thing that comes later in this patchset?

* FSINFO_ATTR_VOLUME_ID comes from s_id, which tends to be the block
  device name (at least for local filesystems)

* FSINFO_ATTR_VOLUME_UUID comes from s_uuid, which some filesystems fill
  in at mount time.

* FSINFO_ATTR_VOLUME_NAME is ... left to individual filesystems to
  implement, and (AFAICT) can be the label that one uses for things
  like: "mount LABEL=foo /home" ?

Assuming I got all of that right, can we please capture what all of
these "IDs" mean in the documentation?

(Assuming I got all that right, the code looks ok.)

--D

>  
>  	memcpy(&p->f_fsid, &buf.f_fsid, sizeof(p->f_fsid));
>  	strlcpy(p->f_fs_name, path->dentry->d_sb->s_type->name,
> 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 f74a4ee36eb3..e5db22d536a3 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1550,6 +1550,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
> diff --git a/samples/vfs/test-fsinfo.c b/samples/vfs/test-fsinfo.c
> index 6fbf0ce099b2..d6ec5713364f 100644
> --- a/samples/vfs/test-fsinfo.c
> +++ b/samples/vfs/test-fsinfo.c
> @@ -140,6 +140,7 @@ static void dump_fsinfo_generic_ids(void *reply, unsigned int size)
>  	printf("\tdev          : %02x:%02x\n", f->f_dev_major, f->f_dev_minor);
>  	printf("\tfs           : type=%x name=%s\n", f->f_fstype, f->f_fs_name);
>  	printf("\tfsid         : %llx\n", (unsigned long long)f->f_fsid);
> +	printf("\tsbid         : %llx\n", (unsigned long long)f->f_sb_id);
>  }
>  
>  static void dump_fsinfo_generic_limits(void *reply, unsigned int size)
> 
> 



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux