From 863d808112b6873354b3b2a71cd3bb0bd8223660 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 29 May 2023 14:16:00 +0200 Subject: [PATCH] overlay, composefs: add fs-verity to files at the moment it is a best-effort implementation to enable fs-verity for the composefs blob as well as for the data files. Signed-off-by: Giuseppe Scrivano --- drivers/driver.go | 1 + drivers/overlay/composefs_notsupported.go | 4 ++ drivers/overlay/composefs_supported.go | 52 +++++++++++++++++++++++ drivers/overlay/overlay.go | 6 +++ 4 files changed, 63 insertions(+) diff --git a/drivers/driver.go b/drivers/driver.go index 1fb04dc3ed..42f732b090 100644 --- a/drivers/driver.go +++ b/drivers/driver.go @@ -206,6 +206,7 @@ const ( type DifferOptions struct { // Format defines the destination directory layout format Format DifferOutputFormat + FilePostProcess func(f* os.File) error } // Differ defines the interface for using a custom differ. diff --git a/drivers/overlay/composefs_notsupported.go b/drivers/overlay/composefs_notsupported.go index fd2c9a3f96..ded84a5927 100644 --- a/drivers/overlay/composefs_notsupported.go +++ b/drivers/overlay/composefs_notsupported.go @@ -21,3 +21,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 c14f1aed5c..106328f604 100644 --- a/drivers/overlay/composefs_supported.go +++ b/drivers/overlay/composefs_supported.go @@ -5,11 +5,16 @@ package overlay import ( "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 +36,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", description) + } + 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, 0644) 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 +124,11 @@ func generateComposeFsBlob(toc []byte, destFile string) error { if err != nil { return err } + + if err := enableVerity("manifest file", newFd); err != nil { + logrus.Warningf("%s", err) + } + return nil } diff --git a/drivers/overlay/overlay.go b/drivers/overlay/overlay.go index 58edf08723..e175ff230b 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 { + logrus.Warningf("%s", err) + } toc := diffOutput.BigData[zstdChunkedManifest] if err := generateComposeFsBlob(toc, d.getErofsBlob(id)); err != nil { return err