lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200923194713.GD88270@redhat.com>
Date:   Wed, 23 Sep 2020 15:47:13 -0400
From:   Vivek Goyal <vgoyal@...hat.com>
To:     Pavel Tikhomirov <ptikhomirov@...tuozzo.com>
Cc:     Miklos Szeredi <miklos@...redi.hu>,
        Amir Goldstein <amir73il@...il.com>,
        linux-unionfs@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v2] ovl: introduce new "index=nouuid" option for inodes
 index feature

On Wed, Sep 23, 2020 at 06:23:08PM +0300, Pavel Tikhomirov wrote:
> This relaxes uuid checks for overlay index feature. It is only possible
> in case there is only one filesystem for all the work/upper/lower
> directories and bare file handles from this backing filesystem are uniq.

Hi Pavel,

Wondering why upper/work has to be on same filesystem as lower for this to
work?

> In case we have multiple filesystems here just fall back to normal
> "index=on".
> 
> This is needed when overlayfs is/was mounted in a container with
> index enabled (e.g.: to be able to resolve inotify watch file handles on
> it to paths in CRIU), and this container is copied and started alongside
> with the original one. This way the "copy" container can't have the same
> uuid on the superblock and mounting the overlayfs from it later would
> fail.
> 
> That is an example of the problem on top of loop+ext4:
> 
> dd if=/dev/zero of=loopbackfile.img bs=100M count=10
> losetup -fP loopbackfile.img
> losetup -a
>   #/dev/loop0: [64768]:35 (/loop-test/loopbackfile.img)
> mkfs.ext4 loopbackfile.img
> mkdir loop-mp
> mount -o loop /dev/loop0 loop-mp
> mkdir loop-mp/{lower,upper,work,merged}
> mount -t overlay overlay -oindex=on,lowerdir=loop-mp/lower,\
> upperdir=loop-mp/upper,workdir=loop-mp/work loop-mp/merged
> umount loop-mp/merged
> umount loop-mp
> e2fsck -f /dev/loop0
> tune2fs -U random /dev/loop0
> 
> mount -o loop /dev/loop0 loop-mp
> mount -t overlay overlay -oindex=on,lowerdir=loop-mp/lower,\
> upperdir=loop-mp/upper,workdir=loop-mp/work loop-mp/merged
>   #mount: /loop-test/loop-mp/merged:
>   #mount(2) system call failed: Stale file handle.
> 
> mount -t overlay overlay -oindex=nouuid,lowerdir=loop-mp/lower,\
> upperdir=loop-mp/upper,workdir=loop-mp/work loop-mp/merged
> 
> If you just change the uuid of the backing filesystem, overlay is not
> mounting any more. In Virtuozzo we copy container disks (ploops) when
> crate the copy of container and we require fs uuid to be uniq for a new
> container.
> 
> v2: in v1 I missed actual uuid check skip - add it
> 
> CC: Amir Goldstein <amir73il@...il.com>
> CC: Vivek Goyal <vgoyal@...hat.com>
> CC: Miklos Szeredi <miklos@...redi.hu>
> CC: linux-unionfs@...r.kernel.org
> CC: linux-kernel@...r.kernel.org
> Signed-off-by: Pavel Tikhomirov <ptikhomirov@...tuozzo.com>
> ---
>  fs/overlayfs/Kconfig     | 16 +++++++++++
>  fs/overlayfs/export.c    |  6 ++--
>  fs/overlayfs/namei.c     | 35 +++++++++++++++--------
>  fs/overlayfs/overlayfs.h | 23 +++++++++++----
>  fs/overlayfs/ovl_entry.h |  2 +-
>  fs/overlayfs/super.c     | 61 +++++++++++++++++++++++++++++-----------
>  6 files changed, 106 insertions(+), 37 deletions(-)

Please put something in Documentation file to explain this option. Also
explain where it is safe to use and where it is not. I am concerned
about the case where recreating lower can result in file handle resolving
to a different file (as discusse in other thread). I think it would
be nice if we mention it explicitly.

Thanks
Vivek

> 
> diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig
> index dd188c7996b3..b00fd44006f9 100644
> --- a/fs/overlayfs/Kconfig
> +++ b/fs/overlayfs/Kconfig
> @@ -61,6 +61,22 @@ config OVERLAY_FS_INDEX
>  
>  	  If unsure, say N.
>  
> +config OVERLAY_FS_INDEX_NOUUID
> +	bool "Overlayfs: relax uuid checks of inodes index feature"
> +	depends on OVERLAY_FS
> +	depends on OVERLAY_FS_INDEX
> +	help
> +	  If this config option is enabled then overlay will skip uuid checks
> +	  for index lower to upper inode map, this only can be done if all
> +	  upper and lower directories are on the same filesystem where basic
> +	  fhandles are uniq.
> +
> +	  It is needed to overcome possible change of uuid on superblock of the
> +	  backing filesystem, e.g. when you copied the virtual disk and mount
> +	  both the copy of the disk and the original one at the same time.
> +
> +	  If unsure, say N.
> +
>  config OVERLAY_FS_NFS_EXPORT
>  	bool "Overlayfs: turn on NFS export feature by default"
>  	depends on OVERLAY_FS
> diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
> index 0e696f72cf65..d53feb7547d9 100644
> --- a/fs/overlayfs/export.c
> +++ b/fs/overlayfs/export.c
> @@ -676,11 +676,12 @@ static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,
>  	struct ovl_fs *ofs = sb->s_fs_info;
>  	struct dentry *dentry;
>  	struct dentry *upper;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	if (!ovl_upper_mnt(ofs))
>  		return ERR_PTR(-EACCES);
>  
> -	upper = ovl_decode_real_fh(fh, ovl_upper_mnt(ofs), true);
> +	upper = ovl_decode_real_fh(fh, ovl_upper_mnt(ofs), true, nouuid);
>  	if (IS_ERR_OR_NULL(upper))
>  		return upper;
>  
> @@ -700,6 +701,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
>  	struct dentry *index = NULL;
>  	struct inode *inode;
>  	int err;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	/* First lookup overlay inode in inode cache by origin fh */
>  	err = ovl_check_origin_fh(ofs, fh, false, NULL, &stack);
> @@ -752,7 +754,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
>  			goto out_err;
>  	}
>  	if (index) {
> -		err = ovl_verify_origin(index, origin.dentry, false);
> +		err = ovl_verify_origin(index, origin.dentry, false, nouuid);
>  		if (err)
>  			goto out_err;
>  	}
> diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> index f7d4358db637..676170d719f8 100644
> --- a/fs/overlayfs/namei.c
> +++ b/fs/overlayfs/namei.c
> @@ -149,7 +149,7 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
>  }
>  
>  struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
> -				  bool connected)
> +				  bool connected, bool nouuid)
>  {
>  	struct dentry *real;
>  	int bytes;
> @@ -158,7 +158,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
>  	 * Make sure that the stored uuid matches the uuid of the lower
>  	 * layer where file handle will be decoded.
>  	 */
> -	if (!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid))
> +	if (!nouuid && !uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid))
>  		return NULL;
>  
>  	bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));
> @@ -342,6 +342,7 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
>  {
>  	struct dentry *origin = NULL;
>  	int i;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	for (i = 1; i < ofs->numlayer; i++) {
>  		/*
> @@ -353,7 +354,7 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
>  			continue;
>  
>  		origin = ovl_decode_real_fh(fh, ofs->layers[i].mnt,
> -					    connected);
> +					    connected, nouuid);
>  		if (origin)
>  			break;
>  	}
> @@ -414,7 +415,7 @@ static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry,
>   * Return 0 on match, -ESTALE on mismatch, < 0 on error.
>   */
>  static int ovl_verify_fh(struct dentry *dentry, const char *name,
> -			 const struct ovl_fh *fh)
> +			 const struct ovl_fh *fh, bool nouuid)
>  {
>  	struct ovl_fh *ofh = ovl_get_fh(dentry, name);
>  	int err = 0;
> @@ -425,8 +426,14 @@ static int ovl_verify_fh(struct dentry *dentry, const char *name,
>  	if (IS_ERR(ofh))
>  		return PTR_ERR(ofh);
>  
> -	if (fh->fb.len != ofh->fb.len || memcmp(&fh->fb, &ofh->fb, fh->fb.len))
> +	if (fh->fb.len != ofh->fb.len) {
>  		err = -ESTALE;
> +	} else {
> +		if (nouuid && !uuid_equal(&fh->fb.uuid, &ofh->fb.uuid))
> +			ofh->fb.uuid = fh->fb.uuid;
> +		if (memcmp(&fh->fb, &ofh->fb, fh->fb.len))
> +			err = -ESTALE;
> +	}
>  
>  	kfree(ofh);
>  	return err;
> @@ -441,7 +448,8 @@ static int ovl_verify_fh(struct dentry *dentry, const char *name,
>   * Return 0 on match, -ESTALE on mismatch, -ENODATA on no xattr, < 0 on error.
>   */
>  int ovl_verify_set_fh(struct dentry *dentry, const char *name,
> -		      struct dentry *real, bool is_upper, bool set)
> +		      struct dentry *real, bool is_upper, bool set,
> +		      bool nouuid)
>  {
>  	struct inode *inode;
>  	struct ovl_fh *fh;
> @@ -454,7 +462,7 @@ int ovl_verify_set_fh(struct dentry *dentry, const char *name,
>  		goto fail;
>  	}
>  
> -	err = ovl_verify_fh(dentry, name, fh);
> +	err = ovl_verify_fh(dentry, name, fh, nouuid);
>  	if (set && err == -ENODATA)
>  		err = ovl_do_setxattr(dentry, name, fh->buf, fh->fb.len, 0);
>  	if (err)
> @@ -477,6 +485,7 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index)
>  {
>  	struct ovl_fh *fh;
>  	struct dentry *upper;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	if (!d_is_dir(index))
>  		return dget(index);
> @@ -485,7 +494,7 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index)
>  	if (IS_ERR_OR_NULL(fh))
>  		return ERR_CAST(fh);
>  
> -	upper = ovl_decode_real_fh(fh, ovl_upper_mnt(ofs), true);
> +	upper = ovl_decode_real_fh(fh, ovl_upper_mnt(ofs), true, nouuid);
>  	kfree(fh);
>  
>  	if (IS_ERR_OR_NULL(upper))
> @@ -514,6 +523,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
>  	struct ovl_path *stack = &origin;
>  	struct dentry *upper = NULL;
>  	int err;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	if (!d_inode(index))
>  		return 0;
> @@ -574,7 +584,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
>  		goto fail;
>  	}
>  
> -	err = ovl_verify_fh(upper, OVL_XATTR_ORIGIN, fh);
> +	err = ovl_verify_fh(upper, OVL_XATTR_ORIGIN, fh, nouuid);
>  	dput(upper);
>  	if (err)
>  		goto fail;
> @@ -690,6 +700,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
>  	struct qstr name;
>  	bool is_dir = d_is_dir(origin);
>  	int err;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	err = ovl_get_index_name(origin, &name);
>  	if (err)
> @@ -741,7 +752,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
>  		}
>  
>  		/* Verify that dir index 'upper' xattr points to upper dir */
> -		err = ovl_verify_upper(index, upper, false);
> +		err = ovl_verify_upper(index, upper, false, nouuid);
>  		if (err) {
>  			if (err == -ESTALE) {
>  				pr_warn_ratelimited("suspected multiply redirected dir found (upper=%pd2, origin=%pd2, index=%pd2).\n",
> @@ -840,6 +851,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>  		.redirect = NULL,
>  		.metacopy = false,
>  	};
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	if (dentry->d_name.len > ofs->namelen)
>  		return ERR_PTR(-ENAMETOOLONG);
> @@ -939,7 +951,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>  		if (upperdentry && !ctr &&
>  		    ((d.is_dir && ovl_verify_lower(dentry->d_sb)) ||
>  		     (!d.is_dir && ofs->config.index && origin_path))) {
> -			err = ovl_verify_origin(upperdentry, this, false);
> +			err = ovl_verify_origin(upperdentry, this, false,
> +						nouuid);
>  			if (err) {
>  				dput(this);
>  				if (d.is_dir)
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 29bc1ec699e7..2aacfa42bb12 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -18,6 +18,12 @@ enum ovl_path_type {
>  	__OVL_PATH_ORIGIN	= (1 << 2),
>  };
>  
> +enum ovl_index_type {
> +	OVL_INDEX_OFF = 0,
> +	OVL_INDEX_ON,
> +	OVL_INDEX_NOUUID,
> +};
> +
>  #define OVL_TYPE_UPPER(type)	((type) & __OVL_PATH_UPPER)
>  #define OVL_TYPE_MERGE(type)	((type) & __OVL_PATH_MERGE)
>  #define OVL_TYPE_ORIGIN(type)	((type) & __OVL_PATH_ORIGIN)
> @@ -362,11 +368,12 @@ static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
>  }
>  
>  struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
> -				  bool connected);
> +				  bool connected, bool nouuid);
>  int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
>  			struct dentry *upperdentry, struct ovl_path **stackp);
>  int ovl_verify_set_fh(struct dentry *dentry, const char *name,
> -		      struct dentry *real, bool is_upper, bool set);
> +		      struct dentry *real, bool is_upper, bool set,
> +		      bool nouuid);
>  struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index);
>  int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index);
>  int ovl_get_index_name(struct dentry *origin, struct qstr *name);
> @@ -379,15 +386,19 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>  bool ovl_lower_positive(struct dentry *dentry);
>  
>  static inline int ovl_verify_origin(struct dentry *upper,
> -				    struct dentry *origin, bool set)
> +				    struct dentry *origin, bool set,
> +				    bool nouuid)
>  {
> -	return ovl_verify_set_fh(upper, OVL_XATTR_ORIGIN, origin, false, set);
> +	return ovl_verify_set_fh(upper, OVL_XATTR_ORIGIN, origin, false, set,
> +				 nouuid);
>  }
>  
>  static inline int ovl_verify_upper(struct dentry *index,
> -				    struct dentry *upper, bool set)
> +				   struct dentry *upper, bool set,
> +				   bool nouuid)
>  {
> -	return ovl_verify_set_fh(index, OVL_XATTR_UPPER, upper, true, set);
> +	return ovl_verify_set_fh(index, OVL_XATTR_UPPER, upper, true, set,
> +				 nouuid);
>  }
>  
>  /* readdir.c */
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index b429c80879ee..2fd2cc515ad2 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -13,7 +13,7 @@ struct ovl_config {
>  	bool redirect_dir;
>  	bool redirect_follow;
>  	const char *redirect_mode;
> -	bool index;
> +	int index;
>  	bool nfs_export;
>  	int xino;
>  	bool metacopy;
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index 4b38141c2985..d1ed580f24b7 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -38,10 +38,12 @@ module_param_named(redirect_always_follow, ovl_redirect_always_follow,
>  MODULE_PARM_DESC(redirect_always_follow,
>  		 "Follow redirects even if redirect_dir feature is turned off");
>  
> -static bool ovl_index_def = IS_ENABLED(CONFIG_OVERLAY_FS_INDEX);
> -module_param_named(index, ovl_index_def, bool, 0644);
> +static int ovl_index_def = IS_ENABLED(CONFIG_OVERLAY_FS_INDEX_NOUUID) ?
> +			   OVL_INDEX_NOUUID :
> +			   IS_ENABLED(CONFIG_OVERLAY_FS_INDEX);
> +module_param_named(index, ovl_index_def, int, 0644);
>  MODULE_PARM_DESC(index,
> -		 "Default to on or off for the inodes index feature");
> +		 "Default to on, off or nouuid for the inodes index feature");
>  
>  static bool ovl_nfs_export_def = IS_ENABLED(CONFIG_OVERLAY_FS_NFS_EXPORT);
>  module_param_named(nfs_export, ovl_nfs_export_def, bool, 0644);
> @@ -352,8 +354,18 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
>  		seq_puts(m, ",default_permissions");
>  	if (strcmp(ofs->config.redirect_mode, ovl_redirect_mode_def()) != 0)
>  		seq_printf(m, ",redirect_dir=%s", ofs->config.redirect_mode);
> -	if (ofs->config.index != ovl_index_def)
> -		seq_printf(m, ",index=%s", ofs->config.index ? "on" : "off");
> +	if (ofs->config.index != ovl_index_def) {
> +		switch (ofs->config.index) {
> +		case OVL_INDEX_OFF:
> +			seq_puts(m, ",index=off");
> +			break;
> +		case OVL_INDEX_NOUUID:
> +			seq_puts(m, ",index=nouuid");
> +			break;
> +		default:
> +			seq_puts(m, ",index=on");
> +		}
> +	}
>  	if (ofs->config.nfs_export != ovl_nfs_export_def)
>  		seq_printf(m, ",nfs_export=%s", ofs->config.nfs_export ?
>  						"on" : "off");
> @@ -404,6 +416,7 @@ enum {
>  	OPT_REDIRECT_DIR,
>  	OPT_INDEX_ON,
>  	OPT_INDEX_OFF,
> +	OPT_INDEX_NOUUID,
>  	OPT_NFS_EXPORT_ON,
>  	OPT_NFS_EXPORT_OFF,
>  	OPT_XINO_ON,
> @@ -422,6 +435,7 @@ static const match_table_t ovl_tokens = {
>  	{OPT_REDIRECT_DIR,		"redirect_dir=%s"},
>  	{OPT_INDEX_ON,			"index=on"},
>  	{OPT_INDEX_OFF,			"index=off"},
> +	{OPT_INDEX_NOUUID,		"index=nouuid"},
>  	{OPT_NFS_EXPORT_ON,		"nfs_export=on"},
>  	{OPT_NFS_EXPORT_OFF,		"nfs_export=off"},
>  	{OPT_XINO_ON,			"xino=on"},
> @@ -532,12 +546,17 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>  			break;
>  
>  		case OPT_INDEX_ON:
> -			config->index = true;
> +			config->index = OVL_INDEX_ON;
>  			index_opt = true;
>  			break;
>  
>  		case OPT_INDEX_OFF:
> -			config->index = false;
> +			config->index = OVL_INDEX_OFF;
> +			index_opt = true;
> +			break;
> +
> +		case OPT_INDEX_NOUUID:
> +			config->index = OVL_INDEX_NOUUID;
>  			index_opt = true;
>  			break;
>  
> @@ -592,7 +611,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>  			pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n");
>  			index_opt = false;
>  		}
> -		config->index = false;
> +		config->index = OVL_INDEX_OFF;
>  	}
>  
>  	err = ovl_parse_redirect_mode(config, config->redirect_mode);
> @@ -644,7 +663,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>  			config->nfs_export = false;
>  		} else {
>  			/* Automatically enable index otherwise. */
> -			config->index = true;
> +			config->index = OVL_INDEX_ON;
>  		}
>  	}
>  
> @@ -859,7 +878,7 @@ static int ovl_lower_dir(const char *name, struct path *path,
>  	fh_type = ovl_can_decode_fh(path->dentry->d_sb);
>  	if ((ofs->config.nfs_export ||
>  	     (ofs->config.index && ofs->config.upperdir)) && !fh_type) {
> -		ofs->config.index = false;
> +		ofs->config.index = OVL_INDEX_OFF;
>  		ofs->config.nfs_export = false;
>  		pr_warn("fs on '%s' does not support file handles, falling back to index=off,nfs_export=off.\n",
>  			name);
> @@ -1259,7 +1278,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
>  	err = ovl_do_setxattr(ofs->workdir, OVL_XATTR_OPAQUE, "0", 1, 0);
>  	if (err) {
>  		ofs->noxattr = true;
> -		ofs->config.index = false;
> +		ofs->config.index = OVL_INDEX_OFF;
>  		ofs->config.metacopy = false;
>  		pr_warn("upper fs does not support xattr, falling back to index=off and metacopy=off.\n");
>  		err = 0;
> @@ -1282,7 +1301,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
>  	/* Check if upper/work fs supports file handles */
>  	fh_type = ovl_can_decode_fh(ofs->workdir->d_sb);
>  	if (ofs->config.index && !fh_type) {
> -		ofs->config.index = false;
> +		ofs->config.index = OVL_INDEX_OFF;
>  		pr_warn("upper fs does not support file handles, falling back to index=off.\n");
>  	}
>  
> @@ -1348,6 +1367,7 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
>  {
>  	struct vfsmount *mnt = ovl_upper_mnt(ofs);
>  	int err;
> +	bool nouuid = ofs->config.index == OVL_INDEX_NOUUID;
>  
>  	err = mnt_want_write(mnt);
>  	if (err)
> @@ -1355,7 +1375,7 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
>  
>  	/* Verify lower root is upper root origin */
>  	err = ovl_verify_origin(upperpath->dentry, oe->lowerstack[0].dentry,
> -				true);
> +				true, nouuid);
>  	if (err) {
>  		pr_err("failed to verify upper root origin\n");
>  		goto out;
> @@ -1385,11 +1405,13 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
>  		 */
>  		if (ovl_check_origin_xattr(ofs->indexdir)) {
>  			err = ovl_verify_set_fh(ofs->indexdir, OVL_XATTR_ORIGIN,
> -						upperpath->dentry, true, false);
> +						upperpath->dentry, true, false,
> +						nouuid);
>  			if (err)
>  				pr_err("failed to verify index dir 'origin' xattr\n");
>  		}
> -		err = ovl_verify_upper(ofs->indexdir, upperpath->dentry, true);
> +		err = ovl_verify_upper(ofs->indexdir, upperpath->dentry, true,
> +				       nouuid);
>  		if (err)
>  			pr_err("failed to verify index dir 'upper' xattr\n");
>  
> @@ -1458,7 +1480,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
>  	if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) {
>  		bad_uuid = true;
>  		if (ofs->config.index || ofs->config.nfs_export) {
> -			ofs->config.index = false;
> +			ofs->config.index = OVL_INDEX_OFF;
>  			ofs->config.nfs_export = false;
>  			pr_warn("%s uuid detected in lower fs '%pd2', falling back to index=off,nfs_export=off.\n",
>  				uuid_is_null(&sb->s_uuid) ? "null" :
> @@ -1889,9 +1911,14 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
>  	if (err)
>  		goto out_free_oe;
>  
> +	if (ofs->config.index == OVL_INDEX_NOUUID && ofs->numfs > 1) {
> +		pr_warn("The index=nouuid requires a single fs for lower and upper, falling back to index=on.\n");
> +		ofs->config.index = OVL_INDEX_ON;
> +	}
> +
>  	/* Show index=off in /proc/mounts for forced r/o mount */
>  	if (!ofs->indexdir) {
> -		ofs->config.index = false;
> +		ofs->config.index = OVL_INDEX_OFF;
>  		if (ovl_upper_mnt(ofs) && ofs->config.nfs_export) {
>  			pr_warn("NFS export requires an index dir, falling back to nfs_export=off.\n");
>  			ofs->config.nfs_export = false;
> -- 
> 2.26.2
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ