|
@@ -5,7 +5,6 @@ import (
|
|
|
"fmt"
|
|
|
"net"
|
|
|
"os"
|
|
|
- "os/exec"
|
|
|
"path/filepath"
|
|
|
"runtime"
|
|
|
"strconv"
|
|
@@ -18,7 +17,6 @@ import (
|
|
|
"github.com/docker/docker/libnetwork/ns"
|
|
|
"github.com/docker/docker/libnetwork/osl/kernel"
|
|
|
"github.com/docker/docker/libnetwork/types"
|
|
|
- "github.com/docker/docker/pkg/reexec"
|
|
|
"github.com/sirupsen/logrus"
|
|
|
"github.com/vishvananda/netlink"
|
|
|
"github.com/vishvananda/netns"
|
|
@@ -28,13 +26,11 @@ import (
|
|
|
const defaultPrefix = "/var/run/docker"
|
|
|
|
|
|
func init() {
|
|
|
- reexec.Register("set-ipv6", reexecSetIPv6)
|
|
|
-
|
|
|
// Lock main() to the initial thread to exclude the goroutines spawned
|
|
|
- // by func (*networkNamespace) InvokeFunc() from being scheduled onto
|
|
|
- // that thread. Changes to the network namespace of the initial thread
|
|
|
- // alter /proc/self/ns/net, which would break any code which
|
|
|
- // (incorrectly) assumes that that file is a handle to the network
|
|
|
+ // by func (*networkNamespace) InvokeFunc() or func setIPv6() below from
|
|
|
+ // being scheduled onto that thread. Changes to the network namespace of
|
|
|
+ // the initial thread alter /proc/self/ns/net, which would break any
|
|
|
+ // code which (incorrectly) assumes that that file is the network
|
|
|
// namespace for the thread it is currently executing on.
|
|
|
runtime.LockOSThread()
|
|
|
}
|
|
@@ -603,66 +599,65 @@ func (n *networkNamespace) checkLoV6() {
|
|
|
n.loV6Enabled = enable
|
|
|
}
|
|
|
|
|
|
-func reexecSetIPv6() {
|
|
|
- runtime.LockOSThread()
|
|
|
- defer runtime.UnlockOSThread()
|
|
|
-
|
|
|
- if len(os.Args) < 3 {
|
|
|
- logrus.Errorf("invalid number of arguments for %s", os.Args[0])
|
|
|
- os.Exit(1)
|
|
|
+func setIPv6(nspath, iface string, enable bool) error {
|
|
|
+ origns, err := netns.Get()
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to get current network namespace: %w", err)
|
|
|
}
|
|
|
+ defer origns.Close()
|
|
|
|
|
|
- ns, err := netns.GetFromPath(os.Args[1])
|
|
|
+ ns, err := netns.GetFromPath(nspath)
|
|
|
if err != nil {
|
|
|
- logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err)
|
|
|
- os.Exit(2)
|
|
|
+ return fmt.Errorf("failed get network namespace %q: %w", nspath, err)
|
|
|
}
|
|
|
defer ns.Close()
|
|
|
|
|
|
- if err = netns.Set(ns); err != nil {
|
|
|
- logrus.Errorf("setting into container netns %q failed: %v", os.Args[1], err)
|
|
|
- os.Exit(3)
|
|
|
- }
|
|
|
+ errCh := make(chan error, 1)
|
|
|
+ go func() {
|
|
|
+ defer close(errCh)
|
|
|
|
|
|
- var (
|
|
|
- action = "disable"
|
|
|
- value = byte('1')
|
|
|
- path = fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", os.Args[2])
|
|
|
- )
|
|
|
+ runtime.LockOSThread()
|
|
|
+ if err = netns.Set(ns); err != nil {
|
|
|
+ errCh <- fmt.Errorf("setting into container netns %q failed: %w", nspath, err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defer func() {
|
|
|
+ if err := netns.Set(origns); err != nil {
|
|
|
+ logrus.WithError(err).Error("libnetwork: restoring thread network namespace failed")
|
|
|
+ // The error is only fatal for the current thread. Keep this
|
|
|
+ // goroutine locked to the thread to make the runtime replace it
|
|
|
+ // with a clean thread once this goroutine returns.
|
|
|
+ } else {
|
|
|
+ runtime.UnlockOSThread()
|
|
|
+ }
|
|
|
+ }()
|
|
|
|
|
|
- if os.Args[3] == "true" {
|
|
|
- action = "enable"
|
|
|
- value = byte('0')
|
|
|
- }
|
|
|
+ var (
|
|
|
+ action = "disable"
|
|
|
+ value = byte('1')
|
|
|
+ path = fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", iface)
|
|
|
+ )
|
|
|
|
|
|
- if _, err := os.Stat(path); err != nil {
|
|
|
- if os.IsNotExist(err) {
|
|
|
- logrus.Warnf("file does not exist: %s : %v Has IPv6 been disabled in this node's kernel?", path, err)
|
|
|
- os.Exit(0)
|
|
|
+ if enable {
|
|
|
+ action = "enable"
|
|
|
+ value = '0'
|
|
|
}
|
|
|
- logrus.Errorf("failed to stat %s : %v", path, err)
|
|
|
- os.Exit(5)
|
|
|
- }
|
|
|
|
|
|
- if err = os.WriteFile(path, []byte{value, '\n'}, 0644); err != nil {
|
|
|
- logrus.Errorf("failed to %s IPv6 forwarding for container's interface %s: %v", action, os.Args[2], err)
|
|
|
- os.Exit(4)
|
|
|
- }
|
|
|
-
|
|
|
- os.Exit(0)
|
|
|
-}
|
|
|
+ if _, err := os.Stat(path); err != nil {
|
|
|
+ if os.IsNotExist(err) {
|
|
|
+ logrus.WithError(err).Warn("Cannot configure IPv6 forwarding on container interface. Has IPv6 been disabled in this node's kernel?")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ errCh <- err
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
-func setIPv6(path, iface string, enable bool) error {
|
|
|
- cmd := &exec.Cmd{
|
|
|
- Path: reexec.Self(),
|
|
|
- Args: append([]string{"set-ipv6"}, path, iface, strconv.FormatBool(enable)),
|
|
|
- Stdout: os.Stdout,
|
|
|
- Stderr: os.Stderr,
|
|
|
- }
|
|
|
- if err := cmd.Run(); err != nil {
|
|
|
- return fmt.Errorf("reexec to set IPv6 failed: %v", err)
|
|
|
- }
|
|
|
- return nil
|
|
|
+ if err = os.WriteFile(path, []byte{value, '\n'}, 0o644); err != nil {
|
|
|
+ errCh <- fmt.Errorf("failed to %s IPv6 forwarding for container's interface %s: %w", action, iface, err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ return <-errCh
|
|
|
}
|
|
|
|
|
|
// ApplyOSTweaks applies linux configs on the sandbox
|