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