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