Skip to content

Commit 128c588

Browse files
author
Zhou Hao
authored
Merge pull request #636 from kinvolk/dongsu/test-path-match-type
validation: add a new test for NSPathMatchTypeError
2 parents 9b65419 + 1fb00d9 commit 128c588

File tree

2 files changed

+106
-16
lines changed

2 files changed

+106
-16
lines changed

validation/linux_ns_path.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,6 @@ import (
1414
"github.com/opencontainers/runtime-tools/validation/util"
1515
)
1616

17-
func getRuntimeToolsNamespace(ns string) string {
18-
// Deal with exceptional cases of "net" and "mnt", because those strings
19-
// cannot be recognized by mapStrToNamespace(), which actually expects
20-
// "network" and "mount" respectively.
21-
switch ns {
22-
case "net":
23-
return "network"
24-
case "mnt":
25-
return "mount"
26-
}
27-
28-
// In other cases, return just the original string
29-
return ns
30-
}
31-
3217
func waitForState(stateCheckFunc func() error) error {
3318
timeout := 3 * time.Second
3419
alarm := time.After(timeout)
@@ -104,7 +89,7 @@ func checkNamespacePath(unsharePid int, ns string) error {
10489
return fmt.Errorf("cannot get the default generator: %v", err)
10590
}
10691

107-
rtns := getRuntimeToolsNamespace(ns)
92+
rtns := util.GetRuntimeToolsNamespace(ns)
10893
g.AddOrReplaceLinuxNamespace(rtns, unshareNsPath)
10994

11095
return util.RuntimeOutsideValidate(g, func(config *rspec.Spec, state *rspec.State) error {

validation/linux_ns_path_type.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
"runtime"
7+
"syscall"
8+
9+
"github.com/mndrix/tap-go"
10+
rspec "github.com/opencontainers/runtime-spec/specs-go"
11+
"github.com/opencontainers/runtime-tools/specerror"
12+
"github.com/opencontainers/runtime-tools/validation/util"
13+
)
14+
15+
func checkNSPathMatchType(t *tap.T, ns, wrongNs string) error {
16+
// Deliberately set ns path with a wrong namespace, to check if the runtime
17+
// returns error when running with the wrong namespace path.
18+
unshareNsPath := fmt.Sprintf("/proc/self/ns/%s", wrongNs)
19+
20+
g, err := util.GetDefaultGenerator()
21+
if err != nil {
22+
return fmt.Errorf("cannot get default config from generator: %v", err)
23+
}
24+
25+
rtns := util.GetRuntimeToolsNamespace(ns)
26+
g.AddOrReplaceLinuxNamespace(rtns, unshareNsPath)
27+
28+
err = util.RuntimeOutsideValidate(g, nil)
29+
30+
t.Ok(err != nil, fmt.Sprintf("got error when setting a wrong namespace path %q with type %s", unshareNsPath, rtns))
31+
if err == nil {
32+
rfcError, errRfc := specerror.NewRFCError(specerror.NSPathMatchTypeError,
33+
fmt.Errorf("got no error when setting a wrong namespace path %q with type %s", unshareNsPath, rtns),
34+
rspec.Version)
35+
if errRfc != nil {
36+
return fmt.Errorf("cannot get new rfcError: %v", errRfc)
37+
}
38+
diagnostic := map[string]string{
39+
"expected": fmt.Sprintf("err == %v", err),
40+
"actual": "err == nil",
41+
"namespace type": rtns,
42+
"level": rfcError.Level.String(),
43+
"reference": rfcError.Reference,
44+
}
45+
t.YAML(diagnostic)
46+
47+
return fmt.Errorf("cannot validate path with wrong type")
48+
}
49+
50+
return nil
51+
}
52+
53+
func testNSPathMatchType(t *tap.T, ns, unshareOpt, wrongNs string) error {
54+
// Calling 'unshare' (part of util-linux) is easier than doing it from
55+
// Golang: mnt namespaces cannot be unshared from multithreaded
56+
// programs.
57+
cmd := exec.Command("unshare", unshareOpt, "--fork", "sleep", "10000")
58+
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
59+
err := cmd.Start()
60+
if err != nil {
61+
return fmt.Errorf("cannot run unshare: %s", err)
62+
}
63+
defer func() {
64+
if cmd.Process != nil {
65+
cmd.Process.Kill()
66+
}
67+
cmd.Wait()
68+
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
69+
}()
70+
if cmd.Process == nil {
71+
return fmt.Errorf("process failed to start")
72+
}
73+
74+
return checkNSPathMatchType(t, ns, wrongNs)
75+
}
76+
77+
func main() {
78+
t := tap.New()
79+
t.Header(0)
80+
81+
cases := []struct {
82+
name string
83+
unshareOpt string
84+
wrongname string
85+
}{
86+
{"cgroup", "--cgroup", "ipc"},
87+
{"ipc", "--ipc", "mnt"},
88+
{"mnt", "--mount", "net"},
89+
{"net", "--net", "pid"},
90+
{"pid", "--pid", "user"},
91+
{"user", "--user", "uts"},
92+
{"uts", "--uts", "cgroup"},
93+
}
94+
95+
for _, c := range cases {
96+
if "linux" != runtime.GOOS {
97+
t.Skip(1, fmt.Sprintf("linux-specific namespace test: %s", c))
98+
}
99+
100+
err := testNSPathMatchType(t, c.name, c.unshareOpt, c.wrongname)
101+
t.Ok(err == nil, fmt.Sprintf("namespace path matches with type %s", c.name))
102+
}
103+
104+
t.AutoPlan()
105+
}

0 commit comments

Comments
 (0)