Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 23 additions & 39 deletions pkg/selectors/kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import (
"errors"
"fmt"
"net"
"net/netip"
"strconv"
"strings"

"github.com/cilium/tetragon/api/v1/tetragon"
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"

"github.com/cilium/tetragon/pkg/api/processapi"
"github.com/cilium/tetragon/pkg/config"
gt "github.com/cilium/tetragon/pkg/generictypes"
"github.com/cilium/tetragon/pkg/idtable"
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/cilium/tetragon/pkg/kernels"
"github.com/cilium/tetragon/pkg/mbset"
"github.com/cilium/tetragon/pkg/reader/namespace"
Expand Down Expand Up @@ -536,17 +538,18 @@ func writeMatchAddrsInMap(k *KernelSelectorState, values []string) error {
for _, v := range values {
addr, maskLen, err := parseAddr(v)
if err != nil {
return fmt.Errorf("MatchArgs value %s invalid: %w", v, err)
return fmt.Errorf("MatchArgs value %s invalid: parse IP: %w", v, err)
}
if len(addr) == 4 {

if len(addr) == net.IPv4len {
val := KernelLPMTrie4{prefixLen: maskLen, addr: binary.LittleEndian.Uint32(addr)}
m4[val] = struct{}{}
} else if len(addr) == 16 {
} else if len(addr) == net.IPv6len {
val := KernelLPMTrie6{prefixLen: maskLen}
copy(val.addr[:], addr)
m6[val] = struct{}{}
} else {
return fmt.Errorf("MatchArgs value %s invalid: should be either 4 or 16 bytes long", v)
return fmt.Errorf("MatchArgs value '%s' invalid: should be either 4 or 16 bytes long", v)
}
}
// write the map ids into the selector
Expand Down Expand Up @@ -576,45 +579,26 @@ func getBase(v string) int {
}

func parseAddr(v string) ([]byte, uint32, error) {
ipaddr := net.ParseIP(v)
if ipaddr != nil {
ipaddr4 := ipaddr.To4()
if ipaddr4 != nil {
return ipaddr4, 32, nil
if strings.Contains(v, "/") {
ipAddr, ipNet, err := net.ParseCIDR(v)
if err != nil {
return nil, 0, fmt.Errorf("CIDR is invalid: %w", err)
}
ipaddr6 := ipaddr.To16()
if ipaddr6 != nil {
return ipaddr6, 128, nil

maskLen, maxMaskLen := ipNet.Mask.Size()
if maxMaskLen == net.IPv6len*8 {
return ipAddr.To16(), uint32(maskLen), nil
}
return nil, 0, errors.New("IP address is not valid: does not parse as IPv4 or IPv6")
}
vParts := strings.Split(v, "/")
if len(vParts) != 2 {
return nil, 0, errors.New("IP address is not valid: should be in format ADDR or ADDR/MASKLEN")
}
ipaddr = net.ParseIP(vParts[0])
if ipaddr == nil {
return nil, 0, errors.New("IP CIDR is not valid: address part does not parse as IPv4 or IPv6")

return ipAddr.To4(), uint32(maskLen), nil
}
maskLen, err := strconv.ParseUint(vParts[1], 10, 32)

ipAddr, err := netip.ParseAddr(v)
if err != nil {
return nil, 0, errors.New("IP CIDR is not valid: mask part does not parse")
}
ipaddr4 := ipaddr.To4()
if ipaddr4 != nil {
if maskLen <= 32 {
return ipaddr4, uint32(maskLen), nil
}
return nil, 0, errors.New("IP CIDR is not valid: IPv4 mask len must be <= 32")
}
ipaddr6 := ipaddr.To16()
if ipaddr6 != nil {
if maskLen <= 128 {
return ipaddr6, uint32(maskLen), nil
}
return nil, 0, errors.New("IP CIDR is not valid: IPv6 mask len must be <= 128")
return nil, 0, fmt.Errorf("IP address is invalid: %w", err)
}
return nil, 0, errors.New("IP CIDR is not valid: address part does not parse")

return ipAddr.AsSlice(), uint32(ipAddr.BitLen()), nil
}

func writeMatchValues(k *KernelSelectorState, values []string, ty, op uint32) error {
Expand Down
89 changes: 88 additions & 1 deletion pkg/selectors/kernel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import (
"strings"
"testing"

"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/stretchr/testify/require"

"github.com/cilium/tetragon/pkg/config"
gt "github.com/cilium/tetragon/pkg/generictypes"
"github.com/cilium/tetragon/pkg/idtable"
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
)

func TestWriteSelectorUint32(t *testing.T) {
Expand Down Expand Up @@ -1007,3 +1009,88 @@ func TestReturnSelectorArgIntActionFollowfd(t *testing.T) {
t.Errorf("\ngot: %v\nexp: %v\n", b[:expectedLen], expected[:expectedLen])
}
}

func TestParseAddr(t *testing.T) {
tests := map[string]struct {
addrStr string
expectedAddr []byte
expectedMaskLen uint32
expectedErr string
}{
"invalid address format": {
addrStr: "1.2.3.4/16/16",
expectedErr: "CIDR is invalid",
},
"invalid ipv4 cidr": {
addrStr: "a.b.c.d/16",
expectedErr: "CIDR is invalid",
},
"invalid ipv6 cidr": {
addrStr: "::gg/16",
expectedErr: "CIDR is invalid",
},
"invalid mask value": {
addrStr: "1.2.3.4/invalid",
expectedErr: "CIDR is invalid",
},
"invalid ipv4 mask len": {
addrStr: "1.2.3.4/33",
expectedErr: "CIDR is invalid",
},
"invalid ipv6 mask len": {
addrStr: "::1/256",
expectedErr: "CIDR is invalid",
},
"invalid ipv4 address": {
addrStr: "a.b.c.d",
expectedErr: "IP address is invalid",
},
"invalid ipv6 address": {
addrStr: "::gg",
expectedErr: "IP address is invalid",
},
"valid ipv4": {
addrStr: "1.2.3.4",
expectedAddr: []byte{1, 2, 3, 4},
expectedMaskLen: 32,
},
"valid ipv4 cidr": {
addrStr: "1.2.3.4/16",
expectedAddr: []byte{1, 2, 3, 4},
expectedMaskLen: 16,
},
"valid ipv6": {
addrStr: "0102::0304",
expectedAddr: []byte{1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4},
expectedMaskLen: 128,
},
"valid ipv6 cidr": {
addrStr: "0102::0304/64",
expectedAddr: []byte{1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4},
expectedMaskLen: 64,
},
"valid ipv4-mapped ipv6": {
addrStr: "::ffff:1.2.3.4",
expectedAddr: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 1, 2, 3, 4},
expectedMaskLen: 128,
},
"valid ipv4-mapped ipv6 cidr": {
addrStr: "::ffff:1.2.3.4/96",
expectedAddr: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 1, 2, 3, 4},
expectedMaskLen: 96,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
addr, maskLen, err := parseAddr(test.addrStr)
if test.expectedErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), test.expectedErr)
} else {
require.Equal(t, test.expectedAddr, addr)
require.Equal(t, test.expectedMaskLen, maskLen)
}
})
}
}
Loading