summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2020-01-08 16:35:01 -0800
committerKevin Krakauer <krakauer@google.com>2020-01-08 16:35:01 -0800
commitf26a576984052a235b63ec79081a8c4a8c8ffc00 (patch)
treed8af92738bc131203aa9714bc91fd804dc5f0567
parent366e050ad516d6085bcae1215e8e122c6077e9ff (diff)
Addressed GH comments
-rw-r--r--pkg/abi/linux/netfilter.go15
-rw-r--r--pkg/sentry/socket/netfilter/netfilter.go87
-rw-r--r--pkg/sentry/socket/netstack/netstack.go5
3 files changed, 47 insertions, 60 deletions
diff --git a/pkg/abi/linux/netfilter.go b/pkg/abi/linux/netfilter.go
index 35d66d622..c4f4ea0b1 100644
--- a/pkg/abi/linux/netfilter.go
+++ b/pkg/abi/linux/netfilter.go
@@ -298,6 +298,7 @@ type IPTReplace struct {
// Entries [0]IPTEntry
}
+// KernelIPTEntry is identical to IPTReplace, but includes the Entries field.
type KernelIPTReplace struct {
IPTReplace
Entries [0]IPTEntry
@@ -306,28 +307,32 @@ type KernelIPTReplace struct {
// SizeOfIPTReplace is the size of an IPTReplace.
const SizeOfIPTReplace = 96
+// ExtensionName holds the name of a netfilter extension.
type ExtensionName [XT_EXTENSION_MAXNAMELEN]byte
// String implements fmt.Stringer.
func (en ExtensionName) String() string {
- return name(en[:])
+ return goString(en[:])
}
+// ExtensionName holds the name of a netfilter table.
type TableName [XT_TABLE_MAXNAMELEN]byte
// String implements fmt.Stringer.
func (tn TableName) String() string {
- return name(tn[:])
+ return goString(tn[:])
}
+// ExtensionName holds the name of a netfilter error. These can also hold
+// user-defined chains.
type ErrorName [XT_FUNCTION_MAXNAMELEN]byte
// String implements fmt.Stringer.
-func (fn ErrorName) String() string {
- return name(fn[:])
+func (en ErrorName) String() string {
+ return goString(en[:])
}
-func name(cstring []byte) string {
+func goString(cstring []byte) string {
for i, c := range cstring {
if c == 0 {
return string(cstring[:i])
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go
index 347342f98..799865b03 100644
--- a/pkg/sentry/socket/netfilter/netfilter.go
+++ b/pkg/sentry/socket/netfilter/netfilter.go
@@ -53,7 +53,7 @@ func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTG
}
// Find the appropriate table.
- table, err := findTable(ep, info.Name.String())
+ table, err := findTable(ep, info.Name)
if err != nil {
return linux.IPTGetinfo{}, err
}
@@ -84,7 +84,7 @@ func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen i
}
// Find the appropriate table.
- table, err := findTable(ep, userEntries.Name.String())
+ table, err := findTable(ep, userEntries.Name)
if err != nil {
return linux.KernelIPTGetEntries{}, err
}
@@ -96,19 +96,19 @@ func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen i
return linux.KernelIPTGetEntries{}, err
}
if binary.Size(entries) > uintptr(outLen) {
- log.Infof("Insufficient GetEntries output size: %d", uintptr(outLen))
+ log.Warningf("Insufficient GetEntries output size: %d", uintptr(outLen))
return linux.KernelIPTGetEntries{}, syserr.ErrInvalidArgument
}
return entries, nil
}
-func findTable(ep tcpip.Endpoint, tableName string) (iptables.Table, *syserr.Error) {
+func findTable(ep tcpip.Endpoint, tablename linux.TableName) (iptables.Table, *syserr.Error) {
ipt, err := ep.IPTables()
if err != nil {
return iptables.Table{}, syserr.FromError(err)
}
- table, ok := ipt.Tables[tableName]
+ table, ok := ipt.Tables[tablename.String()]
if !ok {
return iptables.Table{}, syserr.ErrInvalidArgument
}
@@ -138,17 +138,17 @@ func FillDefaultIPTables(stack *stack.Stack) {
// format expected by the iptables tool. Linux stores each table as a binary
// blob that can only be traversed by parsing a bit, reading some offsets,
// jumping to those offsets, parsing again, etc.
-func convertNetstackToBinary(name string, table iptables.Table) (linux.KernelIPTGetEntries, metadata, *syserr.Error) {
+func convertNetstackToBinary(tablename string, table iptables.Table) (linux.KernelIPTGetEntries, metadata, *syserr.Error) {
// Return values.
var entries linux.KernelIPTGetEntries
var meta metadata
// The table name has to fit in the struct.
- if linux.XT_TABLE_MAXNAMELEN < len(name) {
- log.Infof("Table name too long.")
+ if linux.XT_TABLE_MAXNAMELEN < len(tablename) {
+ log.Warningf("Table name %q too long.", tablename)
return linux.KernelIPTGetEntries{}, metadata{}, syserr.ErrInvalidArgument
}
- copy(entries.Name[:], name)
+ copy(entries.Name[:], tablename)
for ruleIdx, rule := range table.Rules {
// Is this a chain entry point?
@@ -273,11 +273,12 @@ func translateToStandardVerdict(val int32) (iptables.Verdict, *syserr.Error) {
case -linux.NF_DROP - 1:
return iptables.Drop, nil
case -linux.NF_QUEUE - 1:
- log.Infof("Unsupported iptables verdict QUEUE.")
+ log.Warningf("Unsupported iptables verdict QUEUE.")
case linux.NF_RETURN:
- log.Infof("Unsupported iptables verdict RETURN.")
+ log.Warningf("Unsupported iptables verdict RETURN.")
+ default:
+ log.Warningf("Unknown iptables verdict %d.", val)
}
- log.Infof("Unknown iptables verdict %d.", val)
return iptables.Invalid, syserr.ErrInvalidArgument
}
@@ -288,7 +289,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
// Get the basic rules data (struct ipt_replace).
if len(optVal) < linux.SizeOfIPTReplace {
- log.Infof("netfilter.SetEntries: optVal has insufficient size for replace %d", len(optVal))
+ log.Warningf("netfilter.SetEntries: optVal has insufficient size for replace %d", len(optVal))
return syserr.ErrInvalidArgument
}
var replace linux.IPTReplace
@@ -302,7 +303,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
case iptables.TablenameFilter:
table = iptables.EmptyFilterTable()
default:
- log.Infof(fmt.Sprintf("We don't yet support writing to the %q table (gvisor.dev/issue/170)", replace.Name.String()))
+ log.Warningf("We don't yet support writing to the %q table (gvisor.dev/issue/170)", replace.Name.String())
return syserr.ErrInvalidArgument
}
@@ -312,7 +313,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
for entryIdx := uint32(0); entryIdx < replace.NumEntries; entryIdx++ {
// Get the struct ipt_entry.
if len(optVal) < linux.SizeOfIPTEntry {
- log.Infof("netfilter: optVal has insufficient size for entry %d", len(optVal))
+ log.Warningf("netfilter: optVal has insufficient size for entry %d", len(optVal))
return syserr.ErrInvalidArgument
}
var entry linux.IPTEntry
@@ -328,7 +329,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
// filtering. We reject any nonzero IPTIP values for now.
emptyIPTIP := linux.IPTIP{}
if entry.IP != emptyIPTIP {
- log.Infof("netfilter: non-empty struct iptip found")
+ log.Warningf("netfilter: non-empty struct iptip found")
return syserr.ErrInvalidArgument
}
@@ -358,11 +359,11 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
}
}
if ruleIdx := table.BuiltinChains[hk]; ruleIdx == iptables.HookUnset {
- log.Infof("Hook %v is unset.", hk)
+ log.Warningf("Hook %v is unset.", hk)
return syserr.ErrInvalidArgument
}
if ruleIdx := table.Underflows[hk]; ruleIdx == iptables.HookUnset {
- log.Infof("Underflow %v is unset.", hk)
+ log.Warningf("Underflow %v is unset.", hk)
return syserr.ErrInvalidArgument
}
}
@@ -385,7 +386,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
// along with the number of bytes it occupies in optVal.
func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
if len(optVal) < linux.SizeOfXTEntryTarget {
- log.Infof("netfilter: optVal has insufficient size for entry target %d", len(optVal))
+ log.Warningf("netfilter: optVal has insufficient size for entry target %d", len(optVal))
return nil, 0, syserr.ErrInvalidArgument
}
var target linux.XTEntryTarget
@@ -395,14 +396,14 @@ func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
case "":
// Standard target.
if len(optVal) < linux.SizeOfXTStandardTarget {
- log.Infof("netfilter.SetEntries: optVal has insufficient size for standard target %d", len(optVal))
+ log.Warningf("netfilter.SetEntries: optVal has insufficient size for standard target %d", len(optVal))
return nil, 0, syserr.ErrInvalidArgument
}
- var target linux.XTStandardTarget
+ var standardTarget linux.XTStandardTarget
buf = optVal[:linux.SizeOfXTStandardTarget]
- binary.Unmarshal(buf, usermem.ByteOrder, &target)
+ binary.Unmarshal(buf, usermem.ByteOrder, &standardTarget)
- verdict, err := translateToStandardVerdict(target.Verdict)
+ verdict, err := translateToStandardVerdict(standardTarget.Verdict)
if err != nil {
return nil, 0, err
}
@@ -424,9 +425,9 @@ func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
log.Infof("netfilter.SetEntries: optVal has insufficient size for error target %d", len(optVal))
return nil, 0, syserr.ErrInvalidArgument
}
- var target linux.XTErrorTarget
+ var errorTarget linux.XTErrorTarget
buf = optVal[:linux.SizeOfXTErrorTarget]
- binary.Unmarshal(buf, usermem.ByteOrder, &target)
+ binary.Unmarshal(buf, usermem.ByteOrder, &errorTarget)
// Error targets are used in 2 cases:
// * An actual error case. These rules have an error
@@ -435,11 +436,11 @@ func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
// somehow fall through every rule.
// * To mark the start of a user defined chain. These
// rules have an error with the name of the chain.
- switch target.Name.String() {
+ switch errorTarget.Name.String() {
case errorTargetName:
return iptables.PanicTarget{}, linux.SizeOfXTErrorTarget, nil
default:
- log.Infof("Unknown error target %q doesn't exist or isn't supported yet.", target.Name.String())
+ log.Infof("Unknown error target %q doesn't exist or isn't supported yet.", errorTarget.Name.String())
return nil, 0, syserr.ErrInvalidArgument
}
}
@@ -449,22 +450,6 @@ func parseTarget(optVal []byte) (iptables.Target, uint32, *syserr.Error) {
return nil, 0, syserr.ErrInvalidArgument
}
-func chainNameFromHook(hook int) string {
- switch hook {
- case linux.NF_INET_PRE_ROUTING:
- return iptables.ChainNamePrerouting
- case linux.NF_INET_LOCAL_IN:
- return iptables.ChainNameInput
- case linux.NF_INET_FORWARD:
- return iptables.ChainNameForward
- case linux.NF_INET_LOCAL_OUT:
- return iptables.ChainNameOutput
- case linux.NF_INET_POST_ROUTING:
- return iptables.ChainNamePostrouting
- }
- panic(fmt.Sprintf("Unknown hook %d does not correspond to a builtin chain"))
-}
-
func hookFromLinux(hook int) iptables.Hook {
switch hook {
case linux.NF_INET_PRE_ROUTING:
@@ -489,7 +474,7 @@ func printReplace(optVal []byte) {
replaceBuf := optVal[:linux.SizeOfIPTReplace]
optVal = optVal[linux.SizeOfIPTReplace:]
binary.Unmarshal(replaceBuf, usermem.ByteOrder, &replace)
- log.Infof("kevin: Replacing table %q: %+v", replace.Name.String(), replace)
+ log.Infof("Replacing table %q: %+v", replace.Name.String(), replace)
// Read in the list of entries at the end of replace.
var totalOffset uint16
@@ -497,33 +482,33 @@ func printReplace(optVal []byte) {
var entry linux.IPTEntry
entryBuf := optVal[:linux.SizeOfIPTEntry]
binary.Unmarshal(entryBuf, usermem.ByteOrder, &entry)
- log.Infof("kevin: Entry %d (total offset %d): %+v", entryIdx, totalOffset, entry)
+ log.Infof("Entry %d (total offset %d): %+v", entryIdx, totalOffset, entry)
totalOffset += entry.NextOffset
if entry.TargetOffset == linux.SizeOfIPTEntry {
- log.Infof("kevin: Entry has no matches.")
+ log.Infof("Entry has no matches.")
} else {
- log.Infof("kevin: Entry has matches.")
+ log.Infof("Entry has matches.")
}
var target linux.XTEntryTarget
targetBuf := optVal[entry.TargetOffset : entry.TargetOffset+linux.SizeOfXTEntryTarget]
binary.Unmarshal(targetBuf, usermem.ByteOrder, &target)
- log.Infof("kevin: Target named %q: %+v", target.Name.String(), target)
+ log.Infof("Target named %q: %+v", target.Name.String(), target)
switch target.Name.String() {
case "":
var standardTarget linux.XTStandardTarget
stBuf := optVal[entry.TargetOffset : entry.TargetOffset+linux.SizeOfXTStandardTarget]
binary.Unmarshal(stBuf, usermem.ByteOrder, &standardTarget)
- log.Infof("kevin: Standard target with verdict %q (%d).", linux.VerdictStrings[standardTarget.Verdict], standardTarget.Verdict)
+ log.Infof("Standard target with verdict %q (%d).", linux.VerdictStrings[standardTarget.Verdict], standardTarget.Verdict)
case errorTargetName:
var errorTarget linux.XTErrorTarget
etBuf := optVal[entry.TargetOffset : entry.TargetOffset+linux.SizeOfXTErrorTarget]
binary.Unmarshal(etBuf, usermem.ByteOrder, &errorTarget)
- log.Infof("kevin: Error target with name %q.", errorTarget.Name.String())
+ log.Infof("Error target with name %q.", errorTarget.Name.String())
default:
- log.Infof("kevin: Unknown target type.")
+ log.Infof("Unknown target type.")
}
optVal = optVal[entry.NextOffset:]
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go
index 8c07eef4b..cd3dd1a53 100644
--- a/pkg/sentry/socket/netstack/netstack.go
+++ b/pkg/sentry/socket/netstack/netstack.go
@@ -1368,10 +1368,7 @@ func (s *SocketOperations) SetSockOpt(t *kernel.Task, level int, name int, optVa
return syserr.ErrNoDevice
}
// Stack must be a netstack stack.
- if err := netfilter.SetEntries(stack.(*Stack).Stack, optVal); err != nil {
- return err
- }
- return nil
+ return netfilter.SetEntries(stack.(*Stack).Stack, optVal)
case linux.IPT_SO_SET_ADD_COUNTERS:
// TODO(gvisor.dev/issue/170): Counter support.