Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/contributors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,7 @@ users:
pocopepe:
name: Viju Sanjai
email: avijusanjai@gmail.com
Anand-240:
name: Anand Prakash Srivastava
email: anandprakashsrivastava68@gmail.com

10 changes: 6 additions & 4 deletions pkg/unikontainers/unikontainers.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,10 +698,12 @@ func (u *Unikontainer) Exec(metrics m.Writer) error {

// pivot
_, err = findNS(u.Spec.Linux.Namespaces, specs.MountNamespace)
// We just want to check if a mount namespace was define din the list
// Therefore, if there was no error and the mount namespace was found
// we can pivot.
withPivot := err != nil
// Only pivot if a mount namespace entry is actually present in the
// spec, either to join (err is nil) or to create (err is
// ErrNotExistingNS). If the entry is missing entirely, no new mount
// namespace gets created and we have to chroot instead, otherwise
// pivot_root would run against the caller's own root filesystem.
withPivot := err == nil || errors.Is(err, ErrNotExistingNS)
err = changeRoot(rootfsParams.MonRootfs, withPivot)
if err != nil {
return err
Expand Down
42 changes: 42 additions & 0 deletions pkg/unikontainers/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package unikontainers

import (
"encoding/json"
"errors"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -240,6 +241,47 @@ func TestRemovePreservesOrder(t *testing.T) {
assert.Equal(t, []string{"b", "c", "d"}, result)
}

// TestFindNS checks that findNS lets callers tell apart a namespace type
// missing from the spec from one that's present but not created yet
// (empty path). Exec() relies on that distinction to decide when it's
// safe to pivot_root.
func TestFindNS(t *testing.T) {
t.Parallel()

t.Run("namespace type missing from spec", func(t *testing.T) {
t.Parallel()
namespaces := []specs.LinuxNamespace{
{Type: specs.NetworkNamespace, Path: "/dummy/path"},
}
path, err := findNS(namespaces, specs.MountNamespace)
assert.Empty(t, path)
assert.Error(t, err)
assert.False(t, errors.Is(err, ErrNotExistingNS), "a namespace type absent from the spec must not be reported as ErrNotExistingNS")
})

t.Run("namespace present without a path yet", func(t *testing.T) {
t.Parallel()
namespaces := []specs.LinuxNamespace{
{Type: specs.MountNamespace, Path: ""},
}
path, err := findNS(namespaces, specs.MountNamespace)
assert.Empty(t, path)
assert.ErrorIs(t, err, ErrNotExistingNS)
})

t.Run("namespace present with an existing path", func(t *testing.T) {
t.Parallel()
nsPath := t.TempDir()

namespaces := []specs.LinuxNamespace{
{Type: specs.MountNamespace, Path: nsPath},
}
path, err := findNS(namespaces, specs.MountNamespace)
assert.NoError(t, err)
assert.Equal(t, nsPath, path)
})
}

func TestLoadSpec(t *testing.T) {
t.Run("load spec success", func(t *testing.T) {
t.Parallel()
Expand Down
Loading