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

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

 



On Wed, May 3, 2023 at 11:52 AM Alexander Larsson <alexl@xxxxxxxxxx> 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@xxxxxxxxxx>
Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx>

> ---
>  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
>




[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux