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 } // namespace dm 313 } // namespace android 314 315 #endif /* _LIBDM_DMTARGET_H_ */ 316