@@ -544,6 +544,7 @@ struct ovl_copy_up_ctx {
544544 bool origin ;
545545 bool indexed ;
546546 bool metacopy ;
547+ bool metacopy_digest ;
547548};
548549
549550static 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 ));
9881028out_free :
9891029 kfree (capability );
0 commit comments