From 756cfa14a85eb37c1914ec04259ed572cf96b6bf Mon Sep 17 00:00:00 2001 From: Serguei Bezverkhi Date: Tue, 17 Dec 2019 18:02:00 -0500 Subject: [PATCH] Fix concatenated key set validation (#83) --- set.go | 39 +++++++++++++++++++++++------ set_test.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 set_test.go diff --git a/set.go b/set.go index 21173a2..2b9ee7e 100644 --- a/set.go +++ b/set.go @@ -26,6 +26,10 @@ import ( "golang.org/x/sys/unix" ) +// SetConcatTypeBits defines concatination bits, originally defined in +// https://git.netfilter.org/iptables/tree/iptables/nft.c?id=26753888720d8e7eb422ae4311348347f5a05cb4#n1002 +const SetConcatTypeBits = 6 + var allocSetID uint32 // SetDatatype represents a datatype declared by nft. @@ -434,15 +438,10 @@ func setsFromMsg(msg netlink.Message) (*Set, error) { set.IsMap = (flags & unix.NFTA_SET_TABLE) != 0 case unix.NFTA_SET_KEY_TYPE: nftMagic := ad.Uint32() - for _, dt := range nftDatatypes { - if nftMagic == dt.nftMagic { - set.KeyType = dt - break - } - } - if set.KeyType.nftMagic == 0 { - return nil, fmt.Errorf("could not determine key type %x", nftMagic) + if invalidMagic, ok := validateKeyType(nftMagic); !ok { + return nil, fmt.Errorf("could not determine key type %+v", invalidMagic) } + set.KeyType.nftMagic = nftMagic case unix.NFTA_SET_DATA_TYPE: nftMagic := ad.Uint32() // Special case for the data type verdict, in the message it is stored as 0xffffff00 but it is defined as 1 @@ -464,6 +463,30 @@ func setsFromMsg(msg netlink.Message) (*Set, error) { return &set, nil } +func validateKeyType(bits uint32) ([]uint32, bool) { + var unpackTypes []uint32 + var invalidTypes []uint32 + found := false + valid := true + for bits != 0 { + unpackTypes = append(unpackTypes, bits&0x3f) + bits = bits >> SetConcatTypeBits + } + for _, t := range unpackTypes { + for _, dt := range nftDatatypes { + if t == dt.nftMagic { + found = true + } + } + if !found { + invalidTypes = append(invalidTypes, t) + valid = false + } + found = false + } + return invalidTypes, valid +} + var elemHeaderType = netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | unix.NFT_MSG_NEWSETELEM) func elementsFromMsg(msg netlink.Message) ([]SetElement, error) { diff --git a/set_test.go b/set_test.go new file mode 100644 index 0000000..88a55fb --- /dev/null +++ b/set_test.go @@ -0,0 +1,71 @@ +package nftables + +import ( + "reflect" + "testing" +) + +func genSetKeyType(types ...uint32) uint32 { + c := types[0] + for i := 1; i < len(types); i++ { + c = c<