Skip to content

Commit e1a888f

Browse files
committed
golangci-lint: Forbid stdlib net.Interface* functions
The Go stdlib `net.Interface*` family talks to the kernel over a netlink socket with no timeout, so it can block forever. This PR converts the two remaining offenders to `netlink/safenetlink` and add a forbidigo rule so new ones don't creep back in. Fixes: cilium#15051 Signed-off-by: Hadrien Patte <hadrien.patte@datadoghq.com>
1 parent 15de3b2 commit e1a888f

4 files changed

Lines changed: 22 additions & 12 deletions

File tree

.golangci.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ linters:
4747
- pattern: ^netlink\.(Handle\.)?(AddrList|BridgeVlanList|ChainList|ClassList|ConntrackTableList|DevLinkGetDeviceList|DevLinkGetAllPortList|DevlinkGetDeviceParams|FilterList|FouList|GenlFamilyList|GTPPDPList|LinkByName|LinkByAlias|LinkList|LinkSubscribeWithOptions|NeighList|NeighProxyList|NeighListExecute|LinkGetProtinfo|QdiscList|RdmaLinkList|RdmaLinkByName|RdmaLinkDel|RouteList|RouteListFiltered|RouteListFilteredIter|RouteSubscribeWithOptions|RuleList|RuleListFiltered|SocketGet|SocketDiagTCPInfo|SocketDiagTCP|SocketDiagUDPInfo|SocketDiagUDP|UnixSocketDiagInfo|UnixSocketDiag|SocketXDPGetInfo|SocketDiagXDP|VDPAGetDevList|VDPAGetDevConfigList|VDPAGetMGMTDevList|XfrmPolicyList|XfrmStateList)
4848
pkg: ^github.com/vishvananda/netlink$
4949
msg: Found netlink function which can return ErrDumpInterrupted. Use safenetlink package instead.
50+
# The stdlib net.Interface* functions query the kernel over a netlink
51+
# socket without a timeout, so they can block forever. See
52+
# https://github.com/cilium/cilium/issues/15051
53+
- pattern: ^net\.(Interfaces|InterfaceAddrs|InterfaceByIndex|InterfaceByName|Interface\.Addrs)$
54+
pkg: ^net$
55+
msg: 'Found stdlib net.Interface* function which can block forever, see https://github.com/cilium/cilium/issues/15051. Use the netlink or safenetlink package instead.'
5056
analyze-types: true
5157
goheader:
5258
values:

bugtool/cmd/configuration.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import (
77
"bytes"
88
"encoding/json"
99
"fmt"
10-
"net"
1110
"os"
1211
"path/filepath"
1312

1413
"github.com/cilium/cilium/pkg/components"
14+
"github.com/cilium/cilium/pkg/datapath/linux/safenetlink"
1515
"github.com/cilium/cilium/pkg/defaults"
1616
"github.com/cilium/cilium/pkg/mountinfo"
1717
)
@@ -314,18 +314,19 @@ func loadConfigFile(path string) (*BugtoolConfiguration, error) {
314314
// Listing tc filter/chain/classes requires specific interface names.
315315
// Commands are generated per-interface.
316316
func tcInterfaceCommands() []string {
317-
ifaces, err := net.Interfaces()
317+
links, err := safenetlink.LinkList()
318318
if err != nil {
319319
fmt.Fprintf(os.Stderr, "Failed to generate per interface tc commands: %s\n", fmt.Errorf("could not list network interfaces: %w", err))
320320
return nil
321321
}
322322
commands := []string{}
323-
for _, iface := range ifaces {
323+
for _, link := range links {
324+
name := link.Attrs().Name
324325
commands = append(commands,
325-
fmt.Sprintf("tc filter show dev %s ingress", iface.Name),
326-
fmt.Sprintf("tc filter show dev %s egress", iface.Name),
327-
fmt.Sprintf("tc chain show dev %s", iface.Name),
328-
fmt.Sprintf("tc class show dev %s", iface.Name))
326+
fmt.Sprintf("tc filter show dev %s ingress", name),
327+
fmt.Sprintf("tc filter show dev %s egress", name),
328+
fmt.Sprintf("tc chain show dev %s", name),
329+
fmt.Sprintf("tc class show dev %s", name))
329330
}
330331
return commands
331332
}

pkg/auth/mutual_authhandler_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,11 @@ func getRandomOpenPort(t *testing.T) int {
444444
}
445445

446446
func GetLoopBackIP(t *testing.T) string {
447-
addrs, err := net.InterfaceAddrs()
447+
// Test-only helper, so blocking forever on the stdlib netlink socket is not
448+
// a concern here. Retrieving addresses of all interfaces at once has no
449+
// netlink equivalent, and the netlink package is Linux-only while this test
450+
// is not.
451+
addrs, err := net.InterfaceAddrs() //nolint:forbidigo
448452
if err != nil {
449453
t.Fatalf("failed to get interface addresses: %v", err)
450454
}

pkg/datapath/l2responder/l2responder.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"errors"
99
"fmt"
1010
"log/slog"
11-
"net"
1211
"net/netip"
1312

1413
"github.com/cilium/hive/cell"
@@ -101,7 +100,7 @@ func NewL2ResponderReconciler(params params) *l2ResponderReconciler {
101100
if params.AddRemMcMACFunc == nil {
102101
log := params.Logger
103102
params.AddRemMcMACFunc = func(ifindex int, m mac.MAC, add bool) error {
104-
ifi, err := net.InterfaceByIndex(ifindex)
103+
link, err := netlink.LinkByIndex(ifindex)
105104
if err != nil {
106105
return fmt.Errorf("interface by index %d: %w", ifindex, err)
107106
}
@@ -113,10 +112,10 @@ func NewL2ResponderReconciler(params params) *l2ResponderReconciler {
113112
solAddr := netip.AddrFrom16(raw)
114113

115114
if add {
116-
return multicast.JoinGroup(log, ifi.Name, solAddr)
115+
return multicast.JoinGroup(log, link.Attrs().Name, solAddr)
117116
}
118117

119-
return multicast.LeaveGroup(log, ifi.Name, solAddr)
118+
return multicast.LeaveGroup(log, link.Attrs().Name, solAddr)
120119
}
121120
}
122121

0 commit comments

Comments
 (0)