github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/runsc/cmd/exec_test.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "os" 19 "testing" 20 21 "github.com/google/go-cmp/cmp" 22 "github.com/google/go-cmp/cmp/cmpopts" 23 specs "github.com/opencontainers/runtime-spec/specs-go" 24 "github.com/SagerNet/gvisor/pkg/abi/linux" 25 "github.com/SagerNet/gvisor/pkg/sentry/control" 26 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 27 "github.com/SagerNet/gvisor/pkg/urpc" 28 ) 29 30 func TestUser(t *testing.T) { 31 testCases := []struct { 32 input string 33 want user 34 wantErr bool 35 }{ 36 {input: "0", want: user{kuid: 0, kgid: 0}}, 37 {input: "7", want: user{kuid: 7, kgid: 0}}, 38 {input: "49:343", want: user{kuid: 49, kgid: 343}}, 39 {input: "0:2401", want: user{kuid: 0, kgid: 2401}}, 40 {input: "", wantErr: true}, 41 {input: "foo", wantErr: true}, 42 {input: ":123", wantErr: true}, 43 {input: "1:2:3", wantErr: true}, 44 } 45 46 for _, tc := range testCases { 47 var u user 48 if err := u.Set(tc.input); err != nil && tc.wantErr { 49 // We got an error and wanted one. 50 continue 51 } else if err == nil && tc.wantErr { 52 t.Errorf("user.Set(%s): got no error, but wanted one", tc.input) 53 } else if err != nil && !tc.wantErr { 54 t.Errorf("user.Set(%s): got error %v, but wanted none", tc.input, err) 55 } else if u != tc.want { 56 t.Errorf("user.Set(%s): got %+v, but wanted %+v", tc.input, u, tc.want) 57 } 58 } 59 } 60 61 func TestCLIArgs(t *testing.T) { 62 testCases := []struct { 63 ex Exec 64 argv []string 65 expected control.ExecArgs 66 }{ 67 { 68 ex: Exec{ 69 cwd: "/foo/bar", 70 user: user{kuid: 0, kgid: 0}, 71 extraKGIDs: []string{"1", "2", "3"}, 72 caps: []string{"CAP_DAC_OVERRIDE"}, 73 processPath: "", 74 }, 75 argv: []string{"ls", "/"}, 76 expected: control.ExecArgs{ 77 Argv: []string{"ls", "/"}, 78 WorkingDirectory: "/foo/bar", 79 FilePayload: urpc.FilePayload{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}, 80 KUID: 0, 81 KGID: 0, 82 ExtraKGIDs: []auth.KGID{1, 2, 3}, 83 Capabilities: &auth.TaskCapabilities{ 84 BoundingCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 85 EffectiveCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 86 InheritableCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 87 PermittedCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 88 }, 89 }, 90 }, 91 } 92 93 for _, tc := range testCases { 94 e, err := tc.ex.argsFromCLI(tc.argv, true) 95 if err != nil { 96 t.Errorf("argsFromCLI(%+v): got error: %+v", tc.ex, err) 97 } else if !cmp.Equal(*e, tc.expected, cmpopts.IgnoreUnexported(os.File{})) { 98 t.Errorf("argsFromCLI(%+v): got %+v, but expected %+v", tc.ex, *e, tc.expected) 99 } 100 } 101 } 102 103 func TestJSONArgs(t *testing.T) { 104 testCases := []struct { 105 // ex is provided to make sure it is overridden by p. 106 ex Exec 107 p specs.Process 108 expected control.ExecArgs 109 }{ 110 { 111 ex: Exec{ 112 cwd: "/baz/quux", 113 user: user{kuid: 1, kgid: 1}, 114 extraKGIDs: []string{"4", "5", "6"}, 115 caps: []string{"CAP_SETGID"}, 116 processPath: "/bin/foo", 117 }, 118 p: specs.Process{ 119 User: specs.User{UID: 0, GID: 0, AdditionalGids: []uint32{1, 2, 3}}, 120 Args: []string{"ls", "/"}, 121 Cwd: "/foo/bar", 122 Capabilities: &specs.LinuxCapabilities{ 123 Bounding: []string{"CAP_DAC_OVERRIDE"}, 124 Effective: []string{"CAP_DAC_OVERRIDE"}, 125 Inheritable: []string{"CAP_DAC_OVERRIDE"}, 126 Permitted: []string{"CAP_DAC_OVERRIDE"}, 127 }, 128 }, 129 expected: control.ExecArgs{ 130 Argv: []string{"ls", "/"}, 131 WorkingDirectory: "/foo/bar", 132 FilePayload: urpc.FilePayload{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}, 133 KUID: 0, 134 KGID: 0, 135 ExtraKGIDs: []auth.KGID{1, 2, 3}, 136 Capabilities: &auth.TaskCapabilities{ 137 BoundingCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 138 EffectiveCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 139 InheritableCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 140 PermittedCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), 141 }, 142 }, 143 }, 144 } 145 146 for _, tc := range testCases { 147 e, err := argsFromProcess(&tc.p, true) 148 if err != nil { 149 t.Errorf("argsFromProcess(%+v): got error: %+v", tc.p, err) 150 } else if !cmp.Equal(*e, tc.expected, cmpopts.IgnoreUnexported(os.File{})) { 151 t.Errorf("argsFromProcess(%+v): got %+v, but expected %+v", tc.p, *e, tc.expected) 152 } 153 } 154 }