Bug 1323302 - Refuse to run under sudo or otherwise as root in a non-root user's session. r=glandium
MozReview-Commit-ID: EFq9hULWqA8
--- 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);