Skip to content

Commit 3f1cb7e

Browse files
committed
Add test for merge of files with capabilities.
Signed-off-by: Erik Sipsma <[email protected]>
1 parent 30eb659 commit 3f1cb7e

File tree

26 files changed

+5395
-9
lines changed

26 files changed

+5395
-9
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ require (
8787
google.golang.org/genproto v0.0.0-20230131230820-1c016267d619
8888
google.golang.org/grpc v1.52.3
8989
google.golang.org/protobuf v1.28.1
90+
kernel.org/pub/linux/libs/security/libcap/cap v1.2.67
9091
)
9192

9293
require (
@@ -156,4 +157,5 @@ require (
156157
golang.org/x/text v0.7.0 // indirect
157158
golang.org/x/tools v0.5.0 // indirect
158159
gopkg.in/yaml.v3 v3.0.1 // indirect
160+
kernel.org/pub/linux/libs/security/libcap/psx v1.2.67 // indirect
159161
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,10 @@ k8s.io/legacy-cloud-providers v0.17.4/go.mod h1:FikRNoD64ECjkxO36gkDgJeiQWwyZTuB
18901890
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
18911891
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
18921892
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
1893+
kernel.org/pub/linux/libs/security/libcap/cap v1.2.67 h1:sPQ9qlSNR26fToTKbxe/HDWJlXvBLqGmt84LGCQkOy0=
1894+
kernel.org/pub/linux/libs/security/libcap/cap v1.2.67/go.mod h1:GkntoBuwffz19qtdFVB+k2NtWNN+yCKnC/Ykv/hMiTU=
1895+
kernel.org/pub/linux/libs/security/libcap/psx v1.2.67 h1:NxbXJ7pDVq0FKBsqjieT92QDXI2XaqH2HAi4QcCOHt8=
1896+
kernel.org/pub/linux/libs/security/libcap/psx v1.2.67/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
18931897
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
18941898
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
18951899
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=

snapshot/snapshotter_test.go

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/pkg/errors"
2727
"github.com/stretchr/testify/require"
2828
bolt "go.etcd.io/bbolt"
29+
libcap "kernel.org/pub/linux/libs/security/libcap/cap"
2930
)
3031

3132
func newSnapshotter(ctx context.Context, t *testing.T, snapshotterName string) (_ context.Context, _ *mergeSnapshotter, rerr error) {
@@ -372,6 +373,37 @@ func TestHardlinks(t *testing.T) {
372373
}
373374
}
374375

376+
func TestMergeFileCapabilities(t *testing.T) {
377+
requireRoot(t)
378+
for _, snName := range []string{"overlayfs", "native", "native-nohardlink"} {
379+
snName := snName
380+
t.Run(snName, func(t *testing.T) {
381+
t.Parallel()
382+
383+
ctx, sn, err := newSnapshotter(context.Background(), t, snName)
384+
require.NoError(t, err)
385+
386+
setCaps := "cap_net_bind_service=+ep"
387+
base1Snap := committedKey(ctx, t, sn, identity.NewID(), "",
388+
fstest.CreateFile("hasCaps", []byte("capable"), 0700),
389+
fstest.Chown("hasCaps", 1000, 1000),
390+
setFileCap("hasCaps", setCaps),
391+
)
392+
base2Snap := committedKey(ctx, t, sn, identity.NewID(), "",
393+
fstest.CreateFile("foo", []byte("bar"), 0600),
394+
)
395+
396+
mergeSnap := mergeKey(ctx, t, sn, identity.NewID(), []Diff{
397+
{"", base1Snap.Name},
398+
{"", base2Snap.Name},
399+
})
400+
401+
actualCaps := getFileCap(ctx, t, sn, mergeSnap.Name, "hasCaps")
402+
require.Equal(t, "cap_net_bind_service=ep", actualCaps)
403+
})
404+
}
405+
}
406+
375407
func TestUsage(t *testing.T) {
376408
for _, snName := range []string{"overlayfs", "native", "native-nohardlink"} {
377409
snName := snName
@@ -559,7 +591,7 @@ func requireMtime(t *testing.T, path string, mtime time.Time) {
559591
require.Equal(t, mtime.UnixNano(), stat.Mtim.Nano())
560592
}
561593

562-
func tryStatPath(ctx context.Context, t *testing.T, sn *mergeSnapshotter, key, path string) (st *syscall.Stat_t) {
594+
func pathCallback[T any](ctx context.Context, t *testing.T, sn *mergeSnapshotter, key, path string, cb func(t *testing.T, path string) *T) *T {
563595
t.Helper()
564596
mounts, cleanup := getMounts(ctx, t, sn, key)
565597
defer cleanup()
@@ -577,24 +609,32 @@ func tryStatPath(ctx context.Context, t *testing.T, sn *mergeSnapshotter, key, p
577609
}
578610
}
579611
if upperdir != "" {
580-
st = trySyscallStat(t, filepath.Join(upperdir, path))
581-
if st != nil {
582-
return st
612+
r := cb(t, filepath.Join(upperdir, path))
613+
if r != nil {
614+
return r
583615
}
584616
}
585617
for _, lowerdir := range lowerdirs {
586-
st = trySyscallStat(t, filepath.Join(lowerdir, path))
587-
if st != nil {
588-
return st
618+
r := cb(t, filepath.Join(lowerdir, path))
619+
if r != nil {
620+
return r
589621
}
590622
}
591623
return nil
592624
}
593625

626+
var r *T
594627
withMount(ctx, t, sn, key, func(root string) {
595-
st = trySyscallStat(t, filepath.Join(root, path))
628+
r = cb(t, filepath.Join(root, path))
629+
})
630+
return r
631+
}
632+
633+
func tryStatPath(ctx context.Context, t *testing.T, sn *mergeSnapshotter, key, path string) *syscall.Stat_t {
634+
t.Helper()
635+
return pathCallback(ctx, t, sn, key, path, func(t *testing.T, path string) *syscall.Stat_t {
636+
return trySyscallStat(t, path)
596637
})
597-
return st
598638
}
599639

600640
func statPath(ctx context.Context, t *testing.T, sn *mergeSnapshotter, key, path string) (st *syscall.Stat_t) {
@@ -610,3 +650,36 @@ func requireRoot(t *testing.T) {
610650
t.Skip("test requires root")
611651
}
612652
}
653+
654+
func setFileCap(path string, caps string) fstest.Applier {
655+
return applyFn(func(root string) error {
656+
path := filepath.Join(root, path)
657+
capSet, err := libcap.FromText(caps)
658+
if err != nil {
659+
return err
660+
}
661+
return capSet.SetFile(path)
662+
})
663+
}
664+
665+
func getFileCap(ctx context.Context, t *testing.T, sn *mergeSnapshotter, key, path string) string {
666+
t.Helper()
667+
caps := pathCallback(ctx, t, sn, key, path, func(t *testing.T, path string) *string {
668+
t.Helper()
669+
capSet, err := libcap.GetFile(path)
670+
if err != nil {
671+
require.ErrorIs(t, err, os.ErrNotExist)
672+
return nil
673+
}
674+
caps := capSet.String()
675+
return &caps
676+
})
677+
require.NotNil(t, caps)
678+
return *caps
679+
}
680+
681+
type applyFn func(root string) error
682+
683+
func (a applyFn) Apply(root string) error {
684+
return a(root)
685+
}

0 commit comments

Comments
 (0)