github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/ns/init_linux.go (about) 1 package ns 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "strings" 8 "sync" 9 "syscall" 10 "time" 11 12 "github.com/sirupsen/logrus" 13 "github.com/vishvananda/netlink" 14 "github.com/vishvananda/netns" 15 ) 16 17 var ( 18 initNs netns.NsHandle 19 initNl *netlink.Handle 20 initOnce sync.Once 21 // NetlinkSocketsTimeout represents the default timeout duration for the sockets 22 NetlinkSocketsTimeout = 3 * time.Second 23 ) 24 25 // Init initializes a new network namespace 26 func Init() { 27 var err error 28 initNs, err = netns.Get() 29 if err != nil { 30 logrus.Errorf("could not get initial namespace: %v", err) 31 } 32 initNl, err = netlink.NewHandle(getSupportedNlFamilies()...) 33 if err != nil { 34 logrus.Errorf("could not create netlink handle on initial namespace: %v", err) 35 } 36 err = initNl.SetSocketTimeout(NetlinkSocketsTimeout) 37 if err != nil { 38 logrus.Warnf("Failed to set the timeout on the default netlink handle sockets: %v", err) 39 } 40 } 41 42 // SetNamespace sets the initial namespace handler 43 func SetNamespace() error { 44 initOnce.Do(Init) 45 if err := netns.Set(initNs); err != nil { 46 linkInfo, linkErr := getLink() 47 if linkErr != nil { 48 linkInfo = linkErr.Error() 49 } 50 return fmt.Errorf("failed to set to initial namespace, %v, initns fd %d: %v", linkInfo, initNs, err) 51 } 52 return nil 53 } 54 55 // ParseHandlerInt transforms the namespace handler into an integer 56 func ParseHandlerInt() int { 57 return int(getHandler()) 58 } 59 60 // GetHandler returns the namespace handler 61 func getHandler() netns.NsHandle { 62 initOnce.Do(Init) 63 return initNs 64 } 65 66 func getLink() (string, error) { 67 return os.Readlink(fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())) 68 } 69 70 // NlHandle returns the netlink handler 71 func NlHandle() *netlink.Handle { 72 initOnce.Do(Init) 73 return initNl 74 } 75 76 func getSupportedNlFamilies() []int { 77 fams := []int{syscall.NETLINK_ROUTE} 78 // NETLINK_XFRM test 79 if err := checkXfrmSocket(); err != nil { 80 logrus.Warnf("Could not load necessary modules for IPSEC rules: %v", err) 81 } else { 82 fams = append(fams, syscall.NETLINK_XFRM) 83 } 84 // NETLINK_NETFILTER test 85 if err := loadNfConntrackModules(); err != nil { 86 if checkNfSocket() != nil { 87 logrus.Warnf("Could not load necessary modules for Conntrack: %v", err) 88 } else { 89 fams = append(fams, syscall.NETLINK_NETFILTER) 90 } 91 } else { 92 fams = append(fams, syscall.NETLINK_NETFILTER) 93 } 94 95 return fams 96 } 97 98 // API check on required xfrm modules (xfrm_user, xfrm_algo) 99 func checkXfrmSocket() error { 100 fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_XFRM) 101 if err != nil { 102 return err 103 } 104 syscall.Close(fd) 105 return nil 106 } 107 108 func loadNfConntrackModules() error { 109 if out, err := exec.Command("modprobe", "-va", "nf_conntrack").CombinedOutput(); err != nil { 110 return fmt.Errorf("Running modprobe nf_conntrack failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err) 111 } 112 if out, err := exec.Command("modprobe", "-va", "nf_conntrack_netlink").CombinedOutput(); err != nil { 113 return fmt.Errorf("Running modprobe nf_conntrack_netlink failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err) 114 } 115 return nil 116 } 117 118 // API check on required nf_conntrack* modules (nf_conntrack, nf_conntrack_netlink) 119 func checkNfSocket() error { 120 fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_NETFILTER) 121 if err != nil { 122 return err 123 } 124 syscall.Close(fd) 125 return nil 126 }