commit dcc1b9fffe82f55801b90c4ada9c21551e642f62
Author: Yawning Angel <[email protected]>
Date:   Thu Dec 8 05:34:57 2016 +0000

    Tighten the seccomp rules some more.
    
     * Stop being lazy and validate all the socket() flags to allow tor.
    
     * Tighten the rlimit() related calls allowed to firefox.
       ASAN insists on being able to use `setrlimit()`.  I should drop
       support for the "hardened" channel because it increases attack
       surface.
---
 src/cmd/gen-seccomp/seccomp_firefox.go | 34 +++++++++++++++--
 src/cmd/gen-seccomp/seccomp_tor.go     | 69 ++++++++++++++++++++++++++++++++--
 2 files changed, 97 insertions(+), 6 deletions(-)

diff --git a/src/cmd/gen-seccomp/seccomp_firefox.go 
b/src/cmd/gen-seccomp/seccomp_firefox.go
index 9b25a66..03ed1fb 100644
--- a/src/cmd/gen-seccomp/seccomp_firefox.go
+++ b/src/cmd/gen-seccomp/seccomp_firefox.go
@@ -33,6 +33,9 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) 
error {
        defer f.Release()
 
        // TODO; Filter the arguments on more of these calls.
+       //
+       // Maybe draaw inspiration from:
+       // 
https://github.com/mozilla/gecko-dev/blob/master/security/sandbox/linux/SandboxFilter.cpp
        allowedNoArgs := []string{
                "clock_gettime",
                "clock_getres",
@@ -149,7 +152,6 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 
bool) error {
                "rt_sigprocmask",
                "rt_sigreturn",
                "sigaltstack",
-               "setrlimit",
 
                "arch_prctl",
                "capset",
@@ -175,6 +177,9 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 
bool) error {
                "unshare",
                "wait4",
 
+               // ASAN explodes if this doesn't work.  Sigh.
+               "setrlimit",
+
                // Firefox uses this, but will take no for an answer.
                // "quotactl",
 
@@ -198,7 +203,6 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 
bool) error {
                        "_llseek",
 
                        "mmap2",
-                       "prlimit64",
                        "ugetrlimit",
                        "set_thread_area",
                        "waitpid",
@@ -225,10 +229,13 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 
bool) error {
                        return err
                }
 
-               // Unrelated to sockets, only i386 needs this, and it can be 
filtered.
+               // Unrelated to sockets, only i386 needs these, and it can be 
filtered.
                if err = allowCmpEq(f, "time", 0, 0); err != nil {
                        return err
                }
+               if err = ffFilterPrlimit64(f); err != nil {
+                       return err
+               }
        }
 
        // Because we patch PulseAudio's mutex creation, we can omit all PI 
futex
@@ -276,3 +283,24 @@ func ffFilterSocketcall(f *seccomp.ScmpFilter) error {
        }
        return allowCmpEq(f, "socketcall", 0, allowedCalls...)
 }
+
+func ffFilterPrlimit64(f *seccomp.ScmpFilter) error {
+       scall, err := seccomp.GetSyscallFromName("prlimit64")
+       if err != nil {
+               return err
+       }
+
+       // Per Mozilla's sandbox: only prlimit64(0, resource,  NULL, old_limit)
+       // which is functionally equivalent to getrlimit().  0 instead of the
+       // pid() is a glibc-ism.
+
+       isPid0, err := seccomp.MakeCondition(0, seccomp.CompareEqual, 0)
+       if err != nil {
+               return err
+       }
+       isNoNewLimit, err := seccomp.MakeCondition(2, seccomp.CompareEqual, 9)
+       if err != nil {
+               return err
+       }
+       return f.AddRuleConditional(scall, seccomp.ActAllow, 
[]seccomp.ScmpCondition{isPid0, isNoNewLimit})
+}
diff --git a/src/cmd/gen-seccomp/seccomp_tor.go 
b/src/cmd/gen-seccomp/seccomp_tor.go
index d6ec2ca..7300b64 100644
--- a/src/cmd/gen-seccomp/seccomp_tor.go
+++ b/src/cmd/gen-seccomp/seccomp_tor.go
@@ -23,6 +23,8 @@ import (
        seccomp "github.com/seccomp/libseccomp-golang"
 )
 
+var maskedCloexecNonblock = ^(uint64(syscall.SOCK_CLOEXEC | 
syscall.SOCK_NONBLOCK))
+
 func compileTorSeccompProfile(fd *os.File, useBridges bool, is386 bool) error {
        defer fd.Close()
 
@@ -292,7 +294,7 @@ func torFilterAccept4(f *seccomp.ScmpFilter) error {
                return err
        }
 
-       cond, err := seccomp.MakeCondition(3, seccomp.CompareMaskedEqual, 0, 
syscall.SOCK_CLOEXEC|syscall.SOCK_NONBLOCK)
+       cond, err := seccomp.MakeCondition(3, seccomp.CompareMaskedEqual, 
maskedCloexecNonblock, 0)
        if err != nil {
                return nil
        }
@@ -318,8 +320,69 @@ func torFilterPoll(f *seccomp.ScmpFilter) error {
 }
 
 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 */)
+       scall, err := seccomp.GetSyscallFromName("socket")
+       if err != nil {
+               return err
+       }
+
+       makeCondType := func(t uint64) (seccomp.ScmpCondition, error) {
+               return seccomp.MakeCondition(1, seccomp.CompareMaskedEqual, 
maskedCloexecNonblock, t)
+       }
+
+       // tor allows PF_FILE, which is PF_LOCAL on Linux, not sure why.
+
+       for _, d := range []uint64{syscall.AF_INET, syscall.AF_INET6} {
+               isDomain, err := seccomp.MakeCondition(0, seccomp.CompareEqual, 
d)
+               if err != nil {
+                       return err
+               }
+
+               for _, t := range []uint64{syscall.SOCK_STREAM, 
syscall.SOCK_DGRAM} {
+                       protocols := []uint64{syscall.IPPROTO_IP, 
syscall.IPPROTO_UDP}
+                       if t == syscall.SOCK_STREAM {
+                               protocols = append(protocols, 
syscall.IPPROTO_TCP)
+                       }
+
+                       isType, err := makeCondType(t)
+                       if err != nil {
+                               return err
+                       }
+
+                       for _, p := range protocols {
+                               isProtocol, err := seccomp.MakeCondition(2, 
seccomp.CompareEqual, p)
+                               if err != nil {
+                                       return err
+                               }
+
+                               if err = f.AddRuleConditional(scall, 
seccomp.ActAllow, []seccomp.ScmpCondition{isDomain, isType, isProtocol}); err 
!= nil {
+                                       return err
+                               }
+                       }
+               }
+       }
+
+       isAfLocal, err := seccomp.MakeCondition(0, seccomp.CompareEqual, 
syscall.AF_LOCAL)
+       if err != nil {
+               return err
+       }
+       for _, t := range []uint64{syscall.SOCK_STREAM, syscall.SOCK_DGRAM} {
+               isType, err := makeCondType(t)
+               if err != nil {
+                       return err
+               }
+               isProtocol, err := seccomp.MakeCondition(2, 
seccomp.CompareEqual, 0)
+               if err != nil {
+                       return err
+               }
+               if err = f.AddRuleConditional(scall, seccomp.ActAllow, 
[]seccomp.ScmpCondition{isAfLocal, isType, isProtocol}); err != nil {
+                       return err
+               }
+       }
+
+       // tor allows socket(AF_NETLINK, SOCK_RAW, 0), which is used to check 
it's
+       // IP address, but will take "no".
+
+       return nil
 }
 
 func torFilterSetsockopt(f *seccomp.ScmpFilter) error {

_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to