Bug 1515712 - check bundled JAR and XPI files for corruption r=kmag,chutten
authorRobert Helmer <rhelmer@mozilla.com>
Sat, 20 Apr 2019 05:10:00 +0000
changeset 470277 ac6c0bc531e39347f998e8fcd8611ca209a20b1b
parent 470276 718402b108aaa7d0fce776967dd6a141fc1e50b1
child 470278 6e082b6757630d3c57382feb106a674056881f86
push id35891
push userrgurzau@mozilla.com
push dateSat, 20 Apr 2019 09:35:22 +0000
treeherdermozilla-central@6e082b675763 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag, chutten
bugs1515712
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1515712 - check bundled JAR and XPI files for corruption r=kmag,chutten Differential Revision: https://phabricator.services.mozilla.com/D15123
toolkit/components/corroborator/Corroborate.jsm
toolkit/components/corroborator/moz.build
toolkit/components/corroborator/test/xpcshell/data/privileged.xpi
toolkit/components/corroborator/test/xpcshell/data/signed-amo.xpi
toolkit/components/corroborator/test/xpcshell/data/signed-components.xpi
toolkit/components/corroborator/test/xpcshell/data/signed-privileged.xpi
toolkit/components/corroborator/test/xpcshell/data/unsigned.xpi
toolkit/components/corroborator/test/xpcshell/test_verify_jar.js
toolkit/components/corroborator/test/xpcshell/xpcshell.ini
toolkit/components/moz.build
toolkit/components/telemetry/Scalars.yaml
new file mode 100644
--- /dev/null
+++ b/toolkit/components/corroborator/Corroborate.jsm
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+const {FileUtils} = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetters(this, {
+  gCertDB: ["@mozilla.org/security/x509certdb;1", "nsIX509CertDB"],
+});
+
+var EXPORTED_SYMBOLS = ["Corroborate"];
+
+/**
+ * Tools for verifying internal files in Mozilla products.
+ */
+this.Corroborate = {
+  async init() {
+    const appOmniJar = FileUtils.getFile("XCurProcD", [AppConstants.OMNIJAR_NAME]);
+    const greOmniJar = FileUtils.getFile("GreD", [AppConstants.OMNIJAR_NAME]);
+    const systemAddons = FileUtils.getFile("XCurProcD", ["features"]);
+
+    let corruptOmnijar = true;
+    // If an omni jar is missing, we consider that corrupt. Firefox could be running with
+    // an omni jar unpacked, but it would never be signed correctly in that case so there
+    // isn't a point checking further.
+    if (appOmniJar.exists() && greOmniJar.exists()) {
+      corruptOmnijar = !(await this.verifyJar(appOmniJar) && await this.verifyJar(greOmniJar));
+    }
+
+    // It's not necessarily a problem if all built-in system add-ons have been removed,
+    // more that we want to know if any unsigned add-ons are present. The Telemetry Environment
+    // shows which system add-ons are present, anyway.
+    let corruptSystemAddons = false;
+    for (let file of systemAddons.directoryEntries) {
+      if (!await this.verifyJar(file)) {
+        corruptSystemAddons = true;
+        break;
+      }
+    }
+
+    this.reportTelemetry(corruptOmnijar, corruptSystemAddons);
+  },
+
+  /**
+  * Verify signed state of arbitrary JAR file. Currently only JAR files signed
+  * with Mozilla-internal keys are supported.
+  *
+  * @argument file - an nsIFile pointing to the JAR to verify.
+  *
+  * @returns {Promise} - resolves true if file exists and is valid, false otherwise.
+  *                      Never rejects.
+  */
+  verifyJar(file) {
+    let root = Ci.nsIX509CertDB.AddonsPublicRoot;
+    let expectedOrganizationalUnit = "Mozilla Components";
+
+    return new Promise(resolve => {
+      gCertDB.openSignedAppFileAsync(root, file, (rv, _zipReader, cert) => {
+        resolve(Components.isSuccessCode(rv) && cert.organizationalUnit === expectedOrganizationalUnit);
+      });
+    });
+  },
+
+  reportTelemetry(corruptOmnijar, corruptSystemAddons) {
+    Services.telemetry.scalarSet("corroborate.omnijar_corrupted", corruptOmnijar);
+    Services.telemetry.scalarSet("corroborate.system_addons_corrupted", corruptSystemAddons);
+  },
+};
new file mode 100644
--- /dev/null
+++ b/toolkit/components/corroborator/moz.build
@@ -0,0 +1,17 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# 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/.
+
+
+with Files('**'):
+    BUG_COMPONENT = ('Toolkit', 'General')
+
+EXTRA_JS_MODULES += [
+    'Corroborate.jsm',
+]
+
+XPCSHELL_TESTS_MANIFESTS += [
+    'test/xpcshell/xpcshell.ini',
+]
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c22acaacd2fe68e93e61022ae4a39da19a5fd69d
GIT binary patch
literal 4659
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
U(I6(d01%&lHs{;c(q3r)0cXuM5&!@I
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e2ba7d6fd83b474c5d252af0bcb0041068858a97
GIT binary patch
literal 4702
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
QKz6x2FR%UjXL$hs0oyWbEC2ui
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f27ac1fb73ffe1cf53f84757fb742d815fb02823
GIT binary patch
literal 6995
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
E17mB@C;$Ke
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c22acaacd2fe68e93e61022ae4a39da19a5fd69d
GIT binary patch
literal 4659
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
U(I6(d01%&lHs{;c(q3r)0cXuM5&!@I
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9e10be5db3bf82ff31a9829a4378fc9ed6406ff7
GIT binary patch
literal 528
zc$^FHW@h1H00EWM65k^GiC1R=*&xizAj6QGn3tKBT3n)+Rh*v}8p6rIoLu-N8iY$L
zxEUB(zA`c}u!sN^S92*SD8W?6m!%dJXXfWASt%IlfF$w~b5nsFr4XQ`f@4aGE>I3E
zfl#Pqq-OvW0|_P;6y#(kCzb#uih(j9qk*F7sma;-a4t|FGX<or1Zbo~aei)Uc}8kc
zs$Oz_t`b;5Ef)yaas|Nsx4a|Mw|49LY;zzRggJoz1L@W)sVD(^?UdfLXemsug=AzF
zD}WR#q-Ex$DkLZ7DI}#TB<7R=?MqQ8$yZ1!N=?jGD9%jJ%gjqxNX`H{v{(;lF(Z>4
zGp?YOV1R)ojUW;&pjjaSjph<$BQbr0Y~%wViSQdM#BUg;v9f_wGXdd3ARWmF;sF5d
C{()2g
new file mode 100644
--- /dev/null
+++ b/toolkit/components/corroborator/test/xpcshell/test_verify_jar.js
@@ -0,0 +1,39 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+const {Corroborate} = ChromeUtils.import("resource://gre/modules/Corroborate.jsm");
+const {FileUtils} = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+
+add_task(async function test_various_jars() {
+  let result = await Corroborate.verifyJar(do_get_file("data/unsigned.xpi"));
+  equal(result, false, "unsigned files do not verify");
+
+  result = await Corroborate.verifyJar(do_get_file("data/signed-amo.xpi"));
+  equal(result, false, "AMO signed files do not verify");
+
+  result = await Corroborate.verifyJar(do_get_file("data/signed-privileged.xpi"));
+  equal(result, false, "Privileged signed files do not verify");
+
+  let missingFile = do_get_file("data");
+  missingFile.append("missing.xpi");
+
+  result = await Corroborate.verifyJar(missingFile);
+  equal(result, false, "Missing (but expected) files do not verify");
+
+  result = await Corroborate.verifyJar(do_get_file("data/signed-components.xpi"));
+  equal(result, true, "Components signed files do verify");
+});
+
+add_task(async function test_telemetry() {
+  Corroborate.reportTelemetry(true, false);
+
+  const scalars = Services.telemetry.getSnapshotForScalars("main", false).parent;
+
+  ok("corroborate.omnijar_corrupted" in scalars,
+     "omni jar should be corrupted");
+  ok("corroborate.system_addons_corrupted" in scalars,
+     "system addons should not be corrupted");
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/corroborator/test/xpcshell/xpcshell.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+tags = corroborator
+support-files =
+  data/**
+
+[test_verify_jar.js]
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -114,8 +114,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'andr
     ]
 
     XPCOM_MANIFESTS += [
         'components.conf',
     ]
 
 if CONFIG['MOZ_BUILD_APP'] == 'browser':
     DIRS += ['normandy']
+
+# This is only packaged for browser since corrupt JAR and XPI files tend to be a desktop-OS problem.
+if CONFIG['MOZ_BUILD_APP'] == 'browser':
+    DIRS += ['corroborator']
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -4035,11 +4035,39 @@ telemetry.test:
     notification_emails:
       - telemetry-client-dev@mozilla.com
     record_in_processes:
       - 'main'
     record_into_store:
       - 'main'
       - 'sync'
 
+# The following section contains counters for corruption of internal JAR and XPI files.
+corroborate:
+  omnijar_corrupted:
+    bug_numbers:
+      - 1515712
+    description: >-
+          Whether the omni jar (omni.ja) was found to be missing or corrupt when checked during startup.
+    expires: "71"
+    kind: boolean
+    notification_emails:
+      - rhelmer@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - main
+
+  system_addons_corrupted:
+    bug_numbers:
+      - 1515712
+    description: >-
+      Whether any system add-on (XPI files) were found to be missing or corrupt when checked during startup.
+    expires: "71"
+    kind: boolean
+    notification_emails:
+      - rhelmer@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - main
+
 # NOTE: Please don't add new definitions below this point. Consider adding
 # them earlier in the file and leave the telemetry.test category as the last
 # one for readability.