Improve libcontainer namespace and cap format
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
bbc3c913a9
commit
412c081a9b
9 changed files with 128 additions and 206 deletions
|
@ -18,8 +18,8 @@ type Container struct {
|
||||||
WorkingDir string `json:"working_dir,omitempty"` // current working directory
|
WorkingDir string `json:"working_dir,omitempty"` // current working directory
|
||||||
Env []string `json:"environment,omitempty"` // environment to set
|
Env []string `json:"environment,omitempty"` // environment to set
|
||||||
Tty bool `json:"tty,omitempty"` // setup a proper tty or not
|
Tty bool `json:"tty,omitempty"` // setup a proper tty or not
|
||||||
Namespaces Namespaces `json:"namespaces,omitempty"` // namespaces to apply
|
Namespaces map[string]bool `json:"namespaces,omitempty"` // namespaces to apply
|
||||||
CapabilitiesMask Capabilities `json:"capabilities_mask,omitempty"` // capabilities to drop
|
CapabilitiesMask map[string]bool `json:"capabilities_mask,omitempty"` // capabilities to drop
|
||||||
Networks []*Network `json:"networks,omitempty"` // nil for host's network stack
|
Networks []*Network `json:"networks,omitempty"` // nil for host's network stack
|
||||||
Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups
|
Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups
|
||||||
Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux)
|
Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux)
|
||||||
|
|
|
@ -1,151 +1,62 @@
|
||||||
{
|
{
|
||||||
"mounts" : [
|
"namespaces": {
|
||||||
{
|
"NEWNET": true,
|
||||||
"type" : "devtmpfs"
|
"NEWPID": true,
|
||||||
}
|
"NEWIPC": true,
|
||||||
],
|
"NEWUTS": true,
|
||||||
"tty" : true,
|
"NEWNS": true
|
||||||
"environment" : [
|
},
|
||||||
"HOME=/",
|
"networks": [
|
||||||
"PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
|
{
|
||||||
"container=docker",
|
"gateway": "localhost",
|
||||||
"TERM=xterm-256color"
|
"type": "loopback",
|
||||||
],
|
"address": "127.0.0.1/0",
|
||||||
"hostname" : "koye",
|
"mtu": 1500
|
||||||
"cgroups" : {
|
},
|
||||||
"parent" : "docker",
|
{
|
||||||
"name" : "docker-koye"
|
"gateway": "172.17.42.1",
|
||||||
},
|
"context": {
|
||||||
"capabilities_mask" : [
|
"prefix": "veth",
|
||||||
{
|
"bridge": "docker0"
|
||||||
"value" : 8,
|
|
||||||
"key" : "SETPCAP",
|
|
||||||
"enabled" : false
|
|
||||||
},
|
},
|
||||||
{
|
"type": "veth",
|
||||||
"enabled" : false,
|
"address": "172.17.42.2/16",
|
||||||
"value" : 16,
|
"mtu": 1500
|
||||||
"key" : "SYS_MODULE"
|
}
|
||||||
},
|
],
|
||||||
{
|
"capabilities_mask": {
|
||||||
"value" : 17,
|
"SYSLOG": false,
|
||||||
"key" : "SYS_RAWIO",
|
"MKNOD": true,
|
||||||
"enabled" : false
|
"NET_ADMIN": false,
|
||||||
},
|
"MAC_ADMIN": false,
|
||||||
{
|
"MAC_OVERRIDE": false,
|
||||||
"key" : "SYS_PACCT",
|
"AUDIT_CONTROL": false,
|
||||||
"value" : 20,
|
"AUDIT_WRITE": false,
|
||||||
"enabled" : false
|
"SYS_TTY_CONFIG": false,
|
||||||
},
|
"SETPCAP": false,
|
||||||
{
|
"SYS_MODULE": false,
|
||||||
"value" : 21,
|
"SYS_RAWIO": false,
|
||||||
"key" : "SYS_ADMIN",
|
"SYS_PACCT": false,
|
||||||
"enabled" : false
|
"SYS_ADMIN": false,
|
||||||
},
|
"SYS_NICE": false,
|
||||||
{
|
"SYS_RESOURCE": false,
|
||||||
"value" : 23,
|
"SYS_TIME": false
|
||||||
"key" : "SYS_NICE",
|
},
|
||||||
"enabled" : false
|
"cgroups": {
|
||||||
},
|
"name": "docker-koye",
|
||||||
{
|
"parent": "docker"
|
||||||
"value" : 24,
|
},
|
||||||
"key" : "SYS_RESOURCE",
|
"hostname": "koye",
|
||||||
"enabled" : false
|
"environment": [
|
||||||
},
|
"HOME=/",
|
||||||
{
|
"PATH=PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin",
|
||||||
"key" : "SYS_TIME",
|
"container=docker",
|
||||||
"value" : 25,
|
"TERM=xterm-256color"
|
||||||
"enabled" : false
|
],
|
||||||
},
|
"tty": true,
|
||||||
{
|
"mounts": [
|
||||||
"enabled" : false,
|
{
|
||||||
"value" : 26,
|
"type": "devtmpfs"
|
||||||
"key" : "SYS_TTY_CONFIG"
|
}
|
||||||
},
|
]
|
||||||
{
|
|
||||||
"key" : "AUDIT_WRITE",
|
|
||||||
"value" : 29,
|
|
||||||
"enabled" : false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value" : 30,
|
|
||||||
"key" : "AUDIT_CONTROL",
|
|
||||||
"enabled" : false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"enabled" : false,
|
|
||||||
"key" : "MAC_OVERRIDE",
|
|
||||||
"value" : 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"enabled" : false,
|
|
||||||
"key" : "MAC_ADMIN",
|
|
||||||
"value" : 33
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key" : "NET_ADMIN",
|
|
||||||
"value" : 12,
|
|
||||||
"enabled" : false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value" : 27,
|
|
||||||
"key" : "MKNOD",
|
|
||||||
"enabled" : true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value" : 34,
|
|
||||||
"key" : "SYSLOG",
|
|
||||||
"enabled" : false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"networks" : [
|
|
||||||
{
|
|
||||||
"mtu" : 1500,
|
|
||||||
"address" : "127.0.0.1/0",
|
|
||||||
"type" : "loopback",
|
|
||||||
"gateway" : "localhost"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mtu" : 1500,
|
|
||||||
"address" : "172.17.42.2/16",
|
|
||||||
"type" : "veth",
|
|
||||||
"context" : {
|
|
||||||
"bridge" : "docker0",
|
|
||||||
"prefix" : "veth"
|
|
||||||
},
|
|
||||||
"gateway" : "172.17.42.1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"namespaces" : [
|
|
||||||
{
|
|
||||||
"key" : "NEWNS",
|
|
||||||
"value" : 131072,
|
|
||||||
"enabled" : true,
|
|
||||||
"file" : "mnt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key" : "NEWUTS",
|
|
||||||
"value" : 67108864,
|
|
||||||
"enabled" : true,
|
|
||||||
"file" : "uts"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"enabled" : true,
|
|
||||||
"file" : "ipc",
|
|
||||||
"key" : "NEWIPC",
|
|
||||||
"value" : 134217728
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file" : "pid",
|
|
||||||
"enabled" : true,
|
|
||||||
"value" : 536870912,
|
|
||||||
"key" : "NEWPID"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"enabled" : true,
|
|
||||||
"file" : "net",
|
|
||||||
"key" : "NEWNET",
|
|
||||||
"value" : 1073741824
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ func TestContainerJsonFormat(t *testing.T) {
|
||||||
|
|
||||||
var container *Container
|
var container *Container
|
||||||
if err := json.NewDecoder(f).Decode(&container); err != nil {
|
if err := json.NewDecoder(f).Decode(&container); err != nil {
|
||||||
t.Fatal("failed to decode container config")
|
t.Fatalf("failed to decode container config: %s", err)
|
||||||
}
|
}
|
||||||
if container.Hostname != "koye" {
|
if container.Hostname != "koye" {
|
||||||
t.Log("hostname is not set")
|
t.Log("hostname is not set")
|
||||||
|
@ -27,32 +27,32 @@ func TestContainerJsonFormat(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !container.Namespaces.Contains("NEWNET") {
|
if !container.Namespaces["NEWNET"] {
|
||||||
t.Log("namespaces should contain NEWNET")
|
t.Log("namespaces should contain NEWNET")
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.Namespaces.Contains("NEWUSER") {
|
if container.Namespaces["NEWUSER"] {
|
||||||
t.Log("namespaces should not contain NEWUSER")
|
t.Log("namespaces should not contain NEWUSER")
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !container.CapabilitiesMask.Contains("SYS_ADMIN") {
|
if _, exists := container.CapabilitiesMask["SYS_ADMIN"]; !exists {
|
||||||
t.Log("capabilities mask should contain SYS_ADMIN")
|
t.Log("capabilities mask should contain SYS_ADMIN")
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.CapabilitiesMask.Get("SYS_ADMIN").Enabled {
|
if container.CapabilitiesMask["SYS_ADMIN"] {
|
||||||
t.Log("SYS_ADMIN should not be enabled in capabilities mask")
|
t.Log("SYS_ADMIN should not be enabled in capabilities mask")
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !container.CapabilitiesMask.Get("MKNOD").Enabled {
|
if !container.CapabilitiesMask["MKNOD"] {
|
||||||
t.Log("MKNOD should be enabled in capabilities mask")
|
t.Log("MKNOD should be enabled in capabilities mask")
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.CapabilitiesMask.Contains("SYS_CHROOT") {
|
if container.CapabilitiesMask["SYS_CHROOT"] {
|
||||||
t.Log("capabilities mask should not contain SYS_CHROOT")
|
t.Log("capabilities mask should not contain SYS_CHROOT")
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,10 +159,12 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy
|
||||||
|
|
||||||
// GetNamespaceFlags parses the container's Namespaces options to set the correct
|
// GetNamespaceFlags parses the container's Namespaces options to set the correct
|
||||||
// flags on clone, unshare, and setns
|
// flags on clone, unshare, and setns
|
||||||
func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
|
||||||
for _, ns := range namespaces {
|
for key, enabled := range namespaces {
|
||||||
if ns.Enabled {
|
if enabled {
|
||||||
flag |= ns.Value
|
if ns := libcontainer.GetNamespace(key); ns != nil {
|
||||||
|
flag |= ns.Value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flag
|
return flag
|
||||||
|
|
|
@ -23,11 +23,13 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) (int, e
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nsv := range container.Namespaces {
|
for key, enabled := range container.Namespaces {
|
||||||
// skip the PID namespace on unshare because it it not supported
|
// skip the PID namespace on unshare because it it not supported
|
||||||
if nsv.Enabled && nsv.Key != "NEWPID" {
|
if enabled && key != "NEWPID" {
|
||||||
if err := system.Unshare(nsv.Value); err != nil {
|
if ns := libcontainer.GetNamespace(key); ns != nil {
|
||||||
return -1, err
|
if err := system.Unshare(ns.Value); err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +61,7 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) (int, e
|
||||||
|
|
||||||
// if the container has a new pid and mount namespace we need to
|
// if the container has a new pid and mount namespace we need to
|
||||||
// remount proc and sys to pick up the changes
|
// remount proc and sys to pick up the changes
|
||||||
if container.Namespaces.Contains("NEWNS") && container.Namespaces.Contains("NEWPID") {
|
if container.Namespaces["NEWNS"] && container.Namespaces["NEWPID"] {
|
||||||
pid, err := system.Fork()
|
pid, err := system.Fork()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
|
@ -102,13 +104,18 @@ dropAndExec:
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNsFds(pid int, container *libcontainer.Container) ([]uintptr, error) {
|
func getNsFds(pid int, container *libcontainer.Container) ([]uintptr, error) {
|
||||||
fds := make([]uintptr, len(container.Namespaces))
|
fds := []uintptr{}
|
||||||
for i, ns := range container.Namespaces {
|
|
||||||
f, err := os.OpenFile(filepath.Join("/proc/", strconv.Itoa(pid), "ns", ns.File), os.O_RDONLY, 0)
|
for key, enabled := range container.Namespaces {
|
||||||
if err != nil {
|
if enabled {
|
||||||
return fds, err
|
if ns := libcontainer.GetNamespace(key); ns != nil {
|
||||||
|
f, err := os.OpenFile(filepath.Join("/proc/", strconv.Itoa(pid), "ns", ns.File), os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fds, err
|
||||||
|
}
|
||||||
|
fds = append(fds, f.Fd())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fds[i] = f.Fd()
|
|
||||||
}
|
}
|
||||||
return fds, nil
|
return fds, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,6 @@ func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveC
|
||||||
return nil, libcontainer.ErrUnsupported
|
return nil, libcontainer.ErrUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package capabilities
|
package capabilities
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||||
"github.com/syndtr/gocapability/capability"
|
"github.com/syndtr/gocapability/capability"
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DropCapabilities drops capabilities for the current process based
|
// DropCapabilities drops capabilities for the current process based
|
||||||
|
@ -26,9 +27,11 @@ func DropCapabilities(container *libcontainer.Container) error {
|
||||||
// getCapabilitiesMask returns the specific cap mask values for the libcontainer types
|
// getCapabilitiesMask returns the specific cap mask values for the libcontainer types
|
||||||
func getCapabilitiesMask(container *libcontainer.Container) []capability.Cap {
|
func getCapabilitiesMask(container *libcontainer.Container) []capability.Cap {
|
||||||
drop := []capability.Cap{}
|
drop := []capability.Cap{}
|
||||||
for _, c := range container.CapabilitiesMask {
|
for key, enabled := range container.CapabilitiesMask {
|
||||||
if !c.Enabled {
|
if !enabled {
|
||||||
drop = append(drop, c.Value)
|
if c := libcontainer.GetCapability(key); c != nil {
|
||||||
|
drop = append(drop, c.Value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drop
|
return drop
|
||||||
|
|
|
@ -2,6 +2,7 @@ package libcontainer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/syndtr/gocapability/capability"
|
"github.com/syndtr/gocapability/capability"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,31 +39,30 @@ var (
|
||||||
namespaceList = Namespaces{}
|
namespaceList = Namespaces{}
|
||||||
|
|
||||||
capabilityList = Capabilities{
|
capabilityList = Capabilities{
|
||||||
{Key: "SETPCAP", Value: capability.CAP_SETPCAP, Enabled: false},
|
{Key: "SETPCAP", Value: capability.CAP_SETPCAP},
|
||||||
{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE, Enabled: false},
|
{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE},
|
||||||
{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO, Enabled: false},
|
{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO},
|
||||||
{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT, Enabled: false},
|
{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT},
|
||||||
{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN, Enabled: false},
|
{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN},
|
||||||
{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE, Enabled: false},
|
{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE},
|
||||||
{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE, Enabled: false},
|
{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE},
|
||||||
{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME, Enabled: false},
|
{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME},
|
||||||
{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG, Enabled: false},
|
{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG},
|
||||||
{Key: "MKNOD", Value: capability.CAP_MKNOD, Enabled: false},
|
{Key: "MKNOD", Value: capability.CAP_MKNOD},
|
||||||
{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE, Enabled: false},
|
{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE},
|
||||||
{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL, Enabled: false},
|
{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL},
|
||||||
{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE, Enabled: false},
|
{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE},
|
||||||
{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN, Enabled: false},
|
{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
|
||||||
{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN, Enabled: false},
|
{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
|
||||||
{Key: "SYSLOG", Value: capability.CAP_SYSLOG, Enabled: false},
|
{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Namespace struct {
|
Namespace struct {
|
||||||
Key string `json:"key,omitempty"`
|
Key string `json:"key,omitempty"`
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Value int `json:"value,omitempty"`
|
||||||
Value int `json:"value,omitempty"`
|
File string `json:"file,omitempty"`
|
||||||
File string `json:"file,omitempty"`
|
|
||||||
}
|
}
|
||||||
Namespaces []*Namespace
|
Namespaces []*Namespace
|
||||||
)
|
)
|
||||||
|
@ -98,9 +98,8 @@ func (n Namespaces) Get(ns string) *Namespace {
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Capability struct {
|
Capability struct {
|
||||||
Key string `json:"key,omitempty"`
|
Key string `json:"key,omitempty"`
|
||||||
Enabled bool `json:"enabled"`
|
Value capability.Cap `json:"value,omitempty"`
|
||||||
Value capability.Cap `json:"value,omitempty"`
|
|
||||||
}
|
}
|
||||||
Capabilities []*Capability
|
Capabilities []*Capability
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,11 +6,11 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
namespaceList = Namespaces{
|
namespaceList = Namespaces{
|
||||||
{Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt", Enabled: true},
|
{Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt"},
|
||||||
{Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts", Enabled: true},
|
{Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts"},
|
||||||
{Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc", Enabled: true},
|
{Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc"},
|
||||||
{Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user", Enabled: true},
|
{Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user"},
|
||||||
{Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid", Enabled: true},
|
{Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid"},
|
||||||
{Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net", Enabled: true},
|
{Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue