commit 82fcc3247c878cff63bbf34fe0c397638a232bde Author: Yawning Angel yawning@schwanenlied.me Date: Mon Dec 5 10:30:37 2016 +0000
This is the first pass at trying to constrain resource use by sandboxed processes.
I still need to decide what to do about `RLIMIT_AS`, `RLIMIT_DATA`, and `RLIMIT_FSIZE`. I agree that setting them would be sensible, but it needs UI integration, which will take some thinking. --- src/cmd/gen-seccomp/seccomp_firefox.go | 2 +- .../internal/sandbox/rlimit.go | 110 +++++++++++++++++++++ src/cmd/sandboxed-tor-browser/internal/ui/ui.go | 5 + 3 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/src/cmd/gen-seccomp/seccomp_firefox.go b/src/cmd/gen-seccomp/seccomp_firefox.go index 465d8fe..75a7dd3 100644 --- a/src/cmd/gen-seccomp/seccomp_firefox.go +++ b/src/cmd/gen-seccomp/seccomp_firefox.go @@ -117,7 +117,6 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error { "brk", "mincore", "mmap", - "mlock", "mprotect", "mremap", "munmap", @@ -182,6 +181,7 @@ func compileTorBrowserSeccompProfile(fd *os.File, is386 bool) error { // "vfork", // "memfd_create", (PulseAudio? Won't work in our container.) // "personality", + // "mlock", } if is386 { allowedNoArgs386 := []string{ diff --git a/src/cmd/sandboxed-tor-browser/internal/sandbox/rlimit.go b/src/cmd/sandboxed-tor-browser/internal/sandbox/rlimit.go new file mode 100644 index 0000000..9ac9aed --- /dev/null +++ b/src/cmd/sandboxed-tor-browser/internal/sandbox/rlimit.go @@ -0,0 +1,110 @@ +// rlimit.go - Resource limits. +// Copyright (C) 2016 Yawning Angel. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. + +package sandbox + +import "syscall" + +func lowerRlimit(resource int, newHard uint64) error { + var lim syscall.Rlimit + if err := syscall.Getrlimit(resource, &lim); err != nil { + return err + } + + needsSet := false + if newHard < lim.Max { + lim.Max = newHard + needsSet = true + } + if newHard < lim.Cur { + lim.Cur = newHard + needsSet = true + } + if !needsSet { + return nil + } + + return syscall.Setrlimit(resource, &lim) +} + +// SetSensibleRlimits conservatively lowers the rlimits to values that will +// happily support firefox, the updater, tor, and obfs4proxy. +// +// XXX; In the future, this should be applied to each process individually. +// I still need to think about what I'll do for the things that are unset, +// because it should be tied into the UI. +func SetSensibleRlimits() error { + const ( + limStack = 512 * 1024 // 512 KiB + limRSS = 0 // No effect as of 2.6.x... + limNproc = 512 + limNofile = 1024 // Could maybe go as low as 512... + limMlock = 0 // This might need to be increased later. + limLocks = 32 + limSigpending = 64 + limMsgqueue = 0 // Disallowed by seccomp. + limNice = 0 + limRtprio = 0 + limRttime = 0 + + // The syscall package doesn't expose these. + RLIMIT_RSS = 5 + RLIMIT_NPROC = 6 + RLIMIT_MLOCK = 8 + RLIMIT_LOCKS = 10 + RLIMIT_SIGPENDING = 11 + RLIMIT_MSGQUEUE = 12 + RLIMIT_NICE = 13 + RLIMIT_RTPRIO = 14 + RLIMIT_RTTIME = 15 + ) + + if err := lowerRlimit(syscall.RLIMIT_STACK, limStack); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_RSS, limRSS); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_NPROC, limNproc); err != nil { + return err + } + if err := lowerRlimit(syscall.RLIMIT_NOFILE, limNofile); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_MLOCK, limMlock); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_LOCKS, limLocks); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_SIGPENDING, limSigpending); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_MSGQUEUE, limMsgqueue); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_NICE, limNice); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_RTPRIO, limRtprio); err != nil { + return err + } + if err := lowerRlimit(RLIMIT_RTTIME, limRttime); err != nil { + return err + } + + return nil +} diff --git a/src/cmd/sandboxed-tor-browser/internal/ui/ui.go b/src/cmd/sandboxed-tor-browser/internal/ui/ui.go index b2ca8ee..cd9a8c1 100644 --- a/src/cmd/sandboxed-tor-browser/internal/ui/ui.go +++ b/src/cmd/sandboxed-tor-browser/internal/ui/ui.go @@ -206,6 +206,11 @@ func (c *Common) Run() error { log.SetOutput(w) }
+ // Set sensible rlimits. + if err = sandbox.SetSensibleRlimits(); err != nil { + return err + } + // Acquire the lock file. if c.lock, err = newLockFile(c); err != nil { return err
tor-commits@lists.torproject.org