mirror of https://github.com/docker/docs.git
Bump libcontainer to 08b5415ffa3769ff7c1d2f673f613
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
de41640435
commit
6bd3e6357c
|
|
@ -42,7 +42,7 @@ clone git github.com/endophage/gotuf 9bcdad0308e34a49f38448b8ad436ad8860825ce
|
||||||
clone git github.com/jfrazelle/go 6e461eb70cb4187b41a84e9a567d7137bdbe0f16
|
clone git github.com/jfrazelle/go 6e461eb70cb4187b41a84e9a567d7137bdbe0f16
|
||||||
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
|
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
|
||||||
|
|
||||||
clone git github.com/opencontainers/runc v0.0.4 # libcontainer
|
clone git github.com/opencontainers/runc 08b5415ffa3769ff7c1d2f673f61382d69aabb7d # libcontainer
|
||||||
# libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh)
|
# libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh)
|
||||||
clone git github.com/coreos/go-systemd v3
|
clone git github.com/coreos/go-systemd v3
|
||||||
clone git github.com/godbus/dbus v2
|
clone git github.com/godbus/dbus v2
|
||||||
|
|
|
||||||
|
|
@ -32,20 +32,20 @@ struct describing how the container is to be created. A sample would look simil
|
||||||
config := &configs.Config{
|
config := &configs.Config{
|
||||||
Rootfs: rootfs,
|
Rootfs: rootfs,
|
||||||
Capabilities: []string{
|
Capabilities: []string{
|
||||||
"CHOWN",
|
"CAP_CHOWN",
|
||||||
"DAC_OVERRIDE",
|
"CAP_DAC_OVERRIDE",
|
||||||
"FSETID",
|
"CAP_FSETID",
|
||||||
"FOWNER",
|
"CAP_FOWNER",
|
||||||
"MKNOD",
|
"CAP_MKNOD",
|
||||||
"NET_RAW",
|
"CAP_NET_RAW",
|
||||||
"SETGID",
|
"CAP_SETGID",
|
||||||
"SETUID",
|
"CAP_SETUID",
|
||||||
"SETFCAP",
|
"CAP_SETFCAP",
|
||||||
"SETPCAP",
|
"CAP_SETPCAP",
|
||||||
"NET_BIND_SERVICE",
|
"CAP_NET_BIND_SERVICE",
|
||||||
"SYS_CHROOT",
|
"CAP_SYS_CHROOT",
|
||||||
"KILL",
|
"CAP_KILL",
|
||||||
"AUDIT_WRITE",
|
"CAP_AUDIT_WRITE",
|
||||||
},
|
},
|
||||||
Namespaces: configs.Namespaces([]configs.Namespace{
|
Namespaces: configs.Namespaces([]configs.Namespace{
|
||||||
{Type: configs.NEWNS},
|
{Type: configs.NEWNS},
|
||||||
|
|
|
||||||
|
|
@ -12,44 +12,44 @@ import (
|
||||||
const allCapabilityTypes = capability.CAPS | capability.BOUNDS
|
const allCapabilityTypes = capability.CAPS | capability.BOUNDS
|
||||||
|
|
||||||
var capabilityList = map[string]capability.Cap{
|
var capabilityList = map[string]capability.Cap{
|
||||||
"SETPCAP": capability.CAP_SETPCAP,
|
"CAP_SETPCAP": capability.CAP_SETPCAP,
|
||||||
"SYS_MODULE": capability.CAP_SYS_MODULE,
|
"CAP_SYS_MODULE": capability.CAP_SYS_MODULE,
|
||||||
"SYS_RAWIO": capability.CAP_SYS_RAWIO,
|
"CAP_SYS_RAWIO": capability.CAP_SYS_RAWIO,
|
||||||
"SYS_PACCT": capability.CAP_SYS_PACCT,
|
"CAP_SYS_PACCT": capability.CAP_SYS_PACCT,
|
||||||
"SYS_ADMIN": capability.CAP_SYS_ADMIN,
|
"CAP_SYS_ADMIN": capability.CAP_SYS_ADMIN,
|
||||||
"SYS_NICE": capability.CAP_SYS_NICE,
|
"CAP_SYS_NICE": capability.CAP_SYS_NICE,
|
||||||
"SYS_RESOURCE": capability.CAP_SYS_RESOURCE,
|
"CAP_SYS_RESOURCE": capability.CAP_SYS_RESOURCE,
|
||||||
"SYS_TIME": capability.CAP_SYS_TIME,
|
"CAP_SYS_TIME": capability.CAP_SYS_TIME,
|
||||||
"SYS_TTY_CONFIG": capability.CAP_SYS_TTY_CONFIG,
|
"CAP_SYS_TTY_CONFIG": capability.CAP_SYS_TTY_CONFIG,
|
||||||
"MKNOD": capability.CAP_MKNOD,
|
"CAP_MKNOD": capability.CAP_MKNOD,
|
||||||
"AUDIT_WRITE": capability.CAP_AUDIT_WRITE,
|
"CAP_AUDIT_WRITE": capability.CAP_AUDIT_WRITE,
|
||||||
"AUDIT_CONTROL": capability.CAP_AUDIT_CONTROL,
|
"CAP_AUDIT_CONTROL": capability.CAP_AUDIT_CONTROL,
|
||||||
"MAC_OVERRIDE": capability.CAP_MAC_OVERRIDE,
|
"CAP_MAC_OVERRIDE": capability.CAP_MAC_OVERRIDE,
|
||||||
"MAC_ADMIN": capability.CAP_MAC_ADMIN,
|
"CAP_MAC_ADMIN": capability.CAP_MAC_ADMIN,
|
||||||
"NET_ADMIN": capability.CAP_NET_ADMIN,
|
"CAP_NET_ADMIN": capability.CAP_NET_ADMIN,
|
||||||
"SYSLOG": capability.CAP_SYSLOG,
|
"CAP_SYSLOG": capability.CAP_SYSLOG,
|
||||||
"CHOWN": capability.CAP_CHOWN,
|
"CAP_CHOWN": capability.CAP_CHOWN,
|
||||||
"NET_RAW": capability.CAP_NET_RAW,
|
"CAP_NET_RAW": capability.CAP_NET_RAW,
|
||||||
"DAC_OVERRIDE": capability.CAP_DAC_OVERRIDE,
|
"CAP_DAC_OVERRIDE": capability.CAP_DAC_OVERRIDE,
|
||||||
"FOWNER": capability.CAP_FOWNER,
|
"CAP_FOWNER": capability.CAP_FOWNER,
|
||||||
"DAC_READ_SEARCH": capability.CAP_DAC_READ_SEARCH,
|
"CAP_DAC_READ_SEARCH": capability.CAP_DAC_READ_SEARCH,
|
||||||
"FSETID": capability.CAP_FSETID,
|
"CAP_FSETID": capability.CAP_FSETID,
|
||||||
"KILL": capability.CAP_KILL,
|
"CAP_KILL": capability.CAP_KILL,
|
||||||
"SETGID": capability.CAP_SETGID,
|
"CAP_SETGID": capability.CAP_SETGID,
|
||||||
"SETUID": capability.CAP_SETUID,
|
"CAP_SETUID": capability.CAP_SETUID,
|
||||||
"LINUX_IMMUTABLE": capability.CAP_LINUX_IMMUTABLE,
|
"CAP_LINUX_IMMUTABLE": capability.CAP_LINUX_IMMUTABLE,
|
||||||
"NET_BIND_SERVICE": capability.CAP_NET_BIND_SERVICE,
|
"CAP_NET_BIND_SERVICE": capability.CAP_NET_BIND_SERVICE,
|
||||||
"NET_BROADCAST": capability.CAP_NET_BROADCAST,
|
"CAP_NET_BROADCAST": capability.CAP_NET_BROADCAST,
|
||||||
"IPC_LOCK": capability.CAP_IPC_LOCK,
|
"CAP_IPC_LOCK": capability.CAP_IPC_LOCK,
|
||||||
"IPC_OWNER": capability.CAP_IPC_OWNER,
|
"CAP_IPC_OWNER": capability.CAP_IPC_OWNER,
|
||||||
"SYS_CHROOT": capability.CAP_SYS_CHROOT,
|
"CAP_SYS_CHROOT": capability.CAP_SYS_CHROOT,
|
||||||
"SYS_PTRACE": capability.CAP_SYS_PTRACE,
|
"CAP_SYS_PTRACE": capability.CAP_SYS_PTRACE,
|
||||||
"SYS_BOOT": capability.CAP_SYS_BOOT,
|
"CAP_SYS_BOOT": capability.CAP_SYS_BOOT,
|
||||||
"LEASE": capability.CAP_LEASE,
|
"CAP_LEASE": capability.CAP_LEASE,
|
||||||
"SETFCAP": capability.CAP_SETFCAP,
|
"CAP_SETFCAP": capability.CAP_SETFCAP,
|
||||||
"WAKE_ALARM": capability.CAP_WAKE_ALARM,
|
"CAP_WAKE_ALARM": capability.CAP_WAKE_ALARM,
|
||||||
"BLOCK_SUSPEND": capability.CAP_BLOCK_SUSPEND,
|
"CAP_BLOCK_SUSPEND": capability.CAP_BLOCK_SUSPEND,
|
||||||
"AUDIT_READ": capability.CAP_AUDIT_READ,
|
"CAP_AUDIT_READ": capability.CAP_AUDIT_READ,
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCapWhitelist(caps []string) (*whitelist, error) {
|
func newCapWhitelist(caps []string) (*whitelist, error) {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ package cgroups
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -105,12 +104,12 @@ type Mount struct {
|
||||||
Subsystems []string
|
Subsystems []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Mount) GetThisCgroupDir() (string, error) {
|
func (m Mount) GetThisCgroupDir(cgroups map[string]string) (string, error) {
|
||||||
if len(m.Subsystems) == 0 {
|
if len(m.Subsystems) == 0 {
|
||||||
return "", fmt.Errorf("no subsystem for mount")
|
return "", fmt.Errorf("no subsystem for mount")
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetThisCgroupDir(m.Subsystems[0])
|
return getControllerPath(m.Subsystems[0], cgroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCgroupMounts() ([]Mount, error) {
|
func GetCgroupMounts() ([]Mount, error) {
|
||||||
|
|
@ -176,23 +175,22 @@ func GetAllSubsystems() ([]string, error) {
|
||||||
|
|
||||||
// Returns the relative path to the cgroup docker is running in.
|
// Returns the relative path to the cgroup docker is running in.
|
||||||
func GetThisCgroupDir(subsystem string) (string, error) {
|
func GetThisCgroupDir(subsystem string) (string, error) {
|
||||||
f, err := os.Open("/proc/self/cgroup")
|
cgroups, err := ParseCgroupFile("/proc/self/cgroup")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return ParseCgroupFile(subsystem, f)
|
return getControllerPath(subsystem, cgroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInitCgroupDir(subsystem string) (string, error) {
|
func GetInitCgroupDir(subsystem string) (string, error) {
|
||||||
f, err := os.Open("/proc/1/cgroup")
|
|
||||||
|
cgroups, err := ParseCgroupFile("/proc/1/cgroup")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return ParseCgroupFile(subsystem, f)
|
return getControllerPath(subsystem, cgroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadProcsFile(dir string) ([]int, error) {
|
func ReadProcsFile(dir string) ([]int, error) {
|
||||||
|
|
@ -219,23 +217,40 @@ func ReadProcsFile(dir string) ([]int, error) {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseCgroupFile(subsystem string, r io.Reader) (string, error) {
|
func ParseCgroupFile(path string) (map[string]string, error) {
|
||||||
s := bufio.NewScanner(r)
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
s := bufio.NewScanner(f)
|
||||||
|
cgroups := make(map[string]string)
|
||||||
|
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
if err := s.Err(); err != nil {
|
if err := s.Err(); err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
text := s.Text()
|
text := s.Text()
|
||||||
parts := strings.Split(text, ":")
|
parts := strings.Split(text, ":")
|
||||||
|
|
||||||
for _, subs := range strings.Split(parts[1], ",") {
|
for _, subs := range strings.Split(parts[1], ",") {
|
||||||
if subs == subsystem || subs == cgroupNamePrefix+subsystem {
|
cgroups[subs] = parts[2]
|
||||||
return parts[2], nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return cgroups, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getControllerPath(subsystem string, cgroups map[string]string) (string, error) {
|
||||||
|
|
||||||
|
if p, ok := cgroups[subsystem]; ok {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if p, ok := cgroups[cgroupNamePrefix+subsystem]; ok {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
return "", NewNotFoundError(subsystem)
|
return "", NewNotFoundError(subsystem)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
package configs
|
package configs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
|
)
|
||||||
|
|
||||||
type Mount struct {
|
type Mount struct {
|
||||||
// Source path for the mount.
|
// Source path for the mount.
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
|
|
@ -13,6 +21,9 @@ type Mount struct {
|
||||||
// Mount flags.
|
// Mount flags.
|
||||||
Flags int `json:"flags"`
|
Flags int `json:"flags"`
|
||||||
|
|
||||||
|
// Propagation Flags
|
||||||
|
PropagationFlags []int `json:"propagation_flags"`
|
||||||
|
|
||||||
// Mount data applied to the mount.
|
// Mount data applied to the mount.
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
|
|
||||||
|
|
@ -25,3 +36,40 @@ type Mount struct {
|
||||||
// Optional Command to be run after Source is mounted.
|
// Optional Command to be run after Source is mounted.
|
||||||
PostmountCmds []Command `json:"postmount_cmds"`
|
PostmountCmds []Command `json:"postmount_cmds"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Mount) Remount(rootfs string) error {
|
||||||
|
var (
|
||||||
|
dest = m.Destination
|
||||||
|
)
|
||||||
|
if !strings.HasPrefix(dest, rootfs) {
|
||||||
|
dest = filepath.Join(rootfs, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the mount operation followed by additional mounts required to take care
|
||||||
|
// of propagation flags.
|
||||||
|
func (m *Mount) MountPropagate(rootfs string, mountLabel string) error {
|
||||||
|
var (
|
||||||
|
dest = m.Destination
|
||||||
|
data = label.FormatMountLabel(m.Data, mountLabel)
|
||||||
|
)
|
||||||
|
if !strings.HasPrefix(dest, rootfs) {
|
||||||
|
dest = filepath.Join(rootfs, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pflag := range m.PropagationFlags {
|
||||||
|
if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -423,7 +423,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.criuSwrk(nil, req, criuOpts)
|
err = c.criuSwrk(nil, req, criuOpts, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -516,6 +516,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
||||||
FileLocks: proto.Bool(criuOpts.FileLocks),
|
FileLocks: proto.Bool(criuOpts.FileLocks),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range c.config.Mounts {
|
for _, m := range c.config.Mounts {
|
||||||
switch m.Device {
|
switch m.Device {
|
||||||
case "bind":
|
case "bind":
|
||||||
|
|
@ -573,14 +574,36 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.criuSwrk(process, req, criuOpts)
|
err = c.criuSwrk(process, req, criuOpts, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts) error {
|
func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
|
||||||
|
if err := c.cgroupManager.Apply(pid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := fmt.Sprintf("/proc/%d/cgroup", pid)
|
||||||
|
cgroupsPaths, err := cgroups.ParseCgroupFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for c, p := range cgroupsPaths {
|
||||||
|
cgroupRoot := &criurpc.CgroupRoot{
|
||||||
|
Ctrl: proto.String(c),
|
||||||
|
Path: proto.String(p),
|
||||||
|
}
|
||||||
|
req.Opts.CgRoot = append(req.Opts.CgRoot, cgroupRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, applyCgroups bool) error {
|
||||||
fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
|
fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -614,6 +637,13 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if applyCgroups {
|
||||||
|
err := c.criuApplyCgroups(cmd.Process.Pid, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var extFds []string
|
var extFds []string
|
||||||
if process != nil {
|
if process != nil {
|
||||||
extFds, err = getPipeFds(cmd.Process.Pid)
|
extFds, err = getPipeFds(cmd.Process.Pid)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -14,10 +15,10 @@ import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/opencontainers/runc/libcontainer/netlink"
|
|
||||||
"github.com/opencontainers/runc/libcontainer/system"
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
"github.com/opencontainers/runc/libcontainer/user"
|
"github.com/opencontainers/runc/libcontainer/user"
|
||||||
"github.com/opencontainers/runc/libcontainer/utils"
|
"github.com/opencontainers/runc/libcontainer/utils"
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
type initType string
|
type initType string
|
||||||
|
|
@ -186,7 +187,17 @@ func setupUser(config *initConfig) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// change the permissions on the STDIO of the current process so that when the user
|
||||||
|
// is changed for the container, it's STDIO of the process matches the user.
|
||||||
|
for _, fd := range []uintptr{
|
||||||
|
os.Stdin.Fd(),
|
||||||
|
os.Stderr.Fd(),
|
||||||
|
os.Stdout.Fd(),
|
||||||
|
} {
|
||||||
|
if err := syscall.Fchown(int(fd), execUser.Uid, execUser.Gid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
suppGroups := append(execUser.Sgids, addGroups...)
|
suppGroups := append(execUser.Sgids, addGroups...)
|
||||||
if err := syscall.Setgroups(suppGroups); err != nil {
|
if err := syscall.Setgroups(suppGroups); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -223,7 +234,30 @@ func setupNetwork(config *initConfig) error {
|
||||||
|
|
||||||
func setupRoute(config *configs.Config) error {
|
func setupRoute(config *configs.Config) error {
|
||||||
for _, config := range config.Routes {
|
for _, config := range config.Routes {
|
||||||
if err := netlink.AddRoute(config.Destination, config.Source, config.Gateway, config.InterfaceName); err != nil {
|
_, dst, err := net.ParseCIDR(config.Destination)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
src := net.ParseIP(config.Source)
|
||||||
|
if src == nil {
|
||||||
|
return fmt.Errorf("Invalid source for route: %s", config.Source)
|
||||||
|
}
|
||||||
|
gw := net.ParseIP(config.Gateway)
|
||||||
|
if gw == nil {
|
||||||
|
return fmt.Errorf("Invalid gateway for route: %s", config.Gateway)
|
||||||
|
}
|
||||||
|
l, err := netlink.LinkByName(config.InterfaceName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
route := &netlink.Route{
|
||||||
|
Scope: netlink.SCOPE_UNIVERSE,
|
||||||
|
Dst: dst,
|
||||||
|
Src: src,
|
||||||
|
Gw: gw,
|
||||||
|
LinkIndex: l.Attrs().Index,
|
||||||
|
}
|
||||||
|
if err := netlink.RouteAdd(route); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
|
|
||||||
Guillaume J. Charmes <guillaume@docker.com> (@creack)
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
// Packet netlink provide access to low level Netlink sockets and messages.
|
|
||||||
//
|
|
||||||
// Actual implementations are in:
|
|
||||||
// netlink_linux.go
|
|
||||||
// netlink_darwin.go
|
|
||||||
package netlink
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrWrongSockType = errors.New("Wrong socket type")
|
|
||||||
ErrShortResponse = errors.New("Got short response from netlink")
|
|
||||||
ErrInterfaceExists = errors.New("Network interface already exists")
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Route is a subnet associated with the interface to reach it.
|
|
||||||
type Route struct {
|
|
||||||
*net.IPNet
|
|
||||||
Iface *net.Interface
|
|
||||||
Default bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// An IfAddr defines IP network settings for a given network interface
|
|
||||||
type IfAddr struct {
|
|
||||||
Iface *net.Interface
|
|
||||||
IP net.IP
|
|
||||||
IPNet *net.IPNet
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +0,0 @@
|
||||||
// +build arm ppc64 ppc64le
|
|
||||||
|
|
||||||
package netlink
|
|
||||||
|
|
||||||
func ifrDataByte(b byte) uint8 {
|
|
||||||
return uint8(b)
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
// +build !arm,!ppc64,!ppc64le
|
|
||||||
|
|
||||||
package netlink
|
|
||||||
|
|
||||||
func ifrDataByte(b byte) int8 {
|
|
||||||
return int8(b)
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
// +build !linux
|
|
||||||
|
|
||||||
package netlink
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrNotImplemented = errors.New("not implemented")
|
|
||||||
)
|
|
||||||
|
|
||||||
func NetworkGetRoutes() ([]Route, error) {
|
|
||||||
return nil, ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkLinkAdd(name string, linkType string) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkLinkDel(name string) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkLinkUp(iface *net.Interface) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddRoute(destination, source, gateway, device string) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddDefaultGw(ip, device string) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkSetMTU(iface *net.Interface, mtu int) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkSetTxQueueLen(iface *net.Interface, txQueueLen int) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkChangeName(iface *net.Interface, newName string) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkSetNsFd(iface *net.Interface, fd int) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkSetNsPid(iface *net.Interface, nspid int) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkSetMaster(iface, master *net.Interface) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetworkLinkDown(iface *net.Interface) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateBridge(name string, setMacAddr bool) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteBridge(name string) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddToBridge(iface, master *net.Interface) error {
|
|
||||||
return ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/opencontainers/runc/libcontainer/netlink"
|
|
||||||
"github.com/opencontainers/runc/libcontainer/utils"
|
"github.com/opencontainers/runc/libcontainer/utils"
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
var strategies = map[string]networkStrategy{
|
var strategies = map[string]networkStrategy{
|
||||||
|
|
@ -93,11 +93,7 @@ func (l *loopback) create(n *network, nspid int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopback) initialize(config *network) error {
|
func (l *loopback) initialize(config *network) error {
|
||||||
iface, err := net.InterfaceByName("lo")
|
return netlink.LinkSetUp(&netlink.Device{netlink.LinkAttrs{Name: "lo"}})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return netlink.NetworkLinkUp(iface)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopback) attach(n *configs.Network) (err error) {
|
func (l *loopback) attach(n *configs.Network) (err error) {
|
||||||
|
|
@ -115,42 +111,36 @@ type veth struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *veth) detach(n *configs.Network) (err error) {
|
func (v *veth) detach(n *configs.Network) (err error) {
|
||||||
bridge, err := net.InterfaceByName(n.Bridge)
|
return netlink.LinkSetMaster(&netlink.Device{netlink.LinkAttrs{Name: n.HostInterfaceName}}, nil)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
host, err := net.InterfaceByName(n.HostInterfaceName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := netlink.DelFromBridge(host, bridge); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach a container network interface to an external network
|
// attach a container network interface to an external network
|
||||||
func (v *veth) attach(n *configs.Network) (err error) {
|
func (v *veth) attach(n *configs.Network) (err error) {
|
||||||
bridge, err := net.InterfaceByName(n.Bridge)
|
brl, err := netlink.LinkByName(n.Bridge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
host, err := net.InterfaceByName(n.HostInterfaceName)
|
br, ok := brl.(*netlink.Bridge)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Wrong device type %T", brl)
|
||||||
|
}
|
||||||
|
host, err := netlink.LinkByName(n.HostInterfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.AddToBridge(host, bridge); err != nil {
|
|
||||||
|
if err := netlink.LinkSetMaster(host, br); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkSetMTU(host, n.Mtu); err != nil {
|
if err := netlink.LinkSetMTU(host, n.Mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if n.HairpinMode {
|
if n.HairpinMode {
|
||||||
if err := netlink.SetHairpinMode(host, true); err != nil {
|
if err := netlink.LinkSetHairpin(host, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkLinkUp(host); err != nil {
|
if err := netlink.LinkSetUp(host); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,26 +153,32 @@ func (v *veth) create(n *network, nspid int) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
n.TempVethPeerName = tmpName
|
n.TempVethPeerName = tmpName
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
netlink.NetworkLinkDel(n.HostInterfaceName)
|
|
||||||
netlink.NetworkLinkDel(n.TempVethPeerName)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if n.Bridge == "" {
|
if n.Bridge == "" {
|
||||||
return fmt.Errorf("bridge is not specified")
|
return fmt.Errorf("bridge is not specified")
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkCreateVethPair(n.HostInterfaceName, n.TempVethPeerName, n.TxQueueLen); err != nil {
|
veth := &netlink.Veth{
|
||||||
|
LinkAttrs: netlink.LinkAttrs{
|
||||||
|
Name: n.HostInterfaceName,
|
||||||
|
TxQLen: n.TxQueueLen,
|
||||||
|
},
|
||||||
|
PeerName: n.TempVethPeerName,
|
||||||
|
}
|
||||||
|
if err := netlink.LinkAdd(veth); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
netlink.LinkDel(veth)
|
||||||
|
}
|
||||||
|
}()
|
||||||
if err := v.attach(&n.Network); err != nil {
|
if err := v.attach(&n.Network); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
child, err := net.InterfaceByName(n.TempVethPeerName)
|
child, err := netlink.LinkByName(n.TempVethPeerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return netlink.NetworkSetNsPid(child, nspid)
|
return netlink.LinkSetNsPid(child, nspid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *veth) generateTempPeerName() (string, error) {
|
func (v *veth) generateTempPeerName() (string, error) {
|
||||||
|
|
@ -194,53 +190,68 @@ func (v *veth) initialize(config *network) error {
|
||||||
if peer == "" {
|
if peer == "" {
|
||||||
return fmt.Errorf("peer is not specified")
|
return fmt.Errorf("peer is not specified")
|
||||||
}
|
}
|
||||||
child, err := net.InterfaceByName(peer)
|
child, err := netlink.LinkByName(peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkLinkDown(child); err != nil {
|
if err := netlink.LinkSetDown(child); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkChangeName(child, config.Name); err != nil {
|
if err := netlink.LinkSetName(child, config.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// get the interface again after we changed the name as the index also changes.
|
// get the interface again after we changed the name as the index also changes.
|
||||||
if child, err = net.InterfaceByName(config.Name); err != nil {
|
if child, err = netlink.LinkByName(config.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if config.MacAddress != "" {
|
if config.MacAddress != "" {
|
||||||
if err := netlink.NetworkSetMacAddress(child, config.MacAddress); err != nil {
|
mac, err := net.ParseMAC(config.MacAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := netlink.LinkSetHardwareAddr(child, mac); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ip, ipNet, err := net.ParseCIDR(config.Address)
|
ip, err := netlink.ParseAddr(config.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkLinkAddIp(child, ip, ipNet); err != nil {
|
if err := netlink.AddrAdd(child, ip); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if config.IPv6Address != "" {
|
if config.IPv6Address != "" {
|
||||||
if ip, ipNet, err = net.ParseCIDR(config.IPv6Address); err != nil {
|
ip6, err := netlink.ParseAddr(config.IPv6Address)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkLinkAddIp(child, ip, ipNet); err != nil {
|
if err := netlink.AddrAdd(child, ip6); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkSetMTU(child, config.Mtu); err != nil {
|
if err := netlink.LinkSetMTU(child, config.Mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := netlink.NetworkLinkUp(child); err != nil {
|
if err := netlink.LinkSetUp(child); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if config.Gateway != "" {
|
if config.Gateway != "" {
|
||||||
if err := netlink.AddDefaultGw(config.Gateway, config.Name); err != nil {
|
gw := net.ParseIP(config.Gateway)
|
||||||
|
if err := netlink.RouteAdd(&netlink.Route{
|
||||||
|
Scope: netlink.SCOPE_UNIVERSE,
|
||||||
|
LinkIndex: child.Attrs().Index,
|
||||||
|
Gw: gw,
|
||||||
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if config.IPv6Gateway != "" {
|
if config.IPv6Gateway != "" {
|
||||||
if err := netlink.AddDefaultGw(config.IPv6Gateway, config.Name); err != nil {
|
gw := net.ParseIP(config.IPv6Gateway)
|
||||||
|
if err := netlink.RouteAdd(&netlink.Route{
|
||||||
|
Scope: netlink.SCOPE_UNIVERSE,
|
||||||
|
LinkIndex: child.Attrs().Index,
|
||||||
|
Gw: gw,
|
||||||
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,6 @@ func mountCmd(cmd configs.Command) error {
|
||||||
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
var (
|
var (
|
||||||
dest = m.Destination
|
dest = m.Destination
|
||||||
data = label.FormatMountLabel(m.Data, mountLabel)
|
|
||||||
)
|
)
|
||||||
if !strings.HasPrefix(dest, rootfs) {
|
if !strings.HasPrefix(dest, rootfs) {
|
||||||
dest = filepath.Join(rootfs, dest)
|
dest = filepath.Join(rootfs, dest)
|
||||||
|
|
@ -107,12 +106,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), "")
|
return m.MountPropagate(rootfs, mountLabel)
|
||||||
case "mqueue":
|
case "mqueue":
|
||||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), ""); err != nil {
|
if err := m.MountPropagate(rootfs, mountLabel); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return label.SetFileLabel(dest, mountLabel)
|
return label.SetFileLabel(dest, mountLabel)
|
||||||
|
|
@ -123,7 +122,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
|
if err := m.MountPropagate(rootfs, mountLabel); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if stat != nil {
|
if stat != nil {
|
||||||
|
|
@ -136,12 +135,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
|
return m.MountPropagate(rootfs, mountLabel)
|
||||||
case "securityfs":
|
case "securityfs":
|
||||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
|
return m.MountPropagate(rootfs, mountLabel)
|
||||||
case "bind":
|
case "bind":
|
||||||
stat, err := os.Stat(m.Source)
|
stat, err := os.Stat(m.Source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -162,13 +161,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
|
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
|
if err := m.MountPropagate(rootfs, mountLabel); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if m.Flags&syscall.MS_RDONLY != 0 {
|
// bind mount won't change mount options, we need remount to make mount options effective.
|
||||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
|
if err := m.Remount(rootfs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if m.Relabel != "" {
|
if m.Relabel != "" {
|
||||||
if err := label.Validate(m.Relabel); err != nil {
|
if err := label.Validate(m.Relabel); err != nil {
|
||||||
|
|
@ -179,11 +177,6 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.Flags&syscall.MS_PRIVATE != 0 {
|
|
||||||
if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "cgroup":
|
case "cgroup":
|
||||||
binds, err := getCgroupMounts(m)
|
binds, err := getCgroupMounts(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -197,11 +190,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmpfs := &configs.Mount{
|
tmpfs := &configs.Mount{
|
||||||
Source: "tmpfs",
|
Source: "tmpfs",
|
||||||
Device: "tmpfs",
|
Device: "tmpfs",
|
||||||
Destination: m.Destination,
|
Destination: m.Destination,
|
||||||
Flags: defaultMountFlags,
|
Flags: defaultMountFlags,
|
||||||
Data: "mode=755",
|
Data: "mode=755",
|
||||||
|
PropagationFlags: m.PropagationFlags,
|
||||||
}
|
}
|
||||||
if err := mountToRootfs(tmpfs, rootfs, mountLabel); err != nil {
|
if err := mountToRootfs(tmpfs, rootfs, mountLabel); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -236,8 +230,11 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
}
|
}
|
||||||
if m.Flags&syscall.MS_RDONLY != 0 {
|
if m.Flags&syscall.MS_RDONLY != 0 {
|
||||||
// remount cgroup root as readonly
|
// remount cgroup root as readonly
|
||||||
rootfsCgroup := filepath.Join(rootfs, m.Destination)
|
mcgrouproot := &configs.Mount{
|
||||||
if err := syscall.Mount("", rootfsCgroup, "", defaultMountFlags|syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil {
|
Destination: m.Destination,
|
||||||
|
Flags: defaultMountFlags | syscall.MS_RDONLY,
|
||||||
|
}
|
||||||
|
if err := mcgrouproot.Remount(rootfs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -253,10 +250,15 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cgroupPaths, err := cgroups.ParseCgroupFile("/proc/self/cgroup")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var binds []*configs.Mount
|
var binds []*configs.Mount
|
||||||
|
|
||||||
for _, mm := range mounts {
|
for _, mm := range mounts {
|
||||||
dir, err := mm.GetThisCgroupDir()
|
dir, err := mm.GetThisCgroupDir(cgroupPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -265,10 +267,11 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
binds = append(binds, &configs.Mount{
|
binds = append(binds, &configs.Mount{
|
||||||
Device: "bind",
|
Device: "bind",
|
||||||
Source: filepath.Join(mm.Mountpoint, relDir),
|
Source: filepath.Join(mm.Mountpoint, relDir),
|
||||||
Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
|
Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
|
||||||
Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags,
|
Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags,
|
||||||
|
PropagationFlags: m.PropagationFlags,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue