diff --git a/chrome/services/file_util/public/cpp/temporary_file_getter.cc b/chrome/services/file_util/public/cpp/temporary_file_getter.cc index 77c00ad3e7be0e..9ba73db648f8da 100644 --- a/chrome/services/file_util/public/cpp/temporary_file_getter.cc +++ b/chrome/services/file_util/public/cpp/temporary_file_getter.cc @@ -4,24 +4,41 @@ #include "chrome/services/file_util/public/cpp/temporary_file_getter.h" +#include "base/files/file.h" #include "base/files/file_util.h" #include "base/task/thread_pool.h" +#include "build/build_config.h" namespace { constexpr int kMaxNumberOfFilesAllowed = 10; base::File TemporaryFileGetterHelper(int num_files_requested) { + if (num_files_requested > kMaxNumberOfFilesAllowed) { + return base::File(); + } + base::FilePath temp_dir; + if (!base::GetTempDir(&temp_dir)) { + return base::File(); + } + // SECURITY: Use the fd returned by mkstemp directly rather than re-opening + // by path. The previous implementation called base::CreateTemporaryFile + // (which closes the mkstemp fd) and then re-opened the path with + // FLAG_CREATE_ALWAYS, which maps to O_CREAT|O_TRUNC with no O_NOFOLLOW. On + // macOS the browser's temp dir (_CS_DARWIN_USER_TEMP_DIR) is writable by the + // sandboxed GPU/network processes, so a compromised child could race a + // symlink swap and obtain a browser-privilege arbitrary-file-write. Keeping + // the original mkstemp fd closes that window. Same pattern as + // services/webnn/host/weights_file_provider.cc. base::FilePath temp_path; - base::File temp_file; - if (num_files_requested <= kMaxNumberOfFilesAllowed && - base::CreateTemporaryFile(&temp_path)) { - temp_file.Initialize( - temp_path, (base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ | - base::File::FLAG_WRITE | base::File::FLAG_WIN_TEMPORARY | - base::File::FLAG_DELETE_ON_CLOSE)); - } else { - temp_file = base::File(); + base::File temp_file = base::CreateAndOpenTemporaryFileInDir( + temp_dir, &temp_path, base::File::FLAG_WIN_TEMPORARY); + if (temp_file.IsValid()) { +#if BUILDFLAG(IS_WIN) + temp_file.DeleteOnClose(true); +#else + base::DeleteFile(temp_path); +#endif } return temp_file; }