[tor-commits] [sandboxed-tor-browser/master] Bug 21764: Use bubblewrap's `--die-with-parent` when supported.

yawning at torproject.org yawning at torproject.org
Thu Apr 13 07:59:49 UTC 2017


commit 66aaf6fea4293fdb0f9f233ea612e3b53efc4172
Author: Yawning Angel <yawning at schwanenlied.me>
Date:   Thu Apr 13 07:58:01 2017 +0000

    Bug 21764: Use bubblewrap's `--die-with-parent` when supported.
    
    Tor Browser nightly (ESR52, e10s) doesn't exit cleanly when SIGINT is
    sent to `sandboxed-tor-browser` without this.  Unfortunately the option
    requires bubblewrap >= 0.1.8, but at least exiting firefox normally
    works fine with older bubblewrap.
---
 ChangeLog                                          |  1 +
 .../internal/sandbox/hugbox.go                     | 86 +++++++++++++---------
 2 files changed, 51 insertions(+), 36 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 92ce6c0..d634264 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,5 @@
 Changes in version 0.0.5 - UNRELEASED:
+ * Bug 21764: Use bubblewrap's `--die-with-parent` when supported.
  * Fix e10s Web Content crash on systems with grsec kernels.
  * Add `prlimit64` to the firefox system call whitelist.
 
diff --git a/src/cmd/sandboxed-tor-browser/internal/sandbox/hugbox.go b/src/cmd/sandboxed-tor-browser/internal/sandbox/hugbox.go
index 118b7a7..dd2e51a 100644
--- a/src/cmd/sandboxed-tor-browser/internal/sandbox/hugbox.go
+++ b/src/cmd/sandboxed-tor-browser/internal/sandbox/hugbox.go
@@ -91,9 +91,10 @@ type hugbox struct {
 
 	// Internal options, not to be *modified* except via helpers, unless you
 	// know what you are doing.
-	bwrapPath string
-	args      []string
-	fileData  [][]byte
+	bwrapPath    string
+	bwrapVersion *bwrapVersion
+	args         []string
+	fileData     [][]byte
 
 	runtimeDir string // Set at creation time.
 }
@@ -244,6 +245,12 @@ func (h *hugbox) run() (*Process, error) {
 	h.file("/etc/passwd", []byte(passwdBody))
 	h.file("/etc/group", []byte(groupBody))
 
+	dieWithParent := h.bwrapVersion.atLeast(0, 1, 8)
+	if dieWithParent {
+		Debugf("sandbox: bubblewrap supports `--die-with-parent`.")
+		fdArgs = append(fdArgs, "--die-with-parent")
+	}
+
 	if h.fakeDbus {
 		h.setupDbus()
 	}
@@ -421,23 +428,47 @@ func newHugbox() (*hugbox, error) {
 		return nil, fmt.Errorf("sandbox: unable to find bubblewrap binary")
 	}
 
-	// Bubblewrap <= 0.1.2-2 (in Debian terms, 0.1.3 for the rest of us), is
-	// a really bad idea because I'm a retard, and didn't expect bubblewrap
-	// to be ptrace-able when I contributed support for the hostname.
-	//
-	// There is a CVE for it.  Sensible people have made 0.1.3 available,
-	// including jessie-backports.  Ubuntu is still shipping an old version.
-	// Sucks to be them.
-	if ok, err := bubblewrapAtLeast(h.bwrapPath, 0, 1, 3); err != nil {
+	// Query and cache the bubblewrap version.
+	var err error
+	if h.bwrapVersion, err = getBwrapVersion(h.bwrapPath); err != nil {
 		return nil, err
-	} else if !ok {
-		return nil, fmt.Errorf("sandbox: bubblewrap appears to be older than 0.1.3, you MUST upgrade.")
+	} else {
+		Debugf("sandbox: bubblewrap '%v' detected.", h.bwrapVersion)
+
+		// Bubblewrap <= 0.1.2-2 (in Debian terms, 0.1.3 for the rest of us),
+		// is a really bad idea because I'm a retard, and didn't expect
+		// bubblewrap to be ptrace-able when I contributed support for setting
+		// the hostname.
+		if !h.bwrapVersion.atLeast(0, 1, 3) {
+			return nil, fmt.Errorf("sandbox: bubblewrap appears to be older than 0.1.3, you MUST upgrade.")
+		}
 	}
 
 	return h, nil
 }
 
-func getBubblewrapVersion(f string) (int, int, int, error) {
+type bwrapVersion struct {
+	maj, min, pl int
+}
+
+func (v *bwrapVersion) atLeast(maj, min, pl int) bool {
+	if v.maj > maj {
+		return true
+	}
+	if v.maj == maj && v.min > min {
+		return true
+	}
+	if v.maj == maj && v.min == min && v.pl >= pl {
+		return true
+	}
+	return false
+}
+
+func (v *bwrapVersion) String() string {
+	return fmt.Sprintf("%d.%d.%d", v.maj, v.min, v.pl)
+}
+
+func getBwrapVersion(f string) (*bwrapVersion, error) {
 	cmd := &exec.Cmd{
 		Path: f,
 		Args: []string{f, "--version"},
@@ -448,7 +479,7 @@ func getBubblewrapVersion(f string) (int, int, int, error) {
 	}
 	out, err := cmd.CombinedOutput()
 	if err != nil {
-		return 0, 0, 0, fmt.Errorf("sandbox: failed to query bubblewrap version: %v", string(out))
+		return nil, fmt.Errorf("sandbox: failed to query bubblewrap version: %v", string(out))
 	}
 	vStr := strings.TrimPrefix(string(out), "bubblewrap ")
 	vStr = strings.TrimSpace(vStr)
@@ -456,37 +487,20 @@ func getBubblewrapVersion(f string) (int, int, int, error) {
 	// Split into major/minor/pl.
 	v := strings.Split(vStr, ".")
 	if len(v) < 3 {
-		return 0, 0, 0, fmt.Errorf("unable to determine bubblewrap version")
+		return nil, fmt.Errorf("unable to determine bubblewrap version")
 	}
 
+	// Parse the version.
 	var iVers [3]int
 	for i := 0; i < 3; i++ {
 		iv, err := strconv.Atoi(v[i])
 		if err != nil {
-			return 0, 0, 0, fmt.Errorf("unable to determine bubblewrap version: %v", err)
+			return nil, fmt.Errorf("unable to parse bubblewrap version: %v", err)
 		}
 		iVers[i] = iv
 	}
 
-	return iVers[0], iVers[1], iVers[2], nil
-}
-
-func bubblewrapAtLeast(f string, maj, min, pl int) (bool, error) {
-	iMaj, iMin, iPl, err := getBubblewrapVersion(f)
-	if err != nil {
-		return false, err
-	}
-
-	if iMaj > maj {
-		return true, nil
-	}
-	if iMaj == maj && iMin > min {
-		return true, nil
-	}
-	if iMaj == maj && iMin == min && iPl >= pl {
-		return true, nil
-	}
-	return false, nil
+	return &bwrapVersion{maj: iVers[0], min: iVers[1], pl: iVers[2]}, nil
 }
 
 func writeBuffer(w io.WriteCloser, contents []byte) error {



More information about the tor-commits mailing list