Skip to content

Commit bbfac72

Browse files
author
s00613818
committed
fix 714-plugin add netns validation reinforcement
Signed-off-by: s00613818 <[email protected]>
1 parent 54f1587 commit bbfac72

File tree

4 files changed

+88
-13
lines changed

4 files changed

+88
-13
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ go 1.14
55
require (
66
github.com/onsi/ginkgo/v2 v2.1.3
77
github.com/onsi/gomega v1.17.0
8+
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
9+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da
810
)

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl
4141
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
4242
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
4343
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
44+
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
45+
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
4446
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
4547
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
4648
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -63,6 +65,7 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w
6365
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6466
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6567
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
68+
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6669
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6770
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
6871
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

pkg/skel/skel.go

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,26 @@ import (
2424
"io/ioutil"
2525
"log"
2626
"os"
27+
"runtime"
2728
"strings"
2829

2930
"github.com/containernetworking/cni/pkg/types"
3031
"github.com/containernetworking/cni/pkg/utils"
3132
"github.com/containernetworking/cni/pkg/version"
33+
"github.com/vishvananda/netns"
34+
"golang.org/x/sys/unix"
3235
)
3336

3437
// CmdArgs captures all the arguments passed in to the plugin
3538
// via both env vars and stdin
3639
type CmdArgs struct {
37-
ContainerID string
38-
Netns string
39-
IfName string
40-
Args string
41-
Path string
42-
StdinData []byte
40+
ContainerID string
41+
Netns string
42+
IfName string
43+
Args string
44+
Path string
45+
NetnsOverride string
46+
StdinData []byte
4347
}
4448

4549
type dispatcher struct {
@@ -55,7 +59,7 @@ type dispatcher struct {
5559
type reqForCmdEntry map[string]bool
5660

5761
func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, *types.Error) {
58-
var cmd, contID, netns, ifName, args, path string
62+
var cmd, contID, netns, ifName, args, path, netnsOverride string
5963

6064
vars := []struct {
6165
name string
@@ -116,6 +120,15 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, *types.Error) {
116120
"DEL": true,
117121
},
118122
},
123+
{
124+
"CNI_NETNS_OVERRIDE",
125+
&netnsOverride,
126+
reqForCmdEntry{
127+
"ADD": false,
128+
"CHECK": false,
129+
"DEL": false,
130+
},
131+
},
119132
}
120133

121134
argsMissing := make([]string, 0)
@@ -143,12 +156,13 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, *types.Error) {
143156
}
144157

145158
cmdArgs := &CmdArgs{
146-
ContainerID: contID,
147-
Netns: netns,
148-
IfName: ifName,
149-
Args: args,
150-
Path: path,
151-
StdinData: stdinData,
159+
ContainerID: contID,
160+
Netns: netns,
161+
IfName: ifName,
162+
Args: args,
163+
Path: path,
164+
StdinData: stdinData,
165+
NetnsOverride: netnsOverride,
152166
}
153167
return cmd, cmdArgs, nil
154168
}
@@ -190,6 +204,39 @@ func validateConfig(jsonBytes []byte) *types.Error {
190204
return nil
191205
}
192206

207+
// Returns an object representing the current OS thread's network namespace
208+
func getCurrentNS() (netns.NsHandle, error) {
209+
// Lock the thread in case other goroutine executes in it and changes its
210+
// network namespace after getCurrentThreadNetNSPath(), otherwise it might
211+
// return an unexpected network namespace.
212+
runtime.LockOSThread()
213+
defer runtime.UnlockOSThread()
214+
return netns.GetFromPath(getCurrentThreadNetNSPath())
215+
}
216+
217+
func getCurrentThreadNetNSPath() string {
218+
// /proc/self/ns/net returns the namespace of the main thread, not
219+
// of whatever thread this goroutine is running on. Make sure we
220+
// use the thread's net namespace since the thread is switching around
221+
return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
222+
}
223+
224+
func checkNetNS(nsPath string) (bool, *types.Error) {
225+
ns, err := netns.GetFromPath(nsPath)
226+
if err != nil {
227+
return false, nil
228+
}
229+
defer ns.Close()
230+
231+
pluginNS, err := getCurrentNS()
232+
if err != nil {
233+
return false, types.NewError(types.ErrInvalidNetNS, "get plugin's netns failed", "")
234+
}
235+
defer pluginNS.Close()
236+
237+
return pluginNS.Equal(ns), nil
238+
}
239+
193240
func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) *types.Error {
194241
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
195242
if err != nil {
@@ -217,6 +264,17 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error,
217264
switch cmd {
218265
case "ADD":
219266
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdAdd)
267+
if err != nil {
268+
return err
269+
}
270+
if strings.ToUpper(cmdArgs.NetnsOverride) != "TRUE" || cmdArgs.NetnsOverride != "1" {
271+
isPluginNetNS, checkErr := checkNetNS(cmdArgs.Netns)
272+
if checkErr != nil {
273+
return checkErr
274+
} else if isPluginNetNS {
275+
return types.NewError(types.ErrInvalidNetNS, "plugin's netns and netns from CNI_NETNS should not be the same", "")
276+
}
277+
}
220278
case "CHECK":
221279
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
222280
if err != nil {
@@ -241,6 +299,17 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error,
241299
return types.NewError(types.ErrIncompatibleCNIVersion, "plugin version does not allow CHECK", "")
242300
case "DEL":
243301
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel)
302+
if err != nil {
303+
return err
304+
}
305+
if strings.ToUpper(cmdArgs.NetnsOverride) != "TRUE" || cmdArgs.NetnsOverride != "1" {
306+
isPluginNetNS, checkErr := checkNetNS(cmdArgs.Netns)
307+
if checkErr != nil {
308+
return checkErr
309+
} else if isPluginNetNS {
310+
return types.NewError(types.ErrInvalidNetNS, "plugin's netns and netns from CNI_NETNS should not be the same", "")
311+
}
312+
}
244313
case "VERSION":
245314
if err := versionInfo.Encode(t.Stdout); err != nil {
246315
return types.NewError(types.ErrIOFailure, err.Error(), "")

pkg/types/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ const (
165165
ErrIOFailure // 5
166166
ErrDecodingFailure // 6
167167
ErrInvalidNetworkConfig // 7
168+
ErrInvalidNetNS // 8
168169
ErrTryAgainLater uint = 11
169170
ErrInternal uint = 999
170171
)

0 commit comments

Comments
 (0)