| Index: chrome/common/component_flash_hint_file_unittests_linux.cc
|
| diff --git a/chrome/common/component_flash_hint_file_unittests_linux.cc b/chrome/common/component_flash_hint_file_unittests_linux.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a4641b1992010ac982bba72b035f11a5259724fa
|
| --- /dev/null
|
| +++ b/chrome/common/component_flash_hint_file_unittests_linux.cc
|
| @@ -0,0 +1,218 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/common/component_flash_hint_file.h"
|
| +
|
| +#include <errno.h>
|
| +#include <stdlib.h>
|
| +#include <sys/mount.h>
|
| +
|
| +#include "base/files/file_util.h"
|
| +#include "base/files/scoped_temp_dir.h"
|
| +#include "base/path_service.h"
|
| +#include "base/test/scoped_path_override.h"
|
| +#include "chrome/common/chrome_paths.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace chrome {
|
| +
|
| +class ComponentFlashHintFileTest : public testing::Test {};
|
| +
|
| +TEST_F(ComponentFlashHintFileTest, ExistsTest) {
|
| + base::ScopedPathOverride path_override(chrome::DIR_USER_DATA);
|
| + EXPECT_FALSE(ComponentFlashHintFile::DoesHintFileExist());
|
| +}
|
| +
|
| +TEST_F(ComponentFlashHintFileTest, InstallTest) {
|
| + base::ScopedPathOverride path_override(chrome::DIR_USER_DATA);
|
| + EXPECT_FALSE(ComponentFlashHintFile::DoesHintFileExist());
|
| +
|
| + base::FilePath flash_dir;
|
| + ASSERT_TRUE(PathService::Get(
|
| + chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &flash_dir));
|
| +
|
| + base::File::Error error;
|
| + ASSERT_TRUE(base::CreateDirectoryAndGetError(flash_dir, &error));
|
| +
|
| + // Write out a fixed byte array as the flash file.
|
| + uint8_t file[] = {
|
| + 0x4c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67,
|
| + 0x6f, 0x20, 0x67, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x0a, 0x54, 0x6f, 0x20,
|
| + 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x20,
|
| + 0x77, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74,
|
| + 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x64,
|
| + 0x20, 0x74, 0x69, 0x64, 0x65, 0x20, 0x6b, 0x69, 0x73, 0x73, 0x65, 0x73,
|
| + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x72, 0x65};
|
| + flash_dir = flash_dir.Append("libflash.so");
|
| + std::string flash_version = "1.0.0.1";
|
| + ASSERT_TRUE(base::WriteFile(flash_dir, reinterpret_cast<const char*>(file),
|
| + sizeof(file)) == sizeof(file));
|
| + ASSERT_TRUE(ComponentFlashHintFile::RecordFlashUpdate(flash_dir, flash_dir,
|
| + flash_version));
|
| + ASSERT_TRUE(ComponentFlashHintFile::DoesHintFileExist());
|
| +
|
| + // Confirm that the flash plugin can be verified and returned.
|
| + base::FilePath returned_flash_path;
|
| + std::string version;
|
| + ASSERT_TRUE(ComponentFlashHintFile::VerifyAndReturnFlashLocation(
|
| + &returned_flash_path, &version));
|
| + ASSERT_TRUE(returned_flash_path == flash_dir);
|
| + ASSERT_TRUE(version == flash_version);
|
| +
|
| + // Now "corrupt" the flash file and make sure the checksum fails and nothing
|
| + // is returned.
|
| + srand48(time(NULL) ^ getpid());
|
| + int idx = lrand48() % ((sizeof(file) / sizeof(file[0])) - 1);
|
| + if (file[idx] == std::numeric_limits<uint8_t>::max())
|
| + file[idx] = 0x00;
|
| + else
|
| + file[idx] = file[idx] + 1;
|
| + ASSERT_TRUE(base::WriteFile(flash_dir, reinterpret_cast<const char*>(file),
|
| + sizeof(file)) == sizeof(file));
|
| + base::FilePath empty_path;
|
| + std::string empty_version;
|
| + ASSERT_FALSE(ComponentFlashHintFile::VerifyAndReturnFlashLocation(
|
| + &empty_path, &empty_version));
|
| + ASSERT_FALSE(empty_path == flash_dir);
|
| + ASSERT_FALSE(empty_version == flash_version);
|
| +}
|
| +
|
| +TEST_F(ComponentFlashHintFileTest, CorruptionTest) {
|
| + base::ScopedPathOverride path_override(chrome::DIR_USER_DATA);
|
| + EXPECT_FALSE(ComponentFlashHintFile::DoesHintFileExist());
|
| +
|
| + base::FilePath flash_dir;
|
| + ASSERT_TRUE(PathService::Get(
|
| + chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &flash_dir));
|
| +
|
| + base::File::Error error;
|
| + ASSERT_TRUE(base::CreateDirectoryAndGetError(flash_dir, &error));
|
| + flash_dir = flash_dir.Append("libflash.so");
|
| +
|
| + const uint8_t file[] = {
|
| + 0x56, 0x61, 0x20, 0x67, 0x75, 0x76, 0x66, 0x20, 0x62, 0x61, 0x72, 0x20,
|
| + 0x62, 0x73, 0x20, 0x7a, 0x6e, 0x61, 0x6c, 0x20, 0x63, 0x62, 0x66, 0x66,
|
| + 0x76, 0x6f, 0x79, 0x72, 0x20, 0x6a, 0x62, 0x65, 0x79, 0x71, 0x66, 0x2c,
|
| + 0xa, 0x4e, 0x79, 0x79, 0x20, 0x73, 0x62, 0x65, 0x20, 0x67, 0x75, 0x72,
|
| + 0x20, 0x6f, 0x72, 0x66, 0x67, 0x20, 0x62, 0x65, 0x20, 0x66, 0x62, 0x7a,
|
| + 0x72, 0x20, 0x6f, 0x76, 0x6d, 0x6e, 0x65, 0x65, 0x72, 0x20, 0x67, 0x72,
|
| + 0x66, 0x67, 0x3f, 0xa, 0x56, 0x67, 0x20, 0x76, 0x66, 0x20, 0x6a, 0x75,
|
| + 0x6e, 0x67, 0x20, 0x76, 0x67, 0x20, 0x76, 0x66, 0x20, 0x6e, 0x61, 0x71,
|
| + 0x20, 0x6a, 0x75, 0x6e, 0x67, 0x72, 0x69, 0x72, 0x65, 0x2c, 0xa, 0x47,
|
| + 0x76, 0x7a, 0x72, 0x20, 0x76, 0x66, 0x20, 0x66, 0x67, 0x76, 0x79, 0x79,
|
| + 0x20, 0x67, 0x75, 0x72, 0x20, 0x76, 0x61, 0x73, 0x76, 0x61, 0x76, 0x67,
|
| + 0x72, 0x20, 0x77, 0x72, 0x66, 0x67, 0xa, 0x47, 0x75, 0x72, 0x20, 0x73,
|
| + 0x68, 0x67, 0x68, 0x65, 0x72, 0x20, 0x71, 0x76, 0x66, 0x6e, 0x63, 0x63,
|
| + 0x72, 0x6e, 0x65, 0x66, 0x20, 0x76, 0x61, 0x67, 0x62, 0x20, 0x7a, 0x72,
|
| + 0x7a, 0x62, 0x65, 0x6c, 0xa, 0x4a, 0x76, 0x67, 0x75, 0x20, 0x62, 0x61,
|
| + 0x79, 0x6c, 0x20, 0x6e, 0x20, 0x7a, 0x62, 0x7a, 0x72, 0x61, 0x67, 0x20,
|
| + 0x6f, 0x72, 0x67, 0x6a, 0x72, 0x72, 0x61, 0x2e, 0xa, 0x53, 0x62, 0x65,
|
| + 0x72, 0x69, 0x72, 0x65, 0x20, 0x71, 0x6a, 0x72, 0x79, 0x79, 0x66, 0x20,
|
| + 0x76, 0x61, 0x20, 0x67, 0x75, 0x6e, 0x67, 0x20, 0x7a, 0x62, 0x7a, 0x72,
|
| + 0x61, 0x67, 0x2c, 0xa, 0x55, 0x62, 0x63, 0x72, 0x20, 0x76, 0x66, 0x20,
|
| + 0x6a, 0x75, 0x6e, 0x67, 0x20, 0x65, 0x72, 0x7a, 0x6e, 0x76, 0x61, 0x66,
|
| + 0x20, 0x67, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x72, 0x72, 0x61, 0x2e,
|
| + 0x0};
|
| + ASSERT_TRUE(base::WriteFile(flash_dir, reinterpret_cast<const char*>(file),
|
| + sizeof(file)) == sizeof(file));
|
| + std::string flash_version = "1.0.0.1";
|
| + ASSERT_TRUE(ComponentFlashHintFile::RecordFlashUpdate(flash_dir, flash_dir,
|
| + flash_version));
|
| + ASSERT_TRUE(ComponentFlashHintFile::DoesHintFileExist());
|
| +
|
| + // Now write out a new flash version that will not be moved into place.
|
| + const uint8_t updated_file[] = {
|
| + 0x43, 0x72, 0x62, 0x63, 0x79, 0x72, 0x20, 0x66, 0x7a, 0x76, 0x79, 0x76,
|
| + 0x61, 0x74, 0x20, 0x67, 0x75, 0x65, 0x62, 0x68, 0x74, 0x75, 0x20, 0x67,
|
| + 0x75, 0x72, 0x76, 0x65, 0x20, 0x67, 0x72, 0x6e, 0x65, 0x66, 0xa, 0x4a,
|
| + 0x75, 0x62, 0x20, 0x70, 0x6e, 0x61, 0x20, 0x74, 0x76, 0x69, 0x72, 0x20,
|
| + 0x67, 0x75, 0x72, 0x7a, 0x20, 0x6f, 0x6e, 0x70, 0x78, 0x20, 0x67, 0x75,
|
| + 0x72, 0x76, 0x65, 0x20, 0x79, 0x76, 0x69, 0x72, 0x66, 0xa, 0x4e, 0x61,
|
| + 0x71, 0x20, 0x6e, 0x79, 0x79, 0x20, 0x67, 0x75, 0x62, 0x66, 0x72, 0x20,
|
| + 0x6a, 0x6e, 0x66, 0x67, 0x72, 0x71, 0x20, 0x6c, 0x72, 0x6e, 0x65, 0x66,
|
| + 0x3f, 0xa, 0x4a, 0x75, 0x62, 0x20, 0x6a, 0x76, 0x79, 0x79, 0x20, 0x63,
|
| + 0x6e, 0x6c, 0x3f, 0x0};
|
| + base::FilePath flash_dir_update;
|
| + ASSERT_TRUE(PathService::Get(
|
| + chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &flash_dir_update));
|
| + flash_dir_update = flash_dir_update.Append("other_flash.so");
|
| + ASSERT_TRUE(base::WriteFile(flash_dir_update,
|
| + reinterpret_cast<const char*>(updated_file),
|
| + sizeof(updated_file)) == sizeof(updated_file));
|
| + ASSERT_TRUE(ComponentFlashHintFile::RecordFlashUpdate(
|
| + flash_dir_update, flash_dir, flash_version));
|
| + // flash_dir_update needs to be moved to flash_dir, but if that fails (for the
|
| + // test we don't even try), we need to revert the hint file.
|
| + base::FilePath failed_flash_dir;
|
| + std::string failed_version;
|
| + ASSERT_FALSE(ComponentFlashHintFile::VerifyAndReturnFlashLocation(
|
| + &failed_flash_dir, &failed_version));
|
| +}
|
| +
|
| +TEST_F(ComponentFlashHintFileTest, ExecTest1) {
|
| + /*
|
| + errno = 0;
|
| + pid_t pid = base::ForkWithFlags(CLONE_NEWUSER | CLONE_NEWNS, nullptr,
|
| + nullptr);
|
| + PCHECK(errno == 0 || errno == EINVAL) << "Unexpected error condition "
|
| + << errno;
|
| + if (pid == -1) {
|
| + LOG(ERROR) << "Fork failed, not running test.";
|
| + return;
|
| + }
|
| + // Skip the test in the parent process.
|
| + if (pid == 0)
|
| + return;
|
| + */
|
| + ASSERT_TRUE(unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0);
|
| + // Now mount a NOEXEC fs.
|
| + const unsigned long tmpfs_flags = MS_NODEV | MS_NOSUID | MS_NOEXEC;
|
| + base::ScopedTempDir temp_dir;
|
| + ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
| + ASSERT_TRUE(mount("tmpfs", temp_dir.path().value().c_str(), "tmpfs",
|
| + tmpfs_flags, nullptr) == 0);
|
| + base::FilePath file_path = temp_dir.path().Append("plugin.so");
|
| + const uint8_t file[] = {
|
| + 0x56, 0x61, 0x20, 0x67, 0x75, 0x72, 0x20, 0x70, 0x76, 0x67, 0x6c, 0x20,
|
| + 0x6a, 0x75, 0x72, 0x65, 0x72, 0x20, 0x61, 0x62, 0x6f, 0x62, 0x71, 0x6c,
|
| + 0x20, 0x66, 0x7a, 0x76, 0x79, 0x72, 0x66, 0x4e, 0x61, 0x71, 0x20, 0x61,
|
| + 0x62, 0x6f, 0x62, 0x71, 0x6c, 0x20, 0x71, 0x65, 0x72, 0x6e, 0x7a, 0x66,
|
| + 0x56, 0x61, 0x20, 0x67, 0x75, 0x72, 0x20, 0x70, 0x76, 0x67, 0x6c, 0x20,
|
| + 0x6a, 0x75, 0x72, 0x65, 0x72, 0x20, 0x71, 0x72, 0x66, 0x63, 0x72, 0x65,
|
| + 0x6e, 0x67, 0x76, 0x62, 0x61, 0x51, 0x65, 0x76, 0x69, 0x72, 0x66, 0x20,
|
| + 0x67, 0x75, 0x72, 0x20, 0x6f, 0x62, 0x65, 0x72, 0x71, 0x20, 0x67, 0x62,
|
| + 0x20, 0x72, 0x6b, 0x67, 0x65, 0x72, 0x7a, 0x72, 0x66, 0x57, 0x68, 0x66,
|
| + 0x67, 0x20, 0x62, 0x61, 0x72, 0x20, 0x66, 0x63, 0x6e, 0x65, 0x78, 0x20,
|
| + 0x62, 0x73, 0x20, 0x71, 0x72, 0x70, 0x72, 0x61, 0x70, 0x6c, 0x4e, 0x74,
|
| + 0x6e, 0x76, 0x61, 0x66, 0x67, 0x20, 0x6e, 0x20, 0x66, 0x67, 0x6e, 0x65,
|
| + 0x79, 0x72, 0x66, 0x66, 0x20, 0x61, 0x76, 0x74, 0x75, 0x67, 0x42, 0x61,
|
| + 0x72, 0x20, 0x74, 0x79, 0x62, 0x6a, 0x20, 0x62, 0x73, 0x20, 0x75, 0x62,
|
| + 0x63, 0x72, 0x20, 0x6e, 0x61, 0x71, 0x20, 0x71, 0x76, 0x74, 0x61, 0x76,
|
| + 0x67, 0x6c, 0x4e, 0x20, 0x70, 0x75, 0x76, 0x79, 0x71, 0x20, 0x70, 0x6e,
|
| + 0x61, 0x20, 0x73, 0x62, 0x79, 0x79, 0x62, 0x6a, 0x20, 0x67, 0x75, 0x72,
|
| + 0x20, 0x79, 0x76, 0x74, 0x75, 0x67, 0x0,
|
| + };
|
| + ASSERT_TRUE(base::WriteFile(file_path, reinterpret_cast<const char*>(file),
|
| + sizeof(file)) == sizeof(file));
|
| + ASSERT_FALSE(ComponentFlashHintFile::TestExecutableMapping(file_path));
|
| + // ASSERT_TRUE(umount(temp_dir.path().value().c_str()) == 0);
|
| +}
|
| +
|
| +TEST_F(ComponentFlashHintFileTest, ExecTest2) {
|
| + base::ScopedTempDir temp_dir;
|
| + ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
| + base::FilePath file_path = temp_dir.path().Append("plugin.so");
|
| + const uint8_t file[] = {
|
| + 0x55, 0x62, 0x79, 0x71, 0x20, 0x6c, 0x62, 0x68, 0x65, 0x20,
|
| + 0x73, 0x76, 0x65, 0x72, 0x58, 0x72, 0x72, 0x63, 0x20, 0x76,
|
| + 0x67, 0x20, 0x6f, 0x68, 0x65, 0x61, 0x76, 0x61, 0x74, 0x20,
|
| + 0x6f, 0x65, 0x76, 0x74, 0x75, 0x67, 0x0,
|
| + };
|
| +
|
| + ASSERT_TRUE(base::WriteFile(file_path, reinterpret_cast<const char*>(file),
|
| + sizeof(file)) == sizeof(file));
|
| + ASSERT_TRUE(ComponentFlashHintFile::TestExecutableMapping(file_path));
|
| +}
|
| +
|
| +} // namespace chrome
|
|
|