[tor-commits] [tor-browser/tor-browser-31.3.0esr-4.5-1] Bug 13379: Sign our MAR files.

brade at torproject.org brade at torproject.org
Wed Dec 17 22:06:24 UTC 2014


commit 7612aeba131f3eca1c80a369aab97da6fc249565
Author: Kathy Brade <brade at pearlcrescent.com>
Date:   Wed Dec 17 16:37:11 2014 -0500

    Bug 13379: Sign our MAR files.
    
    Configure with --enable-signmar (build the signmar tool).
    Configure with --enable-verify-mar (when updating, require a valid signature
      on the MAR file before it is applied).
    Use the Tor Browser version instead of the Firefox version inside the
      MAR file info block (necessary to prevent downgrade attacks).
    Use NSS on all platforms for checking MAR signatures (Mozilla plans to use
      OS-native APIs on Mac OS and they already do so on Windows).  So that the
      NSS and NSPR libraries the updater depends on can be found at runtime, we
      add the firefox directory to the shared library search path on all platforms.
    Use SHA512-based MAR signatures instead of the SHA1-based ones that Mozilla
      uses.  This is implemented inside MAR_USE_SHA512_RSA_SIG #ifdef's and with
      a signature algorithm ID of 512 to help avoid collisions with future work
      Mozilla might do in this area.
      See: https://bugzilla.mozilla.org/show_bug.cgi?id=1105689
---
 .mozconfig                                 |    4 +--
 .mozconfig-mac                             |    4 +--
 .mozconfig-mingw                           |    4 +--
 modules/libmar/sign/mar_sign.c             |   15 ++++++++--
 modules/libmar/sign/moz.build              |    1 +
 modules/libmar/src/mar_private.h           |    8 +++++
 modules/libmar/tool/Makefile.in            |    1 -
 modules/libmar/tool/mar.c                  |   26 +++++++++++-----
 modules/libmar/tool/moz.build              |    7 +++++
 modules/libmar/verify/cryptox.c            |    8 +++--
 modules/libmar/verify/cryptox.h            |    9 ++++++
 modules/libmar/verify/mar_verify.c         |   21 +++++++++++--
 modules/libmar/verify/moz.build            |   14 +++------
 security/build/Makefile.in                 |    2 +-
 toolkit/mozapps/update/updater/Makefile.in |   14 ++++++++-
 toolkit/mozapps/update/updater/moz.build   |    1 +
 toolkit/mozapps/update/updater/updater.cpp |   21 ++++++++-----
 toolkit/xre/nsUpdateDriver.cpp             |   44 +++++++++++++++++-----------
 18 files changed, 147 insertions(+), 57 deletions(-)

diff --git a/.mozconfig b/.mozconfig
index f0c5510..f2874e8 100755
--- a/.mozconfig
+++ b/.mozconfig
@@ -11,8 +11,8 @@ ac_add_options --enable-optimize
 ac_add_options --enable-official-branding
 ac_add_options --enable-tor-browser-update
 ac_add_options --enable-update-packaging
-# We do not use signed MAR files yet (Mozilla uses them on Windows only).
-ac_add_options --disable-verify-mar
+ac_add_options --enable-signmar
+ac_add_options --enable-verify-mar
 ac_add_options --disable-strip
 ac_add_options --disable-install-strip
 ac_add_options --disable-tests
diff --git a/.mozconfig-mac b/.mozconfig-mac
index 2c06c34..06dc226 100644
--- a/.mozconfig-mac
+++ b/.mozconfig-mac
@@ -38,8 +38,8 @@ ac_add_options --disable-debug
 
 ac_add_options --enable-tor-browser-update
 ac_add_options --enable-update-packaging
-# We do not use signed MAR files yet (Mozilla uses them on Windows only).
-ac_add_options --disable-verify-mar
+ac_add_options --enable-signmar
+ac_add_options --enable-verify-mar
 
 # ICU seems still to have cross-compiling issues:
 ac_add_options --without-intl-api
diff --git a/.mozconfig-mingw b/.mozconfig-mingw
index 691178b..15954d7 100644
--- a/.mozconfig-mingw
+++ b/.mozconfig-mingw
@@ -16,8 +16,8 @@ ac_add_options --enable-strip
 ac_add_options --enable-official-branding
 ac_add_options --enable-tor-browser-update
 ac_add_options --enable-update-packaging
-# We do not use signed MAR files yet (Mozilla uses them on Windows only).
-ac_add_options --disable-verify-mar
+ac_add_options --enable-signmar
+ac_add_options --enable-verify-mar
 
 # ICU seems still to have cross-compiling issues:
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1019744#c19
diff --git a/modules/libmar/sign/mar_sign.c b/modules/libmar/sign/mar_sign.c
index 6f21a31..e867d28 100644
--- a/modules/libmar/sign/mar_sign.c
+++ b/modules/libmar/sign/mar_sign.c
@@ -95,7 +95,12 @@ NSSSignBegin(const char *certName,
     return -1;
   }
 
-  *ctx = SGN_NewContext (SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, *privKey);
+#ifdef MAR_USE_SHA512_RSA_SIG
+  SECOidTag sigAlg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+#else
+  SECOidTag sigAlg = SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE;
+#endif
+  *ctx = SGN_NewContext (sigAlg, *privKey);
   if (!*ctx) {
     fprintf(stderr, "ERROR: Could not create signature context\n");
     return -1;
@@ -991,8 +996,12 @@ mar_repackage_and_sign(const char *NSSConfigDir,
   signaturePlaceholderOffset = ftello(fpDest);
 
   for (k = 0; k < certCount; k++) {
-    /* Write out the signature algorithm ID, Only an ID of 1 is supported */
-    signatureAlgorithmID = htonl(1);
+    /* Write out the signature algorithm ID. */
+#ifdef MAR_USE_SHA512_RSA_SIG
+    signatureAlgorithmID = htonl(SIGNATURE_ALGORITHM_ID_SHA512_RSA);
+#else
+    signatureAlgorithmID = htonl(SIGNATURE_ALGORITHM_ID_SHA1_RSA);
+#endif
     if (WriteAndUpdateSignatures(fpDest, &signatureAlgorithmID,
                                  sizeof(signatureAlgorithmID),
                                  ctxs, certCount, "num signatures")) {
diff --git a/modules/libmar/sign/moz.build b/modules/libmar/sign/moz.build
index a6d0308..2be6da2 100644
--- a/modules/libmar/sign/moz.build
+++ b/modules/libmar/sign/moz.build
@@ -19,6 +19,7 @@ LOCAL_INCLUDES += [
 ]
 
 DEFINES['MAR_NSS'] = True
+DEFINES['MAR_USE_SHA512_RSA_SIG'] = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     USE_STATIC_LIBS = True
diff --git a/modules/libmar/src/mar_private.h b/modules/libmar/src/mar_private.h
index e0c2632..add03f5 100644
--- a/modules/libmar/src/mar_private.h
+++ b/modules/libmar/src/mar_private.h
@@ -21,6 +21,14 @@
    which is 16 bytes */
 #define SIGNATURE_BLOCK_OFFSET 16
 
+/* Signature algorithm IDs. */
+#define SIGNATURE_ALGORITHM_ID_SHA1_RSA 1
+#ifdef MAR_USE_SHA512_RSA_SIG
+/* Use 512 as the algorithm ID so it is less likely that we will conflict with
+   whatever Mozilla chooses when they add support for a stronger signature. */
+#define SIGNATURE_ALGORITHM_ID_SHA512_RSA 512
+#endif
+
 /* Make sure the file is less than 500MB.  We do this to protect against
    invalid MAR files. */
 #define MAX_SIZE_OF_MAR_FILE ((int64_t)524288000)
diff --git a/modules/libmar/tool/Makefile.in b/modules/libmar/tool/Makefile.in
index fb456726..06ec0ea 100644
--- a/modules/libmar/tool/Makefile.in
+++ b/modules/libmar/tool/Makefile.in
@@ -44,6 +44,5 @@ include $(topsrcdir)/config/rules.mk
 ifdef CROSS_COMPILE
 ifdef HOST_NSPR_MDCPUCFG
 HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
-CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
 endif
 endif
diff --git a/modules/libmar/tool/mar.c b/modules/libmar/tool/mar.c
index 821813c..82701a9 100644
--- a/modules/libmar/tool/mar.c
+++ b/modules/libmar/tool/mar.c
@@ -31,7 +31,11 @@ int mar_repackage_and_sign(const char *NSSConfigDir,
                            const char * dest);
 
 static void print_version() {
+#ifdef TOR_BROWSER_UPDATE
+  printf("Version: %s\n", TOR_BROWSER_VERSION);
+#else
   printf("Version: %s\n", MOZ_APP_VERSION);
+#endif
   printf("Default Channel ID: %s\n", MAR_CHANNEL_ID);
 }
 
@@ -61,7 +65,7 @@ static void print_usage() {
          "signed_input_archive.mar base_64_encoded_signature_file "
          "changed_signed_output.mar\n");
   printf("(i) is the index of the certificate to extract\n");
-#if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(MAR_NSS))
+#if (defined(XP_MACOSX) || defined(XP_WIN)) && !defined(MAR_NSS)
   printf("Verify a MAR file:\n");
   printf("  mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
   printf("At most %d signature certificate DER files are specified by "
@@ -116,7 +120,11 @@ int main(int argc, char **argv) {
   char *NSSConfigDir = NULL;
   const char *certNames[MAX_SIGNATURES];
   char *MARChannelID = MAR_CHANNEL_ID;
+#ifdef TOR_BROWSER_UPDATE
+  char *productVersion = TOR_BROWSER_VERSION;
+#else
   char *productVersion = MOZ_APP_VERSION;
+#endif
   uint32_t i, k;
   int rv = -1;
   uint32_t certCount = 0;
@@ -135,8 +143,8 @@ int main(int argc, char **argv) {
 #if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
   memset(certBuffers, 0, sizeof(certBuffers));
 #endif
-#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
-                                 defined(XP_MACOSX))
+#if !defined(NO_SIGN_VERIFY) && (!defined(MAR_NSS) && (defined(XP_WIN) || \
+                                 defined(XP_MACOSX)))
   memset(DERFilePaths, 0, sizeof(DERFilePaths));
   memset(fileSizes, 0, sizeof(fileSizes));
 #endif
@@ -165,8 +173,8 @@ int main(int argc, char **argv) {
       argv += 2;
       argc -= 2;
     } 
-#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
-                                 defined(XP_MACOSX))
+#if !defined(NO_SIGN_VERIFY) && (!defined(MAR_NSS) && (defined(XP_WIN) || \
+                                 defined(XP_MACOSX)))
     /* -D DERFilePath, also matches -D[index] DERFilePath
        We allow an index for verifying to be symmetric
        with the import and export command line arguments. */
@@ -341,6 +349,10 @@ int main(int argc, char **argv) {
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
       rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
                                 &certBuffers[k], &fileSizes[k]);
+      if (rv) {
+        fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
+        break;
+      }
 #else
       /* It is somewhat circuitous to look up a CERTCertificate and then pass
        * in its DER encoding just so we can later re-create that
@@ -357,11 +369,11 @@ int main(int argc, char **argv) {
       } else {
         rv = -1;
       }
-#endif
       if (rv) {
-        fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
+        fprintf(stderr, "ERROR: no certificate named %s", certNames[k]);
         break;
       }
+#endif
     }
 
     if (!rv) {
diff --git a/modules/libmar/tool/moz.build b/modules/libmar/tool/moz.build
index 9e739e0..6b14e00 100644
--- a/modules/libmar/tool/moz.build
+++ b/modules/libmar/tool/moz.build
@@ -17,8 +17,15 @@ HOST_PROGRAM = 'mar'
 for var in ('MAR_CHANNEL_ID', 'MOZ_APP_VERSION'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
+if CONFIG['TOR_BROWSER_UPDATE']:
+    DEFINES['TOR_BROWSER_UPDATE'] = '%s' % CONFIG['TOR_BROWSER_UPDATE']
+if CONFIG['TOR_BROWSER_VERSION']:
+    DEFINES['TOR_BROWSER_VERSION'] = '"%s"' % CONFIG['TOR_BROWSER_VERSION']
+
 if not CONFIG['MOZ_ENABLE_SIGNMAR']:
     DEFINES['NO_SIGN_VERIFY'] = True
+else:
+    DEFINES['MAR_NSS'] = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     USE_STATIC_LIBS = True
diff --git a/modules/libmar/verify/cryptox.c b/modules/libmar/verify/cryptox.c
index af34210..f39669b 100644
--- a/modules/libmar/verify/cryptox.c
+++ b/modules/libmar/verify/cryptox.c
@@ -64,8 +64,12 @@ NSS_VerifyBegin(VFYContext **ctx,
     return CryptoX_Error;
   }
 
-  *ctx = VFY_CreateContext(*publicKey, NULL, 
-                           SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL);
+#ifdef MAR_USE_SHA512_RSA_SIG
+  SECOidTag sigAlg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+#else
+  SECOidTag sigAlg = SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE;
+#endif
+  *ctx = VFY_CreateContext(*publicKey, NULL, sigAlg, NULL);
   if (*ctx == NULL) {
     return CryptoX_Error;
   }
diff --git a/modules/libmar/verify/cryptox.h b/modules/libmar/verify/cryptox.h
index ec8f5ac..8f579b6 100644
--- a/modules/libmar/verify/cryptox.h
+++ b/modules/libmar/verify/cryptox.h
@@ -59,6 +59,10 @@ CryptoX_Result NSS_VerifySignature(VFYContext * const *ctx ,
 
 #elif XP_MACOSX
 
+#ifdef MAR_USE_SHA512_RSA_SIG
+#error MAR_USE_SHA512_RSA_SIG is not implemented.
+#endif
+
 #define CryptoX_InvalidHandleValue NULL
 #define CryptoX_ProviderHandle void*
 #define CryptoX_SignatureHandle void*
@@ -105,6 +109,11 @@ void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey);
 
 #elif defined(XP_WIN) 
 
+#ifdef MAR_USE_SHA512_RSA_SIG
+#error MAR_USE_SHA512_RSA_SIG is not implemented.
+#endif
+
+
 #include <windows.h>
 #include <wincrypt.h>
 
diff --git a/modules/libmar/verify/mar_verify.c b/modules/libmar/verify/mar_verify.c
index 165a802..78b3247 100644
--- a/modules/libmar/verify/mar_verify.c
+++ b/modules/libmar/verify/mar_verify.c
@@ -276,8 +276,25 @@ mar_extract_and_verify_signatures_fp(FILE *fp,
     }
 
     /* We don't try to verify signatures we don't know about */
-    if (signatureAlgorithmIDs[i] != 1) {
-      fprintf(stderr, "ERROR: Unknown signature algorithm ID.\n");
+#ifdef MAR_USE_SHA512_RSA_SIG
+    const uint32_t kSupportedAlgID = SIGNATURE_ALGORITHM_ID_SHA512_RSA;
+#else
+    const uint32_t kSupportedAlgID = SIGNATURE_ALGORITHM_ID_SHA1_RSA;
+#endif
+
+    if (signatureAlgorithmIDs[i] != kSupportedAlgID) {
+#ifdef MAR_USE_SHA512_RSA_SIG
+      if (signatureAlgorithmIDs[i] == SIGNATURE_ALGORITHM_ID_SHA1_RSA) {
+        fprintf(stderr,
+                "ERROR: Unsupported signature algorithm (SHA1 with RSA).\n");
+      } else {
+        fprintf(stderr, "ERROR: Unknown signature algorithm ID %u.\n",
+                        signatureAlgorithmIDs[i]);
+      }
+#else
+      fprintf(stderr, "ERROR: Unknown signature algorithm ID %u.\n",
+                      signatureAlgorithmIDs[i]);
+#endif
       for (i = 0; i < signatureCount; ++i) {
         free(extractedSignatures[i]);
       }
diff --git a/modules/libmar/verify/moz.build b/modules/libmar/verify/moz.build
index 6667bc1..ec5a3a2 100644
--- a/modules/libmar/verify/moz.build
+++ b/modules/libmar/verify/moz.build
@@ -15,16 +15,10 @@ FORCE_STATIC_LIB = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     USE_STATIC_LIBS = True
-elif CONFIG['OS_ARCH'] == 'Darwin':
-    UNIFIED_SOURCES += [
-      'MacVerifyCrypto.cpp',
-    ]
-    LDFLAGS += [
-      '-framework Security',
-    ]
-else:
-    DEFINES['MAR_NSS'] = True
-    LOCAL_INCLUDES += ['../sign']
+
+DEFINES['MAR_NSS'] = True
+DEFINES['MAR_USE_SHA512_RSA_SIG'] = True
+LOCAL_INCLUDES += ['../sign']
 
 LOCAL_INCLUDES += [
     '../src',
diff --git a/security/build/Makefile.in b/security/build/Makefile.in
index 0453492..816acd9 100644
--- a/security/build/Makefile.in
+++ b/security/build/Makefile.in
@@ -289,11 +289,11 @@ endif
 NSS_DIRS += \
   nss/cmd/lib \
   nss/cmd/shlibsign \
+  nss/cmd/certutil \
   $(NULL)
 
 ifdef ENABLE_TESTS
 NSS_DIRS += \
-  nss/cmd/certutil \
   nss/cmd/pk12util \
   nss/cmd/modutil \
   $(NULL)
diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in
index 52cdbeb..bdb9f27 100644
--- a/toolkit/mozapps/update/updater/Makefile.in
+++ b/toolkit/mozapps/update/updater/Makefile.in
@@ -3,6 +3,9 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+# Use NSS for MAR signature verification on all platforms:
+MAR_NSS=1
+
 # Don't link the updater against libmozglue. See bug 687139
 MOZ_GLUE_LDFLAGS =
 MOZ_GLUE_PROGRAM_LDFLAGS =
@@ -22,7 +25,14 @@ LIBS += $(call EXPAND_LIBNAME_PATH,signmar,$(DEPTH)/modules/libmar/sign)
 LIBS += $(call EXPAND_LIBNAME_PATH,verifymar,$(DEPTH)/modules/libmar/verify)
 ifeq ($(OS_ARCH),WINNT)
 OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32 shlwapi)
+ifdef MAR_NSS
+LINK_UPDATER_WITH_NSS=1
+endif
 else
+LINK_UPDATER_WITH_NSS=1
+endif
+
+ifdef LINK_UPDATER_WITH_NSS
 LIBS += $(DIST)/lib/$(LIB_PREFIX)nss3.$(LIB_SUFFIX) \
 	$(DIST)/lib/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \
 	$(NSPR_LIBS)
@@ -49,7 +59,7 @@ endif
 
 include $(topsrcdir)/config/rules.mk
 
-ifneq (,$(filter beta release esr,$(MOZ_UPDATE_CHANNEL)))
+ifneq (,$(filter alpha beta release esr,$(MOZ_UPDATE_CHANNEL)))
 	PRIMARY_CERT = release_primary.der
 	SECONDARY_CERT = release_secondary.der
 else ifneq (,$(filter nightly aurora nightly-elm nightly-profiling nightly-oak nightly-ux,$(MOZ_UPDATE_CHANNEL)))
@@ -81,9 +91,11 @@ libs::
 	rm -f $(DIST)/bin/updater
 endif
 
+ifndef LINK_UPDATER_WITH_NSS
 ifeq ($(OS_ARCH),WINNT)
 EXTRA_LIBS += $(call EXPAND_LIBNAME,crypt32)
 EXTRA_LIBS += $(call EXPAND_LIBNAME,advapi32)
 endif
+endif
 
 CXXFLAGS += $(MOZ_BZ2_CFLAGS)
diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build
index 833164a..950a6f8 100644
--- a/toolkit/mozapps/update/updater/moz.build
+++ b/toolkit/mozapps/update/updater/moz.build
@@ -57,6 +57,7 @@ if have_progressui == 0:
         'progressui_null.cpp',
     ]
 
+DEFINES['MAR_NSS'] = True
 DEFINES['NS_NO_XPCOM'] = True
 DISABLE_STL_WRAPPING = True
 for var in ('MAR_CHANNEL_ID', 'MOZ_APP_VERSION'):
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index 3a3968e..80de531 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -108,10 +108,12 @@ static bool sUseHardLinks = true;
 # define MAYBE_USE_HARD_LINKS 0
 #endif
 
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE)
+#if defined(MAR_NSS) || !defined(XP_WIN)
 #include "nss.h"
 #include "prerror.h"
 #endif
+#endif
 
 #ifdef XP_WIN
 #include "updatehelper.h"
@@ -2422,8 +2424,13 @@ UpdateThreadFunc(void *param)
           MARStrings.MARChannelID[0] = '\0';
         }
 
+#ifdef TOR_BROWSER_UPDATE
+        const char *appVersion = TOR_BROWSER_VERSION;
+#else
+        const char *appVersion = MOZ_APP_VERSION;
+#endif
         rv = gArchiveReader.VerifyProductInformation(MARStrings.MARChannelID,
-                                                     MOZ_APP_VERSION);
+                                                     appVersion);
       }
     }
 #endif
@@ -2526,11 +2533,10 @@ int NS_main(int argc, NS_tchar **argv)
   }
 #endif
 
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
-  // On Windows we rely on CyrptoAPI to do verifications so we don't need to
-  // initialize NSS at all there.
-  // Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
-  // databases.
+#if defined(MOZ_VERIFY_MAR_SIGNATURE)
+#if defined(MAR_NSS) || !defined(XP_WIN)
+  // If using NSS for signature verification, initialize NSS but minimize
+  // the portion we depend on by avoiding all of the NSS databases.
   if (NSS_NoDB_Init(NULL) != SECSuccess) {
    PRErrorCode error = PR_GetError();
    fprintf(stderr, "Could not initialize NSS: %s (%d)",
@@ -2538,6 +2544,7 @@ int NS_main(int argc, NS_tchar **argv)
     _exit(1);
   }
 #endif
+#endif
 
   InitProgressUI(&argc, &argv);
 
diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp
index 1188736..aeb2b6b 100644
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -17,6 +17,7 @@
 #include "prproces.h"
 #include "prlog.h"
 #include "prenv.h"
+#include "prprf.h"
 #include "nsVersionComparator.h"
 #include "nsXREDirProvider.h"
 #include "SpecialSystemDirectory.h"
@@ -39,7 +40,6 @@
 # include <windows.h>
 # include <shlwapi.h>
 # include "nsWindowsHelpers.h"
-# include "prprf.h"
 # define getcwd(path, size) _getcwd(path, size)
 # define getpid() GetCurrentProcessId()
 #elif defined(XP_UNIX)
@@ -134,25 +134,39 @@ GetCurrentWorkingDir(char *buf, size_t size)
 }
 
 
+// In Tor Browser, updater(.exe) depends on some shared libraries that are
+// located in the app directory.  To allow the updater to run when it has been
+// copied into the update directory, we prepend the app directory to the
+// appropriate environment variable so it will be searched by the dynamic
+// linker.
+
 #if defined(XP_WIN)
 #define PATH_SEPARATOR ";"
+#define LD_LIBRARY_PATH_ENVVAR_NAME "PATH"
+#else
+#define PATH_SEPARATOR ":"
+#if defined(XP_MACOSX)
+#define LD_LIBRARY_PATH_ENVVAR_NAME "DYLD_LIBRARY_PATH"
+#else
+#define LD_LIBRARY_PATH_ENVVAR_NAME "LD_LIBRARY_PATH"
+#endif
+#endif
 
-// In Tor Browser, updater.exe depends on some DLLs that are located in the
-// app directory.  To allow the updater to run when it has been copied into
-// the update directory, we append the app directory to the PATH.
 static nsresult
-AdjustPathForUpdater(nsIFile *appDir)
+AdjustLibSearchPathForUpdater(nsIFile *appDir)
 {
   nsAutoCString appPath;
   nsresult rv = appDir->GetNativePath(appPath);
   NS_ENSURE_SUCCESS(rv, rv);
 
   char *s = nullptr;
-  char *pathValue = PR_GetEnv("PATH");
+  char *pathValue = PR_GetEnv(LD_LIBRARY_PATH_ENVVAR_NAME);
   if ((nullptr == pathValue) || ('\0' == *pathValue)) {
-    s = PR_smprintf("PATH=%s", appPath.get());
+    s = PR_smprintf("%s=%s",
+                    LD_LIBRARY_PATH_ENVVAR_NAME, appPath.get());
   } else {
-    s = PR_smprintf("PATH=%s" PATH_SEPARATOR "%s", pathValue, appPath.get());
+    s = PR_smprintf("%s=%s" PATH_SEPARATOR "%s",
+                    LD_LIBRARY_PATH_ENVVAR_NAME, appPath.get(), pathValue);
   }
 
   // We intentionally leak the value that is passed into PR_SetEnv() because
@@ -162,7 +176,7 @@ AdjustPathForUpdater(nsIFile *appDir)
 
   return NS_OK;
 }
-#endif
+
 
 #ifdef DEBUG
 static void
@@ -623,12 +637,10 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
     PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
   }
 
-#if defined(XP_WIN)
-  nsresult rv2 = AdjustPathForUpdater(appDir);
+  nsresult rv2 = AdjustLibSearchPathForUpdater(appDir);
   if (NS_FAILED(rv2)) {
-    LOG(("SwitchToUpdatedApp -- AdjustPathForUpdater failed (0x%x)\n", rv2));
+    LOG(("SwitchToUpdatedApp -- AdjustLibSearchPathForUpdater failed (0x%x)\n", rv2));
   }
-#endif
 
   LOG(("spawning updater process for replacing [%s]\n", updaterPath.get()));
 
@@ -920,12 +932,10 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
     PR_SetEnv("MOZ_OS_UPDATE=1");
   }
 
-#if defined(XP_WIN)
-  nsresult rv2 = AdjustPathForUpdater(appDir);
+  nsresult rv2 = AdjustLibSearchPathForUpdater(appDir);
   if (NS_FAILED(rv2)) {
-    LOG(("ApplyUpdate -- AdjustPathForUpdater failed (0x%x)\n", rv2));
+    LOG(("ApplyUpdate -- AdjustLibSearchPathForUpdater failed (0x%x)\n", rv2));
   }
-#endif
 
 #if defined(MOZ_WIDGET_GONK)
   // We want the updater to be CPU friendly and not subject to being killed by



More information about the tor-commits mailing list