Skip to content

Commit 0c71faf

Browse files
alexlarssonamir73il
authored andcommitted
ovl: Handle verity during copy-up
During regular metacopy, if lowerdata file has fs-verity enabled, and the verity option is enabled, we add the digest to the metacopy xattr. If verity is required, and lowerdata does not have fs-verity enabled, fall back to full copy-up (or the generated metacopy would not validate). Signed-off-by: Alexander Larsson <alexl@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
1 parent 184996e commit 0c71faf

File tree

3 files changed

+79
-5
lines changed

3 files changed

+79
-5
lines changed

fs/overlayfs/copy_up.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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));
@@ -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);

fs/overlayfs/overlayfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,11 +487,14 @@ int ovl_set_metacopy_xattr(struct ovl_fs *ofs, struct dentry *d,
487487
struct ovl_metacopy *metacopy);
488488
bool ovl_is_metacopy_dentry(struct dentry *dentry);
489489
char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int padding);
490+
int ovl_ensure_verity_loaded(struct path *path);
490491
int ovl_get_verity_xattr(struct ovl_fs *ofs, const struct path *path,
491492
u8 *digest_buf, int *buf_length);
492493
int ovl_validate_verity(struct ovl_fs *ofs,
493494
struct path *metapath,
494495
struct path *datapath);
496+
int ovl_get_verity_digest(struct ovl_fs *ofs, struct path *src,
497+
struct ovl_metacopy *metacopy);
495498
int ovl_sync_status(struct ovl_fs *ofs);
496499

497500
static inline void ovl_set_flag(unsigned long flag, struct inode *inode)

fs/overlayfs/util.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int pa
11881188
}
11891189

11901190
/* Call with mounter creds as it may open the file */
1191-
static int ovl_ensure_verity_loaded(struct path *datapath)
1191+
int ovl_ensure_verity_loaded(struct path *datapath)
11921192
{
11931193
struct inode *inode = d_inode(datapath->dentry);
11941194
struct file *filp;
@@ -1262,6 +1262,37 @@ int ovl_validate_verity(struct ovl_fs *ofs,
12621262
return 0;
12631263
}
12641264

1265+
int ovl_get_verity_digest(struct ovl_fs *ofs, struct path *src,
1266+
struct ovl_metacopy *metacopy)
1267+
{
1268+
int err, digest_size;
1269+
1270+
if (!ofs->config.verity_mode || !S_ISREG(d_inode(src->dentry)->i_mode))
1271+
return 0;
1272+
1273+
err = ovl_ensure_verity_loaded(src);
1274+
if (err < 0) {
1275+
pr_warn_ratelimited("lower file '%pd' failed to load fs-verity info\n",
1276+
src->dentry);
1277+
return -EIO;
1278+
}
1279+
1280+
digest_size = fsverity_get_digest(d_inode(src->dentry),
1281+
metacopy->digest, &metacopy->digest_algo, NULL);
1282+
if (digest_size == 0 ||
1283+
WARN_ON_ONCE(digest_size > FS_VERITY_MAX_DIGEST_SIZE)) {
1284+
if (ofs->config.verity_mode == OVL_VERITY_REQUIRE) {
1285+
pr_warn_ratelimited("lower file '%pd' has no fs-verity digest\n",
1286+
src->dentry);
1287+
return -EIO;
1288+
}
1289+
return 0;
1290+
}
1291+
1292+
metacopy->len += digest_size;
1293+
return 0;
1294+
}
1295+
12651296
/*
12661297
* ovl_sync_status() - Check fs sync status for volatile mounts
12671298
*

0 commit comments

Comments
 (0)