Medium firefox Logic Error 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionPrivilege escalation in the Application Update component
ComponentToolkit
Bug ClassLogic Error
Tracker2021757
Fix commitb9ccc4b5e502 (firefox) +85/-3
CISA KEVNot listed
CreditedTomoya Nakanishi
Disclosed2026-08-18

Changed Functions

FunctionChangeNotes
if
toolkit/mozapps/update/common/updatecommon.cpp
modified
if
toolkit/mozapps/update/updater/updater.cpp
modified

Files Changed

  • toolkit/mozapps/update/common/updatecommon.cpp
  • toolkit/mozapps/update/common/updatecommon.h
  • toolkit/mozapps/update/updater/updater.cpp
diff --git a/toolkit/mozapps/update/common/updatecommon.cpp b/toolkit/mozapps/update/common/updatecommon.cpp
index 05fdf6d60b6..ab967f68c51 100644
--- a/toolkit/mozapps/update/common/updatecommon.cpp
+++ b/toolkit/mozapps/update/common/updatecommon.cpp
@@ -2,6 +2,7 @@
  * 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/. */
 
+#include "updatedefines.h"
 #if defined(XP_WIN)
 #  include <windows.h>
 #  include <winioctl.h>  // for FSCTL_GET_REPARSE_POINT
@@ -11,6 +12,10 @@
 #  endif
 #endif
 
+#if defined(XP_MACOSX)
+#  include <os/log.h>
+#endif
+
 #include <stdio.h>
 #include <stdarg.h>
 
@@ -63,7 +68,10 @@ void UpdateLog::Init(NS_tchar* logFilePath) {
   if (dstFilePathLen > 0 && dstFilePathLen < MAXPATHLEN - 1) {
     NS_tstrncpy(mDstFilePath, logFilePath, MAXPATHLEN);
 #if defined(XP_WIN) || defined(XP_MACOSX)
-    logFP = NS_tfopen(mDstFilePath, NS_T("w"));
+    logFP = CreateAndOpenFile(mDstFilePath, false);
+    if (logFP == nullptr) {
+      LogToOS(NS_T("Failed to create FILE*"));
+    }
 #else
     // On platforms that have an updates directory in the installation directory
     // (e.g. platforms other than Windows and Mac) the update log is written to
@@ -87,7 +95,11 @@ void UpdateLog::Finish() {
   fflush(logFP);
   rewind(logFP);
 
-  FILE* updateLogFP = NS_tfopen(mDstFilePath, NS_T("wb+"));
+  FILE* updateLogFP = CreateAndOpenFile(mDstFilePath, true);
+  if (updateLogFP == nullptr) {
+    return;
+  }
+
   while (!feof(logFP)) {
     size_t read = fread(buffer, 1, blockSize, logFP);
     if (ferror(logFP)) {
@@ -190,6 +202,52 @@ void UpdateLog::WarnPrintf(const char* fmt, ...) {
   fflush(logFP);
 }
 
+/**
+ * Creates and opens a file for logging in read/write mode.
+ *
+ * @param filePath  The path of the log file.
+ * @param binary  If the file should be opened as binary (ignored on
+ * macOS/Linux).
+ * @return a pointer to the FILE struct or nullptr on error.
+ */
+FILE* CreateAndOpenFile(NS_tchar* filePath, bool binary) {
+#ifdef XP_WIN
+  return NS_tfopen(filePath, binary ? NS_T("wb+") : NS_T("w+"));
+#else
+  LogToOS(NS_T("Opening logfile"));
+  NS_tchar* lastSeperator = NS_tstrrchr(filePath, '/');
+  if (lastSeperator == NULL) {
+    // No separator, disable logging.
+    return nullptr;
+  }
+
+  long dirLength = lastSeperator - filePath;
+  if (dirLength < 0 || dirLength >= MAXPATHLEN - 13) {
+    // Too short, or too long. Disable logging.
+    return nullptr;
+  }
+
+  NS_tchar tmpFilePath[MAXPATHLEN] = {L'\0'};
+  NS_tstrncpy(tmpFilePath, filePath, MAXPATHLEN);
+  NS_tstrncpy(tmpFilePath + dirLength, "/temp.XXXXXX", 13);
+
+  int fd = mkstemp(tmpFilePath);
+  if (fd == -1) {
+    LogToOS(NS_T("Failed to open tmp"));
+    return nullptr;
+  }
+
+  if (rename(tmpFilePath, filePath) == -1) {
+    LogToOS(NS_T("Failed to rename"));
+    close(fd);
+    return nullptr;
+  }
+
+  LogToOS(NS_T("Opening file*"));
+  return fdopen(fd, "w+");
+#endif
+}
+
 #ifdef XP_WIN
 /**
  * Determine if a path contains symlinks or junctions to disallowed locations
@@ -474,3 +532,21 @@ bool IsValidFullPath(NS_tchar* origFullPath) {
 #endif
   return true;
 }
+
+#if defined(XP_MACOSX)
+// This is never deallocated by the system
+static os_log_t updaterLogger = os_log_create("org.mozilla.updater", "Updater");
+#endif
+
+/**
+ * Logs a message to the system log for debugging purposes before our log
+ * file has been set up.
+ *
+ * @param  message
+ *         The message to log.
+ */
+void LogToOS(const NS_tchar* message) {
+#if defined(XP_MACOSX)
+  os_log(updaterLogger, "%{public}s", message);
+#endif
+}
diff --git a/toolkit/mozapps/update/common/updatecommon.h b/toolkit/mozapps/update/common/updatecommon.h
index 9023dc6bda9..be2e552c0d8 100644
--- a/toolkit/mozapps/update/common/updatecommon.h
+++ b/toolkit/mozapps/update/common/updatecommon.h
@@ -35,6 +35,8 @@ class UpdateLog {
 
 bool IsValidFullPath(NS_tchar* fullPath);
 bool IsProgramFilesPath(NS_tchar* fullPath);
+FILE* CreateAndOpenFile(NS_tchar* logFilePath, bool binary);
+void LogToOS(const NS_tchar* message);
 
 #define LOG_WARN(args) UpdateLog::GetPrimaryLog().WarnPrintf args
 #define LOG(args) UpdateLog::GetPrimaryLog().Printf args
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index f11eae197d8..634935a9ec8 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2510,7 +2510,7 @@ static bool WriteToFile(const NS_tchar* aFilename, const char* aStatus) {
   }
 #endif
 
-  AutoFile statusFile(NS_tfopen(statusFilePath, NS_T("wb+")));
+  AutoFile statusFile(CreateAndOpenFile(statusFilePath, true));
   if (statusFile == nullptr) {
     LOG(("WriteToFile failed to open status file: %d", errno));
     return false;
@@ -3303,6 +3303,8 @@ bool ShouldRunSilently(int argc, NS_tchar** argv) {
 }
 
 int NS_main(int argc, NS_tchar** argv) {
+  LogToOS(NS_T("Updater started"));
+
   // We may need to tweak our argument list when we launch the Second Updater
   // Invocation (SUI), so we are going to make a copy of our arguments to
   // modify.
@@ -3339,6 +3341,7 @@ int NS_main(int argc, NS_tchar** argv) {
 
 #ifdef XP_MACOSX
   if (argc > 2 && NS_tstrcmp(argv[1], NS_T("--openAppBundle")) == 0) {
+    LogToOS(NS_T("Opening App Bundle"));
     // We have been asked to open a .app bundle. The path to the .app bundle and
     // any command line arguments have been passed to us as arguments after
     // "--openAppBundle", so remove the first two arguments and launch the .app
@@ -3398,6 +3401,7 @@ int NS_main(int argc, NS_tchar** argv) {
 
 #ifdef XP_MACOSX
   if (isElevated) {
+    LogToOS(NS_T("Updater is elevated"));
     if (!ObtainUpdaterArguments(&argc, &argv, &gMARStrings)) {
       // Won't actually get here because ObtainUpdaterArguments will terminate
       // the current process on failure.
Loading diff…