diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-06-30 00:48:51 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-06-30 00:48:51 +0000 |
commit | 1360966003efafa2af6a6816dfaf37b69d2d7f67 (patch) | |
tree | ea69b7ab46c8b182612025e2f71d0a9fe7747970 | |
parent | 7a8bc54a0cb8edc370e4a2ac3d9b285dc37a21dc (diff) | |
parent | 57095bd3bd75338fd6a95a7478c9cb444b5e9980 (diff) |
Merge release-20210628.0-10-g57095bd3b (automated)
-rw-r--r-- | pkg/merkletree/merkletree.go | 18 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/verity/filesystem.go | 7 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/verity/verity.go | 24 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/verity/verity_state_autogen.go | 19 |
4 files changed, 47 insertions, 21 deletions
diff --git a/pkg/merkletree/merkletree.go b/pkg/merkletree/merkletree.go index ac7868ad9..0b961d3d9 100644 --- a/pkg/merkletree/merkletree.go +++ b/pkg/merkletree/merkletree.go @@ -151,21 +151,21 @@ type VerityDescriptor struct { Mode uint32 UID uint32 GID uint32 - Children map[string]struct{} + Children []string SymlinkTarget string RootHash []byte } -func (d *VerityDescriptor) String() string { +func (d *VerityDescriptor) encode() []byte { b := new(bytes.Buffer) e := gob.NewEncoder(b) - e.Encode(d.Children) - return fmt.Sprintf("Name: %s, Size: %d, Mode: %d, UID: %d, GID: %d, Children: %v, Symlink: %s, RootHash: %v", d.Name, d.FileSize, d.Mode, d.UID, d.GID, b.Bytes(), d.SymlinkTarget, d.RootHash) + e.Encode(d) + return b.Bytes() } // verify generates a hash from d, and compares it with expected. func (d *VerityDescriptor) verify(expected []byte, hashAlgorithms int) error { - h, err := hashData([]byte(d.String()), hashAlgorithms) + h, err := hashData(d.encode(), hashAlgorithms) if err != nil { return err } @@ -210,7 +210,7 @@ type GenerateParams struct { GID uint32 // Children is a map of children names for a directory. It should be // empty for a regular file. - Children map[string]struct{} + Children []string // SymlinkTarget is the target path of a symlink file, or "" if the file is not a symlink. SymlinkTarget string // HashAlgorithms is the algorithms used to hash data. @@ -242,7 +242,7 @@ func Generate(params *GenerateParams) ([]byte, error) { // If file is a symlink do not generate root hash for file content. if params.SymlinkTarget != "" { - return hashData([]byte(descriptor.String()), params.HashAlgorithms) + return hashData(descriptor.encode(), params.HashAlgorithms) } layout, err := InitLayout(params.Size, params.HashAlgorithms, params.DataAndTreeInSameFile) @@ -315,7 +315,7 @@ func Generate(params *GenerateParams) ([]byte, error) { numBlocks = (numBlocks + layout.hashesPerBlock() - 1) / layout.hashesPerBlock() } descriptor.RootHash = root - return hashData([]byte(descriptor.String()), params.HashAlgorithms) + return hashData(descriptor.encode(), params.HashAlgorithms) } // VerifyParams contains the params used to verify a portion of a file against @@ -339,7 +339,7 @@ type VerifyParams struct { GID uint32 // Children is a map of children names for a directory. It should be // empty for a regular file. - Children map[string]struct{} + Children []string // SymlinkTarget is the target path of a symlink file, or "" if the file is not a symlink. SymlinkTarget string // HashAlgorithms is the algorithms used to hash data. diff --git a/pkg/sentry/fsimpl/verity/filesystem.go b/pkg/sentry/fsimpl/verity/filesystem.go index e84452421..b5735a86d 100644 --- a/pkg/sentry/fsimpl/verity/filesystem.go +++ b/pkg/sentry/fsimpl/verity/filesystem.go @@ -283,7 +283,7 @@ func (fs *filesystem) verifyChildLocked(ctx context.Context, parent *dentry, chi Mode: uint32(parentStat.Mode), UID: parentStat.UID, GID: parentStat.GID, - Children: parent.childrenNames, + Children: parent.childrenList, HashAlgorithms: fs.alg.toLinuxHashAlg(), ReadOffset: int64(offset), ReadSize: int64(merkletree.DigestSize(fs.alg.toLinuxHashAlg())), @@ -404,6 +404,9 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry var buf bytes.Buffer d.hashMu.RLock() + + d.generateChildrenList() + params := &merkletree.VerifyParams{ Out: &buf, Tree: &fdReader, @@ -412,7 +415,7 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry Mode: uint32(stat.Mode), UID: stat.UID, GID: stat.GID, - Children: d.childrenNames, + Children: d.childrenList, HashAlgorithms: fs.alg.toLinuxHashAlg(), ReadOffset: 0, // Set read size to 0 so only the metadata is verified. diff --git a/pkg/sentry/fsimpl/verity/verity.go b/pkg/sentry/fsimpl/verity/verity.go index ffc8f019d..2227b542a 100644 --- a/pkg/sentry/fsimpl/verity/verity.go +++ b/pkg/sentry/fsimpl/verity/verity.go @@ -39,6 +39,7 @@ import ( "encoding/json" "fmt" "math" + "sort" "strconv" "strings" "sync/atomic" @@ -509,6 +510,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt if err := fs.verifyStatAndChildrenLocked(ctx, d, stat); err != nil { return nil, nil, err } + d.generateChildrenList() } d.vfsd.Init(d) @@ -565,6 +567,11 @@ type dentry struct { // populated by enableVerity. childrenNames is also protected by dirMu. childrenNames map[string]struct{} + // childrenList is a complete sorted list of childrenNames. This list + // is generated when verity is enabled, or the first time the file is + // verified in non runtime enable mode. + childrenList []string + // lowerVD is the VirtualDentry in the underlying file system. It is // never modified after initialized. lowerVD vfs.VirtualDentry @@ -750,6 +757,17 @@ func (d *dentry) verityEnabled() bool { return !d.fs.allowRuntimeEnable || len(d.hash) != 0 } +// generateChildrenList generates a sorted childrenList from childrenNames, and +// cache it in d for hashing. +func (d *dentry) generateChildrenList() { + if len(d.childrenList) == 0 && len(d.childrenNames) != 0 { + for child := range d.childrenNames { + d.childrenList = append(d.childrenList, child) + } + sort.Strings(d.childrenList) + } +} + // getLowerAt returns the dentry in the underlying file system, which is // represented by filename relative to d. func (d *dentry) getLowerAt(ctx context.Context, vfsObj *vfs.VirtualFilesystem, filename string) (vfs.VirtualDentry, error) { @@ -963,10 +981,12 @@ func (fd *fileDescription) generateMerkleLocked(ctx context.Context) ([]byte, ui return nil, 0, err } + fd.d.generateChildrenList() + params := &merkletree.GenerateParams{ TreeReader: &merkleReader, TreeWriter: &merkleWriter, - Children: fd.d.childrenNames, + Children: fd.d.childrenList, HashAlgorithms: fd.d.fs.alg.toLinuxHashAlg(), Name: fd.d.name, Mode: uint32(stat.Mode), @@ -1262,7 +1282,7 @@ func (fd *fileDescription) PRead(ctx context.Context, dst usermem.IOSequence, of Mode: fd.d.mode, UID: fd.d.uid, GID: fd.d.gid, - Children: fd.d.childrenNames, + Children: fd.d.childrenList, HashAlgorithms: fd.d.fs.alg.toLinuxHashAlg(), ReadOffset: offset, ReadSize: dst.NumBytes(), diff --git a/pkg/sentry/fsimpl/verity/verity_state_autogen.go b/pkg/sentry/fsimpl/verity/verity_state_autogen.go index 8bbc3e495..dba01a68e 100644 --- a/pkg/sentry/fsimpl/verity/verity_state_autogen.go +++ b/pkg/sentry/fsimpl/verity/verity_state_autogen.go @@ -127,6 +127,7 @@ func (d *dentry) StateFields() []string { "name", "children", "childrenNames", + "childrenList", "lowerVD", "lowerMerkleVD", "symlinkTarget", @@ -150,10 +151,11 @@ func (d *dentry) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(8, &d.name) stateSinkObject.Save(9, &d.children) stateSinkObject.Save(10, &d.childrenNames) - stateSinkObject.Save(11, &d.lowerVD) - stateSinkObject.Save(12, &d.lowerMerkleVD) - stateSinkObject.Save(13, &d.symlinkTarget) - stateSinkObject.Save(14, &d.hash) + stateSinkObject.Save(11, &d.childrenList) + stateSinkObject.Save(12, &d.lowerVD) + stateSinkObject.Save(13, &d.lowerMerkleVD) + stateSinkObject.Save(14, &d.symlinkTarget) + stateSinkObject.Save(15, &d.hash) } // +checklocksignore @@ -169,10 +171,11 @@ func (d *dentry) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(8, &d.name) stateSourceObject.Load(9, &d.children) stateSourceObject.Load(10, &d.childrenNames) - stateSourceObject.Load(11, &d.lowerVD) - stateSourceObject.Load(12, &d.lowerMerkleVD) - stateSourceObject.Load(13, &d.symlinkTarget) - stateSourceObject.Load(14, &d.hash) + stateSourceObject.Load(11, &d.childrenList) + stateSourceObject.Load(12, &d.lowerVD) + stateSourceObject.Load(13, &d.lowerMerkleVD) + stateSourceObject.Load(14, &d.symlinkTarget) + stateSourceObject.Load(15, &d.hash) stateSourceObject.AfterLoad(d.afterLoad) } |