Skip to content

Commit

Permalink
Use the chrome.exe path instead of the directory.
Browse files Browse the repository at this point in the history
Currently the the sandboxed shortcut parser compares
the Chrome executable path with the shortcut target
path before allowing it to be reset. However, the
shortcut target path normally includes "chrome.exe"
in its target path. Thus, it should be added into
the path set to be checked.

This CL also updates the working-directory to be
the chrome exe directory.

Bug: 1174512
Change-Id: Ie742146fa347f47ed41b478a84e3a6c2276f6da2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2691247
Commit-Queue: Bettina Dea <bdea@chromium.org>
Reviewed-by: Joe Mason <joenotcharles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#859084}
  • Loading branch information
Bettina authored and Chromium LUCI CQ committed Mar 2, 2021
1 parent 903c4b7 commit 4924f2c
Show file tree
Hide file tree
Showing 20 changed files with 143 additions and 55 deletions.
8 changes: 4 additions & 4 deletions chrome/chrome_cleaner/chrome_utils/chrome_util.cc
Expand Up @@ -79,7 +79,7 @@ bool RetrieveChromeExePathFromCommandLine(base::FilePath* chrome_exe_path) {
return true;
}

void ListChromeExePaths(std::set<base::FilePath>* paths) {
void ListChromeExeDirectories(std::set<base::FilePath>* paths) {
DCHECK(paths);

static const unsigned int install_paths[] = {
Expand All @@ -106,10 +106,10 @@ void ListChromeExePaths(std::set<base::FilePath>* paths) {
void ListChromeInstallationPaths(std::set<base::FilePath>* paths) {
DCHECK(paths);

std::set<base::FilePath> exe_paths;
ListChromeExePaths(&exe_paths);
std::set<base::FilePath> chrome_exe_directories;
ListChromeExeDirectories(&chrome_exe_directories);

for (const base::FilePath& exe_path : exe_paths) {
for (const base::FilePath& exe_path : chrome_exe_directories) {
base::FilePath pattern = exe_path.Append(L"??.*.*.*");
std::vector<base::FilePath> matches;
CollectMatchingPaths(pattern, &matches);
Expand Down
4 changes: 2 additions & 2 deletions chrome/chrome_cleaner/chrome_utils/chrome_util.h
Expand Up @@ -31,9 +31,9 @@ bool RetrieveChromeVersionAndInstalledDomain(std::wstring* chrome_version,
// path exists.
bool RetrieveChromeExePathFromCommandLine(base::FilePath* chrome_exe_path);

// Search for all Chrome executable paths, for example
// Search for all Chrome executable path directories, for example
// "C:\Program Files\Google\Chrome\Application".
void ListChromeExePaths(std::set<base::FilePath>* paths);
void ListChromeExeDirectories(std::set<base::FilePath>* paths);

// Search for all Chrome versioned installation paths, for example
// "C:\Program Files\Google\Chrome\Application\68.0.3440.84".
Expand Down
6 changes: 3 additions & 3 deletions chrome/chrome_cleaner/chrome_utils/extensions_util.cc
Expand Up @@ -334,11 +334,11 @@ void GetExtensionSettingsForceInstalledExtensions(
void GetMasterPreferencesExtensions(JsonParserAPI* json_parser,
std::vector<ExtensionPolicyFile>* policies,
base::WaitableEvent* done) {
std::set<base::FilePath> exe_paths;
ListChromeExePaths(&exe_paths);
std::set<base::FilePath> chrome_exe_directories;
ListChromeExeDirectories(&chrome_exe_directories);

std::map<base::FilePath, std::string> files_read;
for (const base::FilePath& path : exe_paths) {
for (const base::FilePath& path : chrome_exe_directories) {
const base::FilePath& master_preferences(
path.Append(kMasterPreferencesFileName));
if (!base::PathExists(master_preferences))
Expand Down
11 changes: 7 additions & 4 deletions chrome/chrome_cleaner/components/reset_shortcuts_component.cc
Expand Up @@ -73,6 +73,8 @@ void ResetShortcuts(std::vector<ShortcutInformation> shortcuts,
<< SanitizePath(target_chrome_exe);
}

const base::FilePath& chrome_exe_working_dir = target_chrome_exe.DirName();

for (const ShortcutInformation& shortcut : shortcuts) {
base::FilePath shortcut_path(shortcut.lnk_path);
base::ScopedBlockingCall scoped_blocking_call(
Expand All @@ -82,6 +84,7 @@ void ResetShortcuts(std::vector<ShortcutInformation> shortcuts,
base::win::ShortcutProperties updated_properties;
// Use the first chrome.exe path in the set.
updated_properties.set_target(target_chrome_exe);
updated_properties.set_working_dir(chrome_exe_working_dir);
// Additional Chrome profiles may have custom icons so the icon location
// should be preserved.
base::FilePath icon_location(shortcut.icon_location);
Expand Down Expand Up @@ -112,10 +115,10 @@ ResetShortcutsComponent::ResetShortcutsComponent(
: shortcut_parser_(shortcut_parser) {
shortcut_paths_to_explore_ = GetPathsToExplore();

std::set<base::FilePath> chrome_exe_paths;
ListChromeExePaths(&chrome_exe_paths);
for (const auto& path : chrome_exe_paths) {
chrome_exe_file_path_set_.Insert(path);
std::set<base::FilePath> chrome_exe_directories;
ListChromeExeDirectories(&chrome_exe_directories);
for (const auto& path : chrome_exe_directories) {
chrome_exe_file_path_set_.Insert(path.Append(L"chrome.exe"));
}
}

Expand Down
Expand Up @@ -36,7 +36,7 @@ class ResetShortcutsComponent : public ComponentAPI {
const std::vector<base::FilePath>& fake_shortcut_location_paths_);

void SetChromeExeFilePathSetForTesting(
const FilePathSet& fake_chrome_exe_file_path_set);
const FilePathSet& fake_chrome_exe_working_dirs);

private:
ShortcutParserAPI* shortcut_parser_;
Expand Down
Expand Up @@ -100,9 +100,11 @@ class ResetShortcutsComponentTest : public base::MultiProcessTest {
FilePathSet fake_chrome_exe_file_path_set_;

base::ScopedTempDir temp_dir_with_chrome_lnk_;
base::ScopedTempDir temp_dir_with_other_chrome_lnk_;
std::vector<base::FilePath> temp_dirs_paths_;
base::ScopedTempDir temp_dir_without_chrome_lnk_;
base::FilePath fake_chrome_path_;
base::FilePath fake_other_chrome_path_;

base::test::TaskEnvironment task_environment_;

Expand Down Expand Up @@ -143,6 +145,8 @@ TEST_F(ResetShortcutsComponentTest,
L"--app=app --app-id=appId --profile-directory=tmp/directory");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
}

TEST_F(ResetShortcutsComponentTest, ResetShortcutNoArguments) {
Expand All @@ -162,6 +166,48 @@ TEST_F(ResetShortcutsComponentTest, ResetShortcutNoArguments) {
EXPECT_EQ(found_shortcuts[0].command_line_arguments, L"");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
}

TEST_F(ResetShortcutsComponentTest, ResetShortcutMultipleChromeExe) {
base::win::ShortcutProperties properties;
properties.set_target(fake_chrome_path_);
ASSERT_TRUE(temp_dir_with_chrome_lnk_.CreateUniqueTempDir());
base::win::ScopedHandle unused_lnk_handle = CreateAndOpenShortcutInTempDir(
"Google Chrome.lnk", properties, &temp_dir_with_chrome_lnk_);
ASSERT_TRUE(unused_lnk_handle.IsValid());
temp_dirs_paths_.push_back(temp_dir_with_chrome_lnk_.GetPath());
fake_chrome_exe_file_path_set_.Insert(fake_chrome_path_);

base::win::ShortcutProperties other_properties;
other_properties.set_target(fake_chrome_path_);
ASSERT_TRUE(temp_dir_with_other_chrome_lnk_.CreateUniqueTempDir());
ASSERT_TRUE(base::CreateTemporaryFileInDir(
temp_dir_with_other_chrome_lnk_.GetPath(), &fake_other_chrome_path_));
base::win::ScopedHandle unused_other_lnk_handle =
CreateAndOpenShortcutInTempDir("Google Chrome.lnk", other_properties,
&temp_dir_with_other_chrome_lnk_);
ASSERT_TRUE(unused_other_lnk_handle.IsValid());
temp_dirs_paths_.push_back(temp_dir_with_other_chrome_lnk_.GetPath());
fake_chrome_exe_file_path_set_.Insert(fake_other_chrome_path_);

ResetShortcuts();
std::vector<ShortcutInformation> found_shortcuts = component_->GetShortcuts();

// It should find shortcuts pointing to the first path. The working directory
// should be the first path's directory.
ASSERT_EQ(found_shortcuts.size(), 2u);
EXPECT_EQ(found_shortcuts[0].command_line_arguments, L"");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
base::FilePath(found_shortcuts[1].target_path)));
ASSERT_TRUE(
PathEqual(base::FilePath(found_shortcuts[0].working_dir),
base::FilePath(found_shortcuts[0].target_path).DirName()));
EXPECT_EQ(found_shortcuts[1].command_line_arguments, L"");
ASSERT_TRUE(
PathEqual(base::FilePath(found_shortcuts[1].working_dir),
base::FilePath(found_shortcuts[1].target_path).DirName()));
}

TEST_F(ResetShortcutsComponentTest, ResetShortcutDifferentName) {
Expand All @@ -183,6 +229,8 @@ TEST_F(ResetShortcutsComponentTest, ResetShortcutDifferentName) {
EXPECT_EQ(found_shortcuts[0].command_line_arguments, L"");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
}

TEST_F(ResetShortcutsComponentTest, ResetShortcutFlagsNoParameters) {
Expand All @@ -207,6 +255,8 @@ TEST_F(ResetShortcutsComponentTest, ResetShortcutFlagsNoParameters) {
L"--app --app-id --profile-directory");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
}

TEST_F(ResetShortcutsComponentTest, ResetShortcutBadBinary) {
Expand All @@ -233,6 +283,8 @@ TEST_F(ResetShortcutsComponentTest, ResetShortcutBadBinary) {
EXPECT_EQ(found_shortcuts[0].command_line_arguments, L"");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
}

TEST_F(ResetShortcutsComponentTest, NoResetNonChromeShortcut) {
Expand Down Expand Up @@ -265,6 +317,8 @@ TEST_F(ResetShortcutsComponentTest, NoResetNonChromeShortcut) {
EXPECT_EQ(found_shortcuts[0].command_line_arguments, L"");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
}

TEST_F(ResetShortcutsComponentTest, ResetShortcutPreserveIconLocation) {
Expand Down Expand Up @@ -293,6 +347,8 @@ TEST_F(ResetShortcutsComponentTest, ResetShortcutPreserveIconLocation) {
EXPECT_EQ(found_shortcuts[0].command_line_arguments, L"");
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].target_path),
fake_chrome_path_));
ASSERT_TRUE(PathEqual(base::FilePath(found_shortcuts[0].working_dir),
fake_chrome_path_.DirName()));
EXPECT_EQ(found_shortcuts[0].icon_location, icon_path.value());
EXPECT_EQ(found_shortcuts[0].icon_index, 2);
}
Expand Down
10 changes: 5 additions & 5 deletions chrome/chrome_cleaner/components/system_report_component.cc
Expand Up @@ -773,12 +773,13 @@ void ReportShortcutModifications(ShortcutParserAPI* shortcut_parser) {
base::WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED);

std::set<base::FilePath> chrome_exe_paths;
ListChromeExePaths(&chrome_exe_paths);
std::set<base::FilePath> chrome_exe_directories;
ListChromeExeDirectories(&chrome_exe_directories);

const std::wstring kChromeExecutableName = L"chrome.exe";
FilePathSet chrome_exe_file_path_set;
for (const auto& path : chrome_exe_paths)
chrome_exe_file_path_set.Insert(path);
for (const auto& path : chrome_exe_directories)
chrome_exe_file_path_set.Insert(path.Append(kChromeExecutableName));

shortcut_parser->FindAndParseChromeShortcutsInFoldersAsync(
paths_to_explore, chrome_exe_file_path_set,
Expand All @@ -794,7 +795,6 @@ void ReportShortcutModifications(ShortcutParserAPI* shortcut_parser) {

InitializeFilePathSanitization();

const std::wstring kChromeExecutableName = L"chrome.exe";
for (const ShortcutInformation& shortcut : shortcuts_found) {
base::FilePath target_path(shortcut.target_path);

Expand Down
1 change: 1 addition & 0 deletions chrome/chrome_cleaner/mojom/parser_interface.mojom
Expand Up @@ -26,6 +26,7 @@ interface Parser {
// command line arguments.
ParseShortcut(handle<platform> lkn_file_handle)
=> (LnkParsingResult parsing_result, WString? target_path,
WString? working_dir,
WString? command_line_arguments,
WString? icon_location,
int32 icon_index);
Expand Down
Expand Up @@ -78,6 +78,7 @@ TEST_F(LnkParserSandboxSetupTest, ParseCorrectShortcutSandboxedTest) {

base::win::ShortcutProperties shortcut_properties;
shortcut_properties.set_target(not_lnk_file_path_);
shortcut_properties.set_working_dir(temp_dir_.GetPath());
const int32_t icon_index = 0;
shortcut_properties.set_icon(not_lnk_file_path_, icon_index);
const std::wstring lnk_arguments = L"argument1 -f -t -a -o";
Expand All @@ -98,8 +99,8 @@ TEST_F(LnkParserSandboxSetupTest, ParseCorrectShortcutSandboxedTest) {

ASSERT_EQ(test_result_code_, mojom::LnkParsingResult::SUCCESS);
EXPECT_TRUE(CheckParsedShortcut(test_parsed_shortcut_, not_lnk_file_path_,
lnk_arguments, not_lnk_file_path_,
icon_index));
temp_dir_.GetPath(), lnk_arguments,
not_lnk_file_path_, icon_index));
}

TEST_F(LnkParserSandboxSetupTest, ParseIncorrectShortcutSandboxedTest) {
Expand All @@ -121,7 +122,7 @@ TEST_F(LnkParserSandboxSetupTest, ParseIncorrectShortcutSandboxedTest) {

ASSERT_NE(test_result_code_, mojom::LnkParsingResult::SUCCESS);
EXPECT_TRUE(CheckParsedShortcut(test_parsed_shortcut_, base::FilePath(L""),
L"", base::FilePath(L""),
base::FilePath(L""), L"", base::FilePath(L""),
/*icon_index=*/-1));
}

Expand Down
Expand Up @@ -109,6 +109,7 @@ void SandboxedShortcutParser::OnShortcutsParsingDone(
std::vector<ShortcutInformation>* found_shortcuts,
mojom::LnkParsingResult parsing_result,
const base::Optional<std::wstring>& optional_file_path,
const base::Optional<std::wstring>& optional_working_dir,
const base::Optional<std::wstring>& optional_command_line_arguments,
const base::Optional<std::wstring>& optional_icon_location,
int32_t icon_index) {
Expand All @@ -118,6 +119,9 @@ void SandboxedShortcutParser::OnShortcutsParsingDone(
if (optional_file_path.has_value())
parsed_shortcut.target_path = optional_file_path.value();

if (optional_working_dir.has_value())
parsed_shortcut.working_dir = optional_working_dir.value();

if (optional_command_line_arguments.has_value()) {
parsed_shortcut.command_line_arguments =
optional_command_line_arguments.value();
Expand Down
Expand Up @@ -44,6 +44,7 @@ class SandboxedShortcutParser : public ShortcutParserAPI {
std::vector<ShortcutInformation>* found_shortcuts,
mojom::LnkParsingResult parsing_result,
const base::Optional<std::wstring>& optional_file_path,
const base::Optional<std::wstring>& optional_working_dir,
const base::Optional<std::wstring>& optional_command_line_arguments,
const base::Optional<std::wstring>& optional_icon_location,
int32_t icon_index);
Expand Down
Expand Up @@ -24,6 +24,7 @@ struct ShortcutInformation {

base::FilePath lnk_path;
std::wstring target_path;
std::wstring working_dir;
std::wstring command_line_arguments;
std::wstring icon_location;
int32_t icon_index;
Expand Down
Expand Up @@ -37,13 +37,16 @@ base::win::ScopedHandle CreateAndOpenShortcutInTempDir(

bool CheckParsedShortcut(const ParsedLnkFile& parsed_shortcut,
base::FilePath expected_target_path,
base::FilePath expected_working_dir,
std::wstring expected_arguments,
base::FilePath expected_icon_location,
const int32_t expected_icon_index) {
base::FilePath parsed_file_path(parsed_shortcut.target_path);
return PathEqual(parsed_file_path, expected_target_path) &&
base::FilePath parsed_target_path(parsed_shortcut.target_path);
base::FilePath parsed_working_dir_path(parsed_shortcut.working_dir);
return PathEqual(parsed_target_path, expected_target_path) &&
PathEqual(parsed_working_dir_path, expected_working_dir) &&
(parsed_shortcut.command_line_arguments == expected_arguments) &&
PathEqual(parsed_file_path, expected_icon_location) &&
PathEqual(expected_target_path, expected_icon_location) &&
(parsed_shortcut.icon_index == expected_icon_index);
}

Expand All @@ -52,13 +55,17 @@ void OnLnkParseDone(
mojom::LnkParsingResult* out_result_code,
base::OnceClosure callback,
mojom::LnkParsingResult result_code,
const base::Optional<std::wstring>& optional_file_path,
const base::Optional<std::wstring>& optional_target_path,
const base::Optional<std::wstring>& optional_working_dir,
const base::Optional<std::wstring>& optional_command_line_arguments,
const base::Optional<std::wstring>& optional_icon_location,
int32_t icon_index) {
*out_result_code = result_code;
if (optional_file_path.has_value())
out_parsed_shortcut->target_path = optional_file_path.value();
if (optional_target_path.has_value())
out_parsed_shortcut->target_path = optional_target_path.value();

if (optional_working_dir.has_value())
out_parsed_shortcut->working_dir = optional_working_dir.value();

if (optional_command_line_arguments.has_value()) {
out_parsed_shortcut->command_line_arguments =
Expand Down
Expand Up @@ -25,6 +25,7 @@ base::win::ScopedHandle CreateAndOpenShortcutInTempDir(

bool CheckParsedShortcut(const ParsedLnkFile& parsed_shortcut,
base::FilePath expected_target_path,
base::FilePath expected_working_dir,
std::wstring expected_arguments,
base::FilePath expected_icon_location,
const int32_t icon_index);
Expand All @@ -33,7 +34,8 @@ void OnLnkParseDone(
mojom::LnkParsingResult* out_result_code,
base::OnceClosure callback,
mojom::LnkParsingResult result_code,
const base::Optional<std::wstring>& optional_file_path,
const base::Optional<std::wstring>& optional_target_path,
const base::Optional<std::wstring>& optional_working_dir,
const base::Optional<std::wstring>& optional_command_line_arguments,
const base::Optional<std::wstring>& optional_icon_location,
int32_t optional_icon_index);
Expand Down
Expand Up @@ -327,7 +327,8 @@ mojom::LnkParsingResult internal::ParseLnkBytes(
}

if (has_working_dir &&
!SkipUtf16StringStructure(file_buffer, &current_byte)) {
!ReadUtf16StringStructure(file_buffer, &current_byte,
&parsed_shortcut->working_dir)) {
return mojom::LnkParsingResult::BAD_FORMAT;
}

Expand All @@ -354,6 +355,7 @@ mojom::LnkParsingResult internal::ParseLnkBytes(
}

ParsedLnkFile::ParsedLnkFile() {}
ParsedLnkFile::~ParsedLnkFile() {}

// Please note that the documentation used to write this parser was obtained
// from the following link:
Expand Down
Expand Up @@ -69,7 +69,9 @@ mojom::LnkParsingResult ParseLnkBytes(std::vector<BYTE> file_buffer,

struct ParsedLnkFile {
ParsedLnkFile();
~ParsedLnkFile();
std::wstring target_path;
std::wstring working_dir;
std::wstring command_line_arguments;
std::wstring icon_location;
int32_t icon_index = -1;
Expand Down

0 comments on commit 4924f2c

Please sign in to comment.