Skip to content

Commit 0dd9ee0

Browse files
committed
Merge pull request google#1775 from kevinGC:tcp-matchers-submit
PiperOrigin-RevId: 294340468
2 parents 71af006 + c141eb5 commit 0dd9ee0

File tree

8 files changed

+417
-164
lines changed

8 files changed

+417
-164
lines changed

pkg/abi/linux/netfilter.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,59 @@ func goString(cstring []byte) string {
348348
return string(cstring)
349349
}
350350

351+
// XTTCP holds data for matching TCP packets. It corresponds to struct xt_tcp
352+
// in include/uapi/linux/netfilter/xt_tcpudp.h.
353+
type XTTCP struct {
354+
// SourcePortStart specifies the inclusive start of the range of source
355+
// ports to which the matcher applies.
356+
SourcePortStart uint16
357+
358+
// SourcePortEnd specifies the inclusive end of the range of source ports
359+
// to which the matcher applies.
360+
SourcePortEnd uint16
361+
362+
// DestinationPortStart specifies the start of the destination port
363+
// range to which the matcher applies.
364+
DestinationPortStart uint16
365+
366+
// DestinationPortEnd specifies the end of the destination port
367+
// range to which the matcher applies.
368+
DestinationPortEnd uint16
369+
370+
// Option specifies that a particular TCP option must be set.
371+
Option uint8
372+
373+
// FlagMask masks TCP flags when comparing to the FlagCompare byte. It allows
374+
// for specification of which flags are important to the matcher.
375+
FlagMask uint8
376+
377+
// FlagCompare, in combination with FlagMask, is used to match only packets
378+
// that have certain flags set.
379+
FlagCompare uint8
380+
381+
// InverseFlags flips the meaning of certain fields. See the
382+
// TX_TCP_INV_* flags.
383+
InverseFlags uint8
384+
}
385+
386+
// SizeOfXTTCP is the size of an XTTCP.
387+
const SizeOfXTTCP = 12
388+
389+
// Flags in XTTCP.InverseFlags. Corresponding constants are in
390+
// include/uapi/linux/netfilter/xt_tcpudp.h.
391+
const (
392+
// Invert the meaning of SourcePortStart/End.
393+
XT_TCP_INV_SRCPT = 0x01
394+
// Invert the meaning of DestinationPortStart/End.
395+
XT_TCP_INV_DSTPT = 0x02
396+
// Invert the meaning of FlagCompare.
397+
XT_TCP_INV_FLAGS = 0x04
398+
// Invert the meaning of Option.
399+
XT_TCP_INV_OPTION = 0x08
400+
// Enable all flags.
401+
XT_TCP_INV_MASK = 0x0F
402+
)
403+
351404
// XTUDP holds data for matching UDP packets. It corresponds to struct xt_udp
352405
// in include/uapi/linux/netfilter/xt_tcpudp.h.
353406
type XTUDP struct {

pkg/sentry/socket/netfilter/BUILD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ package(licenses = ["notice"])
55
go_library(
66
name = "netfilter",
77
srcs = [
8+
"extensions.go",
89
"netfilter.go",
10+
"tcp_matcher.go",
11+
"udp_matcher.go",
912
],
1013
# This target depends on netstack and should only be used by epsocket,
1114
# which is allowed to depend on netstack.
@@ -17,6 +20,7 @@ go_library(
1720
"//pkg/sentry/kernel",
1821
"//pkg/syserr",
1922
"//pkg/tcpip",
23+
"//pkg/tcpip/header",
2024
"//pkg/tcpip/iptables",
2125
"//pkg/tcpip/stack",
2226
"//pkg/usermem",
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2020 The gVisor Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package netfilter
16+
17+
import (
18+
"fmt"
19+
20+
"gvisor.dev/gvisor/pkg/abi/linux"
21+
"gvisor.dev/gvisor/pkg/binary"
22+
"gvisor.dev/gvisor/pkg/tcpip/iptables"
23+
"gvisor.dev/gvisor/pkg/usermem"
24+
)
25+
26+
// TODO(gvisor.dev/issue/170): The following per-matcher params should be
27+
// supported:
28+
// - Table name
29+
// - Match size
30+
// - User size
31+
// - Hooks
32+
// - Proto
33+
// - Family
34+
35+
// matchMaker knows how to (un)marshal the matcher named name().
36+
type matchMaker interface {
37+
// name is the matcher name as stored in the xt_entry_match struct.
38+
name() string
39+
40+
// marshal converts from an iptables.Matcher to an ABI struct.
41+
marshal(matcher iptables.Matcher) []byte
42+
43+
// unmarshal converts from the ABI matcher struct to an
44+
// iptables.Matcher.
45+
unmarshal(buf []byte, filter iptables.IPHeaderFilter) (iptables.Matcher, error)
46+
}
47+
48+
// matchMakers maps the name of supported matchers to the matchMaker that
49+
// marshals and unmarshals it. It is immutable after package initialization.
50+
var matchMakers = map[string]matchMaker{}
51+
52+
// registermatchMaker should be called by match extensions to register them
53+
// with the netfilter package.
54+
func registerMatchMaker(mm matchMaker) {
55+
if _, ok := matchMakers[mm.name()]; ok {
56+
panic(fmt.Sprintf("Multiple matches registered with name %q.", mm.name()))
57+
}
58+
matchMakers[mm.name()] = mm
59+
}
60+
61+
func marshalMatcher(matcher iptables.Matcher) []byte {
62+
matchMaker, ok := matchMakers[matcher.Name()]
63+
if !ok {
64+
panic(fmt.Sprintf("Unknown matcher of type %T.", matcher))
65+
}
66+
return matchMaker.marshal(matcher)
67+
}
68+
69+
// marshalEntryMatch creates a marshalled XTEntryMatch with the given name and
70+
// data appended at the end.
71+
func marshalEntryMatch(name string, data []byte) []byte {
72+
nflog("marshaling matcher %q", name)
73+
74+
// We have to pad this struct size to a multiple of 8 bytes.
75+
size := alignUp(linux.SizeOfXTEntryMatch+len(data), 8)
76+
matcher := linux.KernelXTEntryMatch{
77+
XTEntryMatch: linux.XTEntryMatch{
78+
MatchSize: uint16(size),
79+
},
80+
Data: data,
81+
}
82+
copy(matcher.Name[:], name)
83+
84+
buf := make([]byte, 0, size)
85+
buf = binary.Marshal(buf, usermem.ByteOrder, matcher)
86+
return append(buf, make([]byte, size-len(buf))...)
87+
}
88+
89+
func unmarshalMatcher(match linux.XTEntryMatch, filter iptables.IPHeaderFilter, buf []byte) (iptables.Matcher, error) {
90+
matchMaker, ok := matchMakers[match.Name.String()]
91+
if !ok {
92+
return nil, fmt.Errorf("unsupported matcher with name %q", match.Name.String())
93+
}
94+
return matchMaker.unmarshal(buf, filter)
95+
}
96+
97+
// alignUp rounds a length up to an alignment. align must be a power of 2.
98+
func alignUp(length int, align uint) int {
99+
return (length + int(align) - 1) & ^(int(align) - 1)
100+
}

0 commit comments

Comments
 (0)