Bug 1323302 - Refuse to run under sudo or otherwise as root in a non-root user's session. r=glandium draft
authorJed Davis <jld@mozilla.com>
Fri, 30 Mar 2018 18:17:24 -0600
changeset 778215 1a0898cc50eecea80a333b3a9ad70ba285b77820
parent 778203 7b40283bf1c7a2a3e6a8a5d00156a2f506ff465b
push id105435
push userbmo:jld@mozilla.com
push dateThu, 05 Apr 2018 23:21:35 +0000
reviewersglandium
bugs1323302
milestone61.0a1
Bug 1323302 - Refuse to run under sudo or otherwise as root in a non-root user's session. r=glandium MozReview-Commit-ID: EFq9hULWqA8
toolkit/xre/moz.build
toolkit/xre/nsAppRunner.cpp
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -139,18 +139,18 @@ if CONFIG['MOZ_PDF_PRINTING']:
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_GL_DEFAULT_PROVIDER'] == 'GLX':
     DEFINES['USE_GLX_TEST'] = True
 
-for var in ('MOZ_APP_NAME', 'MOZ_APP_BASENAME', 'MOZ_APP_VERSION', 'OS_TARGET',
-            'MOZ_WIDGET_TOOLKIT'):
+for var in ('MOZ_APP_NAME', 'MOZ_APP_BASENAME', 'MOZ_APP_DISPLAYNAME',
+            'MOZ_APP_VERSION', 'OS_TARGET', 'MOZ_WIDGET_TOOLKIT'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
 if CONFIG['MOZ_UPDATER'] and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
     DEFINES['MOZ_UPDATER'] = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DEFINES['WIN32_LEAN_AND_MEAN'] = True
     DEFINES['UNICODE'] = True
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3188,16 +3188,75 @@ bool SafeModeBlockedByPolicy()
     return value == 1;
   }
   return false;
 }
 
 } // anonymous namespace
 #endif // XP_WIN
 
+#if defined(XP_UNIX) && !defined(ANDROID)
+static SmprintfPointer
+FormatUid(uid_t aId)
+{
+  if (const auto pw = getpwuid(aId)) {
+    return mozilla::Smprintf("%s", pw->pw_name);
+  }
+  return mozilla::Smprintf("uid %d", static_cast<int>(aId));
+}
+
+// Bug 1323302: refuse to run under sudo or similar.
+static bool
+CheckForUserMismatch()
+{
+  static char const * const kVars[] = {
+    "HOME",
+#ifdef MOZ_WIDGET_GTK
+    "XDG_RUNTIME_DIR",
+#endif
+#ifdef MOZ_X11
+    "XAUTHORITY",
+#endif
+  };
+
+  const uid_t euid = geteuid();
+  if (euid != 0) {
+    // On Linux it's possible to have superuser capabilities with a
+    // nonzero uid, but anyone who knows enough to make that happen
+    // probably knows enough to debug the resulting problems.
+    // Otherwise, a non-root user can't cause the problems we're
+    // concerned about.
+    return false;
+  }
+
+  for (const auto var : kVars) {
+    if (const auto path = PR_GetEnv(var)) {
+      struct stat st;
+      if (stat(path, &st) == 0) {
+        if (st.st_uid != euid) {
+          const auto owner = FormatUid(st.st_uid);
+          Output(true, "Running " MOZ_APP_DISPLAYNAME " as root in a regular"
+                 " user's session is not supported.  ($%s is %s which is"
+                 " owned by %s.)\n",
+                 var, path, owner.get());
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+#else // !XP_UNIX || ANDROID
+static bool
+CheckForUserMismatch()
+{
+  return false;
+}
+#endif
+
 /*
  * XRE_mainInit - Initial setup and command line parameter processing.
  * Main() will exit early if either return value != 0 or if aExitFlag is
  * true.
  */
 int
 XREMain::XRE_mainInit(bool* aExitFlag)
 {
@@ -3207,16 +3266,20 @@ XREMain::XRE_mainInit(bool* aExitFlag)
 
   atexit(UnexpectedExit);
   auto expectedShutdown = mozilla::MakeScopeExit([&] {
     MozExpectedExit();
   });
 
   StartupTimeline::Record(StartupTimeline::MAIN);
 
+  if (CheckForUserMismatch()) {
+    return 1;
+  }
+
   if (PR_GetEnv("MOZ_CHAOSMODE")) {
     ChaosFeature feature = ChaosFeature::Any;
     long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
     if (featureInt) {
       // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
       feature = static_cast<ChaosFeature>(featureInt);
     }
     ChaosMode::SetChaosFeature(feature);