diff options
author | Treehugger Robot | 2017-05-15 20:04:33 -0500 |
---|---|---|
committer | Gerrit Code Review | 2017-05-15 20:04:34 -0500 |
commit | b9b95ee3a9dfa05008d783081d6e7db7d56d0574 (patch) | |
tree | e3c2cc0ed37c539d16adb00f38343e3acfba6f6f | |
parent | 3cfc1ab89dd841c69f0d477e75d534329a7a2e47 (diff) | |
parent | 6879cc1e2ee91f47fa05a01dfbce9dfef7504501 (diff) | |
download | platform-system-core-b9b95ee3a9dfa05008d783081d6e7db7d56d0574.tar.gz platform-system-core-b9b95ee3a9dfa05008d783081d6e7db7d56d0574.tar.xz platform-system-core-b9b95ee3a9dfa05008d783081d6e7db7d56d0574.zip |
Merge "fs_mgr: support different dm-verity error modes"
-rw-r--r-- | fs_mgr/fs_mgr_avb.cpp | 170 |
1 files changed, 95 insertions, 75 deletions
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 2b3220127..661800374 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp | |||
@@ -16,15 +16,14 @@ | |||
16 | 16 | ||
17 | #include "fs_mgr_avb.h" | 17 | #include "fs_mgr_avb.h" |
18 | 18 | ||
19 | #include <errno.h> | ||
20 | #include <fcntl.h> | 19 | #include <fcntl.h> |
21 | #include <inttypes.h> | ||
22 | #include <libgen.h> | 20 | #include <libgen.h> |
23 | #include <stdio.h> | ||
24 | #include <string.h> | 21 | #include <string.h> |
25 | #include <sys/stat.h> | 22 | #include <sys/ioctl.h> |
26 | #include <sys/types.h> | 23 | #include <sys/types.h> |
27 | #include <unistd.h> | 24 | |
25 | #include <sstream> | ||
26 | #include <string> | ||
28 | #include <vector> | 27 | #include <vector> |
29 | 28 | ||
30 | #include <android-base/file.h> | 29 | #include <android-base/file.h> |
@@ -33,11 +32,7 @@ | |||
33 | #include <android-base/stringprintf.h> | 32 | #include <android-base/stringprintf.h> |
34 | #include <android-base/strings.h> | 33 | #include <android-base/strings.h> |
35 | #include <android-base/unique_fd.h> | 34 | #include <android-base/unique_fd.h> |
36 | #include <cutils/properties.h> | ||
37 | #include <libavb/libavb.h> | 35 | #include <libavb/libavb.h> |
38 | #include <openssl/sha.h> | ||
39 | #include <sys/ioctl.h> | ||
40 | #include <utils/Compat.h> | ||
41 | 36 | ||
42 | #include "fs_mgr.h" | 37 | #include "fs_mgr.h" |
43 | #include "fs_mgr_priv.h" | 38 | #include "fs_mgr_priv.h" |
@@ -45,48 +40,6 @@ | |||
45 | #include "fs_mgr_priv_dm_ioctl.h" | 40 | #include "fs_mgr_priv_dm_ioctl.h" |
46 | #include "fs_mgr_priv_sha.h" | 41 | #include "fs_mgr_priv_sha.h" |
47 | 42 | ||
48 | /* The format of dm-verity construction parameters: | ||
49 | * <version> <dev> <hash_dev> <data_block_size> <hash_block_size> | ||
50 | * <num_data_blocks> <hash_start_block> <algorithm> <digest> <salt> | ||
51 | */ | ||
52 | #define VERITY_TABLE_FORMAT \ | ||
53 | "%u %s %s %u %u " \ | ||
54 | "%" PRIu64 " %" PRIu64 " %s %s %s " | ||
55 | |||
56 | #define VERITY_TABLE_PARAMS(hashtree_desc, blk_device, digest, salt) \ | ||
57 | hashtree_desc.dm_verity_version, blk_device, blk_device, hashtree_desc.data_block_size, \ | ||
58 | hashtree_desc.hash_block_size, \ | ||
59 | hashtree_desc.image_size / hashtree_desc.data_block_size, /* num_data_blocks. */ \ | ||
60 | hashtree_desc.tree_offset / hashtree_desc.hash_block_size, /* hash_start_block. */ \ | ||
61 | (char*)hashtree_desc.hash_algorithm, digest, salt | ||
62 | |||
63 | #define VERITY_TABLE_OPT_RESTART "restart_on_corruption" | ||
64 | #define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks" | ||
65 | |||
66 | /* The default format of dm-verity optional parameters: | ||
67 | * <#opt_params> ignore_zero_blocks restart_on_corruption | ||
68 | */ | ||
69 | #define VERITY_TABLE_OPT_DEFAULT_FORMAT "2 %s %s" | ||
70 | #define VERITY_TABLE_OPT_DEFAULT_PARAMS VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART | ||
71 | |||
72 | /* The FEC (forward error correction) format of dm-verity optional parameters: | ||
73 | * <#opt_params> use_fec_from_device <fec_dev> | ||
74 | * fec_roots <num> fec_blocks <num> fec_start <offset> | ||
75 | * ignore_zero_blocks restart_on_corruption | ||
76 | */ | ||
77 | #define VERITY_TABLE_OPT_FEC_FORMAT \ | ||
78 | "10 use_fec_from_device %s fec_roots %u fec_blocks %" PRIu64 " fec_start %" PRIu64 " %s %s" | ||
79 | |||
80 | /* Note that fec_blocks is the size that FEC covers, *not* the | ||
81 | * size of the FEC data. Since we use FEC for everything up until | ||
82 | * the FEC data, it's the same as the offset (fec_start). | ||
83 | */ | ||
84 | #define VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device) \ | ||
85 | blk_device, hashtree_desc.fec_num_roots, \ | ||
86 | hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_blocks */ \ | ||
87 | hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_start */ \ | ||
88 | VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART | ||
89 | |||
90 | static inline bool nibble_value(const char& c, uint8_t* value) { | 43 | static inline bool nibble_value(const char& c, uint8_t* value) { |
91 | FS_MGR_CHECK(value != nullptr); | 44 | FS_MGR_CHECK(value != nullptr); |
92 | 45 | ||
@@ -280,10 +233,81 @@ bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_da | |||
280 | return true; | 233 | return true; |
281 | } | 234 | } |
282 | 235 | ||
283 | static bool hashtree_load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, | 236 | // Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel. |
284 | int fd, const std::string& blk_device, | 237 | // See the following link for more details: |
285 | const AvbHashtreeDescriptor& hashtree_desc, | 238 | // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity |
286 | const std::string& salt, const std::string& root_digest) { | 239 | static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, |
240 | const std::string& salt, const std::string& root_digest, | ||
241 | const std::string& blk_device) { | ||
242 | // Loads androidboot.veritymode from kernel cmdline. | ||
243 | std::string verity_mode; | ||
244 | if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) { | ||
245 | verity_mode = "enforcing"; // Defaults to enforcing when it's absent. | ||
246 | } | ||
247 | |||
248 | // Converts veritymode to the format used in kernel. | ||
249 | std::string dm_verity_mode; | ||
250 | if (verity_mode == "enforcing") { | ||
251 | dm_verity_mode = "restart_on_corruption"; | ||
252 | } else if (verity_mode == "logging") { | ||
253 | dm_verity_mode = "ignore_corruption"; | ||
254 | } else if (verity_mode != "eio") { // Default dm_verity_mode is eio. | ||
255 | LERROR << "Unknown androidboot.veritymode: " << verity_mode; | ||
256 | return ""; | ||
257 | } | ||
258 | |||
259 | // dm-verity construction parameters: | ||
260 | // <version> <dev> <hash_dev> | ||
261 | // <data_block_size> <hash_block_size> | ||
262 | // <num_data_blocks> <hash_start_block> | ||
263 | // <algorithm> <digest> <salt> | ||
264 | // [<#opt_params> <opt_params>] | ||
265 | std::ostringstream verity_table; | ||
266 | verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " " | ||
267 | << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " " | ||
268 | << hashtree_desc.image_size / hashtree_desc.data_block_size << " " | ||
269 | << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " " | ||
270 | << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt; | ||
271 | |||
272 | // Continued from the above optional parameters: | ||
273 | // [<#opt_params> <opt_params>] | ||
274 | int optional_argc = 0; | ||
275 | std::ostringstream optional_args; | ||
276 | |||
277 | // dm-verity optional parameters for FEC (forward error correction): | ||
278 | // use_fec_from_device <fec_dev> | ||
279 | // fec_roots <num> | ||
280 | // fec_blocks <num> | ||
281 | // fec_start <offset> | ||
282 | if (hashtree_desc.fec_size > 0) { | ||
283 | // Note that fec_blocks is the size that FEC covers, *NOT* the | ||
284 | // size of the FEC data. Since we use FEC for everything up until | ||
285 | // the FEC data, it's the same as the offset (fec_start). | ||
286 | optional_argc += 8; | ||
287 | // clang-format off | ||
288 | optional_args << "use_fec_from_device " << blk_device | ||
289 | << " fec_roots " << hashtree_desc.fec_num_roots | ||
290 | << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size | ||
291 | << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size | ||
292 | << " "; | ||
293 | // clang-format on | ||
294 | } | ||
295 | |||
296 | if (!dm_verity_mode.empty()) { | ||
297 | optional_argc += 1; | ||
298 | optional_args << dm_verity_mode << " "; | ||
299 | } | ||
300 | |||
301 | // Always use ignore_zero_blocks. | ||
302 | optional_argc += 1; | ||
303 | optional_args << "ignore_zero_blocks"; | ||
304 | |||
305 | verity_table << " " << optional_argc << " " << optional_args.str(); | ||
306 | return verity_table.str(); | ||
307 | } | ||
308 | |||
309 | static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd, | ||
310 | uint64_t image_size, const std::string& verity_table) { | ||
287 | fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG); | 311 | fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG); |
288 | 312 | ||
289 | // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. | 313 | // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. |
@@ -294,35 +318,25 @@ static bool hashtree_load_verity_table(struct dm_ioctl* io, const std::string& d | |||
294 | io->target_count = 1; | 318 | io->target_count = 1; |
295 | dm_target->status = 0; | 319 | dm_target->status = 0; |
296 | dm_target->sector_start = 0; | 320 | dm_target->sector_start = 0; |
297 | dm_target->length = hashtree_desc.image_size / 512; | 321 | dm_target->length = image_size / 512; |
298 | strcpy(dm_target->target_type, "verity"); | 322 | strcpy(dm_target->target_type, "verity"); |
299 | 323 | ||
300 | // Builds the verity params. | 324 | // Builds the verity params. |
301 | char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); | 325 | char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); |
302 | size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); | 326 | size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); |
303 | 327 | ||
304 | int res = 0; | 328 | LINFO << "Loading verity table: '" << verity_table << "'"; |
305 | if (hashtree_desc.fec_size > 0) { | ||
306 | res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_FEC_FORMAT, | ||
307 | VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(), | ||
308 | salt.c_str()), | ||
309 | VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device.c_str())); | ||
310 | } else { | ||
311 | res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_DEFAULT_FORMAT, | ||
312 | VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(), | ||
313 | salt.c_str()), | ||
314 | VERITY_TABLE_OPT_DEFAULT_PARAMS); | ||
315 | } | ||
316 | 329 | ||
317 | if (res < 0 || (size_t)res >= bufsize) { | 330 | // Copies verity_table to verity_params (including the terminating null byte). |
318 | LERROR << "Error building verity table; insufficient buffer size?"; | 331 | if (verity_table.size() > bufsize - 1) { |
332 | LERROR << "Verity table size too large: " << verity_table.size() | ||
333 | << " (max allowable size: " << bufsize - 1 << ")"; | ||
319 | return false; | 334 | return false; |
320 | } | 335 | } |
321 | 336 | memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1); | |
322 | LINFO << "Loading verity table: '" << verity_params << "'"; | ||
323 | 337 | ||
324 | // Sets ext target boundary. | 338 | // Sets ext target boundary. |
325 | verity_params += strlen(verity_params) + 1; | 339 | verity_params += verity_table.size() + 1; |
326 | verity_params = (char*)(((unsigned long)verity_params + 7) & ~7); | 340 | verity_params = (char*)(((unsigned long)verity_params + 7) & ~7); |
327 | dm_target->next = verity_params - buffer; | 341 | dm_target->next = verity_params - buffer; |
328 | 342 | ||
@@ -362,9 +376,15 @@ static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, | |||
362 | return false; | 376 | return false; |
363 | } | 377 | } |
364 | 378 | ||
379 | std::string verity_table = | ||
380 | construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device); | ||
381 | if (verity_table.empty()) { | ||
382 | LERROR << "Failed to construct verity table."; | ||
383 | return false; | ||
384 | } | ||
385 | |||
365 | // Loads the verity mapping table. | 386 | // Loads the verity mapping table. |
366 | if (!hashtree_load_verity_table(io, mount_point, fd, std::string(fstab_entry->blk_device), | 387 | if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) { |
367 | hashtree_desc, salt, root_digest)) { | ||
368 | LERROR << "Couldn't load verity table!"; | 388 | LERROR << "Couldn't load verity table!"; |
369 | return false; | 389 | return false; |
370 | } | 390 | } |