blob: 575cadc122f2811ca0cee2740641fb11fda70539 [file] [log] [blame]
Greg Kerr3e750f42016-06-29 15:20:21 -07001// Copyright 2016 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Greg Kerra6c0c522016-07-25 11:15:31 -07005#include "imageloader_impl.h"
6
Greg Kerr6a5ee862016-10-19 11:32:43 -07007#include <stdint.h>
Greg Kerr3e750f42016-06-29 15:20:21 -07008
Greg Kerr3e750f42016-06-29 15:20:21 -07009#include <list>
Greg Kerr019d59c2016-11-17 14:28:49 -080010#include <string>
Greg Kerr3e750f42016-06-29 15:20:21 -070011#include <vector>
12
Greg Kerr019d59c2016-11-17 14:28:49 -080013#include "component.h"
Greg Kerr2f76fde2016-08-29 16:39:45 -070014#include "mock_verity_mounter.h"
Greg Kerr019d59c2016-11-17 14:28:49 -080015#include "test_utilities.h"
Greg Kerr2f76fde2016-08-29 16:39:45 -070016#include "verity_mounter.h"
Greg Kerr3e750f42016-06-29 15:20:21 -070017
Greg Kerr3e750f42016-06-29 15:20:21 -070018#include <base/files/file_path.h>
19#include <base/files/file_util.h>
20#include <base/files/scoped_temp_dir.h>
Greg Kerr89be05f2016-07-27 10:40:32 -070021#include <base/memory/ptr_util.h>
Greg Kerr89be05f2016-07-27 10:40:32 -070022#include <gmock/gmock.h>
23#include <gtest/gtest.h>
Greg Kerr3e750f42016-06-29 15:20:21 -070024
25namespace imageloader {
26
Greg Kerr89be05f2016-07-27 10:40:32 -070027using testing::_;
28
Greg Kerr3e750f42016-06-29 15:20:21 -070029class ImageLoaderTest : public testing::Test {
30 public:
Greg Kerr019d59c2016-11-17 14:28:49 -080031 ImageLoaderTest() {
32 CHECK(scoped_temp_dir_.CreateUniqueTempDir());
33 temp_dir_ = scoped_temp_dir_.path();
34 CHECK(base::SetPosixFilePermissions(temp_dir_, kComponentDirPerms));
35 }
36
Greg Kerra6c0c522016-07-25 11:15:31 -070037 ImageLoaderConfig GetConfig(const char* path) {
38 std::vector<uint8_t> key(std::begin(kDevPublicKey),
39 std::end(kDevPublicKey));
Greg Kerr2f76fde2016-08-29 16:39:45 -070040 auto ops = base::MakeUnique<MockVerityMounter>();
Greg Kerr89be05f2016-07-27 10:40:32 -070041 ImageLoaderConfig config(key, path, "/foo", std::move(ops));
Greg Kerra6c0c522016-07-25 11:15:31 -070042 return config;
43 }
44
Greg Kerr019d59c2016-11-17 14:28:49 -080045 base::ScopedTempDir scoped_temp_dir_;
46 base::FilePath temp_dir_;
Greg Kerr3e750f42016-06-29 15:20:21 -070047};
48
Greg Kerra6c0c522016-07-25 11:15:31 -070049// Test the RegisterComponent public interface.
50TEST_F(ImageLoaderTest, RegisterComponentAndGetVersion) {
Greg Kerr019d59c2016-11-17 14:28:49 -080051 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
Greg Kerra6c0c522016-07-25 11:15:31 -070052 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -080053 GetTestComponentPath().value()));
Greg Kerra6c0c522016-07-25 11:15:31 -070054
Greg Kerr019d59c2016-11-17 14:28:49 -080055 base::FilePath comp_dir = temp_dir_.Append(kTestComponentName);
Greg Kerra6c0c522016-07-25 11:15:31 -070056 ASSERT_TRUE(base::DirectoryExists(comp_dir));
57
Greg Kerr89be05f2016-07-27 10:40:32 -070058 base::FilePath hint_file = comp_dir.Append("latest-version");
Greg Kerra6c0c522016-07-25 11:15:31 -070059 ASSERT_TRUE(base::PathExists(hint_file));
60
61 std::string hint_file_contents;
62 ASSERT_TRUE(
63 base::ReadFileToStringWithMaxSize(hint_file, &hint_file_contents, 4096));
64 EXPECT_EQ(kTestDataVersion, hint_file_contents);
65
66 base::FilePath version_dir = comp_dir.Append(kTestDataVersion);
67 ASSERT_TRUE(base::DirectoryExists(version_dir));
68
Greg Kerrf50e24a2017-01-06 17:12:32 -080069 // Make sure it actually checks the reported version against the real version.
70 EXPECT_FALSE(loader.RegisterComponent(kTestComponentName, kTestUpdatedVersion,
71 GetTestComponentPath().value()));
72
Greg Kerra6c0c522016-07-25 11:15:31 -070073 // Now copy a new version into place.
Greg Kerr89be05f2016-07-27 10:40:32 -070074 EXPECT_TRUE(
75 loader.RegisterComponent(kTestComponentName, kTestUpdatedVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -080076 GetTestComponentPath(kTestUpdatedVersion).value()));
Greg Kerra6c0c522016-07-25 11:15:31 -070077
78 std::string hint_file_contents2;
79 ASSERT_TRUE(
80 base::ReadFileToStringWithMaxSize(hint_file, &hint_file_contents2, 4096));
81 EXPECT_EQ(kTestUpdatedVersion, hint_file_contents2);
82
83 base::FilePath version_dir2 = comp_dir.Append(kTestUpdatedVersion);
84 ASSERT_TRUE(base::DirectoryExists(version_dir2));
85
Greg Kerr89be05f2016-07-27 10:40:32 -070086 EXPECT_EQ(kTestUpdatedVersion,
87 loader.GetComponentVersion(kTestComponentName));
Greg Kerra6c0c522016-07-25 11:15:31 -070088
89 // Reject rollback to an older version.
90 EXPECT_FALSE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -080091 GetTestComponentPath().value()));
Greg Kerra6c0c522016-07-25 11:15:31 -070092
Greg Kerr89be05f2016-07-27 10:40:32 -070093 EXPECT_EQ(kTestUpdatedVersion,
94 loader.GetComponentVersion(kTestComponentName));
Greg Kerra6c0c522016-07-25 11:15:31 -070095}
96
Greg Kerr1c7403c2016-11-11 11:57:44 -080097// Pretend ImageLoader crashed, by creating an incomplete installation, and then
98// attempt registration with ImageLoader.
99TEST_F(ImageLoaderTest, RegisterComponentAfterCrash) {
Greg Kerr1c7403c2016-11-11 11:57:44 -0800100 // Now create the junk there.
101 const std::string junk_contents ="Bad file contents";
102 const base::FilePath junk_path =
Greg Kerr019d59c2016-11-17 14:28:49 -0800103 temp_dir_.Append(kTestComponentName).Append(kTestDataVersion);
Greg Kerr1c7403c2016-11-11 11:57:44 -0800104 ASSERT_TRUE(base::CreateDirectory(junk_path));
105 ASSERT_EQ(static_cast<int>(junk_contents.size()),
106 base::WriteFile(junk_path.Append("junkfile"), junk_contents.data(),
107 junk_contents.size()));
Greg Kerr019d59c2016-11-17 14:28:49 -0800108 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
Greg Kerr1c7403c2016-11-11 11:57:44 -0800109 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800110 GetTestComponentPath().value()));
Greg Kerr4bd78132016-07-19 11:51:16 -0700111}
112
Greg Kerr89be05f2016-07-27 10:40:32 -0700113TEST_F(ImageLoaderTest, MountValidImage) {
114 std::vector<uint8_t> key(std::begin(kDevPublicKey), std::end(kDevPublicKey));
Greg Kerr2f76fde2016-08-29 16:39:45 -0700115 auto mount_mock = base::MakeUnique<MockVerityMounter>();
116 ON_CALL(*mount_mock, Mount(_, _, _)).WillByDefault(testing::Return(true));
117 EXPECT_CALL(*mount_mock, Mount(_, _, _)).Times(2);
Greg Kerr89be05f2016-07-27 10:40:32 -0700118
Greg Kerr89be05f2016-07-27 10:40:32 -0700119 base::ScopedTempDir scoped_mount_dir;
Greg Kerr89be05f2016-07-27 10:40:32 -0700120 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
121
Greg Kerr019d59c2016-11-17 14:28:49 -0800122 ImageLoaderConfig config(key, temp_dir_.value().c_str(),
Greg Kerr2f76fde2016-08-29 16:39:45 -0700123 scoped_mount_dir.path().value().c_str(),
124 std::move(mount_mock));
Greg Kerr89be05f2016-07-27 10:40:32 -0700125 ImageLoaderImpl loader(std::move(config));
126
127 // We previously tested RegisterComponent, so assume this works if it reports
128 // true.
129 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800130 GetTestComponentPath().value()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700131
132 const std::string expected_path =
133 scoped_mount_dir.path().value() + "/PepperFlashPlayer/22.0.0.158";
Greg Kerrc5b91692016-09-14 12:09:22 -0700134 EXPECT_EQ(expected_path, loader.LoadComponent(kTestComponentName));
135
136 // Let's also test mounting the component at a fixed point.
137 const std::string expected_path2 =
138 scoped_mount_dir.path().value() + "/FixedMountPoint";
139 EXPECT_TRUE(loader.LoadComponent(kTestComponentName, expected_path2));
Greg Kerr89be05f2016-07-27 10:40:32 -0700140}
141
142TEST_F(ImageLoaderTest, MountInvalidImage) {
143 std::vector<uint8_t> key(std::begin(kDevPublicKey), std::end(kDevPublicKey));
Greg Kerr2f76fde2016-08-29 16:39:45 -0700144 auto mount_mock = base::MakeUnique<MockVerityMounter>();
145 ON_CALL(*mount_mock, Mount(_, _, _)).WillByDefault(testing::Return(true));
146 EXPECT_CALL(*mount_mock, Mount(_, _, _)).Times(0);
Greg Kerr89be05f2016-07-27 10:40:32 -0700147
Greg Kerr89be05f2016-07-27 10:40:32 -0700148 base::ScopedTempDir scoped_mount_dir;
Greg Kerr89be05f2016-07-27 10:40:32 -0700149 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
150
Greg Kerr019d59c2016-11-17 14:28:49 -0800151 ImageLoaderConfig config(key, temp_dir_.value().c_str(),
Greg Kerr2f76fde2016-08-29 16:39:45 -0700152 scoped_mount_dir.path().value().c_str(),
153 std::move(mount_mock));
Greg Kerr89be05f2016-07-27 10:40:32 -0700154 ImageLoaderImpl loader(std::move(config));
155
156 // We previously tested RegisterComponent, so assume this works if it reports
157 // true.
158 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800159 GetTestComponentPath().value()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700160
Greg Kerr019d59c2016-11-17 14:28:49 -0800161 base::FilePath table = temp_dir_.Append(kTestComponentName)
Greg Kerr89be05f2016-07-27 10:40:32 -0700162 .Append(kTestDataVersion)
Greg Kerr30cd5fb2016-09-29 12:37:02 -0700163 .Append("table");
Greg Kerr89be05f2016-07-27 10:40:32 -0700164 std::string contents = "corrupt";
165 ASSERT_EQ(static_cast<int>(contents.size()),
Greg Kerr30cd5fb2016-09-29 12:37:02 -0700166 base::WriteFile(table, contents.data(), contents.size()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700167 ASSERT_EQ("", loader.LoadComponent(kTestComponentName));
168}
169
Greg Kerr2f76fde2016-08-29 16:39:45 -0700170TEST_F(ImageLoaderTest, SetupTable) {
171 std::string base_table = "0 40 verity payload=ROOT_DEV hashtree=HASH_DEV "
172 "hashstart=40 alg=sha256 root_hexdigest="
173 "34663b9920632778d38a0943a5472cae196bd4bf1d7dfa191506e7a8e7ec84d2 "
174 "salt=fcfc9b5a329e44be73a323188ae75ca644122d920161f672f6935623831d07e2";
175
176 // Make sure excess newlines are rejected.
177 std::string bad_table = base_table + "\n\n";
178 EXPECT_FALSE(VerityMounter::SetupTable(&bad_table, "/dev/loop6"));
179
180 // Make sure it does the right replacements on a simple base table.
181 std::string good_table = base_table;
182 EXPECT_TRUE(VerityMounter::SetupTable(&good_table, "/dev/loop6"));
183
184 std::string known_good_table =
185 "0 40 verity payload=/dev/loop6 hashtree=/dev/loop6 "
186 "hashstart=40 alg=sha256 root_hexdigest="
187 "34663b9920632778d38a0943a5472cae196bd4bf1d7dfa191506e7a8e7ec84d2 "
188 "salt=fcfc9b5a329e44be73a323188ae75ca644122d920161f672f6935623831d07e2 "
189 "error_behavior=eio";
190 EXPECT_EQ(known_good_table, good_table);
191
192 // Make sure the newline is stripped.
193 std::string good_table_newline = base_table + "\n";
194 EXPECT_TRUE(VerityMounter::SetupTable(&good_table_newline, "/dev/loop6"));
195 EXPECT_EQ(known_good_table, good_table_newline);
196
197 // Make sure error_behavior isn't appended twice.
198 std::string good_table_error = base_table + " error_behavior=eio\n";
199 EXPECT_TRUE(VerityMounter::SetupTable(&good_table_error, "/dev/loop6"));
200 EXPECT_EQ(known_good_table, good_table_error);
201}
202
Greg Kerra6c0c522016-07-25 11:15:31 -0700203} // namespace imageloader