Skip to content

Commit

Permalink
overlay, composefs: add fs-verity to files
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
giuseppe committed Jul 3, 2023
1 parent 6b545ef commit dd1c18d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 7 deletions.
4 changes: 4 additions & 0 deletions drivers/overlay/composefs_notsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
78 changes: 71 additions & 7 deletions drivers/overlay/composefs_supported.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ package overlay

import (
"bytes"
"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"
)

Expand All @@ -32,6 +38,43 @@ 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 err
}
return nil
}
return filepath.WalkDir(path, walkFn)
}

func generateComposeFsBlob(toc []byte, destFile string) error {
writerJson, err := getComposeFsHelper()
if err != nil {
Expand All @@ -44,14 +87,35 @@ func generateComposeFsBlob(toc []byte, destFile string) error {
}
outFd := os.NewFile(uintptr(fd), "outFd")

defer outFd.Close()
cmd := exec.Command(writerJson, "--format=erofs", "--out=/proc/self/fd/3", "/proc/self/fd/0")
cmd.ExtraFiles = []*os.File{outFd}
cmd.Stdin = bytes.NewReader(toc)
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to convert json to erofs: %w", err)
fd, err = unix.Open(fmt.Sprintf("/proc/self/fd/%d", outFd.Fd()), unix.O_RDONLY|unix.O_CLOEXEC, 0)
if err != nil {
outFd.Close()
return fmt.Errorf("failed to dup output file: %w", err)
}
newFd := os.NewFile(uintptr(fd), "newFd")
defer newFd.Close()

err = func() error {
// a scope to close outFd before setting fsverity on the read-only fd.
defer outFd.Close()

cmd := exec.Command(writerJson, "--format=erofs", "--out=/proc/self/fd/3", "/proc/self/fd/0")
cmd.ExtraFiles = []*os.File{outFd}
cmd.Stderr = os.Stderr
cmd.Stdin = bytes.NewReader(toc)
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to convert json to erofs: %w", err)
}
return nil
}()
if err != nil {
return err
}

if err := enableVerity("manifest file", int(newFd.Fd())); err != nil && !errors.Is(err, unix.ENOTSUP) && !errors.Is(err, unix.ENOTTY) {
logrus.Warningf("%s", err)
}

return nil
}

Expand Down
5 changes: 5 additions & 0 deletions drivers/overlay/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -2064,6 +2064,11 @@ func (d *Driver) ApplyDiffFromStagingDirectory(id, parent, stagingDirectory stri
}

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
Expand Down

0 comments on commit dd1c18d

Please sign in to comment.