1 // Copyright 2018 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
5 #include <brillo/blkdev_utils/device_mapper_task.h>
6
7 #include <libdevmapper.h>
8 #include <string>
9 #include <utility>
10
11 #include <brillo/blkdev_utils/device_mapper.h>
12
13 namespace brillo {
14
DevmapperTaskImpl(int type)15 DevmapperTaskImpl::DevmapperTaskImpl(int type)
16 : task_(DmTaskPtr(dm_task_create(type), &dm_task_destroy)) {}
17
SetName(const std::string & name)18 bool DevmapperTaskImpl::SetName(const std::string& name) {
19 if (!task_ || !dm_task_set_name(task_.get(), name.c_str())) {
20 LOG(ERROR) << "SetName failed";
21 return false;
22 }
23 return true;
24 }
25
AddTarget(uint64_t start,uint64_t length,const std::string & type,const SecureBlob & parameters)26 bool DevmapperTaskImpl::AddTarget(uint64_t start,
27 uint64_t length,
28 const std::string& type,
29 const SecureBlob& parameters) {
30 // Strings stored in SecureBlob don't end with '\0'. Unfortunately,
31 // this causes accesses beyond the allocated storage space if any
32 // of the functions expecting a c-string get passed a SecureBlob.data().
33 // Temporarily, assign to a string.
34 // TODO(sarthakkukreti): Evaluate creation of a SecureCString to keep
35 // string data safe.
36 std::string parameters_str = parameters.to_string();
37 if (!task_ ||
38 !dm_task_add_target(task_.get(), start, length, type.c_str(),
39 parameters_str.c_str())) {
40 LOG(ERROR) << "AddTarget failed";
41 return false;
42 }
43 // Clear the string.
44 parameters_str.clear();
45 return true;
46 }
47
GetNextTarget(uint64_t * start,uint64_t * length,std::string * type,SecureBlob * parameters)48 bool DevmapperTaskImpl::GetNextTarget(uint64_t* start,
49 uint64_t* length,
50 std::string* type,
51 SecureBlob* parameters) {
52 if (!task_) {
53 LOG(ERROR) << "GetNextTarget: invalid task.";
54 return false;
55 }
56
57 char *type_cstr, *parameters_cstr;
58 next_target_ = dm_get_next_target(task_.get(), next_target_, start, length,
59 &type_cstr, ¶meters_cstr);
60
61 if (type_cstr)
62 *type = std::string(type_cstr);
63 if (parameters_cstr) {
64 SecureBlob parameters_blob(parameters_cstr);
65 memset(parameters_cstr, 0, parameters_blob.size());
66 *parameters = std::move(parameters_blob);
67 }
68
69 return (next_target_ != nullptr);
70 }
71
Run(bool udev_sync)72 bool DevmapperTaskImpl::Run(bool udev_sync) {
73 uint32_t cookie = 0;
74
75 if (!task_) {
76 LOG(ERROR) << "Invalid task.";
77 return false;
78 }
79
80 if (udev_sync && !dm_task_set_cookie(task_.get(), &cookie, 0)) {
81 LOG(ERROR) << "dm_task_set_cookie failed";
82 return false;
83 }
84
85 if (!dm_task_run(task_.get())) {
86 LOG(ERROR) << "dm_task_run failed";
87 return false;
88 }
89
90 // Make sure the node exists before continuing.
91 // TODO(sarthakkukreti): move to dm_udev_wait_immediate() on uprevving lvm2.
92 return udev_sync ? (dm_udev_wait(cookie) != 0) : true;
93 }
94
95 } // namespace brillo
96