Skip to content

Commit fd37091

Browse files
kerumetogvisor-bot
authored andcommitted
Handle NESTED attributes tagged with NLA_F_NESTED flag.
Linux provides support for nested attributes tagged with or without the NLA_F_NESTED flag for nftables. The nft CLI tags its attributes with this flag, so functionality was introduced to handle this. Updates #11778 PiperOrigin-RevId: 800213277
1 parent b2a5598 commit fd37091

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

pkg/sentry/socket/netlink/netfilter/protocol.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -495,12 +495,12 @@ func (p *Protocol) addChain(attrs map[uint16]nlmsg.BytesView, tab *nftables.Tabl
495495
// chainParseHook parses the hook attributes and returns a complete
496496
// BaseChainInfo.
497497
func (p *Protocol) chainParseHook(chain *nftables.Chain, family stack.AddressFamily, hdata nlmsg.AttrsView) (*nftables.BaseChainInfo, *syserr.AnnotatedError) {
498-
hookAttrs, ok := hdata.Parse()
499-
var hookInfo nftables.HookInfo
498+
hookAttrs, ok := nftables.NfParse(hdata)
500499
if !ok {
501500
return nil, syserr.NewAnnotatedError(syserr.ErrInvalidArgument, fmt.Sprintf("Nftables: Failed to parse hook attributes"))
502501
}
503502

503+
var hookInfo nftables.HookInfo
504504
if chain != nil {
505505
// TODO: b/434243967 - Support updating existing chains.
506506
return nil, syserr.NewAnnotatedError(syserr.ErrNotSupported, fmt.Sprintf("Nftables: Updating hook attributes are not supported for existing chains"))
@@ -935,7 +935,7 @@ func parseNestedExprs(nestedAttrBytes nlmsg.AttrsView) ([]nftables.ExprInfo, *sy
935935
}
936936
numExprs++
937937

938-
exprAttrs, ok := nlmsg.AttrsView(value).Parse()
938+
exprAttrs, ok := nftables.NfParse(nlmsg.AttrsView(value))
939939
if !ok {
940940
return nil, syserr.NewAnnotatedError(syserr.ErrInvalidArgument, "Nftables: Failed to parse attributes for expression")
941941
}
@@ -1139,7 +1139,7 @@ func (p *Protocol) ProcessMessage(ctx context.Context, s *netlink.Socket, msg *n
11391139
return syserr.ErrInvalidArgument
11401140
}
11411141

1142-
attrs, ok := atr.Parse()
1142+
attrs, ok := nftables.NfParse(atr)
11431143
if !ok {
11441144
log.Debugf("Failed to parse message attributes")
11451145
return syserr.ErrInvalidArgument
@@ -1206,7 +1206,7 @@ func (p *Protocol) receiveBatchMessage(ctx context.Context, s *netlink.Socket, m
12061206
return syserr.NewAnnotatedError(syserr.ErrInvalidArgument, "Nftables: Failed to get message data")
12071207
}
12081208

1209-
attrs, ok := atr.Parse()
1209+
attrs, ok := nftables.NfParse(atr)
12101210
if !ok {
12111211
return syserr.NewAnnotatedError(syserr.ErrInvalidArgument, "Failed to parse message attributes for batch message")
12121212
}
@@ -1322,7 +1322,7 @@ func (p *Protocol) processBatchMessage(ctx context.Context, s *netlink.Socket, b
13221322
continue
13231323
}
13241324

1325-
attrs, ok := atr.Parse()
1325+
attrs, ok := nftables.NfParse(atr)
13261326
if !ok {
13271327
netlink.DumpErrorMessage(hdr, ms, syserr.ErrInvalidArgument)
13281328
continue

pkg/tcpip/nftables/nft_immediate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func newImmediate(dreg uint8, data registerData) (*immediate, *syserr.AnnotatedE
4343
// InitImmediate initializes the immediate operation from the expression info.
4444
func initImmediate(tab *Table, exprInfo ExprInfo) (*immediate, *syserr.AnnotatedError) {
4545
// We now have attributes specific to immediate expressions.
46-
immDataAttrs, ok := exprInfo.ExprData.Parse()
46+
immDataAttrs, ok := NfParse(exprInfo.ExprData)
4747
if !ok {
4848
return nil, syserr.NewAnnotatedError(syserr.ErrInvalidArgument, "Nftables: Failed to parse immediate expression data")
4949
}

pkg/tcpip/nftables/nftables_types.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ func AFtoNetlinkAF(af uint8) (stack.AddressFamily, *syserr.Error) {
956956

957957
// nftDataInit creates a new registerData struct from the passed in data bytes.
958958
func nftDataInit(tab *Table, regType uint32, dataBytes nlmsg.AttrsView) (registerData, *syserr.AnnotatedError) {
959-
dataAttrs, ok := dataBytes.Parse()
959+
dataAttrs, ok := NfParse(dataBytes)
960960
if !ok {
961961
return nil, syserr.NewAnnotatedError(syserr.ErrInvalidArgument, fmt.Sprintf("Nftables: Failed to parse data bytes for nested expression data"))
962962
}
@@ -1049,7 +1049,7 @@ func nftValidateRegister(reg uint32, regType uint32, data registerData) (uint8,
10491049
// validateVerdictData validates the verdict data bytes and returns the data as a verdict.
10501050
func validateVerdictData(tab *Table, bytes nlmsg.AttrsView) (stack.NFVerdict, *syserr.AnnotatedError) {
10511051
v := stack.NFVerdict{}
1052-
verdictAttrs, ok := bytes.Parse()
1052+
verdictAttrs, ok := NfParse(bytes)
10531053
if !ok {
10541054
return v, syserr.NewAnnotatedError(syserr.ErrInvalidArgument, "Nftables: Failed to parse verdict data")
10551055
}
@@ -1116,6 +1116,25 @@ func HasAttr(attrName uint16, attrs map[uint16]nlmsg.BytesView) bool {
11161116
return ok
11171117
}
11181118

1119+
// NfParse parses the data bytes, clearing the nested attribute bit if present.
1120+
// For nested attributes, Linux supports these attributes having the bit
1121+
// set or unset. It is cleared here for consistency.
1122+
func NfParse(data nlmsg.AttrsView) (map[uint16]nlmsg.BytesView, bool) {
1123+
attrs, ok := data.Parse()
1124+
if !ok {
1125+
return nil, ok
1126+
}
1127+
1128+
newAttrs := make(map[uint16]nlmsg.BytesView)
1129+
// TODO - b/421437663: If any validation has to be done on nested attributes,
1130+
// it should be done here.
1131+
for attr, attrData := range attrs {
1132+
newAttrs[attr & ^linux.NLA_F_NESTED] = attrData
1133+
}
1134+
1135+
return newAttrs, ok
1136+
}
1137+
11191138
// deepCopyRule returns a deep copy of the Rule struct.
11201139
func deepCopyRule(rule *Rule, chainCopy *Chain) *Rule {
11211140
return &Rule{

0 commit comments

Comments
 (0)