diff mbox series

[v2,4/6] ovl: Add framework for verity support

Message ID 0292ade77250a8bb563744f596ecaab5614cbd80.1683102959.git.alexl@redhat.com (mailing list archive)
State Superseded
Headers show
Series ovl: Add support for fs-verity checking of lowerdata | expand

Commit Message

Alexander Larsson May 3, 2023, 8:51 a.m. UTC
This adds the scaffolding (docs, config, mount options) for supporting
for a new overlay xattr "overlay.verity", which contains a fs-verity
digest. This is used for metacopy files, and the actual fs-verity
digest of the lowerdata file needs to match it. The mount option
"verity" specifies how this xattrs is handled.

If you enable verity it ("verity=on") all existing xattrs are
validated before use, and during metacopy we generate verity xattr in
the upper metacopy file if the source file has verity enabled. This
means later accesses can guarantee that the correct data is used.

Additionally you can use "verity=require". In this mode all metacopy
files must have a valid verity xattr. For this to work metadata
copy-up must be able to create a verity xattr (so that later accesses
are validated). Therefore, in this mode, if the lower data file
doesn't have fs-verity enabled we fall back to a full copy rather than
a metacopy.

Actual implementation follows in a separate commit.

Signed-off-by: Alexander Larsson <alexl@redhat.com>
---
 Documentation/filesystems/overlayfs.rst | 27 +++++++++
 fs/overlayfs/ovl_entry.h                |  3 +
 fs/overlayfs/super.c                    | 74 ++++++++++++++++++++++++-
 3 files changed, 102 insertions(+), 2 deletions(-)

Comments

Amir Goldstein May 3, 2023, 11:51 a.m. UTC | #1
On Wed, May 3, 2023 at 11:52 AM Alexander Larsson <alexl@redhat.com> wrote:
>
> This adds the scaffolding (docs, config, mount options) for supporting
> for a new overlay xattr "overlay.verity", which contains a fs-verity
> digest. This is used for metacopy files, and the actual fs-verity
> digest of the lowerdata file needs to match it. The mount option
> "verity" specifies how this xattrs is handled.
>
> If you enable verity it ("verity=on") all existing xattrs are
> validated before use, and during metacopy we generate verity xattr in
> the upper metacopy file if the source file has verity enabled. This
> means later accesses can guarantee that the correct data is used.
>
> Additionally you can use "verity=require". In this mode all metacopy
> files must have a valid verity xattr. For this to work metadata
> copy-up must be able to create a verity xattr (so that later accesses
> are validated). Therefore, in this mode, if the lower data file
> doesn't have fs-verity enabled we fall back to a full copy rather than
> a metacopy.
>
> Actual implementation follows in a separate commit.
>
> Signed-off-by: Alexander Larsson <alexl@redhat.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>

> ---
>  Documentation/filesystems/overlayfs.rst | 27 +++++++++
>  fs/overlayfs/ovl_entry.h                |  3 +
>  fs/overlayfs/super.c                    | 74 ++++++++++++++++++++++++-
>  3 files changed, 102 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
> index bc95343bafba..7e2b445a4139 100644
> --- a/Documentation/filesystems/overlayfs.rst
> +++ b/Documentation/filesystems/overlayfs.rst
> @@ -407,6 +407,33 @@ when a "metacopy" file in one of the lower layers above it, has a "redirect"
>  to the absolute path of the "lower data" file in the "data-only" lower layer.
>
>
> +fs-verity support
> +----------------------
> +
> +When metadata copy up is used for a file, then the xattr
> +"trusted.overlay.verity" may be set on the metacopy file. This
> +specifies the expected fs-verity digest of the lowerdata file. This
> +may then be used to verify the content of the source file at the time
> +the file is opened. During metacopy copy up overlayfs can also set
> +this xattr.
> +
> +This is controlled by the "verity" mount option, which supports
> +these values:
> +
> +- "off":
> +    The verity xattr is never used. This is the default if verity
> +    option is not specified.
> +- "on":
> +    Whenever a metacopy files specifies an expected digest, the
> +    corresponding data file must match the specified digest.
> +    When generating a metacopy file the verity xattr will be set
> +    from the source file fs-verity digest (if it has one).
> +- "require":
> +    Same as "on", but additionally all metacopy files must specify a
> +    verity xattr. This means metadata copy up will only be used if
> +    the data file has fs-verity enabled, otherwise a full copy-up is
> +    used.
> +
>  Sharing and copying layers
>  --------------------------
>
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index c6c7d09b494e..95464a1cb371 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -13,6 +13,9 @@ struct ovl_config {
>         bool redirect_dir;
>         bool redirect_follow;
>         const char *redirect_mode;
> +       bool verity;
> +       bool require_verity;
> +       const char *verity_mode;
>         bool index;
>         bool uuid;
>         bool nfs_export;
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index c6209592bb3f..a4662883b619 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -244,6 +244,7 @@ static void ovl_free_fs(struct ovl_fs *ofs)
>         kfree(ofs->config.upperdir);
>         kfree(ofs->config.workdir);
>         kfree(ofs->config.redirect_mode);
> +       kfree(ofs->config.verity_mode);
>         if (ofs->creator_cred)
>                 put_cred(ofs->creator_cred);
>         kfree(ofs);
> @@ -334,6 +335,11 @@ static const char *ovl_redirect_mode_def(void)
>         return ovl_redirect_dir_def ? "on" : "off";
>  }
>
> +static const char *ovl_verity_mode_def(void)
> +{
> +       return "off";
> +}
> +
>  static const char * const ovl_xino_str[] = {
>         "off",
>         "auto",
> @@ -383,6 +389,8 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
>                 seq_puts(m, ",volatile");
>         if (ofs->config.userxattr)
>                 seq_puts(m, ",userxattr");
> +       if (strcmp(ofs->config.verity_mode, ovl_verity_mode_def()) != 0)
> +               seq_printf(m, ",verity=%s", ofs->config.verity_mode);
>         return 0;
>  }
>
> @@ -438,6 +446,7 @@ enum {
>         OPT_METACOPY_ON,
>         OPT_METACOPY_OFF,
>         OPT_VOLATILE,
> +       OPT_VERITY,
>         OPT_ERR,
>  };
>
> @@ -460,6 +469,7 @@ static const match_table_t ovl_tokens = {
>         {OPT_METACOPY_ON,               "metacopy=on"},
>         {OPT_METACOPY_OFF,              "metacopy=off"},
>         {OPT_VOLATILE,                  "volatile"},
> +       {OPT_VERITY,                    "verity=%s"},
>         {OPT_ERR,                       NULL}
>  };
>
> @@ -509,6 +519,21 @@ static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode)
>         return 0;
>  }
>
> +static int ovl_parse_verity_mode(struct ovl_config *config, const char *mode)
> +{
> +       if (strcmp(mode, "on") == 0) {
> +               config->verity = true;
> +       } else if (strcmp(mode, "require") == 0) {
> +               config->verity = true;
> +               config->require_verity = true;
> +       } else if (strcmp(mode, "off") != 0) {
> +               pr_err("bad mount option \"verity=%s\"\n", mode);
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
>  static int ovl_parse_opt(char *opt, struct ovl_config *config)
>  {
>         char *p;
> @@ -520,6 +545,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>         if (!config->redirect_mode)
>                 return -ENOMEM;
>
> +       config->verity_mode = kstrdup(ovl_verity_mode_def(), GFP_KERNEL);
> +       if (!config->verity_mode)
> +               return -ENOMEM;
> +
>         while ((p = ovl_next_opt(&opt)) != NULL) {
>                 int token;
>                 substring_t args[MAX_OPT_ARGS];
> @@ -620,6 +649,13 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                         config->userxattr = true;
>                         break;
>
> +               case OPT_VERITY:
> +                       kfree(config->verity_mode);
> +                       config->verity_mode = match_strdup(&args[0]);
> +                       if (!config->verity_mode)
> +                               return -ENOMEM;
> +                       break;
> +
>                 default:
>                         pr_err("unrecognized mount option \"%s\" or missing value\n",
>                                         p);
> @@ -651,6 +687,22 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>         if (err)
>                 return err;
>
> +       err = ovl_parse_verity_mode(config, config->verity_mode);
> +       if (err)
> +               return err;
> +
> +       /* Resolve verity -> metacopy dependency */
> +       if (config->verity && !config->metacopy) {
> +               /* Don't allow explicit specified conflicting combinations */
> +               if (metacopy_opt) {
> +                       pr_err("conflicting options: metacopy=off,verity=%s\n",
> +                              config->verity_mode);
> +                       return -EINVAL;
> +               }
> +               /* Otherwise automatically enable metacopy. */
> +               config->metacopy = true;
> +       }
> +
>         /*
>          * This is to make the logic below simpler.  It doesn't make any other
>          * difference, since config->redirect_dir is only used for upper.
> @@ -665,6 +717,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                                config->redirect_mode);
>                         return -EINVAL;
>                 }
> +               if (config->verity && redirect_opt) {
> +                       pr_err("conflicting options: verity=%s,redirect_dir=%s\n",
> +                              config->verity_mode, config->redirect_mode);
> +                       return -EINVAL;
> +               }
>                 if (redirect_opt) {
>                         /*
>                          * There was an explicit redirect_dir=... that resulted
> @@ -700,7 +757,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                 }
>         }
>
> -       /* Resolve nfs_export -> !metacopy dependency */
> +       /* Resolve nfs_export -> !metacopy && !verity dependency */
>         if (config->nfs_export && config->metacopy) {
>                 if (nfs_export_opt && metacopy_opt) {
>                         pr_err("conflicting options: nfs_export=on,metacopy=on\n");
> @@ -713,6 +770,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                          */
>                         pr_info("disabling nfs_export due to metacopy=on\n");
>                         config->nfs_export = false;
> +               } else if (config->verity) {
> +                       /*
> +                        * There was an explicit verity=.. that resulted
> +                        * in this conflict.
> +                        */
> +                       pr_info("disabling nfs_export due to verity=%s\n",
> +                               config->verity_mode);
> +                       config->nfs_export = false;
>                 } else {
>                         /*
>                          * There was an explicit nfs_export=on that resulted
> @@ -724,7 +789,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>         }
>
>
> -       /* Resolve userxattr -> !redirect && !metacopy dependency */
> +       /* Resolve userxattr -> !redirect && !metacopy && !verity dependency */
>         if (config->userxattr) {
>                 if (config->redirect_follow && redirect_opt) {
>                         pr_err("conflicting options: userxattr,redirect_dir=%s\n",
> @@ -735,6 +800,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                         pr_err("conflicting options: userxattr,metacopy=on\n");
>                         return -EINVAL;
>                 }
> +               if (config->verity) {
> +                       pr_err("conflicting options: userxattr,verity=%s\n",
> +                              config->verity_mode);
> +                       return -EINVAL;
> +               }
>                 /*
>                  * Silently disable default setting of redirect and metacopy.
>                  * This shall be the default in the future as well: these
> --
> 2.39.2
>
Eric Biggers May 14, 2023, 7:22 p.m. UTC | #2
On Wed, May 03, 2023 at 10:51:37AM +0200, Alexander Larsson wrote:
> +- "require":
> +    Same as "on", but additionally all metacopy files must specify a
> +    verity xattr. This means metadata copy up will only be used if
> +    the data file has fs-verity enabled, otherwise a full copy-up is
> +    used.

The second sentence makes it sound like an attacker can inject arbitrary data
just by replacing a data file with one that doesn't have fsverity enabled.

I really hope that's not the case?

I *think* there is a subtlety here involving "metacopy files" that were created
ahead of time by the user, vs. being generated by overlayfs.  But it's not
really explained.

- Eric
Alexander Larsson May 15, 2023, 5:44 a.m. UTC | #3
On Sun, May 14, 2023 at 9:22 PM Eric Biggers <ebiggers@kernel.org> wrote:
>
> On Wed, May 03, 2023 at 10:51:37AM +0200, Alexander Larsson wrote:
> > +- "require":
> > +    Same as "on", but additionally all metacopy files must specify a
> > +    verity xattr. This means metadata copy up will only be used if
> > +    the data file has fs-verity enabled, otherwise a full copy-up is
> > +    used.
>
> The second sentence makes it sound like an attacker can inject arbitrary data
> just by replacing a data file with one that doesn't have fsverity enabled.
>
> I really hope that's not the case?
>
> I *think* there is a subtlety here involving "metacopy files" that were created
> ahead of time by the user, vs. being generated by overlayfs.  But it's not
> really explained.

I'm not sure what you mean here? When you say "replacing a data file",
do you mean "changing the content of the lowerdir"? Because if you can
just change lowerdir content then you can make users of the overlayfs
mount read whatever data you want (independent of metacopy or any of
this).

The second sentence above relates to this case:

* A lower dir file "lower/a" does not have fsverity enabled.
* Someone does "chown mnt/a"
* This causes overlayfs to make a "copy up" operation of the "lower/a"
to "upper/a"
* But, we can't use the optimized "copy metacopy only" version of
"copy up", because we could then not specify a digest xattr on the new
file, so we copy the content of "lower/a" to "upper/a".

What exactly is your worry in this case?
Eric Biggers May 15, 2023, 6 a.m. UTC | #4
On Mon, May 15, 2023 at 07:44:13AM +0200, Alexander Larsson wrote:
> On Sun, May 14, 2023 at 9:22 PM Eric Biggers <ebiggers@kernel.org> wrote:
> >
> > On Wed, May 03, 2023 at 10:51:37AM +0200, Alexander Larsson wrote:
> > > +- "require":
> > > +    Same as "on", but additionally all metacopy files must specify a
> > > +    verity xattr. This means metadata copy up will only be used if
> > > +    the data file has fs-verity enabled, otherwise a full copy-up is
> > > +    used.
> >
> > The second sentence makes it sound like an attacker can inject arbitrary data
> > just by replacing a data file with one that doesn't have fsverity enabled.
> >
> > I really hope that's not the case?
> >
> > I *think* there is a subtlety here involving "metacopy files" that were created
> > ahead of time by the user, vs. being generated by overlayfs.  But it's not
> > really explained.
> 
> I'm not sure what you mean here? When you say "replacing a data file",
> do you mean "changing the content of the lowerdir"?

Yes.  Specifically the data-only lowerdir.

> Because if you can just change lowerdir content then you can make users of the
> overlayfs mount read whatever data you want (independent of metacopy or any of
> this).

But isn't preventing that the whole point of your feature?

What am I missing?

- Eric
Alexander Larsson May 15, 2023, 6:46 a.m. UTC | #5
On Mon, May 15, 2023 at 8:00 AM Eric Biggers <ebiggers@kernel.org> wrote:
>
> On Mon, May 15, 2023 at 07:44:13AM +0200, Alexander Larsson wrote:
> > On Sun, May 14, 2023 at 9:22 PM Eric Biggers <ebiggers@kernel.org> wrote:
> > >
> > > On Wed, May 03, 2023 at 10:51:37AM +0200, Alexander Larsson wrote:
> > > > +- "require":
> > > > +    Same as "on", but additionally all metacopy files must specify a
> > > > +    verity xattr. This means metadata copy up will only be used if
> > > > +    the data file has fs-verity enabled, otherwise a full copy-up is
> > > > +    used.
> > >
> > > The second sentence makes it sound like an attacker can inject arbitrary data
> > > just by replacing a data file with one that doesn't have fsverity enabled.
> > >
> > > I really hope that's not the case?
> > >
> > > I *think* there is a subtlety here involving "metacopy files" that were created
> > > ahead of time by the user, vs. being generated by overlayfs.  But it's not
> > > really explained.
> >
> > I'm not sure what you mean here? When you say "replacing a data file",
> > do you mean "changing the content of the lowerdir"?
>
> Yes.  Specifically the data-only lowerdir.
>
> > Because if you can just change lowerdir content then you can make users of the
> > overlayfs mount read whatever data you want (independent of metacopy or any of
> > this).
>
> But isn't preventing that the whole point of your feature?
>
> What am I missing?

If by "your feature", you mean the full composefs idea, then things
are different. In this case the root mount is an overlayfs with two
lowerdirs and no upper. The uppermost lower is a read-only erofs mount
with metadata and overlay xattrs for all files, and the lowermost one
is a data-only dir. You cannot modify the uppermost layer (since it's
a fsverity readonly erofs file). If you modify a data-only file it
will be detected at validation, because it can only be reached from
redirects in the image file, and we ensured all image files specified
a digest. There is no upper dir, so the overlayfs mount itself is not
writable, and thus there can be any meta-copy-up operations triggered
at all.

However, even if you had an upper dir ("writable composefs" usecase) I
don't see a problem. If you trigger a full (i.e. non-metadata) copy-up
then the copy-up operation itself will validate the data from the
lower at copy time (due to the verity xattr on the "middle layer").


I think again there is some confusion due to the two kinds of usecases
for the verity support. The basic usecase is just for general
robustness. I.e it allows the kernel to record information about the
original state of the content file when generating a metacopy
reference to it. If you later accidentally mount the overlayfs against
the wrong lower version you will get told about it. The second usecase
is the tamper proofing image case (composefs), and its security
depends on more details (i.e. the readonly image part and its
construction).
diff mbox series

Patch

diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
index bc95343bafba..7e2b445a4139 100644
--- a/Documentation/filesystems/overlayfs.rst
+++ b/Documentation/filesystems/overlayfs.rst
@@ -407,6 +407,33 @@  when a "metacopy" file in one of the lower layers above it, has a "redirect"
 to the absolute path of the "lower data" file in the "data-only" lower layer.
 
 
+fs-verity support
+----------------------
+
+When metadata copy up is used for a file, then the xattr
+"trusted.overlay.verity" may be set on the metacopy file. This
+specifies the expected fs-verity digest of the lowerdata file. This
+may then be used to verify the content of the source file at the time
+the file is opened. During metacopy copy up overlayfs can also set
+this xattr.
+
+This is controlled by the "verity" mount option, which supports
+these values:
+
+- "off":
+    The verity xattr is never used. This is the default if verity
+    option is not specified.
+- "on":
+    Whenever a metacopy files specifies an expected digest, the
+    corresponding data file must match the specified digest.
+    When generating a metacopy file the verity xattr will be set
+    from the source file fs-verity digest (if it has one).
+- "require":
+    Same as "on", but additionally all metacopy files must specify a
+    verity xattr. This means metadata copy up will only be used if
+    the data file has fs-verity enabled, otherwise a full copy-up is
+    used.
+
 Sharing and copying layers
 --------------------------
 
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index c6c7d09b494e..95464a1cb371 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -13,6 +13,9 @@  struct ovl_config {
 	bool redirect_dir;
 	bool redirect_follow;
 	const char *redirect_mode;
+	bool verity;
+	bool require_verity;
+	const char *verity_mode;
 	bool index;
 	bool uuid;
 	bool nfs_export;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index c6209592bb3f..a4662883b619 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -244,6 +244,7 @@  static void ovl_free_fs(struct ovl_fs *ofs)
 	kfree(ofs->config.upperdir);
 	kfree(ofs->config.workdir);
 	kfree(ofs->config.redirect_mode);
+	kfree(ofs->config.verity_mode);
 	if (ofs->creator_cred)
 		put_cred(ofs->creator_cred);
 	kfree(ofs);
@@ -334,6 +335,11 @@  static const char *ovl_redirect_mode_def(void)
 	return ovl_redirect_dir_def ? "on" : "off";
 }
 
+static const char *ovl_verity_mode_def(void)
+{
+	return "off";
+}
+
 static const char * const ovl_xino_str[] = {
 	"off",
 	"auto",
@@ -383,6 +389,8 @@  static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
 		seq_puts(m, ",volatile");
 	if (ofs->config.userxattr)
 		seq_puts(m, ",userxattr");
+	if (strcmp(ofs->config.verity_mode, ovl_verity_mode_def()) != 0)
+		seq_printf(m, ",verity=%s", ofs->config.verity_mode);
 	return 0;
 }
 
@@ -438,6 +446,7 @@  enum {
 	OPT_METACOPY_ON,
 	OPT_METACOPY_OFF,
 	OPT_VOLATILE,
+	OPT_VERITY,
 	OPT_ERR,
 };
 
@@ -460,6 +469,7 @@  static const match_table_t ovl_tokens = {
 	{OPT_METACOPY_ON,		"metacopy=on"},
 	{OPT_METACOPY_OFF,		"metacopy=off"},
 	{OPT_VOLATILE,			"volatile"},
+	{OPT_VERITY,			"verity=%s"},
 	{OPT_ERR,			NULL}
 };
 
@@ -509,6 +519,21 @@  static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode)
 	return 0;
 }
 
+static int ovl_parse_verity_mode(struct ovl_config *config, const char *mode)
+{
+	if (strcmp(mode, "on") == 0) {
+		config->verity = true;
+	} else if (strcmp(mode, "require") == 0) {
+		config->verity = true;
+		config->require_verity = true;
+	} else if (strcmp(mode, "off") != 0) {
+		pr_err("bad mount option \"verity=%s\"\n", mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int ovl_parse_opt(char *opt, struct ovl_config *config)
 {
 	char *p;
@@ -520,6 +545,10 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 	if (!config->redirect_mode)
 		return -ENOMEM;
 
+	config->verity_mode = kstrdup(ovl_verity_mode_def(), GFP_KERNEL);
+	if (!config->verity_mode)
+		return -ENOMEM;
+
 	while ((p = ovl_next_opt(&opt)) != NULL) {
 		int token;
 		substring_t args[MAX_OPT_ARGS];
@@ -620,6 +649,13 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 			config->userxattr = true;
 			break;
 
+		case OPT_VERITY:
+			kfree(config->verity_mode);
+			config->verity_mode = match_strdup(&args[0]);
+			if (!config->verity_mode)
+				return -ENOMEM;
+			break;
+
 		default:
 			pr_err("unrecognized mount option \"%s\" or missing value\n",
 					p);
@@ -651,6 +687,22 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 	if (err)
 		return err;
 
+	err = ovl_parse_verity_mode(config, config->verity_mode);
+	if (err)
+		return err;
+
+	/* Resolve verity -> metacopy dependency */
+	if (config->verity && !config->metacopy) {
+		/* Don't allow explicit specified conflicting combinations */
+		if (metacopy_opt) {
+			pr_err("conflicting options: metacopy=off,verity=%s\n",
+			       config->verity_mode);
+			return -EINVAL;
+		}
+		/* Otherwise automatically enable metacopy. */
+		config->metacopy = true;
+	}
+
 	/*
 	 * This is to make the logic below simpler.  It doesn't make any other
 	 * difference, since config->redirect_dir is only used for upper.
@@ -665,6 +717,11 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 			       config->redirect_mode);
 			return -EINVAL;
 		}
+		if (config->verity && redirect_opt) {
+			pr_err("conflicting options: verity=%s,redirect_dir=%s\n",
+			       config->verity_mode, config->redirect_mode);
+			return -EINVAL;
+		}
 		if (redirect_opt) {
 			/*
 			 * There was an explicit redirect_dir=... that resulted
@@ -700,7 +757,7 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 		}
 	}
 
-	/* Resolve nfs_export -> !metacopy dependency */
+	/* Resolve nfs_export -> !metacopy && !verity dependency */
 	if (config->nfs_export && config->metacopy) {
 		if (nfs_export_opt && metacopy_opt) {
 			pr_err("conflicting options: nfs_export=on,metacopy=on\n");
@@ -713,6 +770,14 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 			 */
 			pr_info("disabling nfs_export due to metacopy=on\n");
 			config->nfs_export = false;
+		} else if (config->verity) {
+			/*
+			 * There was an explicit verity=.. that resulted
+			 * in this conflict.
+			 */
+			pr_info("disabling nfs_export due to verity=%s\n",
+				config->verity_mode);
+			config->nfs_export = false;
 		} else {
 			/*
 			 * There was an explicit nfs_export=on that resulted
@@ -724,7 +789,7 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 	}
 
 
-	/* Resolve userxattr -> !redirect && !metacopy dependency */
+	/* Resolve userxattr -> !redirect && !metacopy && !verity dependency */
 	if (config->userxattr) {
 		if (config->redirect_follow && redirect_opt) {
 			pr_err("conflicting options: userxattr,redirect_dir=%s\n",
@@ -735,6 +800,11 @@  static int ovl_parse_opt(char *opt, struct ovl_config *config)
 			pr_err("conflicting options: userxattr,metacopy=on\n");
 			return -EINVAL;
 		}
+		if (config->verity) {
+			pr_err("conflicting options: userxattr,verity=%s\n",
+			       config->verity_mode);
+			return -EINVAL;
+		}
 		/*
 		 * Silently disable default setting of redirect and metacopy.
 		 * This shall be the default in the future as well: these