blob: caba5346fdfe439f3259a5812e1d832202e8eea6 [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
Ben Chan045849f2017-12-18 17:27:07 -08005#include "imageloader/imageloader_impl.h"
Greg Kerra6c0c522016-07-25 11:15:31 -07006
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>
Ben Chanea104dd2017-09-29 00:43:04 -070010#include <memory>
Greg Kerr019d59c2016-11-17 14:28:49 -080011#include <string>
Greg Kerr3e750f42016-06-29 15:20:21 -070012#include <vector>
13
Qijiang Fan713061e2021-03-08 15:45:12 +090014#include <base/check.h>
Greg Kerr3e750f42016-06-29 15:20:21 -070015#include <base/files/file_path.h>
16#include <base/files/file_util.h>
17#include <base/files/scoped_temp_dir.h>
Greg Kerr89be05f2016-07-27 10:40:32 -070018#include <gmock/gmock.h>
19#include <gtest/gtest.h>
Greg Kerr3e750f42016-06-29 15:20:21 -070020
Ben Chan045849f2017-12-18 17:27:07 -080021#include "imageloader/component.h"
Amin Hassani17a185b2021-02-10 12:07:57 -080022#include "imageloader/mock_global_context.h"
Greg Kerr09f06de2018-02-16 15:32:07 -080023#include "imageloader/mock_helper_process_proxy.h"
Ben Chan045849f2017-12-18 17:27:07 -080024#include "imageloader/test_utilities.h"
25#include "imageloader/verity_mounter.h"
26
Greg Kerr3e750f42016-06-29 15:20:21 -070027namespace imageloader {
28
Greg Kerr89be05f2016-07-27 10:40:32 -070029using testing::_;
30
Greg Kerr3e750f42016-06-29 15:20:21 -070031class ImageLoaderTest : public testing::Test {
32 public:
Greg Kerr019d59c2016-11-17 14:28:49 -080033 ImageLoaderTest() {
34 CHECK(scoped_temp_dir_.CreateUniqueTempDir());
Eric Carusoa5dfc942018-01-22 15:44:45 -080035 temp_dir_ = scoped_temp_dir_.GetPath();
Greg Kerr019d59c2016-11-17 14:28:49 -080036 CHECK(base::SetPosixFilePermissions(temp_dir_, kComponentDirPerms));
37 }
38
Amin Hassani17a185b2021-02-10 12:07:57 -080039 void SetUp() override {
40 g_ctx_.SetAsCurrent();
41 ON_CALL(g_ctx_, IsOfficialBuild()).WillByDefault(testing::Return(true));
42 }
43
Greg Kerra6c0c522016-07-25 11:15:31 -070044 ImageLoaderConfig GetConfig(const char* path) {
Eric Caruso0b79bc82017-03-21 13:44:34 -070045 Keys keys;
46 keys.push_back(std::vector<uint8_t>(std::begin(kDevPublicKey),
47 std::end(kDevPublicKey)));
48 keys.push_back(std::vector<uint8_t>(std::begin(kOciDevPublicKey),
49 std::end(kOciDevPublicKey)));
50 ImageLoaderConfig config(keys, path, "/foo");
Greg Kerra6c0c522016-07-25 11:15:31 -070051 return config;
52 }
53
Greg Kerr019d59c2016-11-17 14:28:49 -080054 base::ScopedTempDir scoped_temp_dir_;
55 base::FilePath temp_dir_;
Amin Hassani17a185b2021-02-10 12:07:57 -080056
57 MockGlobalContext g_ctx_;
Greg Kerr3e750f42016-06-29 15:20:21 -070058};
59
Greg Kerra6c0c522016-07-25 11:15:31 -070060// Test the RegisterComponent public interface.
61TEST_F(ImageLoaderTest, RegisterComponentAndGetVersion) {
Greg Kerr019d59c2016-11-17 14:28:49 -080062 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
Greg Kerra6c0c522016-07-25 11:15:31 -070063 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -080064 GetTestComponentPath().value()));
Greg Kerra6c0c522016-07-25 11:15:31 -070065
Greg Kerr019d59c2016-11-17 14:28:49 -080066 base::FilePath comp_dir = temp_dir_.Append(kTestComponentName);
Greg Kerra6c0c522016-07-25 11:15:31 -070067 ASSERT_TRUE(base::DirectoryExists(comp_dir));
68
Greg Kerr89be05f2016-07-27 10:40:32 -070069 base::FilePath hint_file = comp_dir.Append("latest-version");
Greg Kerra6c0c522016-07-25 11:15:31 -070070 ASSERT_TRUE(base::PathExists(hint_file));
71
72 std::string hint_file_contents;
73 ASSERT_TRUE(
74 base::ReadFileToStringWithMaxSize(hint_file, &hint_file_contents, 4096));
75 EXPECT_EQ(kTestDataVersion, hint_file_contents);
76
77 base::FilePath version_dir = comp_dir.Append(kTestDataVersion);
78 ASSERT_TRUE(base::DirectoryExists(version_dir));
79
Greg Kerrf50e24a2017-01-06 17:12:32 -080080 // Make sure it actually checks the reported version against the real version.
81 EXPECT_FALSE(loader.RegisterComponent(kTestComponentName, kTestUpdatedVersion,
82 GetTestComponentPath().value()));
83
Greg Kerra6c0c522016-07-25 11:15:31 -070084 // Now copy a new version into place.
Ben Chana92a9f02017-12-18 17:47:23 -080085 EXPECT_TRUE(loader.RegisterComponent(
86 kTestComponentName, kTestUpdatedVersion,
87 GetTestComponentPath(kTestUpdatedVersion).value()));
Greg Kerra6c0c522016-07-25 11:15:31 -070088
89 std::string hint_file_contents2;
90 ASSERT_TRUE(
91 base::ReadFileToStringWithMaxSize(hint_file, &hint_file_contents2, 4096));
92 EXPECT_EQ(kTestUpdatedVersion, hint_file_contents2);
93
94 base::FilePath version_dir2 = comp_dir.Append(kTestUpdatedVersion);
95 ASSERT_TRUE(base::DirectoryExists(version_dir2));
96
Greg Kerr89be05f2016-07-27 10:40:32 -070097 EXPECT_EQ(kTestUpdatedVersion,
98 loader.GetComponentVersion(kTestComponentName));
Greg Kerra6c0c522016-07-25 11:15:31 -070099
100 // Reject rollback to an older version.
101 EXPECT_FALSE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800102 GetTestComponentPath().value()));
Greg Kerra6c0c522016-07-25 11:15:31 -0700103
Greg Kerr89be05f2016-07-27 10:40:32 -0700104 EXPECT_EQ(kTestUpdatedVersion,
105 loader.GetComponentVersion(kTestComponentName));
Greg Kerra6c0c522016-07-25 11:15:31 -0700106}
107
Greg Kerr1c7403c2016-11-11 11:57:44 -0800108// Pretend ImageLoader crashed, by creating an incomplete installation, and then
109// attempt registration with ImageLoader.
110TEST_F(ImageLoaderTest, RegisterComponentAfterCrash) {
Greg Kerr1c7403c2016-11-11 11:57:44 -0800111 // Now create the junk there.
Colin Howesad6271a2018-11-21 15:36:05 -0800112 const std::string junk_contents = "Bad file contents";
Greg Kerr1c7403c2016-11-11 11:57:44 -0800113 const base::FilePath junk_path =
Greg Kerr019d59c2016-11-17 14:28:49 -0800114 temp_dir_.Append(kTestComponentName).Append(kTestDataVersion);
Greg Kerr1c7403c2016-11-11 11:57:44 -0800115 ASSERT_TRUE(base::CreateDirectory(junk_path));
116 ASSERT_EQ(static_cast<int>(junk_contents.size()),
117 base::WriteFile(junk_path.Append("junkfile"), junk_contents.data(),
118 junk_contents.size()));
Greg Kerr019d59c2016-11-17 14:28:49 -0800119 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
Greg Kerr1c7403c2016-11-11 11:57:44 -0800120 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800121 GetTestComponentPath().value()));
Greg Kerr4bd78132016-07-19 11:51:16 -0700122}
123
Greg Kerr89be05f2016-07-27 10:40:32 -0700124TEST_F(ImageLoaderTest, MountValidImage) {
Eric Caruso0b79bc82017-03-21 13:44:34 -0700125 Keys keys;
Colin Howesad6271a2018-11-21 15:36:05 -0800126 keys.push_back(
127 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
Eric Caruso0b79bc82017-03-21 13:44:34 -0700128
Greg Kerr09f06de2018-02-16 15:32:07 -0800129 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Xiaochu Liue61e1d62018-11-12 13:20:09 -0800130 EXPECT_CALL(*helper_mock, SendMountCommand(_, _, FileSystem::kSquashFS, _))
Xiaochu Liuc2264342017-08-14 16:37:42 -0700131 .Times(2);
132 ON_CALL(*helper_mock, SendMountCommand(_, _, _, _))
Greg Kerr9944e242017-01-26 15:09:31 -0800133 .WillByDefault(testing::Return(true));
Greg Kerr89be05f2016-07-27 10:40:32 -0700134
Greg Kerr89be05f2016-07-27 10:40:32 -0700135 base::ScopedTempDir scoped_mount_dir;
Greg Kerr89be05f2016-07-27 10:40:32 -0700136 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
137
Eric Caruso0b79bc82017-03-21 13:44:34 -0700138 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800139 scoped_mount_dir.GetPath().value().c_str());
Greg Kerr89be05f2016-07-27 10:40:32 -0700140 ImageLoaderImpl loader(std::move(config));
141
142 // We previously tested RegisterComponent, so assume this works if it reports
143 // true.
144 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800145 GetTestComponentPath().value()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700146
147 const std::string expected_path =
Eric Carusoa5dfc942018-01-22 15:44:45 -0800148 scoped_mount_dir.GetPath().value() + "/PepperFlashPlayer/22.0.0.158";
Greg Kerr9944e242017-01-26 15:09:31 -0800149 EXPECT_EQ(expected_path,
150 loader.LoadComponent(kTestComponentName, helper_mock.get()));
Greg Kerrc5b91692016-09-14 12:09:22 -0700151
152 // Let's also test mounting the component at a fixed point.
153 const std::string expected_path2 =
Eric Carusoa5dfc942018-01-22 15:44:45 -0800154 scoped_mount_dir.GetPath().value() + "/FixedMountPoint";
Greg Kerr9944e242017-01-26 15:09:31 -0800155 EXPECT_TRUE(loader.LoadComponent(kTestComponentName, expected_path2,
156 helper_mock.get()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700157}
158
Greg Kerr772abab2017-06-16 14:51:01 -0700159TEST_F(ImageLoaderTest, LoadComponentAtPath) {
160 Keys keys;
161 keys.push_back(
162 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
163
Greg Kerr09f06de2018-02-16 15:32:07 -0800164 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Xiaochu Liue61e1d62018-11-12 13:20:09 -0800165 EXPECT_CALL(*helper_mock, SendMountCommand(_, _, FileSystem::kSquashFS, _))
Xiaochu Liuc2264342017-08-14 16:37:42 -0700166 .Times(1);
167 ON_CALL(*helper_mock, SendMountCommand(_, _, _, _))
Greg Kerr772abab2017-06-16 14:51:01 -0700168 .WillByDefault(testing::Return(true));
169
170 base::ScopedTempDir scoped_mount_dir;
171 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
172
173 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800174 scoped_mount_dir.GetPath().value().c_str());
Greg Kerr772abab2017-06-16 14:51:01 -0700175 ImageLoaderImpl loader(std::move(config));
176
177 const std::string expected_path =
Eric Carusoa5dfc942018-01-22 15:44:45 -0800178 scoped_mount_dir.GetPath().value() + "/PepperFlashPlayer/22.0.0.158";
Greg Kerr772abab2017-06-16 14:51:01 -0700179 const std::string mnt_path = loader.LoadComponentAtPath(
180 kTestComponentName, GetTestComponentPath(), helper_mock.get());
181 EXPECT_EQ(expected_path, mnt_path);
182}
183
Xiaochu Liu5e708b82017-11-13 13:59:12 -0800184TEST_F(ImageLoaderTest, CleanupAll) {
185 Keys keys;
186 keys.push_back(
187 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
188
Greg Kerr09f06de2018-02-16 15:32:07 -0800189 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Colin Howesad6271a2018-11-21 15:36:05 -0800190 EXPECT_CALL(*helper_mock, SendUnmountAllCommand(_, _, _)).Times(1);
Xiaochu Liu5e708b82017-11-13 13:59:12 -0800191 ON_CALL(*helper_mock, SendUnmountAllCommand(_, _, _))
192 .WillByDefault(testing::Return(true));
193
194 base::ScopedTempDir scoped_mount_dir;
195 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
196
197 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800198 scoped_mount_dir.GetPath().value().c_str());
Xiaochu Liu5e708b82017-11-13 13:59:12 -0800199 ImageLoaderImpl loader(std::move(config));
200
201 base::FilePath rootpath("/");
202 std::vector<std::string> paths;
203 EXPECT_EQ(loader.CleanupAll(true, rootpath, &paths, helper_mock.get()), true);
204}
205
206TEST_F(ImageLoaderTest, Cleanup) {
207 Keys keys;
208 keys.push_back(
209 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
210
Greg Kerr09f06de2018-02-16 15:32:07 -0800211 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Xiaochu Liu5e708b82017-11-13 13:59:12 -0800212 EXPECT_CALL(*helper_mock, SendUnmountCommand(_)).Times(1);
213 ON_CALL(*helper_mock, SendUnmountCommand(_))
214 .WillByDefault(testing::Return(true));
215
216 base::ScopedTempDir scoped_mount_dir;
217 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
218
219 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800220 scoped_mount_dir.GetPath().value().c_str());
Xiaochu Liu5e708b82017-11-13 13:59:12 -0800221 ImageLoaderImpl loader(std::move(config));
222
223 base::FilePath path("/");
224 EXPECT_EQ(loader.Cleanup(path, helper_mock.get()), true);
225}
226
Xiaochu Liuc2264342017-08-14 16:37:42 -0700227TEST_F(ImageLoaderTest, LoadExt4Image) {
Greg Kerre8704202017-07-27 12:54:31 -0700228 Keys keys;
Xiaochu Liuc2264342017-08-14 16:37:42 -0700229 keys.push_back(
230 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
Greg Kerre8704202017-07-27 12:54:31 -0700231
Greg Kerr09f06de2018-02-16 15:32:07 -0800232 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Xiaochu Liue61e1d62018-11-12 13:20:09 -0800233 EXPECT_CALL(*helper_mock, SendMountCommand(_, _, FileSystem::kExt4, _))
Xiaochu Liuc2264342017-08-14 16:37:42 -0700234 .Times(1);
235 ON_CALL(*helper_mock, SendMountCommand(_, _, _, _))
236 .WillByDefault(testing::Return(true));
237
238 base::ScopedTempDir scoped_mount_dir;
239 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
240
241 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800242 scoped_mount_dir.GetPath().value().c_str());
Xiaochu Liuc2264342017-08-14 16:37:42 -0700243 ImageLoaderImpl loader(std::move(config));
244
245 const std::string expected_path =
Eric Carusoa5dfc942018-01-22 15:44:45 -0800246 scoped_mount_dir.GetPath().value() + "/ext4/9824.0.4";
Xiaochu Liuc2264342017-08-14 16:37:42 -0700247 const std::string mnt_path = loader.LoadComponentAtPath(
248 "ext4", GetTestDataPath("ext4_component"), helper_mock.get());
249 EXPECT_EQ(expected_path, mnt_path);
250}
251
Xiaochu Liuf6106e52018-08-10 13:09:00 -0700252TEST_F(ImageLoaderTest, UnloadDlcImage) {
253 Keys keys;
254 keys.push_back(
255 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
256
257 base::ScopedTempDir scoped_mount_dir;
258 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
259
260 const std::string dlc_id = "dlc_id";
Amin Hassani0badef12019-03-18 17:08:02 -0700261 const std::string dlc_package = "dlc_package";
Xiaochu Liuf6106e52018-08-10 13:09:00 -0700262 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Amin Hassani0badef12019-03-18 17:08:02 -0700263 EXPECT_CALL(*helper_mock, SendUnmountCommand(scoped_mount_dir.GetPath()
264 .Append(dlc_id)
265 .Append(dlc_package)
266 .value()
267 .c_str()))
Xiaochu Liuf6106e52018-08-10 13:09:00 -0700268 .Times(1);
269 ON_CALL(*helper_mock, SendUnmountCommand(_))
270 .WillByDefault(testing::Return(true));
271
272 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
273 scoped_mount_dir.GetPath().value().c_str());
274 ImageLoaderImpl loader(std::move(config));
275
Amin Hassani0badef12019-03-18 17:08:02 -0700276 loader.UnloadDlcImage(dlc_id, dlc_package, helper_mock.get());
Xiaochu Liuf6106e52018-08-10 13:09:00 -0700277}
278
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700279TEST_F(ImageLoaderTest, RemoveImageAtPathRemovable) {
280 Keys keys;
281 keys.push_back(
282 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
283
284 base::ScopedTempDir scoped_mount_dir;
285 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
286 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800287 scoped_mount_dir.GetPath().value().c_str());
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700288 ImageLoaderImpl loader(std::move(config));
289
290 // Make a copy to avoid permanent loss of test data.
291 base::ScopedTempDir component_root;
292 ASSERT_TRUE(component_root.CreateUniqueTempDir());
Eric Carusoa5dfc942018-01-22 15:44:45 -0800293 base::FilePath component_path = component_root.GetPath().Append("9824.0.4");
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700294 ASSERT_TRUE(base::CreateDirectory(component_path));
Colin Howesad6271a2018-11-21 15:36:05 -0800295 std::unique_ptr<Component> component = Component::Create(
296 base::FilePath(GetTestDataPath("ext4_component")), keys);
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700297 ASSERT_TRUE(component->CopyTo(component_path));
298
299 // Remove the component.
Eric Carusoa5dfc942018-01-22 15:44:45 -0800300 EXPECT_TRUE(loader.RemoveComponentAtPath("ext4", component_root.GetPath(),
301 component_path));
302 EXPECT_FALSE(base::PathExists(component_root.GetPath()));
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700303}
304
305TEST_F(ImageLoaderTest, RemoveImageAtPathNotRemovable) {
306 Keys keys;
307 keys.push_back(
308 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
309
310 base::ScopedTempDir scoped_mount_dir;
311 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
312 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800313 scoped_mount_dir.GetPath().value().c_str());
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700314 ImageLoaderImpl loader(std::move(config));
315
316 // Make a copy to avoid permanent loss of test data.
317 base::ScopedTempDir component_root;
318 ASSERT_TRUE(component_root.CreateUniqueTempDir());
Eric Carusoa5dfc942018-01-22 15:44:45 -0800319 base::FilePath component_path = component_root.GetPath().Append("9824.0.4");
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700320 ASSERT_TRUE(base::CreateDirectory(component_path));
321 std::unique_ptr<Component> component =
Colin Howesad6271a2018-11-21 15:36:05 -0800322 Component::Create(base::FilePath(GetTestComponentPath()), keys);
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700323 ASSERT_TRUE(component->CopyTo(component_path));
324
325 // Remove the component.
326 EXPECT_FALSE(loader.RemoveComponentAtPath(
Eric Carusoa5dfc942018-01-22 15:44:45 -0800327 kTestComponentName, component_root.GetPath(), component_path));
328 EXPECT_TRUE(base::PathExists(component_root.GetPath()));
Xiaochu Liu7a224d92017-10-06 17:33:41 -0700329}
330
Xiaochu Liuc2264342017-08-14 16:37:42 -0700331TEST_F(ImageLoaderTest, MountInvalidImage) {
332 Keys keys;
333 keys.push_back(
334 std::vector<uint8_t>(std::begin(kDevPublicKey), std::end(kDevPublicKey)));
335
Greg Kerr09f06de2018-02-16 15:32:07 -0800336 auto helper_mock = std::make_unique<MockHelperProcessProxy>();
Xiaochu Liue61e1d62018-11-12 13:20:09 -0800337 EXPECT_CALL(*helper_mock, SendMountCommand(_, _, FileSystem::kSquashFS, _))
Xiaochu Liuc2264342017-08-14 16:37:42 -0700338 .Times(0);
339 ON_CALL(*helper_mock, SendMountCommand(_, _, _, _))
Greg Kerr9944e242017-01-26 15:09:31 -0800340 .WillByDefault(testing::Return(true));
Greg Kerr89be05f2016-07-27 10:40:32 -0700341
Greg Kerr89be05f2016-07-27 10:40:32 -0700342 base::ScopedTempDir scoped_mount_dir;
Greg Kerr89be05f2016-07-27 10:40:32 -0700343 ASSERT_TRUE(scoped_mount_dir.CreateUniqueTempDir());
344
Eric Caruso0b79bc82017-03-21 13:44:34 -0700345 ImageLoaderConfig config(keys, temp_dir_.value().c_str(),
Eric Carusoa5dfc942018-01-22 15:44:45 -0800346 scoped_mount_dir.GetPath().value().c_str());
Greg Kerr89be05f2016-07-27 10:40:32 -0700347 ImageLoaderImpl loader(std::move(config));
348
349 // We previously tested RegisterComponent, so assume this works if it reports
350 // true.
351 ASSERT_TRUE(loader.RegisterComponent(kTestComponentName, kTestDataVersion,
Greg Kerr019d59c2016-11-17 14:28:49 -0800352 GetTestComponentPath().value()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700353
Greg Kerr019d59c2016-11-17 14:28:49 -0800354 base::FilePath table = temp_dir_.Append(kTestComponentName)
Colin Howesad6271a2018-11-21 15:36:05 -0800355 .Append(kTestDataVersion)
356 .Append("table");
Greg Kerr89be05f2016-07-27 10:40:32 -0700357 std::string contents = "corrupt";
358 ASSERT_EQ(static_cast<int>(contents.size()),
Greg Kerr30cd5fb2016-09-29 12:37:02 -0700359 base::WriteFile(table, contents.data(), contents.size()));
Greg Kerr9944e242017-01-26 15:09:31 -0800360 ASSERT_EQ("", loader.LoadComponent(kTestComponentName, helper_mock.get()));
Greg Kerr89be05f2016-07-27 10:40:32 -0700361}
362
Greg Kerr2f76fde2016-08-29 16:39:45 -0700363TEST_F(ImageLoaderTest, SetupTable) {
Colin Howesad6271a2018-11-21 15:36:05 -0800364 std::string base_table =
365 "0 40 verity payload=ROOT_DEV hashtree=HASH_DEV "
Greg Kerr2f76fde2016-08-29 16:39:45 -0700366 "hashstart=40 alg=sha256 root_hexdigest="
367 "34663b9920632778d38a0943a5472cae196bd4bf1d7dfa191506e7a8e7ec84d2 "
368 "salt=fcfc9b5a329e44be73a323188ae75ca644122d920161f672f6935623831d07e2";
369
370 // Make sure excess newlines are rejected.
371 std::string bad_table = base_table + "\n\n";
372 EXPECT_FALSE(VerityMounter::SetupTable(&bad_table, "/dev/loop6"));
373
374 // Make sure it does the right replacements on a simple base table.
375 std::string good_table = base_table;
376 EXPECT_TRUE(VerityMounter::SetupTable(&good_table, "/dev/loop6"));
377
378 std::string known_good_table =
379 "0 40 verity payload=/dev/loop6 hashtree=/dev/loop6 "
380 "hashstart=40 alg=sha256 root_hexdigest="
381 "34663b9920632778d38a0943a5472cae196bd4bf1d7dfa191506e7a8e7ec84d2 "
382 "salt=fcfc9b5a329e44be73a323188ae75ca644122d920161f672f6935623831d07e2 "
383 "error_behavior=eio";
384 EXPECT_EQ(known_good_table, good_table);
385
386 // Make sure the newline is stripped.
387 std::string good_table_newline = base_table + "\n";
388 EXPECT_TRUE(VerityMounter::SetupTable(&good_table_newline, "/dev/loop6"));
389 EXPECT_EQ(known_good_table, good_table_newline);
390
391 // Make sure error_behavior isn't appended twice.
392 std::string good_table_error = base_table + " error_behavior=eio\n";
393 EXPECT_TRUE(VerityMounter::SetupTable(&good_table_error, "/dev/loop6"));
394 EXPECT_EQ(known_good_table, good_table_error);
395}
396
Eric Caruso0b79bc82017-03-21 13:44:34 -0700397TEST_F(ImageLoaderTest, SecondKey) {
398 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
399 ASSERT_TRUE(loader.RegisterComponent(kTestOciComponentName,
400 kTestOciComponentVersion,
401 GetTestOciComponentPath().value()));
402
403 base::FilePath comp_dir = temp_dir_.Append(kTestOciComponentName);
404 ASSERT_TRUE(base::DirectoryExists(comp_dir));
405
406 base::FilePath version_dir = comp_dir.Append(kTestOciComponentVersion);
407 ASSERT_TRUE(base::DirectoryExists(version_dir));
408}
409
Eric Caruso26a91442017-10-25 16:05:40 -0700410TEST_F(ImageLoaderTest, GetMetadata) {
411 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
412 ASSERT_TRUE(loader.RegisterComponent(kMetadataComponentName,
413 kTestOciComponentVersion,
414 GetMetadataComponentPath().value()));
415
416 // We shouldn't need to load the component to get the metadata.
417 std::map<std::string, std::string> metadata;
418 ASSERT_TRUE(loader.GetComponentMetadata(kMetadataComponentName, &metadata));
419 std::map<std::string, std::string> expected_metadata{
Colin Howesad6271a2018-11-21 15:36:05 -0800420 {"foo", "bar"},
421 {"baz", "quux"},
Eric Caruso26a91442017-10-25 16:05:40 -0700422 };
423 ASSERT_EQ(expected_metadata, metadata);
424}
425
426TEST_F(ImageLoaderTest, GetEmptyMetadata) {
427 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
428 ASSERT_TRUE(loader.RegisterComponent(kTestOciComponentName,
429 kTestOciComponentVersion,
430 GetTestOciComponentPath().value()));
431
432 // If there's no metadata, we should get nothing.
433 std::map<std::string, std::string> metadata;
434 ASSERT_TRUE(loader.GetComponentMetadata(kTestOciComponentName, &metadata));
435 ASSERT_TRUE(metadata.empty());
436}
437
438TEST_F(ImageLoaderTest, MetadataFailure) {
439 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
440 // Metadata is optional, but malformed metadata should not be present in the
441 // manifest. If it is, fail to load the component.
442 ASSERT_FALSE(loader.RegisterComponent(kBadMetadataComponentName,
443 kTestOciComponentVersion,
444 GetBadMetadataComponentPath().value()));
445
446 ASSERT_FALSE(loader.RegisterComponent(
Colin Howesad6271a2018-11-21 15:36:05 -0800447 kNonDictMetadataComponentName, kTestOciComponentVersion,
Eric Caruso26a91442017-10-25 16:05:40 -0700448 GetNonDictMetadataComponentPath().value()));
Eric Caruso26a91442017-10-25 16:05:40 -0700449}
450
Greg Kerr285f58f2018-10-25 11:33:46 -0700451TEST_F(ImageLoaderTest, ValidIdTest) {
452 // alpha numerical IDs:
453 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("alpha"));
454 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("01234"));
455 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("alphanum01234"));
456 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("01234alphanumerical"));
457 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("dash-id0123"));
458 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("underscore_id_0123"));
459 EXPECT_TRUE(ImageLoaderImpl::IsIdValid("0123-a_dash-id"));
460 EXPECT_TRUE(ImageLoaderImpl::IsIdValid(u8"unicode_id"));
461 // first char is illegal:
462 EXPECT_FALSE(ImageLoaderImpl::IsIdValid("-non-alpha"));
463 EXPECT_FALSE(ImageLoaderImpl::IsIdValid("_non-alpha"));
464 EXPECT_FALSE(ImageLoaderImpl::IsIdValid(".non-alpha"));
465 // non-alpha numerical IDs:
466 EXPECT_FALSE(ImageLoaderImpl::IsIdValid("dot.id"));
467 EXPECT_FALSE(ImageLoaderImpl::IsIdValid("../../../../evilid"));
468 EXPECT_FALSE(ImageLoaderImpl::IsIdValid(u8"unicode_id_#"));
469 // ID is too long.
470 EXPECT_FALSE(
471 ImageLoaderImpl::IsIdValid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
472}
473
Amin Hassani17a185b2021-02-10 12:07:57 -0800474TEST_F(ImageLoaderTest, NoSignatureOfficialImage) {
475 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
476 // On official builds a component with no signature file should fail.
477 EXPECT_FALSE(loader.RegisterComponent(kNoSignatureComponentName,
478 kTestOciComponentVersion,
479 GetNoSignatureComponentPath().value()));
480}
481
482TEST_F(ImageLoaderTest, NoSignatureNonOfficialImage) {
483 ImageLoaderImpl loader(GetConfig(temp_dir_.value().c_str()));
484
485 // On non-official builds a component with no signature file should succeed.
486 EXPECT_CALL(g_ctx_, IsOfficialBuild()).WillRepeatedly(testing::Return(false));
487 EXPECT_TRUE(loader.RegisterComponent(kNoSignatureComponentName,
488 kTestOciComponentVersion,
489 GetNoSignatureComponentPath().value()));
490}
491
Colin Howesad6271a2018-11-21 15:36:05 -0800492} // namespace imageloader