Skip to content

Commit 63580f6

Browse files
committed
Merge tag 'ovl-update-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs
Pull overlayfs updates from Amir Goldstein: - add verification feature needed by composefs (Alexander Larsson) - improve integration of overlayfs and fanotify (Amir Goldstein) - fortify some overlayfs code (Andrea Righi) * tag 'ovl-update-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs: ovl: validate superblock in OVL_FS() ovl: make consistent use of OVL_FS() ovl: Kconfig: introduce CONFIG_OVERLAY_FS_DEBUG ovl: auto generate uuid for new overlay filesystems ovl: store persistent uuid/fsid with uuid=on ovl: add support for unique fsid per instance ovl: support encoding non-decodable file handles ovl: Handle verity during copy-up ovl: Validate verity xattr when resolving lowerdata ovl: Add versioned header for overlay.metacopy xattr ovl: Add framework for verity support
2 parents 1687d8a + adcd459 commit 63580f6

File tree

13 files changed

+654
-68
lines changed

13 files changed

+654
-68
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: 72 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

@@ -610,6 +657,31 @@ can be useful in case the underlying disk is copied and the UUID of this copy
610657
is changed. This is only applicable if all lower/upper/work directories are on
611658
the same filesystem, otherwise it will fallback to normal behaviour.
612659

660+
661+
UUID and fsid
662+
-------------
663+
664+
The UUID of overlayfs instance itself and the fsid reported by statfs(2) are
665+
controlled by the "uuid" mount option, which supports these values:
666+
667+
- "null":
668+
UUID of overlayfs is null. fsid is taken from upper most filesystem.
669+
- "off":
670+
UUID of overlayfs is null. fsid is taken from upper most filesystem.
671+
UUID of underlying layers is ignored.
672+
- "on":
673+
UUID of overlayfs is generated and used to report a unique fsid.
674+
UUID is stored in xattr "trusted.overlay.uuid", making overlayfs fsid
675+
unique and persistent. This option requires an overlayfs with upper
676+
filesystem that supports xattrs.
677+
- "auto": (default)
678+
UUID is taken from xattr "trusted.overlay.uuid" if it exists.
679+
Upgrade to "uuid=on" on first time mount of new overlay filesystem that
680+
meets the prerequites.
681+
Downgrade to "uuid=null" for existing overlay filesystems that were never
682+
mounted with "uuid=on".
683+
684+
613685
Volatile mount
614686
--------------
615687

fs/overlayfs/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,12 @@ config OVERLAY_FS_METACOPY
124124
that doesn't support this feature will have unexpected results.
125125

126126
If unsure, say N.
127+
128+
config OVERLAY_FS_DEBUG
129+
bool "Overlayfs: turn on extra debugging checks"
130+
default n
131+
depends on OVERLAY_FS
132+
help
133+
Say Y here to enable extra debugging checks in overlayfs.
134+
135+
If unsure, say N.

fs/overlayfs/copy_up.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
416416
if (is_upper)
417417
fh->fb.flags |= OVL_FH_FLAG_PATH_UPPER;
418418
fh->fb.len = sizeof(fh->fb) + buflen;
419-
if (ofs->config.uuid)
419+
if (ovl_origin_uuid(ofs))
420420
fh->fb.uuid = *uuid;
421421

422422
return fh;
@@ -544,6 +544,7 @@ struct ovl_copy_up_ctx {
544544
bool origin;
545545
bool indexed;
546546
bool metacopy;
547+
bool metacopy_digest;
547548
};
548549

549550
static int ovl_link_up(struct ovl_copy_up_ctx *c)
@@ -641,8 +642,20 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp)
641642
}
642643

643644
if (c->metacopy) {
644-
err = ovl_check_setxattr(ofs, temp, OVL_XATTR_METACOPY,
645-
NULL, 0, -EOPNOTSUPP);
645+
struct path lowerdatapath;
646+
struct ovl_metacopy metacopy_data = OVL_METACOPY_INIT;
647+
648+
ovl_path_lowerdata(c->dentry, &lowerdatapath);
649+
if (WARN_ON_ONCE(lowerdatapath.dentry == NULL))
650+
return -EIO;
651+
err = ovl_get_verity_digest(ofs, &lowerdatapath, &metacopy_data);
652+
if (err)
653+
return err;
654+
655+
if (metacopy_data.digest_algo)
656+
c->metacopy_digest = true;
657+
658+
err = ovl_set_metacopy_xattr(ofs, temp, &metacopy_data);
646659
if (err)
647660
return err;
648661
}
@@ -751,9 +764,15 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
751764
if (err)
752765
goto cleanup;
753766

754-
if (!c->metacopy)
755-
ovl_set_upperdata(d_inode(c->dentry));
756767
inode = d_inode(c->dentry);
768+
if (c->metacopy_digest)
769+
ovl_set_flag(OVL_HAS_DIGEST, inode);
770+
else
771+
ovl_clear_flag(OVL_HAS_DIGEST, inode);
772+
ovl_clear_flag(OVL_VERIFIED_DIGEST, inode);
773+
774+
if (!c->metacopy)
775+
ovl_set_upperdata(inode);
757776
ovl_inode_update(inode, temp);
758777
if (S_ISDIR(inode->i_mode))
759778
ovl_set_flag(OVL_WHITEOUTS, inode);
@@ -813,6 +832,12 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
813832
if (err)
814833
goto out_fput;
815834

835+
if (c->metacopy_digest)
836+
ovl_set_flag(OVL_HAS_DIGEST, d_inode(c->dentry));
837+
else
838+
ovl_clear_flag(OVL_HAS_DIGEST, d_inode(c->dentry));
839+
ovl_clear_flag(OVL_VERIFIED_DIGEST, d_inode(c->dentry));
840+
816841
if (!c->metacopy)
817842
ovl_set_upperdata(d_inode(c->dentry));
818843
ovl_inode_update(d_inode(c->dentry), dget(temp));
@@ -907,7 +932,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
907932
static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
908933
int flags)
909934
{
910-
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
935+
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
911936

912937
if (!ofs->config.metacopy)
913938
return false;
@@ -918,6 +943,19 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
918943
if (flags && ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC)))
919944
return false;
920945

946+
/* Fall back to full copy if no fsverity on source data and we require verity */
947+
if (ofs->config.verity_mode == OVL_VERITY_REQUIRE) {
948+
struct path lowerdata;
949+
950+
ovl_path_lowerdata(dentry, &lowerdata);
951+
952+
if (WARN_ON_ONCE(lowerdata.dentry == NULL) ||
953+
ovl_ensure_verity_loaded(&lowerdata) ||
954+
!fsverity_active(d_inode(lowerdata.dentry))) {
955+
return false;
956+
}
957+
}
958+
921959
return true;
922960
}
923961

@@ -984,6 +1022,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
9841022
if (err)
9851023
goto out_free;
9861024

1025+
ovl_clear_flag(OVL_HAS_DIGEST, d_inode(c->dentry));
1026+
ovl_clear_flag(OVL_VERIFIED_DIGEST, d_inode(c->dentry));
9871027
ovl_set_upperdata(d_inode(c->dentry));
9881028
out_free:
9891029
kfree(capability);
@@ -1078,7 +1118,7 @@ static int ovl_copy_up_flags(struct dentry *dentry, int flags)
10781118
* not very important to optimize this case, so do lazy lowerdata lookup
10791119
* before any copy up, so we can do it before taking ovl_inode_lock().
10801120
*/
1081-
err = ovl_maybe_lookup_lowerdata(dentry);
1121+
err = ovl_verify_lowerdata(dentry);
10821122
if (err)
10831123
return err;
10841124

fs/overlayfs/export.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,28 +174,37 @@ static int ovl_connect_layer(struct dentry *dentry)
174174
* U = upper file handle
175175
* L = lower file handle
176176
*
177-
* (*) Connecting an overlay dir from real lower dentry is not always
177+
* (*) Decoding a connected overlay dir from real lower dentry is not always
178178
* possible when there are redirects in lower layers and non-indexed merge dirs.
179179
* To mitigate those case, we may copy up the lower dir ancestor before encode
180-
* a lower dir file handle.
180+
* of a decodable file handle for non-upper dir.
181181
*
182182
* Return 0 for upper file handle, > 0 for lower file handle or < 0 on error.
183183
*/
184184
static int ovl_check_encode_origin(struct dentry *dentry)
185185
{
186-
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
186+
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
187+
bool decodable = ofs->config.nfs_export;
188+
189+
/* Lower file handle for non-upper non-decodable */
190+
if (!ovl_dentry_upper(dentry) && !decodable)
191+
return 0;
187192

188193
/* Upper file handle for pure upper */
189194
if (!ovl_dentry_lower(dentry))
190195
return 0;
191196

192197
/*
193-
* Upper file handle for non-indexed upper.
194-
*
195198
* Root is never indexed, so if there's an upper layer, encode upper for
196199
* root.
197200
*/
198-
if (ovl_dentry_upper(dentry) &&
201+
if (dentry == dentry->d_sb->s_root)
202+
return 0;
203+
204+
/*
205+
* Upper decodable file handle for non-indexed upper.
206+
*/
207+
if (ovl_dentry_upper(dentry) && decodable &&
199208
!ovl_test_flag(OVL_INDEX, d_inode(dentry)))
200209
return 0;
201210

@@ -205,7 +214,7 @@ static int ovl_check_encode_origin(struct dentry *dentry)
205214
* ovl_connect_layer() will try to make origin's layer "connected" by
206215
* copying up a "connectable" ancestor.
207216
*/
208-
if (d_is_dir(dentry) && ovl_upper_mnt(ofs))
217+
if (d_is_dir(dentry) && ovl_upper_mnt(ofs) && decodable)
209218
return ovl_connect_layer(dentry);
210219

211220
/* Lower file handle for indexed and non-upper dir/non-dir */
@@ -435,7 +444,7 @@ static struct dentry *ovl_lookup_real_inode(struct super_block *sb,
435444
struct dentry *real,
436445
const struct ovl_layer *layer)
437446
{
438-
struct ovl_fs *ofs = sb->s_fs_info;
447+
struct ovl_fs *ofs = OVL_FS(sb);
439448
struct dentry *index = NULL;
440449
struct dentry *this = NULL;
441450
struct inode *inode;
@@ -656,7 +665,7 @@ static struct dentry *ovl_get_dentry(struct super_block *sb,
656665
struct ovl_path *lowerpath,
657666
struct dentry *index)
658667
{
659-
struct ovl_fs *ofs = sb->s_fs_info;
668+
struct ovl_fs *ofs = OVL_FS(sb);
660669
const struct ovl_layer *layer = upper ? &ofs->layers[0] : lowerpath->layer;
661670
struct dentry *real = upper ?: (index ?: lowerpath->dentry);
662671

@@ -681,7 +690,7 @@ static struct dentry *ovl_get_dentry(struct super_block *sb,
681690
static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,
682691
struct ovl_fh *fh)
683692
{
684-
struct ovl_fs *ofs = sb->s_fs_info;
693+
struct ovl_fs *ofs = OVL_FS(sb);
685694
struct dentry *dentry;
686695
struct dentry *upper;
687696

@@ -701,7 +710,7 @@ static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,
701710
static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
702711
struct ovl_fh *fh)
703712
{
704-
struct ovl_fs *ofs = sb->s_fs_info;
713+
struct ovl_fs *ofs = OVL_FS(sb);
705714
struct ovl_path origin = { };
706715
struct ovl_path *stack = &origin;
707716
struct dentry *dentry = NULL;
@@ -876,3 +885,8 @@ const struct export_operations ovl_export_operations = {
876885
.get_name = ovl_get_name,
877886
.get_parent = ovl_get_parent,
878887
};
888+
889+
/* encode_fh() encodes non-decodable file handles with nfs_export=off */
890+
const struct export_operations ovl_export_fid_operations = {
891+
.encode_fh = ovl_encode_fh,
892+
};

fs/overlayfs/file.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
115115
if (allow_meta) {
116116
ovl_path_real(dentry, &realpath);
117117
} else {
118-
/* lazy lookup of lowerdata */
119-
err = ovl_maybe_lookup_lowerdata(dentry);
118+
/* lazy lookup and verify of lowerdata */
119+
err = ovl_verify_lowerdata(dentry);
120120
if (err)
121121
return err;
122122

@@ -159,8 +159,8 @@ static int ovl_open(struct inode *inode, struct file *file)
159159
struct path realpath;
160160
int err;
161161

162-
/* lazy lookup of lowerdata */
163-
err = ovl_maybe_lookup_lowerdata(dentry);
162+
/* lazy lookup and verify lowerdata */
163+
err = ovl_verify_lowerdata(dentry);
164164
if (err)
165165
return err;
166166

fs/overlayfs/inode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ static const char *ovl_get_link(struct dentry *dentry,
341341

342342
bool ovl_is_private_xattr(struct super_block *sb, const char *name)
343343
{
344-
struct ovl_fs *ofs = sb->s_fs_info;
344+
struct ovl_fs *ofs = OVL_FS(sb);
345345

346346
if (ofs->config.userxattr)
347347
return strncmp(name, OVL_XATTR_USER_PREFIX,
@@ -696,7 +696,7 @@ int ovl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
696696
int ovl_update_time(struct inode *inode, int flags)
697697
{
698698
if (flags & S_ATIME) {
699-
struct ovl_fs *ofs = inode->i_sb->s_fs_info;
699+
struct ovl_fs *ofs = OVL_FS(inode->i_sb);
700700
struct path upperpath = {
701701
.mnt = ovl_upper_mnt(ofs),
702702
.dentry = ovl_upperdentry_dereference(OVL_I(inode)),
@@ -1291,7 +1291,7 @@ struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir)
12911291
static bool ovl_hash_bylower(struct super_block *sb, struct dentry *upper,
12921292
struct dentry *lower, bool index)
12931293
{
1294-
struct ovl_fs *ofs = sb->s_fs_info;
1294+
struct ovl_fs *ofs = OVL_FS(sb);
12951295

12961296
/* No, if pure upper */
12971297
if (!lower)
@@ -1311,7 +1311,7 @@ static bool ovl_hash_bylower(struct super_block *sb, struct dentry *upper,
13111311
return false;
13121312

13131313
/* No, if non-indexed upper with NFS export */
1314-
if (sb->s_export_op && upper)
1314+
if (ofs->config.nfs_export && upper)
13151315
return false;
13161316

13171317
/* Otherwise, hash by lower inode for fsnotify */

0 commit comments

Comments
 (0)