diff --git a/drivers/overlay/composefs_notsupported.go b/drivers/overlay/composefs_notsupported.go index 273ef4699d..75eae0affb 100644 --- a/drivers/overlay/composefs_notsupported.go +++ b/drivers/overlay/composefs_notsupported.go @@ -18,3 +18,7 @@ func generateComposeFsBlob(toc []byte, destFile string) error { func mountErofsBlob(blobFile, mountPoint string) error { return fmt.Errorf("composefs is not supported") } + +func enableVerityRecursive(path string) error { + return fmt.Errorf("composefs is not supported") +} diff --git a/drivers/overlay/composefs_supported.go b/drivers/overlay/composefs_supported.go index e5c73a27a7..390e38d570 100644 --- a/drivers/overlay/composefs_supported.go +++ b/drivers/overlay/composefs_supported.go @@ -4,12 +4,18 @@ package overlay import ( + "errors" "fmt" + "io/fs" "os" "os/exec" + "path/filepath" "sync" + "syscall" + "unsafe" "github.com/containers/storage/pkg/loopback" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -31,12 +37,54 @@ func composeFsSupported() bool { return err == nil } +func enableVerity(description string, fd int) error { + enableArg := unix.FsverityEnableArg{ + Version: 1, + Hash_algorithm: unix.FS_VERITY_HASH_ALG_SHA256, + Block_size: 4096, + } + + _, _, e1 := syscall.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.FS_IOC_ENABLE_VERITY), uintptr(unsafe.Pointer(&enableArg))) + if e1 != 0 { + return fmt.Errorf("failed to enable verity for %q: %w", description, e1) + } + return nil +} + +func enableVerityRecursive(path string) error { + walkFn := func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.Type().IsRegular() { + return nil + } + + f, err := os.Open(path) + if err != nil { + return err + } + defer f.Close() + + if err := enableVerity(path, int(f.Fd())); err != nil { + return fmt.Errorf("file %s: %w", path, err) + } + return nil + } + return filepath.WalkDir(path, walkFn) +} + func generateComposeFsBlob(toc []byte, destFile string) error { outFd, err := unix.Openat(unix.AT_FDCWD, destFile, unix.O_WRONLY|unix.O_CREAT|unix.O_TRUNC|unix.O_EXCL, 0o644) if err != nil { return fmt.Errorf("failed to open output file: %w", err) } + newFd, err := unix.Open(fmt.Sprintf("/proc/self/fd/%d", outFd), unix.O_RDONLY, 0) + if err != nil { + return fmt.Errorf("failed to dup output file: %w", err) + } + defer unix.Close(newFd) writerJson, err := getComposeFsHelper() if err != nil { @@ -77,6 +125,11 @@ func generateComposeFsBlob(toc []byte, destFile string) error { if err != nil { return err } + + if err := enableVerity("manifest file", newFd); err != nil && !errors.Is(err, unix.ENOTSUP) && !errors.Is(err, unix.ENOTTY) { + logrus.Warningf("%s", err) + } + return nil } diff --git a/drivers/overlay/overlay.go b/drivers/overlay/overlay.go index 58edf08723..cbdfe1db2e 100644 --- a/drivers/overlay/overlay.go +++ b/drivers/overlay/overlay.go @@ -2062,7 +2062,13 @@ func (d *Driver) ApplyDiffFromStagingDirectory(id, parent, stagingDirectory stri } dest := "" + if d.useComposeFs() { + // FIXME: move this logic into the differ so we don't have to open + // the file twice. + if err := enableVerityRecursive(stagingDirectory); err != nil && !errors.Is(err, unix.ENOTSUP) && !errors.Is(err, unix.ENOTTY) { + logrus.Warningf("%s", err) + } toc := diffOutput.BigData[zstdChunkedManifest] if err := generateComposeFsBlob(toc, d.getErofsBlob(id)); err != nil { return err