Skip to content

Commit ae8cba4

Browse files
alexlarssonamir73il
authored andcommitted
ovl: Add framework for verity support
This adds the scaffolding (docs, config, mount options) for supporting the new digest field in the metacopy xattr. This contains a fs-verity digest that need to match the fs-verity digest of the lowerdata file. The mount option "verity" specifies how this xattr is handled. If you enable verity ("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 same 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 <[email protected]> Reviewed-by: Amir Goldstein <[email protected]> Acked-by: Eric Biggers <[email protected]> Signed-off-by: Amir Goldstein <[email protected]>
1 parent 52a93d3 commit ae8cba4

File tree

5 files changed

+114
-3
lines changed

5 files changed

+114
-3
lines changed

Documentation/filesystems/fsverity.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ the file has fs-verity enabled. This can perform better than
326326
FS_IOC_GETFLAGS and FS_IOC_MEASURE_VERITY because it doesn't require
327327
opening the file, and opening verity files can be expensive.
328328

329+
.. _accessing_verity_files:
330+
329331
Accessing verity files
330332
======================
331333

Documentation/filesystems/overlayfs.rst

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,53 @@ when a "metacopy" file in one of the lower layers above it, has a "redirect"
405405
to the absolute path of the "lower data" file in the "data-only" lower layer.
406406

407407

408+
fs-verity support
409+
----------------------
410+
411+
During metadata copy up of a lower file, if the source file has
412+
fs-verity enabled and overlay verity support is enabled, then the
413+
digest of the lower file is added to the "trusted.overlay.metacopy"
414+
xattr. This is then used to verify the content of the lower file
415+
each the time the metacopy file is opened.
416+
417+
When a layer containing verity xattrs is used, it means that any such
418+
metacopy file in the upper layer is guaranteed to match the content
419+
that was in the lower at the time of the copy-up. If at any time
420+
(during a mount, after a remount, etc) such a file in the lower is
421+
replaced or modified in any way, access to the corresponding file in
422+
overlayfs will result in EIO errors (either on open, due to overlayfs
423+
digest check, or from a later read due to fs-verity) and a detailed
424+
error is printed to the kernel logs. For more details of how fs-verity
425+
file access works, see :ref:`Documentation/filesystems/fsverity.rst
426+
<accessing_verity_files>`.
427+
428+
Verity can be used as a general robustness check to detect accidental
429+
changes in the overlayfs directories in use. But, with additional care
430+
it can also give more powerful guarantees. For example, if the upper
431+
layer is fully trusted (by using dm-verity or something similar), then
432+
an untrusted lower layer can be used to supply validated file content
433+
for all metacopy files. If additionally the untrusted lower
434+
directories are specified as "Data-only", then they can only supply
435+
such file content, and the entire mount can be trusted to match the
436+
upper layer.
437+
438+
This feature is controlled by the "verity" mount option, which
439+
supports these values:
440+
441+
- "off":
442+
The metacopy digest is never generated or used. This is the
443+
default if verity option is not specified.
444+
- "on":
445+
Whenever a metacopy files specifies an expected digest, the
446+
corresponding data file must match the specified digest. When
447+
generating a metacopy file the verity digest will be set in it
448+
based on the source file (if it has one).
449+
- "require":
450+
Same as "on", but additionally all metacopy files must specify a
451+
digest (or EIO is returned on open). This means metadata copy up
452+
will only be used if the data file has fs-verity enabled,
453+
otherwise a full copy-up is used.
454+
408455
Sharing and copying layers
409456
--------------------------
410457

fs/overlayfs/overlayfs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ enum {
7070
OVL_XINO_ON,
7171
};
7272

73+
enum {
74+
OVL_VERITY_OFF,
75+
OVL_VERITY_ON,
76+
OVL_VERITY_REQUIRE,
77+
};
78+
7379
/*
7480
* The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
7581
* where:

fs/overlayfs/ovl_entry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct ovl_config {
1010
char *workdir;
1111
bool default_permissions;
1212
int redirect_mode;
13+
int verity_mode;
1314
bool index;
1415
bool uuid;
1516
bool nfs_export;

fs/overlayfs/params.c

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum {
5555
Opt_userxattr,
5656
Opt_xino,
5757
Opt_metacopy,
58+
Opt_verity,
5859
Opt_volatile,
5960
};
6061

@@ -101,6 +102,23 @@ static int ovl_redirect_mode_def(void)
101102
OVL_REDIRECT_NOFOLLOW;
102103
}
103104

105+
static const struct constant_table ovl_parameter_verity[] = {
106+
{ "off", OVL_VERITY_OFF },
107+
{ "on", OVL_VERITY_ON },
108+
{ "require", OVL_VERITY_REQUIRE },
109+
{}
110+
};
111+
112+
static const char *ovl_verity_mode(struct ovl_config *config)
113+
{
114+
return ovl_parameter_verity[config->verity_mode].name;
115+
}
116+
117+
static int ovl_verity_mode_def(void)
118+
{
119+
return OVL_VERITY_OFF;
120+
}
121+
104122
#define fsparam_string_empty(NAME, OPT) \
105123
__fsparam(fs_param_is_string, NAME, OPT, fs_param_can_be_empty, NULL)
106124

@@ -116,6 +134,7 @@ const struct fs_parameter_spec ovl_parameter_spec[] = {
116134
fsparam_flag("userxattr", Opt_userxattr),
117135
fsparam_enum("xino", Opt_xino, ovl_parameter_xino),
118136
fsparam_enum("metacopy", Opt_metacopy, ovl_parameter_bool),
137+
fsparam_enum("verity", Opt_verity, ovl_parameter_verity),
119138
fsparam_flag("volatile", Opt_volatile),
120139
{}
121140
};
@@ -572,6 +591,9 @@ static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
572591
config->metacopy = result.uint_32;
573592
ctx->set.metacopy = true;
574593
break;
594+
case Opt_verity:
595+
config->verity_mode = result.uint_32;
596+
break;
575597
case Opt_volatile:
576598
config->ovl_volatile = true;
577599
break;
@@ -762,20 +784,37 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
762784
config->ovl_volatile = false;
763785
}
764786

787+
/* Resolve verity -> metacopy dependency */
788+
if (config->verity_mode && !config->metacopy) {
789+
/* Don't allow explicit specified conflicting combinations */
790+
if (set.metacopy) {
791+
pr_err("conflicting options: metacopy=off,verity=%s\n",
792+
ovl_verity_mode(config));
793+
return -EINVAL;
794+
}
795+
/* Otherwise automatically enable metacopy. */
796+
config->metacopy = true;
797+
}
798+
765799
/*
766800
* This is to make the logic below simpler. It doesn't make any other
767801
* difference, since redirect_dir=on is only used for upper.
768802
*/
769803
if (!config->upperdir && config->redirect_mode == OVL_REDIRECT_FOLLOW)
770804
config->redirect_mode = OVL_REDIRECT_ON;
771805

772-
/* Resolve metacopy -> redirect_dir dependency */
806+
/* Resolve verity -> metacopy -> redirect_dir dependency */
773807
if (config->metacopy && config->redirect_mode != OVL_REDIRECT_ON) {
774808
if (set.metacopy && set.redirect) {
775809
pr_err("conflicting options: metacopy=on,redirect_dir=%s\n",
776810
ovl_redirect_mode(config));
777811
return -EINVAL;
778812
}
813+
if (config->verity_mode && set.redirect) {
814+
pr_err("conflicting options: verity=%s,redirect_dir=%s\n",
815+
ovl_verity_mode(config), ovl_redirect_mode(config));
816+
return -EINVAL;
817+
}
779818
if (set.redirect) {
780819
/*
781820
* There was an explicit redirect_dir=... that resulted
@@ -812,7 +851,7 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
812851
}
813852
}
814853

815-
/* Resolve nfs_export -> !metacopy dependency */
854+
/* Resolve nfs_export -> !metacopy && !verity dependency */
816855
if (config->nfs_export && config->metacopy) {
817856
if (set.nfs_export && set.metacopy) {
818857
pr_err("conflicting options: nfs_export=on,metacopy=on\n");
@@ -825,6 +864,14 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
825864
*/
826865
pr_info("disabling nfs_export due to metacopy=on\n");
827866
config->nfs_export = false;
867+
} else if (config->verity_mode) {
868+
/*
869+
* There was an explicit verity=.. that resulted
870+
* in this conflict.
871+
*/
872+
pr_info("disabling nfs_export due to verity=%s\n",
873+
ovl_verity_mode(config));
874+
config->nfs_export = false;
828875
} else {
829876
/*
830877
* There was an explicit nfs_export=on that resulted
@@ -836,7 +883,7 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
836883
}
837884

838885

839-
/* Resolve userxattr -> !redirect && !metacopy dependency */
886+
/* Resolve userxattr -> !redirect && !metacopy && !verity dependency */
840887
if (config->userxattr) {
841888
if (set.redirect &&
842889
config->redirect_mode != OVL_REDIRECT_NOFOLLOW) {
@@ -848,6 +895,11 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
848895
pr_err("conflicting options: userxattr,metacopy=on\n");
849896
return -EINVAL;
850897
}
898+
if (config->verity_mode) {
899+
pr_err("conflicting options: userxattr,verity=%s\n",
900+
ovl_verity_mode(config));
901+
return -EINVAL;
902+
}
851903
/*
852904
* Silently disable default setting of redirect and metacopy.
853905
* This shall be the default in the future as well: these
@@ -909,5 +961,8 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry)
909961
seq_puts(m, ",volatile");
910962
if (ofs->config.userxattr)
911963
seq_puts(m, ",userxattr");
964+
if (ofs->config.verity_mode != ovl_verity_mode_def())
965+
seq_printf(m, ",verity=%s",
966+
ovl_verity_mode(&ofs->config));
912967
return 0;
913968
}

0 commit comments

Comments
 (0)