[tor-commits] [sandboxed-tor-browser/master] Bundle version handling improvements.

yawning at torproject.org yawning at torproject.org
Thu Dec 1 02:00:35 UTC 2016


commit 27241df5207a293b8452e92bd0b030dad233547b
Author: Yawning Angel <yawning at schwanenlied.me>
Date:   Thu Dec 1 01:39:59 2016 +0000

    Bundle version handling improvements.
    
     * Add the ability to compare string formatted versions vs the installed
       version in the manifest.
     * On update, check to ensure that it will actually be an update, and
       not a sidegrade/downgrade.
    
    The code banks on alpha versioning starting at 1, eg: "7.0a1".
---
 .../internal/sandbox/application.go                |  2 +-
 .../internal/ui/config/manifest.go                 | 84 +++++++++++++++++-----
 .../sandboxed-tor-browser/internal/ui/install.go   | 11 ++-
 3 files changed, 75 insertions(+), 22 deletions(-)

diff --git a/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go b/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go
index a431dac..7620802 100644
--- a/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go
+++ b/src/cmd/sandboxed-tor-browser/internal/sandbox/application.go
@@ -287,7 +287,7 @@ func applyPaXAttributes(manif *config.Manifest, f string) error {
 	// Strip off the attribute if this is a non-grsec kernel, or the bundle is
 	// sufficiently recent to the point where the required W^X fixes are present
 	// in the JIT.
-	if !IsGrsecKernel() || manif.BundleVersionAtLeast(7, 0) {
+	if !IsGrsecKernel() || manif.BundleVersionAtLeast("7.0a1") {
 		if sz > 0 {
 			log.Printf("sandbox: Removing Tor Browser PaX attributes.")
 			syscall.Removexattr(f, paxAttr)
diff --git a/src/cmd/sandboxed-tor-browser/internal/ui/config/manifest.go b/src/cmd/sandboxed-tor-browser/internal/ui/config/manifest.go
index 4891d37..393a31e 100644
--- a/src/cmd/sandboxed-tor-browser/internal/ui/config/manifest.go
+++ b/src/cmd/sandboxed-tor-browser/internal/ui/config/manifest.go
@@ -71,38 +71,84 @@ func (m *Manifest) Sync() error {
 
 // BundleVersionAtLeast returns true if the bundle version is greater than or
 // equal to the specified version.
-func (m *Manifest) BundleVersionAtLeast(major, minor int) bool {
-	vStr := strings.TrimSuffix(m.Version, "-hardened")
-	if m.Version == "" {
+func (m *Manifest) BundleVersionAtLeast(vStr string) bool {
+	cmp, err := bundleVersionCompare(m.Version, vStr)
+	if err != nil {
 		return false
 	}
-	if m.Channel == "alpha" || m.Channel == "hardened" {
-		vStr = strings.Replace(vStr, "a", ".", 1)
-	}
+	return cmp >= 0
+}
 
-	// Split into major/minor/pl.
-	v := strings.Split(vStr, ".")
-	if len(v) < 2 { // Need at least a major/minor.
+// BundleUpdateVersionValid returns true if the proposed update version is
+// actually an update.
+func (m *Manifest) BundleUpdateVersionValid(vStr string) bool {
+	cmp, err := bundleVersionCompare(m.Version, vStr)
+	if err != nil {
 		return false
 	}
+	return cmp < 0
+}
+
+func bundleVersionParse(vStr string) (*[4]int, error) {
+	vStr = strings.TrimSuffix(vStr, "-hardened")
+	vStr = strings.Replace(vStr, "a", ".0.", 1)
+
+	var out [4]int
+	for idx, s := range strings.Split(vStr, ".") {
+		i, err := strconv.Atoi(s)
+		if err != nil {
+			return nil, err
+		}
+		out[idx] = i
+	}
+	out[3] = -out[3] // XXX: I hope there never is "7.0a" or "7.0a0"
+
+	return &out, nil
+}
+
+func bundleVersionCompare(a, b string) (int, error) {
+	a = strings.ToLower(strings.TrimSpace(a))
+	b = strings.ToLower(strings.TrimSpace(b))
+
+	if a == b {
+		return 0, nil // Equal.
+	}
 
-	iMaj, err := strconv.Atoi(v[0])
+	aVer, err := bundleVersionParse(a)
 	if err != nil {
-		return false
+		return 0, err
 	}
-	iMin, err := strconv.Atoi(v[1])
+	bVer, err := bundleVersionParse(b)
 	if err != nil {
-		return false
+		return 0, err
+	}
+
+	for i := 0; i < 3; i++ {
+		if aVer[i] > bVer[i] {
+			return 1, nil
+		}
+		if aVer[i] < bVer[i] {
+			return -1, nil
+		}
+	}
+
+	if aVer[3] < 0 && bVer[3] >= 0 { // Alpha vs Release.
+		return -1, nil
+	}
+	if aVer[3] >= 0 && bVer[3] < 0 { // Release vs Alpha.
+		return 1, nil
 	}
 
-	// Do the version comparison.
-	if iMaj > major {
-		return true
+	// Alpha vs Alpha.
+	aVer[3], bVer[3] = -aVer[3], -bVer[3]
+	if aVer[3] < bVer[3] {
+		return -1, nil
 	}
-	if iMaj == major && iMin >= minor {
-		return true
+	if bVer[3] < aVer[3] {
+		return 1, nil
 	}
-	return false
+
+	return 0, nil // One is probably hardened, the other isn't.
 }
 
 // Purge deletes the manifest.
diff --git a/src/cmd/sandboxed-tor-browser/internal/ui/install.go b/src/cmd/sandboxed-tor-browser/internal/ui/install.go
index 16bde15..5680319 100644
--- a/src/cmd/sandboxed-tor-browser/internal/ui/install.go
+++ b/src/cmd/sandboxed-tor-browser/internal/ui/install.go
@@ -210,11 +210,18 @@ func (c *Common) doUpdate(async *Async, dialFn dialFunc) {
 		return
 	}
 
+	// Ensure that the update entry version is actually neweer.
+	if !c.Manif.BundleUpdateVersionValid(update.AppVersion) {
+		log.Printf("launch: Update server provided a downgrade: '%v'", update.AppVersion)
+		async.Err = fmt.Errorf("update server provided a downgrade: '%v'", update.AppVersion)
+		return
+	}
+
 	// Figure out the best MAR to download.
 	patches := make(map[string]*installer.Patch)
 	for _, v := range update.Patch {
 		if patches[v.Type] != nil {
-			async.Err = fmt.Errorf("duplicate patch entry for kind: %v", v.Type)
+			async.Err = fmt.Errorf("duplicate patch entry for kind: '%v'", v.Type)
 			return
 		}
 		patches[v.Type] = &v
@@ -253,7 +260,7 @@ func (c *Common) doUpdate(async *Async, dialFn dialFunc) {
 			return
 		}
 	default:
-		async.Err = fmt.Errorf("unsupported hash function: %v", patch.HashFunction)
+		async.Err = fmt.Errorf("unsupported hash function: '%v'", patch.HashFunction)
 		return
 	}
 



More information about the tor-commits mailing list