commit 1db6b5aeec0983b264469be96690d916e236e314
Author: Yawning Angel <[email protected]>
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
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to