• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 DmTargetStripe final : public DmTarget {
120   public:
DmTargetStripe(uint64_t start,uint64_t length,uint64_t chunksize,const std::string & block_device0,const std::string & block_device1)121     DmTargetStripe(uint64_t start, uint64_t length, uint64_t chunksize,
122                    const std::string& block_device0, const std::string& block_device1)
123         : DmTarget(start, length),
124           chunksize(chunksize),
125           block_device0_(block_device0),
126           block_device1_(block_device1) {}
127 
name()128     std::string name() const override { return "striped"; }
129     std::string GetParameterString() const override;
130 
131   private:
132     uint64_t chunksize;
133     std::string block_device0_;
134     std::string block_device1_;
135 };
136 
137 class DmTargetVerity final : public DmTarget {
138   public:
139     DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
140                    const std::string& block_device, const std::string& hash_device,
141                    uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks,
142                    uint32_t hash_start_block, const std::string& hash_algorithm,
143                    const std::string& root_digest, const std::string& salt);
144 
145     void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start);
146     void SetVerityMode(const std::string& mode);
147     void IgnoreZeroBlocks();
148     void CheckAtMostOnce();
149 
name()150     std::string name() const override { return "verity"; }
151     std::string GetParameterString() const override;
Valid()152     bool Valid() const override { return valid_; }
153 
154   private:
155     std::vector<std::string> base_args_;
156     std::vector<std::string> optional_args_;
157     bool valid_;
158 };
159 
160 class DmTargetAndroidVerity final : public DmTarget {
161   public:
DmTargetAndroidVerity(uint64_t start,uint64_t length,const std::string & block_device,const std::string & keyid)162     DmTargetAndroidVerity(uint64_t start, uint64_t length, const std::string& block_device,
163                           const std::string& keyid)
164         : DmTarget(start, length), keyid_(keyid), block_device_(block_device) {}
165 
name()166     std::string name() const override { return "android-verity"; }
167     std::string GetParameterString() const override;
168 
169   private:
170     std::string keyid_;
171     std::string block_device_;
172 };
173 
174 // This is the same as DmTargetVerity, but the table may be specified as a raw
175 // string. This code exists only for fs_mgr_verity and should be avoided. Use
176 // DmTargetVerity for new code instead.
177 class DmTargetVerityString final : public DmTarget {
178   public:
DmTargetVerityString(uint64_t start,uint64_t length,const std::string & target_string)179     DmTargetVerityString(uint64_t start, uint64_t length, const std::string& target_string)
180         : DmTarget(start, length), target_string_(target_string) {}
181 
name()182     std::string name() const override { return "verity"; }
GetParameterString()183     std::string GetParameterString() const override { return target_string_; }
Valid()184     bool Valid() const override { return true; }
185 
186   private:
187     std::string target_string_;
188 };
189 
190 // dm-bow is the backup on write target that can provide checkpoint capability
191 // for file systems that do not support checkpoints natively
192 class DmTargetBow final : public DmTarget {
193   public:
DmTargetBow(uint64_t start,uint64_t length,const std::string & target_string)194     DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string)
195         : DmTarget(start, length), target_string_(target_string) {}
196 
SetBlockSize(uint32_t block_size)197     void SetBlockSize(uint32_t block_size) { block_size_ = block_size; }
198 
name()199     std::string name() const override { return "bow"; }
200     std::string GetParameterString() const override;
201 
202   private:
203     std::string target_string_;
204     uint32_t block_size_ = 0;
205 };
206 
207 enum class SnapshotStorageMode {
208     // The snapshot will be persisted to the COW device.
209     Persistent,
210     // The snapshot will be lost on reboot.
211     Transient,
212     // The snapshot will be merged from the COW device into the base device,
213     // in the background.
214     Merge
215 };
216 
217 // Writes to a snapshot device will be written to the given COW device. Reads
218 // will read from the COW device or base device. The chunk size is specified
219 // in sectors.
220 class DmTargetSnapshot final : public DmTarget {
221   public:
DmTargetSnapshot(uint64_t start,uint64_t length,const std::string & base_device,const std::string & cow_device,SnapshotStorageMode mode,uint64_t chunk_size)222     DmTargetSnapshot(uint64_t start, uint64_t length, const std::string& base_device,
223                      const std::string& cow_device, SnapshotStorageMode mode, uint64_t chunk_size)
224         : DmTarget(start, length),
225           base_device_(base_device),
226           cow_device_(cow_device),
227           mode_(mode),
228           chunk_size_(chunk_size) {}
229 
230     std::string name() const override;
231     std::string GetParameterString() const override;
Valid()232     bool Valid() const override { return true; }
233 
234     struct Status {
235         uint64_t sectors_allocated;
236         uint64_t total_sectors;
237         uint64_t metadata_sectors;
238         std::string error;
239     };
240 
241     static double MergePercent(const Status& status, uint64_t sectors_initial = 0);
242     static bool ParseStatusText(const std::string& text, Status* status);
243     static bool ReportsOverflow(const std::string& target_type);
244     static bool GetDevicesFromParams(const std::string& params, std::string* base_device,
245                                      std::string* cow_device);
246 
247   private:
248     std::string base_device_;
249     std::string cow_device_;
250     SnapshotStorageMode mode_;
251     uint64_t chunk_size_;
252 };
253 
254 // snapshot-origin will read/write directly to the backing device, updating any
255 // snapshot devices with a matching origin.
256 class DmTargetSnapshotOrigin final : public DmTarget {
257   public:
DmTargetSnapshotOrigin(uint64_t start,uint64_t length,const std::string & device)258     DmTargetSnapshotOrigin(uint64_t start, uint64_t length, const std::string& device)
259         : DmTarget(start, length), device_(device) {}
260 
name()261     std::string name() const override { return "snapshot-origin"; }
GetParameterString()262     std::string GetParameterString() const override { return device_; }
Valid()263     bool Valid() const override { return true; }
264 
265   private:
266     std::string device_;
267 };
268 
269 class DmTargetCrypt final : public DmTarget {
270   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)271     DmTargetCrypt(uint64_t start, uint64_t length, const std::string& cipher,
272                   const std::string& key, uint64_t iv_sector_offset, const std::string& device,
273                   uint64_t device_sector)
274         : DmTarget(start, length),
275           cipher_(cipher),
276           key_(key),
277           iv_sector_offset_(iv_sector_offset),
278           device_(device),
279           device_sector_(device_sector) {}
280 
AllowDiscards()281     void AllowDiscards() { allow_discards_ = true; }
AllowEncryptOverride()282     void AllowEncryptOverride() { allow_encrypt_override_ = true; }
SetIvLargeSectors()283     void SetIvLargeSectors() { iv_large_sectors_ = true; }
SetSectorSize(uint32_t sector_size)284     void SetSectorSize(uint32_t sector_size) { sector_size_ = sector_size; }
285 
name()286     std::string name() const override { return "crypt"; }
Valid()287     bool Valid() const override { return true; }
288     std::string GetParameterString() const override;
289 
290   private:
291     std::string cipher_;
292     std::string key_;
293     uint64_t iv_sector_offset_;
294     std::string device_;
295     uint64_t device_sector_;
296     bool allow_discards_ = false;
297     bool allow_encrypt_override_ = false;
298     bool iv_large_sectors_ = false;
299     uint32_t sector_size_ = 0;
300 };
301 
302 class DmTargetDefaultKey final : public DmTarget {
303   public:
DmTargetDefaultKey(uint64_t start,uint64_t length,const std::string & cipher,const std::string & key,const std::string & blockdev,uint64_t start_sector)304     DmTargetDefaultKey(uint64_t start, uint64_t length, const std::string& cipher,
305                        const std::string& key, const std::string& blockdev, uint64_t start_sector)
306         : DmTarget(start, length),
307           cipher_(cipher),
308           key_(key),
309           blockdev_(blockdev),
310           start_sector_(start_sector) {}
311 
name()312     std::string name() const override { return kName; }
313     bool Valid() const override;
314     std::string GetParameterString() const override;
SetUseLegacyOptionsFormat()315     void SetUseLegacyOptionsFormat() { use_legacy_options_format_ = true; }
SetSetDun()316     void SetSetDun() { set_dun_ = true; }
SetWrappedKeyV0()317     void SetWrappedKeyV0() { is_hw_wrapped_ = true; }
318 
319   private:
320     inline static const std::string kName = "default-key";
321 
322     std::string cipher_;
323     std::string key_;
324     std::string blockdev_;
325     uint64_t start_sector_;
326     bool use_legacy_options_format_ = false;
327     bool set_dun_ = false;
328     bool is_hw_wrapped_ = false;
329 };
330 
331 class DmTargetUser final : public DmTarget {
332   public:
DmTargetUser(uint64_t start,uint64_t length,std::string control_device)333     DmTargetUser(uint64_t start, uint64_t length, std::string control_device)
334         : DmTarget(start, length), control_device_(control_device) {}
335 
name()336     std::string name() const override { return "user"; }
control_device()337     std::string control_device() const { return control_device_; }
338     std::string GetParameterString() const override;
339 
340   private:
341     std::string control_device_;
342 };
343 
344 class DmTargetError final : public DmTarget {
345   public:
DmTargetError(uint64_t start,uint64_t length)346     DmTargetError(uint64_t start, uint64_t length) : DmTarget(start, length) {}
347 
name()348     std::string name() const override { return "error"; }
GetParameterString()349     std::string GetParameterString() const override { return ""; }
350 };
351 
352 class DmTargetThinPool final : public DmTarget {
353   public:
354     DmTargetThinPool(uint64_t start, uint64_t length, const std::string& metadata_dev,
355                      const std::string& data_dev, uint64_t data_block_size,
356                      uint64_t low_water_mark);
357 
name()358     std::string name() const override { return "thin-pool"; }
359     std::string GetParameterString() const override;
360     bool Valid() const override;
361 
362   private:
363     std::string metadata_dev_;
364     std::string data_dev_;
365     uint64_t data_block_size_;
366     uint64_t low_water_mark_;
367 };
368 
369 class DmTargetThin final : public DmTarget {
370   public:
371     DmTargetThin(uint64_t start, uint64_t length, const std::string& pool_dev, uint64_t dev_id);
372 
name()373     std::string name() const override { return "thin"; }
374     std::string GetParameterString() const override;
375 
376   private:
377     std::string pool_dev_;
378     uint64_t dev_id_;
379 };
380 
381 }  // namespace dm
382 }  // namespace android
383 
384 #endif /* _LIBDM_DMTARGET_H_ */
385