1 /*
2  *  Copyright 2018 Google, Inc
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16 
17 #ifndef _LIBDM_DMTARGET_H_
18 #define _LIBDM_DMTARGET_H_
19 
20 #include <linux/dm-ioctl.h>
21 #include <stdint.h>
22 
23 #include <string>
24 #include <vector>
25 
26 namespace android {
27 namespace dm {
28 
29 class DmTargetTypeInfo {
30   public:
DmTargetTypeInfo()31     DmTargetTypeInfo() : major_(0), minor_(0), patch_(0) {}
DmTargetTypeInfo(const struct dm_target_versions * info)32     DmTargetTypeInfo(const struct dm_target_versions* info)
33         : name_(info->name),
34           major_(info->version[0]),
35           minor_(info->version[1]),
36           patch_(info->version[2]) {}
37 
name()38     const std::string& name() const { return name_; }
version()39     std::string version() const {
40         return std::to_string(major_) + "." + std::to_string(minor_) + "." + std::to_string(patch_);
41     }
42 
major_version()43     uint32_t major_version() const { return major_; }
minor_version()44     uint32_t minor_version() const { return minor_; }
patch_level()45     uint32_t patch_level() const { return patch_; }
46 
IsAtLeast(uint32_t major,uint32_t minor,uint32_t patch)47     bool IsAtLeast(uint32_t major, uint32_t minor, uint32_t patch) const {
48         if (major_ > major) return true;
49         if (major_ < major) return false;
50         if (minor_ > minor) return true;
51         if (minor_ < minor) return false;
52         return patch_ >= patch;
53     }
54 
55   private:
56     std::string name_;
57     uint32_t major_;
58     uint32_t minor_;
59     uint32_t patch_;
60 };
61 
62 class DmTarget {
63   public:
DmTarget(uint64_t start,uint64_t length)64     DmTarget(uint64_t start, uint64_t length) : start_(start), length_(length) {}
65 
66     virtual ~DmTarget() = default;
67 
68     // Returns name of the target.
69     virtual std::string name() const = 0;
70 
71     // Return the first logical sector represented by this target.
start()72     uint64_t start() const { return start_; }
73 
74     // Returns size in number of sectors when this target is part of
75     // a DmTable, return 0 otherwise.
size()76     uint64_t size() const { return length_; }
77 
78     // Function that converts this object to a string of arguments that can
79     // be passed to the kernel for adding this target in a table. Each target (e.g. verity, linear)
80     // must implement this, for it to be used on a device.
81     std::string Serialize() const;
82 
Valid()83     virtual bool Valid() const { return true; }
84 
85   protected:
86     // Get the parameter string that is passed to the end of the dm_target_spec
87     // for this target type.
88     virtual std::string GetParameterString() const = 0;
89 
90   private:
91     // logical sector number start and total length (in terms of 512-byte sectors) represented
92     // by this target within a DmTable.
93     uint64_t start_, length_;
94 };
95 
96 class DmTargetZero final : public DmTarget {
97   public:
DmTargetZero(uint64_t start,uint64_t length)98     DmTargetZero(uint64_t start, uint64_t length) : DmTarget(start, length) {}
99 
name()100     std::string name() const override { return "zero"; }
101     std::string GetParameterString() const override;
102 };
103 
104 class DmTargetLinear final : public DmTarget {
105   public:
DmTargetLinear(uint64_t start,uint64_t length,const std::string & block_device,uint64_t physical_sector)106     DmTargetLinear(uint64_t start, uint64_t length, const std::string& block_device,
107                    uint64_t physical_sector)
108         : DmTarget(start, length), block_device_(block_device), physical_sector_(physical_sector) {}
109 
name()110     std::string name() const override { return "linear"; }
111     std::string GetParameterString() const override;
block_device()112     const std::string& block_device() const { return block_device_; }
113 
114   private:
115     std::string block_device_;
116     uint64_t physical_sector_;
117 };
118 
119 class DmTargetVerity final : public DmTarget {
120   public:
121     DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
122                    const std::string& block_device, const std::string& hash_device,
123                    uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks,
124                    uint32_t hash_start_block, const std::string& hash_algorithm,
125                    const std::string& root_digest, const std::string& salt);
126 
127     void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start);
128     void SetVerityMode(const std::string& mode);
129     void IgnoreZeroBlocks();
130 
name()131     std::string name() const override { return "verity"; }
132     std::string GetParameterString() const override;
Valid()133     bool Valid() const override { return valid_; }
134 
135   private:
136     std::vector<std::string> base_args_;
137     std::vector<std::string> optional_args_;
138     bool valid_;
139 };
140 
141 class DmTargetAndroidVerity final : public DmTarget {
142   public:
DmTargetAndroidVerity(uint64_t start,uint64_t length,const std::string & block_device,const std::string & keyid)143     DmTargetAndroidVerity(uint64_t start, uint64_t length, const std::string& block_device,
144                           const std::string& keyid)
145         : DmTarget(start, length), keyid_(keyid), block_device_(block_device) {}
146 
name()147     std::string name() const override { return "android-verity"; }
148     std::string GetParameterString() const override;
149 
150   private:
151     std::string keyid_;
152     std::string block_device_;
153 };
154 
155 // This is the same as DmTargetVerity, but the table may be specified as a raw
156 // string. This code exists only for fs_mgr_verity and should be avoided. Use
157 // DmTargetVerity for new code instead.
158 class DmTargetVerityString final : public DmTarget {
159   public:
DmTargetVerityString(uint64_t start,uint64_t length,const std::string & target_string)160     DmTargetVerityString(uint64_t start, uint64_t length, const std::string& target_string)
161         : DmTarget(start, length), target_string_(target_string) {}
162 
name()163     std::string name() const override { return "verity"; }
GetParameterString()164     std::string GetParameterString() const override { return target_string_; }
Valid()165     bool Valid() const override { return true; }
166 
167   private:
168     std::string target_string_;
169 };
170 
171 // dm-bow is the backup on write target that can provide checkpoint capability
172 // for file systems that do not support checkpoints natively
173 class DmTargetBow final : public DmTarget {
174   public:
DmTargetBow(uint64_t start,uint64_t length,const std::string & target_string)175     DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string)
176         : DmTarget(start, length), target_string_(target_string) {}
177 
SetBlockSize(uint32_t block_size)178     void SetBlockSize(uint32_t block_size) { block_size_ = block_size; }
179 
name()180     std::string name() const override { return "bow"; }
181     std::string GetParameterString() const override;
182 
183   private:
184     std::string target_string_;
185     uint32_t block_size_ = 0;
186 };
187 
188 enum class SnapshotStorageMode {
189     // The snapshot will be persisted to the COW device.
190     Persistent,
191     // The snapshot will be lost on reboot.
192     Transient,
193     // The snapshot will be merged from the COW device into the base device,
194     // in the background.
195     Merge
196 };
197 
198 // Writes to a snapshot device will be written to the given COW device. Reads
199 // will read from the COW device or base device. The chunk size is specified
200 // in sectors.
201 class DmTargetSnapshot final : public DmTarget {
202   public:
DmTargetSnapshot(uint64_t start,uint64_t length,const std::string & base_device,const std::string & cow_device,SnapshotStorageMode mode,uint64_t chunk_size)203     DmTargetSnapshot(uint64_t start, uint64_t length, const std::string& base_device,
204                      const std::string& cow_device, SnapshotStorageMode mode, uint64_t chunk_size)
205         : DmTarget(start, length),
206           base_device_(base_device),
207           cow_device_(cow_device),
208           mode_(mode),
209           chunk_size_(chunk_size) {}
210 
211     std::string name() const override;
212     std::string GetParameterString() const override;
Valid()213     bool Valid() const override { return true; }
214 
215     struct Status {
216         uint64_t sectors_allocated;
217         uint64_t total_sectors;
218         uint64_t metadata_sectors;
219         std::string error;
220     };
221 
222     static double MergePercent(const Status& status, uint64_t sectors_initial = 0);
223     static bool ParseStatusText(const std::string& text, Status* status);
224     static bool ReportsOverflow(const std::string& target_type);
225     static bool GetDevicesFromParams(const std::string& params, std::string* base_device,
226                                      std::string* cow_device);
227 
228   private:
229     std::string base_device_;
230     std::string cow_device_;
231     SnapshotStorageMode mode_;
232     uint64_t chunk_size_;
233 };
234 
235 // snapshot-origin will read/write directly to the backing device, updating any
236 // snapshot devices with a matching origin.
237 class DmTargetSnapshotOrigin final : public DmTarget {
238   public:
DmTargetSnapshotOrigin(uint64_t start,uint64_t length,const std::string & device)239     DmTargetSnapshotOrigin(uint64_t start, uint64_t length, const std::string& device)
240         : DmTarget(start, length), device_(device) {}
241 
name()242     std::string name() const override { return "snapshot-origin"; }
GetParameterString()243     std::string GetParameterString() const override { return device_; }
Valid()244     bool Valid() const override { return true; }
245 
246   private:
247     std::string device_;
248 };
249 
250 class DmTargetCrypt final : public DmTarget {
251   public:
DmTargetCrypt(uint64_t start,uint64_t length,const std::string & cipher,const std::string & key,uint64_t iv_sector_offset,const std::string & device,uint64_t device_sector)252     DmTargetCrypt(uint64_t start, uint64_t length, const std::string& cipher,
253                   const std::string& key, uint64_t iv_sector_offset, const std::string& device,
254                   uint64_t device_sector)
255         : DmTarget(start, length),
256           cipher_(cipher),
257           key_(key),
258           iv_sector_offset_(iv_sector_offset),
259           device_(device),
260           device_sector_(device_sector) {}
261 
AllowDiscards()262     void AllowDiscards() { allow_discards_ = true; }
AllowEncryptOverride()263     void AllowEncryptOverride() { allow_encrypt_override_ = true; }
SetIvLargeSectors()264     void SetIvLargeSectors() { iv_large_sectors_ = true; }
SetSectorSize(uint32_t sector_size)265     void SetSectorSize(uint32_t sector_size) { sector_size_ = sector_size; }
266 
name()267     std::string name() const override { return "crypt"; }
Valid()268     bool Valid() const override { return true; }
269     std::string GetParameterString() const override;
270 
271   private:
272     std::string cipher_;
273     std::string key_;
274     uint64_t iv_sector_offset_;
275     std::string device_;
276     uint64_t device_sector_;
277     bool allow_discards_ = false;
278     bool allow_encrypt_override_ = false;
279     bool iv_large_sectors_ = false;
280     uint32_t sector_size_ = 0;
281 };
282 
283 class DmTargetDefaultKey final : public DmTarget {
284   public:
DmTargetDefaultKey(uint64_t start,uint64_t length,const std::string & cipher,const std::string & key,const std::string & blockdev,uint64_t start_sector)285     DmTargetDefaultKey(uint64_t start, uint64_t length, const std::string& cipher,
286                        const std::string& key, const std::string& blockdev, uint64_t start_sector)
287         : DmTarget(start, length),
288           cipher_(cipher),
289           key_(key),
290           blockdev_(blockdev),
291           start_sector_(start_sector) {}
292 
name()293     std::string name() const override { return kName; }
294     bool Valid() const override;
295     std::string GetParameterString() const override;
SetUseLegacyOptionsFormat()296     void SetUseLegacyOptionsFormat() { use_legacy_options_format_ = true; }
SetSetDun()297     void SetSetDun() { set_dun_ = true; }
SetWrappedKeyV0()298     void SetWrappedKeyV0() { is_hw_wrapped_ = true; }
299 
300   private:
301     inline static const std::string kName = "default-key";
302 
303     std::string cipher_;
304     std::string key_;
305     std::string blockdev_;
306     uint64_t start_sector_;
307     bool use_legacy_options_format_ = false;
308     bool set_dun_ = false;
309     bool is_hw_wrapped_ = false;
310 };
311 
312 class DmTargetUser final : public DmTarget {
313   public:
DmTargetUser(uint64_t start,uint64_t length,std::string control_device)314     DmTargetUser(uint64_t start, uint64_t length, std::string control_device)
315         : DmTarget(start, length), control_device_(control_device) {}
316 
name()317     std::string name() const override { return "user"; }
control_device()318     std::string control_device() const { return control_device_; }
319     std::string GetParameterString() const override;
320 
321   private:
322     std::string control_device_;
323 };
324 
325 }  // namespace dm
326 }  // namespace android
327 
328 #endif /* _LIBDM_DMTARGET_H_ */
329