Gracefully handle missing xfrm modules

If xfrm modules cannot be loaded:
- Create netlink.Handle only for ROUTE socket
- Reject local join on overlay secure network

Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
Alessandro Boch 2016-06-15 13:07:52 -07:00
parent b39f13f80e
commit 117131c41b
6 changed files with 36 additions and 10 deletions

View File

@ -3,6 +3,7 @@ package overlay
import (
"fmt"
"net"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/driverapi"
@ -31,6 +32,12 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
return fmt.Errorf("cannot join secure network: encryption keys not present")
}
nlh := ns.NlHandle()
if n.secure && !nlh.SupportsNetlinkFamily(syscall.NETLINK_XFRM) {
return fmt.Errorf("cannot join secure network: required modules to install IPSEC rules are missing on host")
}
s := n.getSubnetforIP(ep.addr)
if s == nil {
return fmt.Errorf("could not find subnet for endpoint %s", eid)
@ -65,8 +72,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err)
}
nlh := ns.NlHandle()
// Set the container interface and its peer MTU to 1450 to allow
// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
// outer UDP(8) + vxlan header(8))

View File

@ -284,7 +284,7 @@ func populateVNITbl() {
}
defer ns.Close()
nlh, err := netlink.NewHandleAt(ns)
nlh, err := netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE)
if err != nil {
logrus.Errorf("Could not open netlink handle during vni population for ns %s: %v", path, err)
return nil

View File

@ -3,6 +3,7 @@ package overlay
import (
"fmt"
"strings"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/netutils"
@ -128,7 +129,7 @@ func deleteVxlanByVNI(path string, vni uint32) error {
}
defer ns.Close()
nlh, err = netlink.NewHandleAt(ns)
nlh, err = netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE)
if err != nil {
return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err)
}

View File

@ -3,6 +3,8 @@ package ns
import (
"fmt"
"os"
"os/exec"
"strings"
"sync"
"syscall"
@ -24,7 +26,7 @@ func Init() {
if err != nil {
log.Errorf("could not get initial namespace: %v", err)
}
initNl, err = netlink.NewHandle()
initNl, err = netlink.NewHandle(getSupportedNlFamilies()...)
if err != nil {
log.Errorf("could not create netlink handle on initial namespace: %v", err)
}
@ -32,6 +34,7 @@ func Init() {
// SetNamespace sets the initial namespace handler
func SetNamespace() error {
initOnce.Do(Init)
if err := netns.Set(initNs); err != nil {
linkInfo, linkErr := getLink()
if linkErr != nil {
@ -62,3 +65,22 @@ func NlHandle() *netlink.Handle {
initOnce.Do(Init)
return initNl
}
func getSupportedNlFamilies() []int {
fams := []int{syscall.NETLINK_ROUTE}
if err := loadXfrmModules(); err != nil {
log.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
return fams
}
return append(fams, syscall.NETLINK_XFRM)
}
func loadXfrmModules() error {
if out, err := exec.Command("modprobe", "-va", "xfrm_user").CombinedOutput(); err != nil {
return fmt.Errorf("Running modprobe xfrm_user failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
}
if out, err := exec.Command("modprobe", "-va", "xfrm_algo").CombinedOutput(); err != nil {
return fmt.Errorf("Running modprobe xfrm_algo failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
}
return nil
}

View File

@ -30,7 +30,6 @@ var (
gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
nsOnce sync.Once
)
// The networkNamespace type is the linux implementation of the Sandbox
@ -196,7 +195,7 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
}
defer sboxNs.Close()
n.nlHandle, err = netlink.NewHandleAt(sboxNs)
n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE)
if err != nil {
return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
}
@ -238,7 +237,7 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
}
defer sboxNs.Close()
n.nlHandle, err = netlink.NewHandleAt(sboxNs)
n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE)
if err != nil {
return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
}
@ -326,7 +325,6 @@ func (n *networkNamespace) InvokeFunc(f func()) error {
// InitOSContext initializes OS context while configuring network resources
func InitOSContext() func() {
nsOnce.Do(ns.Init)
runtime.LockOSThread()
if err := ns.SetNamespace(); err != nil {
log.Error(err)

View File

@ -197,7 +197,7 @@ func TestDisableIPv6DAD(t *testing.T) {
LinkAttrs: netlink.LinkAttrs{Name: "sideA"},
PeerName: "sideB",
}
nlh, err := netlink.NewHandle()
nlh, err := netlink.NewHandle(syscall.NETLINK_ROUTE)
if err != nil {
t.Fatal(err)
}