From 577f04308d7b3758477a4c890f274e9b8ffd5db4 Mon Sep 17 00:00:00 2001 From: Thea Heinen Date: Wed, 26 Jul 2023 14:56:46 -0700 Subject: [PATCH] rule: Changes IPProto type to u8 netlink defines[1] the type of FRA_IP_PROTO to be a u8 but the definition in rule.go treats this field as a u32. This causes messages to appear in kernel logs with "attribute type 22 has an invalid length." This is exercised in TestRuleAddDel, although it does not cause the test to fail because netlink parses it permissively. The type of `IPProto` in `type Rule` is left as int to avoid a breaking API change. Instead, it is truncated in userspace before sending to the kernel. Truncation is how the kernel handles larger values, so we don't expect this to change semantics. [1]: https://elixir.bootlin.com/linux/v6.19.14/source/net/core/fib_rules.c#L862 Co-authored-by: conjones --- rule.go | 2 +- rule_linux.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/rule.go b/rule.go index 9d74c7cd8..b4a02f8a2 100644 --- a/rule.go +++ b/rule.go @@ -25,7 +25,7 @@ type Rule struct { Invert bool Dport *RulePortRange Sport *RulePortRange - IPProto int + IPProto int // IPProto is represented as uint8 in the kernel and will be truncated before sending UIDRange *RuleUIDRange Protocol uint8 Type uint8 diff --git a/rule_linux.go b/rule_linux.go index 901744769..2db9ea406 100644 --- a/rule_linux.go +++ b/rule_linux.go @@ -154,9 +154,7 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { } if rule.IPProto > 0 { - b := make([]byte, 4) - native.PutUint32(b, uint32(rule.IPProto)) - req.AddData(nl.NewRtAttr(nl.FRA_IP_PROTO, b)) + req.AddData(nl.NewRtAttr(nl.FRA_IP_PROTO, []byte{byte(rule.IPProto)})) } if rule.Dport != nil { @@ -282,7 +280,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) ( case nl.FRA_PRIORITY: rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) case nl.FRA_IP_PROTO: - rule.IPProto = int(native.Uint32(attrs[j].Value[0:4])) + rule.IPProto = int(attrs[j].Value[0]) case nl.FRA_DPORT_RANGE: rule.Dport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) case nl.FRA_SPORT_RANGE: