update to use containerd seccomp package

Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
Jess Frazelle 2018-03-22 09:02:35 -04:00
parent 9ff5e389ff
commit 09243b740c
8199 changed files with 30742 additions and 1598219 deletions

View file

@ -1,53 +0,0 @@
package fstest
import (
"io/ioutil"
"os"
"github.com/containerd/continuity"
"github.com/pkg/errors"
)
// CheckDirectoryEqual compares two directory paths to make sure that
// the content of the directories is the same.
func CheckDirectoryEqual(d1, d2 string) error {
c1, err := continuity.NewContext(d1)
if err != nil {
return errors.Wrap(err, "failed to build context")
}
c2, err := continuity.NewContext(d2)
if err != nil {
return errors.Wrap(err, "failed to build context")
}
m1, err := continuity.BuildManifest(c1)
if err != nil {
return errors.Wrap(err, "failed to build manifest")
}
m2, err := continuity.BuildManifest(c2)
if err != nil {
return errors.Wrap(err, "failed to build manifest")
}
diff := diffResourceList(m1.Resources, m2.Resources)
if diff.HasDiff() {
return errors.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String())
}
return nil
}
// CheckDirectoryEqualWithApplier compares directory against applier
func CheckDirectoryEqualWithApplier(root string, a Applier) error {
applied, err := ioutil.TempDir("", "fstest")
if err != nil {
return err
}
defer os.RemoveAll(applied)
if err := a.Apply(applied); err != nil {
return err
}
return CheckDirectoryEqual(applied, root)
}

View file

@ -1,189 +0,0 @@
package fstest
import (
"bytes"
"fmt"
"github.com/containerd/continuity"
)
type resourceUpdate struct {
Original continuity.Resource
Updated continuity.Resource
}
func (u resourceUpdate) String() string {
return fmt.Sprintf("%s(mode: %o, uid: %d, gid: %d) -> %s(mode: %o, uid: %d, gid: %d)",
u.Original.Path(), u.Original.Mode(), u.Original.UID(), u.Original.GID(),
u.Updated.Path(), u.Updated.Mode(), u.Updated.UID(), u.Updated.GID(),
)
}
type resourceListDifference struct {
Additions []continuity.Resource
Deletions []continuity.Resource
Updates []resourceUpdate
}
func (l resourceListDifference) HasDiff() bool {
return len(l.Additions) > 0 || len(l.Deletions) > 0 || len(l.Updates) > 0
}
func (l resourceListDifference) String() string {
buf := bytes.NewBuffer(nil)
for _, add := range l.Additions {
fmt.Fprintf(buf, "+ %s\n", add.Path())
}
for _, del := range l.Deletions {
fmt.Fprintf(buf, "- %s\n", del.Path())
}
for _, upt := range l.Updates {
fmt.Fprintf(buf, "~ %s\n", upt.String())
}
return string(buf.Bytes())
}
// diffManifest compares two resource lists and returns the list
// of adds updates and deletes, resource lists are not reordered
// before doing difference.
func diffResourceList(r1, r2 []continuity.Resource) resourceListDifference {
i1 := 0
i2 := 0
var d resourceListDifference
for i1 < len(r1) && i2 < len(r2) {
p1 := r1[i1].Path()
p2 := r2[i2].Path()
switch {
case p1 < p2:
d.Deletions = append(d.Deletions, r1[i1])
i1++
case p1 == p2:
if !compareResource(r1[i1], r2[i2]) {
d.Updates = append(d.Updates, resourceUpdate{
Original: r1[i1],
Updated: r2[i2],
})
}
i1++
i2++
case p1 > p2:
d.Additions = append(d.Additions, r2[i2])
i2++
}
}
for i1 < len(r1) {
d.Deletions = append(d.Deletions, r1[i1])
i1++
}
for i2 < len(r2) {
d.Additions = append(d.Additions, r2[i2])
i2++
}
return d
}
func compareResource(r1, r2 continuity.Resource) bool {
if r1.Path() != r2.Path() {
return false
}
if r1.Mode() != r2.Mode() {
return false
}
if r1.UID() != r2.UID() {
return false
}
if r1.GID() != r2.GID() {
return false
}
// TODO(dmcgowan): Check if is XAttrer
return compareResourceTypes(r1, r2)
}
func compareResourceTypes(r1, r2 continuity.Resource) bool {
switch t1 := r1.(type) {
case continuity.RegularFile:
t2, ok := r2.(continuity.RegularFile)
if !ok {
return false
}
return compareRegularFile(t1, t2)
case continuity.Directory:
t2, ok := r2.(continuity.Directory)
if !ok {
return false
}
return compareDirectory(t1, t2)
case continuity.SymLink:
t2, ok := r2.(continuity.SymLink)
if !ok {
return false
}
return compareSymLink(t1, t2)
case continuity.NamedPipe:
t2, ok := r2.(continuity.NamedPipe)
if !ok {
return false
}
return compareNamedPipe(t1, t2)
case continuity.Device:
t2, ok := r2.(continuity.Device)
if !ok {
return false
}
return compareDevice(t1, t2)
default:
// TODO(dmcgowan): Should this panic?
return r1 == r2
}
}
func compareRegularFile(r1, r2 continuity.RegularFile) bool {
if r1.Size() != r2.Size() {
return false
}
p1 := r1.Paths()
p2 := r2.Paths()
if len(p1) != len(p2) {
return false
}
for i := range p1 {
if p1[i] != p2[i] {
return false
}
}
d1 := r1.Digests()
d2 := r2.Digests()
if len(d1) != len(d2) {
return false
}
for i := range d1 {
if d1[i] != d2[i] {
return false
}
}
return true
}
func compareSymLink(r1, r2 continuity.SymLink) bool {
return r1.Target() == r2.Target()
}
func compareDirectory(r1, r2 continuity.Directory) bool {
return true
}
func compareNamedPipe(r1, r2 continuity.NamedPipe) bool {
return true
}
func compareDevice(r1, r2 continuity.Device) bool {
return r1.Major() == r2.Major() && r1.Minor() == r2.Minor()
}

View file

@ -1,120 +0,0 @@
package fstest
import (
"io/ioutil"
"os"
"path/filepath"
"time"
)
// Applier applies single file changes
type Applier interface {
Apply(root string) error
}
type applyFn func(root string) error
func (a applyFn) Apply(root string) error {
return a(root)
}
// CreateFile returns a file applier which creates a file as the
// provided name with the given content and permission.
func CreateFile(name string, content []byte, perm os.FileMode) Applier {
return applyFn(func(root string) error {
fullPath := filepath.Join(root, name)
if err := ioutil.WriteFile(fullPath, content, perm); err != nil {
return err
}
return os.Chmod(fullPath, perm)
})
}
// Remove returns a file applier which removes the provided file name
func Remove(name string) Applier {
return applyFn(func(root string) error {
return os.Remove(filepath.Join(root, name))
})
}
// RemoveAll returns a file applier which removes the provided file name
// as in os.RemoveAll
func RemoveAll(name string) Applier {
return applyFn(func(root string) error {
return os.RemoveAll(filepath.Join(root, name))
})
}
// CreateDir returns a file applier to create the directory with
// the provided name and permission
func CreateDir(name string, perm os.FileMode) Applier {
return applyFn(func(root string) error {
fullPath := filepath.Join(root, name)
if err := os.MkdirAll(fullPath, perm); err != nil {
return err
}
return os.Chmod(fullPath, perm)
})
}
// Rename returns a file applier which renames a file
func Rename(old, new string) Applier {
return applyFn(func(root string) error {
return os.Rename(filepath.Join(root, old), filepath.Join(root, new))
})
}
// Chown returns a file applier which changes the ownership of a file
func Chown(name string, uid, gid int) Applier {
return applyFn(func(root string) error {
return os.Chown(filepath.Join(root, name), uid, gid)
})
}
// Chtimes changes access and mod time of file.
// Use Lchtimes for symbolic links.
func Chtimes(name string, atime, mtime time.Time) Applier {
return applyFn(func(root string) error {
return os.Chtimes(filepath.Join(root, name), atime, mtime)
})
}
// Chmod returns a file applier which changes the file permission
func Chmod(name string, perm os.FileMode) Applier {
return applyFn(func(root string) error {
return os.Chmod(filepath.Join(root, name), perm)
})
}
// Symlink returns a file applier which creates a symbolic link
func Symlink(oldname, newname string) Applier {
return applyFn(func(root string) error {
return os.Symlink(oldname, filepath.Join(root, newname))
})
}
// Link returns a file applier which creates a hard link
func Link(oldname, newname string) Applier {
return applyFn(func(root string) error {
return os.Link(filepath.Join(root, oldname), filepath.Join(root, newname))
})
}
// TODO: Make platform specific, windows applier is always no-op
//func Mknod(name string, mode int32, dev int) Applier {
// return func(root string) error {
// return return syscall.Mknod(path, mode, dev)
// }
//}
// Apply returns a new applier from the given appliers
func Apply(appliers ...Applier) Applier {
return applyFn(func(root string) error {
for _, a := range appliers {
if err := a.Apply(root); err != nil {
return err
}
}
return nil
})
}

View file

@ -1,29 +0,0 @@
// +build !windows
package fstest
import (
"path/filepath"
"time"
"github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix"
)
// SetXAttr sets the xatter for the file
func SetXAttr(name, key, value string) Applier {
return applyFn(func(root string) error {
return sysx.LSetxattr(name, key, []byte(value), 0)
})
}
// Lchtimes changes access and mod time of file without following symlink
func Lchtimes(name string, atime, mtime time.Time) Applier {
return applyFn(func(root string) error {
path := filepath.Join(root, name)
at := unix.NsecToTimespec(atime.UnixNano())
mt := unix.NsecToTimespec(mtime.UnixNano())
utimes := [2]unix.Timespec{at, mt}
return unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW)
})
}

View file

@ -1,14 +0,0 @@
package fstest
import (
"time"
"github.com/pkg/errors"
)
// Lchtimes changes access and mod time of file without following symlink
func Lchtimes(name string, atime, mtime time.Time) Applier {
return applyFn(func(root string) error {
return errors.New("Not implemented")
})
}

View file

@ -1,220 +0,0 @@
package fstest
import (
"context"
"io/ioutil"
"os"
"testing"
)
// TestApplier applies the test context
type TestApplier interface {
TestContext(context.Context) (context.Context, func(), error)
Apply(context.Context, Applier) (string, func(), error)
}
// FSSuite runs the path test suite
func FSSuite(t *testing.T, a TestApplier) {
t.Run("Basic", makeTest(t, a, basicTest))
t.Run("Deletion", makeTest(t, a, deletionTest))
t.Run("Update", makeTest(t, a, updateTest))
t.Run("DirectoryPermission", makeTest(t, a, directoryPermissionsTest))
t.Run("ParentDirectoryPermission", makeTest(t, a, parentDirectoryPermissionsTest))
t.Run("HardlinkUnmodified", makeTest(t, a, hardlinkUnmodified))
t.Run("HardlinkBeforeUnmodified", makeTest(t, a, hardlinkBeforeUnmodified))
t.Run("HardlinkBeforeModified", makeTest(t, a, hardlinkBeforeModified))
}
func makeTest(t *testing.T, ta TestApplier, as []Applier) func(t *testing.T) {
return func(t *testing.T) {
ctx, cleanup, err := ta.TestContext(context.Background())
if err != nil {
t.Fatalf("Unable to get test context: %+v", err)
}
defer cleanup()
applyDir, err := ioutil.TempDir("", "test-expected-")
if err != nil {
t.Fatalf("Unable to make temp directory: %+v", err)
}
defer os.RemoveAll(applyDir)
for i, a := range as {
testDir, c, err := ta.Apply(ctx, a)
if err != nil {
t.Fatalf("Apply failed at %d: %+v", i, err)
}
if err := a.Apply(applyDir); err != nil {
if c != nil {
c()
}
t.Fatalf("Error applying change to apply directory: %+v", err)
}
err = CheckDirectoryEqual(applyDir, testDir)
if c != nil {
c()
}
if err != nil {
t.Fatalf("Directories not equal at %d (expected <> tested): %+v", i, err)
}
}
}
}
var (
// baseApplier creates a basic filesystem layout
// with multiple types of files for basic tests.
baseApplier = Apply(
CreateDir("/etc/", 0755),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
Link("/etc/hosts", "/etc/hosts.allow"),
CreateDir("/usr/local/lib", 0755),
CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0755),
Symlink("libnothing.so", "/usr/local/lib/libnothing.so.2"),
CreateDir("/home", 0755),
CreateDir("/home/derek", 0700),
)
// basicTest covers basic operations
basicTest = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0600),
CreateFile("/etc/badfile", []byte(""), 0666),
CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640),
),
Apply(
Remove("/etc/badfile"),
Rename("/home/derek", "/home/notderek"),
),
Apply(
RemoveAll("/usr"),
Remove("/etc/hosts.allow"),
),
Apply(
RemoveAll("/home"),
CreateDir("/home/derek", 0700),
CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640),
Link("/etc/hosts", "/etc/hosts.allow"),
),
}
// deletionTest covers various deletion scenarios to ensure
// deletions are properly picked up and applied
deletionTest = []Applier{
Apply(
CreateDir("/test/somedir", 0755),
CreateDir("/lib", 0700),
CreateFile("/lib/hidden", []byte{}, 0644),
),
Apply(
CreateFile("/test/a", []byte{}, 0644),
CreateFile("/test/b", []byte{}, 0644),
CreateDir("/test/otherdir", 0755),
CreateFile("/test/otherdir/.empty", []byte{}, 0644),
RemoveAll("/lib"),
CreateDir("/lib", 0700),
CreateFile("/lib/not-hidden", []byte{}, 0644),
),
Apply(
Remove("/test/a"),
Remove("/test/b"),
RemoveAll("/test/otherdir"),
CreateFile("/lib/newfile", []byte{}, 0644),
),
}
// updateTest covers file updates for content and permission
updateTest = []Applier{
Apply(
CreateDir("/d1", 0755),
CreateDir("/d2", 0700),
CreateFile("/d1/f1", []byte("something..."), 0644),
CreateFile("/d1/f2", []byte("else..."), 0644),
CreateFile("/d1/f3", []byte("entirely..."), 0644),
),
Apply(
CreateFile("/d1/f1", []byte("file content of a different length"), 0664),
Remove("/d1/f3"),
CreateFile("/d1/f3", []byte("updated content"), 0664),
Chmod("/d1/f2", 0766),
Chmod("/d2", 0777),
),
}
// directoryPermissionsTest covers directory permissions on update
directoryPermissionsTest = []Applier{
Apply(
CreateDir("/d1", 0700),
CreateDir("/d2", 0751),
CreateDir("/d3", 0777),
),
Apply(
CreateFile("/d1/f", []byte("irrelevant"), 0644),
CreateDir("/d1/d", 0700),
CreateFile("/d1/d/f", []byte("irrelevant"), 0644),
CreateFile("/d2/f", []byte("irrelevant"), 0644),
CreateFile("/d3/f", []byte("irrelevant"), 0644),
),
}
// parentDirectoryPermissionsTest covers directory permissions for updated
// files
parentDirectoryPermissionsTest = []Applier{
Apply(
CreateDir("/d1", 0700),
CreateDir("/d1/a", 0700),
CreateDir("/d1/a/b", 0700),
CreateDir("/d1/a/b/c", 0700),
CreateFile("/d1/a/b/f", []byte("content1"), 0644),
CreateDir("/d2", 0751),
CreateDir("/d2/a/b", 0751),
CreateDir("/d2/a/b/c", 0751),
CreateFile("/d2/a/b/f", []byte("content1"), 0644),
),
Apply(
CreateFile("/d1/a/b/f", []byte("content1"), 0644),
Chmod("/d1/a/b/c", 0700),
CreateFile("/d2/a/b/f", []byte("content2"), 0644),
Chmod("/d2/a/b/c", 0751),
),
}
hardlinkUnmodified = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
),
Apply(
Link("/etc/hosts", "/etc/hosts.deny"),
),
}
// Hardlink name before with modification
// Tests link is created for unmodified files when new hardlinked file is seen first
hardlinkBeforeUnmodified = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
),
Apply(
Link("/etc/hosts", "/etc/before-hosts"),
),
}
// Hardlink name after without modification
// tests link is created for modified file with new hardlink
hardlinkBeforeModified = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
),
Apply(
Remove("/etc/hosts"),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
Link("/etc/hosts", "/etc/before-hosts"),
),
}
)