summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTreehugger Robot2017-05-15 20:04:33 -0500
committerGerrit Code Review2017-05-15 20:04:34 -0500
commitb9b95ee3a9dfa05008d783081d6e7db7d56d0574 (patch)
treee3c2cc0ed37c539d16adb00f38343e3acfba6f6f
parent3cfc1ab89dd841c69f0d477e75d534329a7a2e47 (diff)
parent6879cc1e2ee91f47fa05a01dfbce9dfef7504501 (diff)
downloadplatform-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.cpp170
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
90static inline bool nibble_value(const char& c, uint8_t* value) { 43static 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
283static 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) { 239static 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
309static 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 }