[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [sandboxed-tor-browser/master] Filter socketcall() by argument.
commit 1db6b5aeec0983b264469be96690d916e236e314
Author: Yawning Angel <yawning@xxxxxxxxxxxxxxx>
Date: Wed Dec 7 07:05:09 2016 +0000
Filter socketcall() by argument.
This still isn't great, particularly firefox that appears to need all
the socket calls, but at least this denies calls that neither container
needs.
---
src/cmd/gen-seccomp/main.go | 2 -
src/cmd/gen-seccomp/seccomp.go | 28 ++++++++--
src/cmd/gen-seccomp/seccomp_firefox.go | 57 +++++++++++++++-----
src/cmd/gen-seccomp/seccomp_tor.go | 96 +++++++++++++++++++---------------
4 files changed, 119 insertions(+), 64 deletions(-)
diff --git a/src/cmd/gen-seccomp/main.go b/src/cmd/gen-seccomp/main.go
index 3ad1be5..5dcbbf2 100644
--- a/src/cmd/gen-seccomp/main.go
+++ b/src/cmd/gen-seccomp/main.go
@@ -32,8 +32,6 @@ func main() {
log.Fatalf("failed to get absolute path: %v", err)
}
- log.Printf("outDir: %v", outDir)
-
// Tor Browser (amd64)
f, err := os.Create(filepath.Join(outDir, "tor-amd64.bpf"))
if err != nil {
diff --git a/src/cmd/gen-seccomp/seccomp.go b/src/cmd/gen-seccomp/seccomp.go
index 9ec17e8..ece1e7e 100644
--- a/src/cmd/gen-seccomp/seccomp.go
+++ b/src/cmd/gen-seccomp/seccomp.go
@@ -66,6 +66,28 @@ const (
fionread = 0x541b
tcgets = 0x5401
tiocgpgrp = 0x540f
+
+ // socketcall() call numbers (linux/net.h)
+ sysSocket = 1 // sys_socket()
+ sysBind = 2 // sys_bind()
+ sysConnect = 3 // sys_connect()
+ sysListen = 4 // sys_listen()
+ sysAccept = 5 // sys_accept()
+ sysGetsockname = 6 // sys_getsockname()
+ sysGetpeername = 7 // sys_getpeername()
+ sysSocketpair = 8 // sys_socketpair()
+ sysSend = 9 // sys_send()
+ sysRecv = 10 // sys_recv()
+ sysSendto = 11 // sys_sendto()
+ sysRecvfrom = 12 // sys_recvfrom()
+ sysShutdown = 13 // sys_shutdown()
+ sysSetsockopt = 14 // sys_setsockopt()
+ sysGetsockopt = 15 // sys_getsockopt()
+ sysSendmsg = 16 // sys_sendmsg()
+ sysRecvmsg = 17 // sys_recvmsg()
+ sysAccept4 = 18 // sys_accept4()
+ sysRecvmmsg = 19 // sys_recvmmsg
+ sysSendmmsg = 20 // sys_sendmmsg
)
func newWhitelist(is386 bool) (*seccomp.ScmpFilter, error) {
@@ -95,11 +117,7 @@ func allowSyscalls(f *seccomp.ScmpFilter, calls []string, is386 bool) error {
for _, scallName := range calls {
scall, err := seccomp.GetSyscallFromName(scallName)
if err != nil {
- if is386 && scallName == "newselect" {
- scall = seccomp.ScmpSyscall(142)
- } else {
- return fmt.Errorf("seccomp: unknown system call: %v", scallName)
- }
+ return fmt.Errorf("seccomp: unknown system call: %v", scallName)
}
if err = f.AddRule(scall, seccomp.ActAllow); err != nil {
return err
diff --git a/src/cmd/gen-seccomp/seccomp_firefox.go b/src/cmd/gen-seccomp/seccomp_firefox.go
index 22e4bb5..9b25a66 100644
--- a/src/cmd/gen-seccomp/seccomp_firefox.go
+++ b/src/cmd/gen-seccomp/seccomp_firefox.go
@@ -19,6 +19,8 @@ package main
import (
"os"
"syscall"
+
+ seccomp "github.com/seccomp/libseccomp-golang"
)
func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error {
@@ -30,6 +32,7 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error {
}
defer f.Release()
+ // TODO; Filter the arguments on more of these calls.
allowedNoArgs := []string{
"clock_gettime",
"clock_getres",
@@ -207,11 +210,7 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error {
"recv",
"send",
- "newselect",
-
- "socket", // Filtered on amd64.
-
- "socketcall", // Fuck Debian stable.... :(
+ "_newselect",
}
allowedNoArgs = append(allowedNoArgs, allowedNoArgs386...)
}
@@ -219,6 +218,19 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error {
return err
}
+ // Like with how I do the tor rules, handle socketcall() before everything
+ // else.
+ if is386 {
+ if err = ffFilterSocketcall(f); err != nil {
+ return err
+ }
+
+ // Unrelated to sockets, only i386 needs this, and it can be filtered.
+ if err = allowCmpEq(f, "time", 0, 0); err != nil {
+ return err
+ }
+ }
+
// Because we patch PulseAudio's mutex creation, we can omit all PI futex
// calls.
if err = allowCmpEq(f, "futex", 1, futexWait, futexWaitPrivate, futexWakePrivate, futexCmpRequeuePrivate, futexWakeOpPrivate, futexWaitBitsetPrivate|futexClockRealtime, futexWake, futexWaitBitsetPrivate); err != nil {
@@ -234,16 +246,33 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error {
if err = allowCmpEq(f, "prctl", 0, syscall.PR_SET_NAME, syscall.PR_GET_NAME, syscall.PR_GET_TIMERSLACK, syscall.PR_SET_SECCOMP); err != nil {
return err
}
-
- if is386 {
- if err = allowCmpEq(f, "time", 0, 0); err != nil {
- return err
- }
- } else {
- if err = allowCmpEq(f, "socket", 0, syscall.AF_UNIX); err != nil {
- return err
- }
+ if err = allowCmpEq(f, "socket", 0, syscall.AF_UNIX); err != nil {
+ return err
}
return f.ExportBPF(fd)
}
+
+func ffFilterSocketcall(f *seccomp.ScmpFilter) error {
+ // This is kind of pointless because it allows basically all the things.
+ allowedCalls := []uint64{
+ sysSocket,
+ sysBind,
+ sysConnect,
+ sysListen,
+ sysGetsockname,
+ sysGetpeername,
+ sysSocketpair,
+ sysSend,
+ sysRecv,
+ sysSendto,
+ sysRecvfrom,
+ sysShutdown,
+ sysSetsockopt,
+ sysGetsockopt,
+ sysSendmsg,
+ sysRecvmsg,
+ sysAccept4,
+ }
+ return allowCmpEq(f, "socketcall", 0, allowedCalls...)
+}
diff --git a/src/cmd/gen-seccomp/seccomp_tor.go b/src/cmd/gen-seccomp/seccomp_tor.go
index 0a1b8cc..d6ec2ca 100644
--- a/src/cmd/gen-seccomp/seccomp_tor.go
+++ b/src/cmd/gen-seccomp/seccomp_tor.go
@@ -118,14 +118,18 @@ func compileTorSeccompProfile(fd *os.File, useBridges bool, is386 bool) error {
"ugetrlimit",
"set_thread_area",
-
- "socketcall", // I *SHOULDN"T* need this, but Debian stable freaks out.
}
allowedNoArgs = append(allowedNoArgs, allowedNoArgs386...)
}
if err = allowSyscalls(f, allowedNoArgs, is386); err != nil {
return err
}
+ if is386 {
+ // Handle socketcall() before filtering other things.
+ if err = torFilterSocketcall(f, useBridges); err != nil {
+ return err
+ }
+ }
if err = allowCmpEq(f, "time", 0, 0); err != nil {
return err
@@ -157,22 +161,22 @@ func compileTorSeccompProfile(fd *os.File, useBridges bool, is386 bool) error {
if err = allowCmpEq(f, "mremap", 3, mremapMaymove); err != nil {
return err
}
- if err = torFilterAccept4(f, is386); err != nil {
+ if err = torFilterAccept4(f); err != nil {
return err
}
if err = torFilterPoll(f); err != nil {
return err
}
- if err = torFilterSocket(f, is386); err != nil {
+ if err = torFilterSocket(f); err != nil {
return err
}
- if err = torFilterSetsockopt(f, is386); err != nil {
+ if err = torFilterSetsockopt(f); err != nil {
return err
}
- if err = torFilterGetsockopt(f, is386); err != nil {
+ if err = torFilterGetsockopt(f); err != nil {
return err
}
- if err = torFilterSocketpair(f, is386); err != nil {
+ if err = torFilterSocketpair(f); err != nil {
return err
}
if err = torFilterMmap(f, is386); err != nil {
@@ -196,7 +200,7 @@ func compileTorSeccompProfile(fd *os.File, useBridges bool, is386 bool) error {
"getppid",
}
if is386 {
- obfsCalls = append(obfsCalls, "newselect")
+ obfsCalls = append(obfsCalls, "_newselect")
}
if err = allowSyscalls(f, obfsCalls, is386); err != nil {
return err
@@ -212,7 +216,7 @@ func compileTorSeccompProfile(fd *os.File, useBridges bool, is386 bool) error {
if err = allowCmpEq(f, "futex", 1, futexWake, futexWait); err != nil {
return err
}
- if err = obfsFilterSetsockopt(f, is386); err != nil {
+ if err = obfsFilterSetsockopt(f); err != nil {
return err
}
if err = obfsFilterMmap(f, is386); err != nil {
@@ -223,6 +227,40 @@ func compileTorSeccompProfile(fd *os.File, useBridges bool, is386 bool) error {
return f.ExportBPF(fd)
}
+func torFilterSocketcall(f *seccomp.ScmpFilter, useBridges bool) error {
+ // This interface needs to die in a fire, because it's leaving
+ // gaping attack surface. It kind of will assuming that things
+ // move on to 4.3 or later.
+ //
+ // Emperically on Fedora 25 getsockopt and setsockopt still are
+ // multiplexed, though that may just be my rules or libseccomp2.
+ //
+ // Re-test after Debian stable moves to a modern kernel.
+
+ allowedCalls := []uint64{
+ sysSocket,
+ sysBind,
+ sysConnect,
+ sysListen,
+ sysGetsockname,
+ sysSocketpair,
+ sysSend,
+ sysRecv,
+ sysSendto,
+ sysRecvfrom,
+ sysSetsockopt,
+ sysGetsockopt,
+ sysSendmsg,
+ sysRecvmsg,
+ sysAccept4,
+ }
+ if useBridges {
+ allowedCalls = append(allowedCalls, sysGetpeername)
+ }
+
+ return allowCmpEq(f, "socketcall", 0, allowedCalls...)
+}
+
func torFilterPrctl(f *seccomp.ScmpFilter) error {
scall, err := seccomp.GetSyscallFromName("prctl")
if err != nil {
@@ -248,17 +286,11 @@ func torFilterPrctl(f *seccomp.ScmpFilter) error {
return f.AddRuleConditional(scall, seccomp.ActAllow, []seccomp.ScmpCondition{isPrSetDeathsig})
}
-func torFilterAccept4(f *seccomp.ScmpFilter, is386 bool) error {
+func torFilterAccept4(f *seccomp.ScmpFilter) error {
scall, err := seccomp.GetSyscallFromName("accept4")
if err != nil {
return err
}
- if is386 {
- // XXX: The tor common/sandbox.c file, explcitly allows socketcall()
- // by arg for this call, and only this call, when libseccomp should
- // do the right thing.
- return f.AddRule(scall, seccomp.ActAllow)
- }
cond, err := seccomp.MakeCondition(3, seccomp.CompareMaskedEqual, 0, syscall.SOCK_CLOEXEC|syscall.SOCK_NONBLOCK)
if err != nil {
@@ -285,27 +317,16 @@ func torFilterPoll(f *seccomp.ScmpFilter) error {
return f.AddRuleConditional(scall, seccomp.ActAllow, []seccomp.ScmpCondition{isPollIn, timeoutIsTen})
}
-func torFilterSocket(f *seccomp.ScmpFilter, is386 bool) error {
- scall, err := seccomp.GetSyscallFromName("socket")
- if err != nil {
- return err
- }
- if is386 {
- return f.AddRule(scall, seccomp.ActAllow)
- }
-
+func torFilterSocket(f *seccomp.ScmpFilter) error {
// XXX: Tighten this some more.
return allowCmpEq(f, "socket", 0, syscall.AF_UNIX, syscall.AF_INET, syscall.AF_INET6 /*, syscall.AF_NETLINK */)
}
-func torFilterSetsockopt(f *seccomp.ScmpFilter, is386 bool) error {
+func torFilterSetsockopt(f *seccomp.ScmpFilter) error {
scall, err := seccomp.GetSyscallFromName("setsockopt")
if err != nil {
return err
}
- if is386 {
- return f.AddRule(scall, seccomp.ActAllow)
- }
isSolSocket, err := seccomp.MakeCondition(1, seccomp.CompareEqual, syscall.SOL_SOCKET)
if err != nil {
@@ -331,14 +352,11 @@ func torFilterSetsockopt(f *seccomp.ScmpFilter, is386 bool) error {
return nil
}
-func torFilterGetsockopt(f *seccomp.ScmpFilter, is386 bool) error {
+func torFilterGetsockopt(f *seccomp.ScmpFilter) error {
scall, err := seccomp.GetSyscallFromName("getsockopt")
if err != nil {
return err
}
- if is386 {
- return f.AddRule(scall, seccomp.ActAllow)
- }
isSolSocket, err := seccomp.MakeCondition(1, seccomp.CompareEqual, syscall.SOL_SOCKET)
if err != nil {
@@ -351,14 +369,11 @@ func torFilterGetsockopt(f *seccomp.ScmpFilter, is386 bool) error {
return f.AddRuleConditional(scall, seccomp.ActAllow, []seccomp.ScmpCondition{isSolSocket, optIsError})
}
-func torFilterSocketpair(f *seccomp.ScmpFilter, is386 bool) error {
+func torFilterSocketpair(f *seccomp.ScmpFilter) error {
scall, err := seccomp.GetSyscallFromName("socketpair")
if err != nil {
return err
}
- if is386 {
- return f.AddRule(scall, seccomp.ActAllow)
- }
isPfLocal, err := seccomp.MakeCondition(0, seccomp.CompareEqual, syscall.AF_LOCAL)
if err != nil {
@@ -530,12 +545,7 @@ func torFilterFcntl(f *seccomp.ScmpFilter, is386 bool) error {
return nil
}
-func obfsFilterSetsockopt(f *seccomp.ScmpFilter, is386 bool) error {
- // 386 already blindly allows all setsockopt() calls.
- if is386 {
- return nil
- }
-
+func obfsFilterSetsockopt(f *seccomp.ScmpFilter) error {
scall, err := seccomp.GetSyscallFromName("setsockopt")
if err != nil {
return err
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits