diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-04 17:46:04 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-04 17:46:04 -0500 |
| commit | 42bd06e93d108a3ee5b8b4eaa350ec81853cb217 (patch) | |
| tree | 857034936a2c29c79c5cfde47c660225007b060f | |
| parent | 4710e78940d8d957f24b8f085f961f1279f8fbff (diff) | |
| parent | 84db119f5a83e1bf9cffbc6d9cf16487eda1c056 (diff) | |
Merge tag 'tags/upstream-4.20-rc1' of git://git.infradead.org/linux-ubifs
Pull UBIFS updates from Richard Weinberger:
- Full filesystem authentication feature, UBIFS is now able to have the
whole filesystem structure authenticated plus user data encrypted and
authenticated.
- Minor cleanups
* tag 'tags/upstream-4.20-rc1' of git://git.infradead.org/linux-ubifs: (26 commits)
ubifs: Remove unneeded semicolon
Documentation: ubifs: Add authentication whitepaper
ubifs: Enable authentication support
ubifs: Do not update inode size in-place in authenticated mode
ubifs: Add hashes and HMACs to default filesystem
ubifs: authentication: Authenticate super block node
ubifs: Create hash for default LPT
ubfis: authentication: Authenticate master node
ubifs: authentication: Authenticate LPT
ubifs: Authenticate replayed journal
ubifs: Add auth nodes to garbage collector journal head
ubifs: Add authentication nodes to journal
ubifs: authentication: Add hashes to index nodes
ubifs: Add hashes to the tree node cache
ubifs: Create functions to embed a HMAC in a node
ubifs: Add helper functions for authentication support
ubifs: Add separate functions to init/crc a node
ubifs: Format changes for authentication support
ubifs: Store read superblock node
ubifs: Drop write_node
...
| -rw-r--r-- | Documentation/filesystems/ubifs-authentication.md | 426 | ||||
| -rw-r--r-- | Documentation/filesystems/ubifs.txt | 7 | ||||
| -rw-r--r-- | drivers/mtd/ubi/attach.c | 1 | ||||
| -rw-r--r-- | drivers/mtd/ubi/build.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/Kconfig | 11 | ||||
| -rw-r--r-- | fs/ubifs/Makefile | 1 | ||||
| -rw-r--r-- | fs/ubifs/auth.c | 502 | ||||
| -rw-r--r-- | fs/ubifs/debug.c | 6 | ||||
| -rw-r--r-- | fs/ubifs/gc.c | 49 | ||||
| -rw-r--r-- | fs/ubifs/io.c | 110 | ||||
| -rw-r--r-- | fs/ubifs/journal.c | 289 | ||||
| -rw-r--r-- | fs/ubifs/log.c | 24 | ||||
| -rw-r--r-- | fs/ubifs/lpt.c | 184 | ||||
| -rw-r--r-- | fs/ubifs/lpt_commit.c | 44 | ||||
| -rw-r--r-- | fs/ubifs/master.c | 64 | ||||
| -rw-r--r-- | fs/ubifs/misc.h | 5 | ||||
| -rw-r--r-- | fs/ubifs/recovery.c | 120 | ||||
| -rw-r--r-- | fs/ubifs/replay.c | 177 | ||||
| -rw-r--r-- | fs/ubifs/sb.c | 209 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 91 | ||||
| -rw-r--r-- | fs/ubifs/tnc.c | 36 | ||||
| -rw-r--r-- | fs/ubifs/tnc_commit.c | 27 | ||||
| -rw-r--r-- | fs/ubifs/tnc_misc.c | 26 | ||||
| -rw-r--r-- | fs/ubifs/ubifs-media.h | 46 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 253 |
25 files changed, 2418 insertions, 292 deletions
diff --git a/Documentation/filesystems/ubifs-authentication.md b/Documentation/filesystems/ubifs-authentication.md new file mode 100644 index 000000000000..028b3e2e25f9 --- /dev/null +++ b/Documentation/filesystems/ubifs-authentication.md | |||
| @@ -0,0 +1,426 @@ | |||
| 1 | % UBIFS Authentication | ||
| 2 | % sigma star gmbh | ||
| 3 | % 2018 | ||
| 4 | |||
| 5 | # Introduction | ||
| 6 | |||
| 7 | UBIFS utilizes the fscrypt framework to provide confidentiality for file | ||
| 8 | contents and file names. This prevents attacks where an attacker is able to | ||
| 9 | read contents of the filesystem on a single point in time. A classic example | ||
| 10 | is a lost smartphone where the attacker is unable to read personal data stored | ||
| 11 | on the device without the filesystem decryption key. | ||
| 12 | |||
| 13 | At the current state, UBIFS encryption however does not prevent attacks where | ||
| 14 | the attacker is able to modify the filesystem contents and the user uses the | ||
| 15 | device afterwards. In such a scenario an attacker can modify filesystem | ||
| 16 | contents arbitrarily without the user noticing. One example is to modify a | ||
| 17 | binary to perform a malicious action when executed [DMC-CBC-ATTACK]. Since | ||
| 18 | most of the filesystem metadata of UBIFS is stored in plain, this makes it | ||
| 19 | fairly easy to swap files and replace their contents. | ||
| 20 | |||
| 21 | Other full disk encryption systems like dm-crypt cover all filesystem metadata, | ||
| 22 | which makes such kinds of attacks more complicated, but not impossible. | ||
| 23 | Especially, if the attacker is given access to the device multiple points in | ||
| 24 | time. For dm-crypt and other filesystems that build upon the Linux block IO | ||
| 25 | layer, the dm-integrity or dm-verity subsystems [DM-INTEGRITY, DM-VERITY] | ||
| 26 | can be used to get full data authentication at the block layer. | ||
| 27 | These can also be combined with dm-crypt [CRYPTSETUP2]. | ||
| 28 | |||
| 29 | This document describes an approach to get file contents _and_ full metadata | ||
| 30 | authentication for UBIFS. Since UBIFS uses fscrypt for file contents and file | ||
| 31 | name encryption, the authentication system could be tied into fscrypt such that | ||
| 32 | existing features like key derivation can be utilized. It should however also | ||
| 33 | be possible to use UBIFS authentication without using encryption. | ||
| 34 | |||
| 35 | |||
| 36 | ## MTD, UBI & UBIFS | ||
| 37 | |||
| 38 | On Linux, the MTD (Memory Technology Devices) subsystem provides a uniform | ||
| 39 | interface to access raw flash devices. One of the more prominent subsystems that | ||
| 40 | work on top of MTD is UBI (Unsorted Block Images). It provides volume management | ||
| 41 | for flash devices and is thus somewhat similar to LVM for block devices. In | ||
| 42 | addition, it deals with flash-specific wear-leveling and transparent I/O error | ||
| 43 | handling. UBI offers logical erase blocks (LEBs) to the layers on top of it | ||
| 44 | and maps them transparently to physical erase blocks (PEBs) on the flash. | ||
| 45 | |||
| 46 | UBIFS is a filesystem for raw flash which operates on top of UBI. Thus, wear | ||
| 47 | leveling and some flash specifics are left to UBI, while UBIFS focuses on | ||
| 48 | scalability, performance and recoverability. | ||
| 49 | |||
| 50 | |||
| 51 | |||
| 52 | +------------+ +*******+ +-----------+ +-----+ | ||
| 53 | | | * UBIFS * | UBI-BLOCK | | ... | | ||
| 54 | | JFFS/JFFS2 | +*******+ +-----------+ +-----+ | ||
| 55 | | | +-----------------------------+ +-----------+ +-----+ | ||
| 56 | | | | UBI | | MTD-BLOCK | | ... | | ||
| 57 | +------------+ +-----------------------------+ +-----------+ +-----+ | ||
| 58 | +------------------------------------------------------------------+ | ||
| 59 | | MEMORY TECHNOLOGY DEVICES (MTD) | | ||
| 60 | +------------------------------------------------------------------+ | ||
| 61 | +-----------------------------+ +--------------------------+ +-----+ | ||
| 62 | | NAND DRIVERS | | NOR DRIVERS | | ... | | ||
| 63 | +-----------------------------+ +--------------------------+ +-----+ | ||
| 64 | |||
| 65 | Figure 1: Linux kernel subsystems for dealing with raw flash | ||
| 66 | |||
| 67 | |||
| 68 | |||
| 69 | Internally, UBIFS maintains multiple data structures which are persisted on | ||
| 70 | the flash: | ||
| 71 | |||
| 72 | - *Index*: an on-flash B+ tree where the leaf nodes contain filesystem data | ||
| 73 | - *Journal*: an additional data structure to collect FS changes before updating | ||
| 74 | the on-flash index and reduce flash wear. | ||
| 75 | - *Tree Node Cache (TNC)*: an in-memory B+ tree that reflects the current FS | ||
| 76 | state to avoid frequent flash reads. It is basically the in-memory | ||
| 77 | representation of the index, but contains additional attributes. | ||
| 78 | - *LEB property tree (LPT)*: an on-flash B+ tree for free space accounting per | ||
| 79 | UBI LEB. | ||
| 80 | |||
| 81 | In the remainder of this section we will cover the on-flash UBIFS data | ||
| 82 | structures in more detail. The TNC is of less importance here since it is never | ||
| 83 | persisted onto the flash directly. More details on UBIFS can also be found in | ||
| 84 | [UBIFS-WP]. | ||
| 85 | |||
| 86 | |||
| 87 | ### UBIFS Index & Tree Node Cache | ||
| 88 | |||
| 89 | Basic on-flash UBIFS entities are called *nodes*. UBIFS knows different types | ||
| 90 | of nodes. Eg. data nodes (`struct ubifs_data_node`) which store chunks of file | ||
| 91 | contents or inode nodes (`struct ubifs_ino_node`) which represent VFS inodes. | ||
| 92 | Almost all types of nodes share a common header (`ubifs_ch`) containing basic | ||
| 93 | information like node type, node length, a sequence number, etc. (see | ||
| 94 | `fs/ubifs/ubifs-media.h`in kernel source). Exceptions are entries of the LPT | ||
| 95 | and some less important node types like padding nodes which are used to pad | ||
| 96 | unusable content at the end of LEBs. | ||
| 97 | |||
| 98 | To avoid re-writing the whole B+ tree on every single change, it is implemented | ||
| 99 | as *wandering tree*, where only the changed nodes are re-written and previous | ||
| 100 | versions of them are obsoleted without erasing them right away. As a result, | ||
| 101 | the index is not stored in a single place on the flash, but *wanders* around | ||
| 102 | and there are obsolete parts on the flash as long as the LEB containing them is | ||
| 103 | not reused by UBIFS. To find the most recent version of the index, UBIFS stores | ||
| 104 | a special node called *master node* into UBI LEB 1 which always points to the | ||
| 105 | most recent root node of the UBIFS index. For recoverability, the master node | ||
| 106 | is additionally duplicated to LEB 2. Mounting UBIFS is thus a simple read of | ||
| 107 | LEB 1 and 2 to get the current master node and from there get the location of | ||
| 108 | the most recent on-flash index. | ||
| 109 | |||
| 110 | The TNC is the in-memory representation of the on-flash index. It contains some | ||
| 111 | additional runtime attributes per node which are not persisted. One of these is | ||
| 112 | a dirty-flag which marks nodes that have to be persisted the next time the | ||
| 113 | index is written onto the flash. The TNC acts as a write-back cache and all | ||
| 114 | modifications of the on-flash index are done through the TNC. Like other caches, | ||
| 115 | the TNC does not have to mirror the full index into memory, but reads parts of | ||
| 116 | it from flash whenever needed. A *commit* is the UBIFS operation of updating the | ||
| 117 | on-flash filesystem structures like the index. On every commit, the TNC nodes | ||
| 118 | marked as dirty are written to the flash to update the persisted index. | ||
| 119 | |||
| 120 | |||
| 121 | ### Journal | ||
| 122 | |||
| 123 | To avoid wearing out the flash, the index is only persisted (*commited*) when | ||
| 124 | certain conditions are met (eg. `fsync(2)`). The journal is used to record | ||
| 125 | any changes (in form of inode nodes, data nodes etc.) between commits | ||
| 126 | of the index. During mount, the journal is read from the flash and replayed | ||
| 127 | onto the TNC (which will be created on-demand from the on-flash index). | ||
| 128 | |||
| 129 | UBIFS reserves a bunch of LEBs just for the journal called *log area*. The | ||
| 130 | amount of log area LEBs is configured on filesystem creation (using | ||
| 131 | `mkfs.ubifs`) and stored in the superblock node. The log area contains only | ||
| 132 | two types of nodes: *reference nodes* and *commit start nodes*. A commit start | ||
| 133 | node is written whenever an index commit is performed. Reference nodes are | ||
| 134 | written on every journal update. Each reference node points to the position of | ||
| 135 | other nodes (inode nodes, data nodes etc.) on the flash that are part of this | ||
| 136 | journal entry. These nodes are called *buds* and describe the actual filesystem | ||
| 137 | changes including their data. | ||
| 138 | |||
| 139 | The log area is maintained as a ring. Whenever the journal is almost full, | ||
| 140 | a commit is initiated. This also writes a commit start node so that during | ||
| 141 | mount, UBIFS will seek for the most recent commit start node and just replay | ||
| 142 | every reference node after that. Every reference node before the commit start | ||
| 143 | node will be ignored as they are already part of the on-flash index. | ||
| 144 | |||
| 145 | When writing a journal entry, UBIFS first ensures that enough space is | ||
| 146 | available to write the reference node and buds part of this entry. Then, the | ||
| 147 | reference node is written and afterwards the buds describing the file changes. | ||
| 148 | On replay, UBIFS will record every reference node and inspect the location of | ||
| 149 | the referenced LEBs to discover the buds. If these are corrupt or missing, | ||
| 150 | UBIFS will attempt to recover them by re-reading the LEB. This is however only | ||
| 151 | done for the last referenced LEB of the journal. Only this can become corrupt | ||
| 152 | because of a power cut. If the recovery fails, UBIFS will not mount. An error | ||
| 153 | for every other LEB will directly cause UBIFS to fail the mount operation. | ||
| 154 | |||
| 155 | |||
| 156 | | ---- LOG AREA ---- | ---------- MAIN AREA ------------ | | ||
| 157 | |||
| 158 | -----+------+-----+--------+---- ------+-----+-----+--------------- | ||
| 159 | \ | | | | / / | | | \ | ||
| 160 | / CS | REF | REF | | \ \ DENT | INO | INO | / | ||
| 161 | \ | | | | / / | | | \ | ||
| 162 | ----+------+-----+--------+--- -------+-----+-----+---------------- | ||
| 163 | | | ^ ^ | ||
| 164 | | | | | | ||
| 165 | +------------------------+ | | ||
| 166 | | | | ||
| 167 | +-------------------------------+ | ||
| 168 | |||
| 169 | |||
| 170 | Figure 2: UBIFS flash layout of log area with commit start nodes | ||
| 171 | (CS) and reference nodes (REF) pointing to main area | ||
| 172 | containing their buds | ||
| 173 | |||
| 174 | |||
| 175 | ### LEB Property Tree/Table | ||
| 176 | |||
| 177 | The LEB property tree is used to store per-LEB information. This includes the | ||
| 178 | LEB type and amount of free and *dirty* (old, obsolete content) space [1] on | ||
| 179 | the LEB. The type is important, because UBIFS never mixes index nodes with data | ||
| 180 | nodes on a single LEB and thus each LEB has a specific purpose. This again is | ||
| 181 | useful for free space calculations. See [UBIFS-WP] for more details. | ||
| 182 | |||
| 183 | The LEB property tree again is a B+ tree, but it is much smaller than the | ||
| 184 | index. Due to its smaller size it is always written as one chunk on every | ||
| 185 | commit. Thus, saving the LPT is an atomic operation. | ||
| 186 | |||
| 187 | |||
| 188 | [1] Since LEBs can only be appended and never overwritten, there is a | ||
| 189 | difference between free space ie. the remaining space left on the LEB to be | ||
| 190 | written to without erasing it and previously written content that is obsolete | ||
| 191 | but can't be overwritten without erasing the full LEB. | ||
| 192 | |||
| 193 | |||
| 194 | # UBIFS Authentication | ||
| 195 | |||
| 196 | This chapter introduces UBIFS authentication which enables UBIFS to verify | ||
| 197 | the authenticity and integrity of metadata and file contents stored on flash. | ||
| 198 | |||
| 199 | |||
| 200 | ## Threat Model | ||
| 201 | |||
| 202 | UBIFS authentication enables detection of offline data modification. While it | ||
| 203 | does not prevent it, it enables (trusted) code to check the integrity and | ||
| 204 | authenticity of on-flash file contents and filesystem metadata. This covers | ||
| 205 | attacks where file contents are swapped. | ||
| 206 | |||
| 207 | UBIFS authentication will not protect against rollback of full flash contents. | ||
| 208 | Ie. an attacker can still dump the flash and restore it at a later time without | ||
| 209 | detection. It will also not protect against partial rollback of individual | ||
| 210 | index commits. That means that an attacker is able to partially undo changes. | ||
| 211 | This is possible because UBIFS does not immediately overwrites obsolete | ||
| 212 | versions of the index tree or the journal, but instead marks them as obsolete | ||
| 213 | and garbage collection erases them at a later time. An attacker can use this by | ||
| 214 | erasing parts of the current tree and restoring old versions that are still on | ||
| 215 | the flash and have not yet been erased. This is possible, because every commit | ||
| 216 | will always write a new version of the index root node and the master node | ||
| 217 | without overwriting the previous version. This is further helped by the | ||
| 218 | wear-leveling operations of UBI which copies contents from one physical | ||
| 219 | eraseblock to another and does not atomically erase the first eraseblock. | ||
| 220 | |||
| 221 | UBIFS authentication does not cover attacks where an attacker is able to | ||
| 222 | execute code on the device after the authentication key was provided. | ||
| 223 | Additional measures like secure boot and trusted boot have to be taken to | ||
| 224 | ensure that only trusted code is executed on a device. | ||
| 225 | |||
| 226 | |||
| 227 | ## Authentication | ||
| 228 | |||
| 229 | To be able to fully trust data read from flash, all UBIFS data structures | ||
| 230 | stored on flash are authenticated. That is: | ||
| 231 | |||
| 232 | - The index which includes file contents, file metadata like extended | ||
| 233 | attributes, file length etc. | ||
| 234 | - The journal which also contains file contents and metadata by recording changes | ||
| 235 | to the filesystem | ||
| 236 | - The LPT which stores UBI LEB metadata which UBIFS uses for free space accounting | ||
| 237 | |||
| 238 | |||
| 239 | ### Index Authentication | ||
| 240 | |||
| 241 | Through UBIFS' concept of a wandering tree, it already takes care of only | ||
| 242 | updating and persisting changed parts from leaf node up to the root node | ||
| 243 | of the full B+ tree. This enables us to augment the index nodes of the tree | ||
| 244 | with a hash over each node's child nodes. As a result, the index basically also | ||
| 245 | a Merkle tree. Since the leaf nodes of the index contain the actual filesystem | ||
| 246 | data, the hashes of their parent index nodes thus cover all the file contents | ||
| 247 | and file metadata. When a file changes, the UBIFS index is updated accordingly | ||
| 248 | from the leaf nodes up to the root node including the master node. This process | ||
| 249 | can be hooked to recompute the hash only for each changed node at the same time. | ||
| 250 | Whenever a file is read, UBIFS can verify the hashes from each leaf node up to | ||
| 251 | the root node to ensure the node's integrity. | ||
| 252 | |||
| 253 | To ensure the authenticity of the whole index, the UBIFS master node stores a | ||
| 254 | keyed hash (HMAC) over its own contents and a hash of the root node of the index | ||
| 255 | tree. As mentioned above, the master node is always written to the flash whenever | ||
| 256 | the index is persisted (ie. on index commit). | ||
| 257 | |||
| 258 | Using this approach only UBIFS index nodes and the master node are changed to | ||
| 259 | include a hash. All other types of nodes will remain unchanged. This reduces | ||
| 260 | the storage overhead which is precious for users of UBIFS (ie. embedded | ||
| 261 | devices). | ||
| 262 | |||
| 263 | |||
| 264 | +---------------+ | ||
| 265 | | Master Node | | ||
| 266 | | (hash) | | ||
| 267 | +---------------+ | ||
| 268 | | | ||
| 269 | v | ||
| 270 | +-------------------+ | ||
| 271 | | Index Node #1 | | ||
| 272 | | | | ||
| 273 | | branch0 branchn | | ||
| 274 | | (hash) (hash) | | ||
| 275 | +-------------------+ | ||
| 276 | | ... | (fanout: 8) | ||
| 277 | | | | ||
| 278 | +-------+ +------+ | ||
| 279 | | | | ||
| 280 | v v | ||
| 281 | +-------------------+ +-------------------+ | ||
| 282 | | Index Node #2 | | Index Node #3 | | ||
| 283 | | | | | | ||
| 284 | | branch0 branchn | | branch0 branchn | | ||
| 285 | | (hash) (hash) | | (hash) (hash) | | ||
| 286 | +-------------------+ +-------------------+ | ||
| 287 | | ... | ... | | ||
| 288 | v v v | ||
| 289 | +-----------+ +----------+ +-----------+ | ||
| 290 | | Data Node | | INO Node | | DENT Node | | ||
| 291 | +-----------+ +----------+ +-----------+ | ||
| 292 | |||
| 293 | |||
| 294 | Figure 3: Coverage areas of index node hash and master node HMAC | ||
| 295 | |||
| 296 | |||
| 297 | |||
| 298 | The most important part for robustness and power-cut safety is to atomically | ||
| 299 | persist the hash and file contents. Here the existing UBIFS logic for how | ||
| 300 | changed nodes are persisted is already designed for this purpose such that | ||
| 301 | UBIFS can safely recover if a power-cut occurs while persisting. Adding | ||
| 302 | hashes to index nodes does not change this since each hash will be persisted | ||
| 303 | atomically together with its respective node. | ||
| 304 | |||
| 305 | |||
| 306 | ### Journal Authentication | ||
| 307 | |||
| 308 | The journal is authenticated too. Since the journal is continuously written | ||
| 309 | it is necessary to also add authentication information frequently to the | ||
| 310 | journal so that in case of a powercut not too much data can't be authenticated. | ||
| 311 | This is done by creating a continuous hash beginning from the commit start node | ||
| 312 | over the previous reference nodes, the current reference node, and the bud | ||
| 313 | nodes. From time to time whenever it is suitable authentication nodes are added | ||
| 314 | between the bud nodes. This new node type contains a HMAC over the current state | ||
| 315 | of the hash chain. That way a journal can be authenticated up to the last | ||
| 316 | authentication node. The tail of the journal which may not have a authentication | ||
| 317 | node cannot be authenticated and is skipped during journal replay. | ||
| 318 | |||
| 319 | We get this picture for journal authentication: | ||
| 320 | |||
| 321 | ,,,,,,,, | ||
| 322 | ,......,........................................... | ||
| 323 | ,. CS , hash1.----. hash2.----. | ||
| 324 | ,. | , . |hmac . |hmac | ||
| 325 | ,. v , . v . v | ||
| 326 | ,.REF#0,-> bud -> bud -> bud.-> auth -> bud -> bud.-> auth ... | ||
| 327 | ,..|...,........................................... | ||
| 328 | , | , | ||
| 329 | , | ,,,,,,,,,,,,,,, | ||
| 330 | . | hash3,----. | ||
| 331 | , | , |hmac | ||
| 332 | , v , v | ||
| 333 | , REF#1 -> bud -> bud,-> auth ... | ||
| 334 | ,,,|,,,,,,,,,,,,,,,,,, | ||
| 335 | v | ||
| 336 | REF#2 -> ... | ||
| 337 | | | ||
| 338 | V | ||
| 339 | ... | ||
| 340 | |||
| 341 | Since the hash also includes the reference nodes an attacker cannot reorder or | ||
| 342 | skip any journal heads for replay. An attacker can only remove bud nodes or | ||
| 343 | reference nodes from the end of the journal, effectively rewinding the | ||
| 344 | filesystem at maximum back to the last commit. | ||
| 345 | |||
| 346 | The location of the log area is stored in the master node. Since the master | ||
| 347 | node is authenticated with a HMAC as described above, it is not possible to | ||
| 348 | tamper with that without detection. The size of the log area is specified when | ||
| 349 | the filesystem is created using `mkfs.ubifs` and stored in the superblock node. | ||
| 350 | To avoid tampering with this and other values stored there, a HMAC is added to | ||
| 351 | the superblock struct. The superblock node is stored in LEB 0 and is only | ||
| 352 | modified on feature flag or similar changes, but never on file changes. | ||
| 353 | |||
| 354 | |||
| 355 | ### LPT Authentication | ||
| 356 | |||
| 357 | The location of the LPT root node on the flash is stored in the UBIFS master | ||
| 358 | node. Since the LPT is written and read atomically on every commit, there is | ||
| 359 | no need to authenticate individual nodes of the tree. It suffices to | ||
| 360 | protect the integrity of the full LPT by a simple hash stored in the master | ||
| 361 | node. Since the master node itself is authenticated, the LPTs authenticity can | ||
| 362 | be verified by verifying the authenticity of the master node and comparing the | ||
| 363 | LTP hash stored there with the hash computed from the read on-flash LPT. | ||
| 364 | |||
| 365 | |||
| 366 | ## Key Management | ||
| 367 | |||
| 368 | For simplicity, UBIFS authentication uses a single key to compute the HMACs | ||
| 369 | of superblock, master, commit start and reference nodes. This key has to be | ||
| 370 | available on creation of the filesystem (`mkfs.ubifs`) to authenticate the | ||
| 371 | superblock node. Further, it has to be available on mount of the filesystem | ||
| 372 | to verify authenticated nodes and generate new HMACs for changes. | ||
| 373 | |||
| 374 | UBIFS authentication is intended to operate side-by-side with UBIFS encryption | ||
| 375 | (fscrypt) to provide confidentiality and authenticity. Since UBIFS encryption | ||
| 376 | has a different approach of encryption policies per directory, there can be | ||
| 377 | multiple fscrypt master keys and there might be folders without encryption. | ||
| 378 | UBIFS authentication on the other hand has an all-or-nothing approach in the | ||
| 379 | sense that it either authenticates everything of the filesystem or nothing. | ||
| 380 | Because of this and because UBIFS authentication should also be usable without | ||
| 381 | encryption, it does not share the same master key with fscrypt, but manages | ||
| 382 | a dedicated authentication key. | ||
| 383 | |||
| 384 | The API for providing the authentication key has yet to be defined, but the | ||
| 385 | key can eg. be provided by userspace through a keyring similar to the way it | ||
| 386 | is currently done in fscrypt. It should however be noted that the current | ||
| 387 | fscrypt approach has shown its flaws and the userspace API will eventually | ||
| 388 | change [FSCRYPT-POLICY2]. | ||
| 389 | |||
| 390 | Nevertheless, it will be possible for a user to provide a single passphrase | ||
| 391 | or key in userspace that covers UBIFS authentication and encryption. This can | ||
| 392 | be solved by the corresponding userspace tools which derive a second key for | ||
| 393 | authentication in addition to the derived fscrypt master key used for | ||
| 394 | encryption. | ||
| 395 | |||
| 396 | To be able to check if the proper key is available on mount, the UBIFS | ||
| 397 | superblock node will additionally store a hash of the authentication key. This | ||
| 398 | approach is similar to the approach proposed for fscrypt encryption policy v2 | ||
| 399 | [FSCRYPT-POLICY2]. | ||
| 400 | |||
| 401 | |||
| 402 | # Future Extensions | ||
| 403 | |||
| 404 | In certain cases where a vendor wants to provide an authenticated filesystem | ||
| 405 | image to customers, it should be possible to do so without sharing the secret | ||
| 406 | UBIFS authentication key. Instead, in addition the each HMAC a digital | ||
| 407 | signature could be stored where the vendor shares the public key alongside the | ||
| 408 | filesystem image. In case this filesystem has to be modified afterwards, | ||
| 409 | UBIFS can exchange all digital signatures with HMACs on first mount similar | ||
| 410 | to the way the IMA/EVM subsystem deals with such situations. The HMAC key | ||
| 411 | will then have to be provided beforehand in the normal way. | ||
| 412 | |||
| 413 | |||
| 414 | # References | ||
| 415 | |||
| 416 | [CRYPTSETUP2] http://www.saout.de/pipermail/dm-crypt/2017-November/005745.html | ||
| 417 | |||
| 418 | [DMC-CBC-ATTACK] http://www.jakoblell.com/blog/2013/12/22/practical-malleability-attack-against-cbc-encrypted-luks-partitions/ | ||
| 419 | |||
| 420 | [DM-INTEGRITY] https://www.kernel.org/doc/Documentation/device-mapper/dm-integrity.txt | ||
| 421 | |||
| 422 | [DM-VERITY] https://www.kernel.org/doc/Documentation/device-mapper/verity.txt | ||
| 423 | |||
| 424 | [FSCRYPT-POLICY2] https://www.spinics.net/lists/linux-ext4/msg58710.html | ||
| 425 | |||
| 426 | [UBIFS-WP] http://www.linux-mtd.infradead.org/doc/ubifs_whitepaper.pdf | ||
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index a0a61d2f389f..acc80442a3bb 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt | |||
| @@ -91,6 +91,13 @@ chk_data_crc do not skip checking CRCs on data nodes | |||
| 91 | compr=none override default compressor and set it to "none" | 91 | compr=none override default compressor and set it to "none" |
| 92 | compr=lzo override default compressor and set it to "lzo" | 92 | compr=lzo override default compressor and set it to "lzo" |
| 93 | compr=zlib override default compressor and set it to "zlib" | 93 | compr=zlib override default compressor and set it to "zlib" |
| 94 | auth_key= specify the key used for authenticating the filesystem. | ||
| 95 | Passing this option makes authentication mandatory. | ||
| 96 | The passed key must be present in the kernel keyring | ||
| 97 | and must be of type 'logon' | ||
| 98 | auth_hash_name= The hash algorithm used for authentication. Used for | ||
| 99 | both hashing and for creating HMACs. Typical values | ||
| 100 | include "sha256" or "sha512" | ||
| 94 | 101 | ||
| 95 | 102 | ||
| 96 | Quick usage instructions | 103 | Quick usage instructions |
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 93ceea4f27d5..e294d3986ba9 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c | |||
| @@ -1072,6 +1072,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, | |||
| 1072 | * be a result of power cut during erasure. | 1072 | * be a result of power cut during erasure. |
| 1073 | */ | 1073 | */ |
| 1074 | ai->maybe_bad_peb_count += 1; | 1074 | ai->maybe_bad_peb_count += 1; |
| 1075 | /* fall through */ | ||
| 1075 | case UBI_IO_BAD_HDR: | 1076 | case UBI_IO_BAD_HDR: |
| 1076 | /* | 1077 | /* |
| 1077 | * If we're facing a bad VID header we have to drop *all* | 1078 | * If we're facing a bad VID header we have to drop *all* |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index d2a726654ff1..a4e3454133a4 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -1334,8 +1334,10 @@ static int bytes_str_to_int(const char *str) | |||
| 1334 | switch (*endp) { | 1334 | switch (*endp) { |
| 1335 | case 'G': | 1335 | case 'G': |
| 1336 | result *= 1024; | 1336 | result *= 1024; |
| 1337 | /* fall through */ | ||
| 1337 | case 'M': | 1338 | case 'M': |
| 1338 | result *= 1024; | 1339 | result *= 1024; |
| 1340 | /* fall through */ | ||
| 1339 | case 'K': | 1341 | case 'K': |
| 1340 | result *= 1024; | 1342 | result *= 1024; |
| 1341 | if (endp[1] == 'i' && endp[2] == 'B') | 1343 | if (endp[1] == 'i' && endp[2] == 'B') |
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index bbc78549be4c..529856fbccd0 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig | |||
| @@ -7,6 +7,7 @@ config UBIFS_FS | |||
| 7 | select CRYPTO if UBIFS_FS_ZLIB | 7 | select CRYPTO if UBIFS_FS_ZLIB |
| 8 | select CRYPTO_LZO if UBIFS_FS_LZO | 8 | select CRYPTO_LZO if UBIFS_FS_LZO |
| 9 | select CRYPTO_DEFLATE if UBIFS_FS_ZLIB | 9 | select CRYPTO_DEFLATE if UBIFS_FS_ZLIB |
| 10 | select CRYPTO_HASH_INFO | ||
| 10 | depends on MTD_UBI | 11 | depends on MTD_UBI |
| 11 | help | 12 | help |
| 12 | UBIFS is a file system for flash devices which works on top of UBI. | 13 | UBIFS is a file system for flash devices which works on top of UBI. |
| @@ -85,3 +86,13 @@ config UBIFS_FS_SECURITY | |||
| 85 | the extended attribute support in advance. | 86 | the extended attribute support in advance. |
| 86 | 87 | ||
| 87 | If you are not using a security module, say N. | 88 | If you are not using a security module, say N. |
| 89 | |||
| 90 | config UBIFS_FS_AUTHENTICATION | ||
| 91 | bool "UBIFS authentication support" | ||
| 92 | select CRYPTO_HMAC | ||
| 93 | help | ||
| 94 | Enable authentication support for UBIFS. This feature offers protection | ||
| 95 | against offline changes for both data and metadata of the filesystem. | ||
| 96 | If you say yes here you should also select a hashing algorithm such as | ||
| 97 | sha256, these are not selected automatically since there are many | ||
| 98 | different options. | ||
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile index 6197d7e539e4..5f838319c8d5 100644 --- a/fs/ubifs/Makefile +++ b/fs/ubifs/Makefile | |||
| @@ -8,3 +8,4 @@ ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o | |||
| 8 | ubifs-y += misc.o | 8 | ubifs-y += misc.o |
| 9 | ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o | 9 | ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o |
| 10 | ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o | 10 | ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o |
| 11 | ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o | ||
diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c new file mode 100644 index 000000000000..124e965a28b3 --- /dev/null +++ b/fs/ubifs/auth.c | |||
| @@ -0,0 +1,502 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * This file is part of UBIFS. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * This file implements various helper functions for UBIFS authentication support | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/crypto.h> | ||
| 13 | #include <crypto/hash.h> | ||
| 14 | #include <crypto/sha.h> | ||
| 15 | #include <crypto/algapi.h> | ||
| 16 | #include <keys/user-type.h> | ||
| 17 | |||
| 18 | #include "ubifs.h" | ||
| 19 | |||
| 20 | /** | ||
| 21 | * ubifs_node_calc_hash - calculate the hash of a UBIFS node | ||
| 22 | * @c: UBIFS file-system description object | ||
| 23 | * @node: the node to calculate a hash for | ||
| 24 | * @hash: the returned hash | ||
| 25 | * | ||
| 26 | * Returns 0 for success or a negative error code otherwise. | ||
| 27 | */ | ||
| 28 | int __ubifs_node_calc_hash(const struct ubifs_info *c, const void *node, | ||
| 29 | u8 *hash) | ||
| 30 | { | ||
| 31 | const struct ubifs_ch *ch = node; | ||
| 32 | SHASH_DESC_ON_STACK(shash, c->hash_tfm); | ||
| 33 | int err; | ||
| 34 | |||
| 35 | shash->tfm = c->hash_tfm; | ||
| 36 | shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 37 | |||
| 38 | err = crypto_shash_digest(shash, node, le32_to_cpu(ch->len), hash); | ||
| 39 | if (err < 0) | ||
| 40 | return err; | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | /** | ||
| 45 | * ubifs_hash_calc_hmac - calculate a HMAC from a hash | ||
| 46 | * @c: UBIFS file-system description object | ||
| 47 | * @hash: the node to calculate a HMAC for | ||
| 48 | * @hmac: the returned HMAC | ||
| 49 | * | ||
| 50 | * Returns 0 for success or a negative error code otherwise. | ||
| 51 | */ | ||
| 52 | static int ubifs_hash_calc_hmac(const struct ubifs_info *c, const u8 *hash, | ||
| 53 | u8 *hmac) | ||
| 54 | { | ||
| 55 | SHASH_DESC_ON_STACK(shash, c->hmac_tfm); | ||
| 56 | int err; | ||
| 57 | |||
| 58 | shash->tfm = c->hmac_tfm; | ||
| 59 | shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 60 | |||
| 61 | err = crypto_shash_digest(shash, hash, c->hash_len, hmac); | ||
| 62 | if (err < 0) | ||
| 63 | return err; | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | /** | ||
| 68 | * ubifs_prepare_auth_node - Prepare an authentication node | ||
| 69 | * @c: UBIFS file-system description object | ||
| 70 | * @node: the node to calculate a hash for | ||
| 71 | * @hash: input hash of previous nodes | ||
| 72 | * | ||
| 73 | * This function prepares an authentication node for writing onto flash. | ||
| 74 | * It creates a HMAC from the given input hash and writes it to the node. | ||
| 75 | * | ||
| 76 | * Returns 0 for success or a negative error code otherwise. | ||
| 77 | */ | ||
| 78 | int ubifs_prepare_auth_node(struct ubifs_info *c, void *node, | ||
| 79 | struct shash_desc *inhash) | ||
| 80 | { | ||
| 81 | SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm); | ||
| 82 | struct ubifs_auth_node *auth = node; | ||
| 83 | u8 *hash; | ||
| 84 | int err; | ||
| 85 | |||
| 86 | hash = kmalloc(crypto_shash_descsize(c->hash_tfm), GFP_NOFS); | ||
| 87 | if (!hash) | ||
| 88 | return -ENOMEM; | ||
| 89 | |||
| 90 | hash_desc->tfm = c->hash_tfm; | ||
| 91 | hash_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 92 | ubifs_shash_copy_state(c, inhash, hash_desc); | ||
| 93 | |||
| 94 | err = crypto_shash_final(hash_desc, hash); | ||
| 95 | if (err) | ||
| 96 | goto out; | ||
| 97 | |||
| 98 | err = ubifs_hash_calc_hmac(c, hash, auth->hmac); | ||
| 99 | if (err) | ||
| 100 | goto out; | ||
| 101 | |||
| 102 | auth->ch.node_type = UBIFS_AUTH_NODE; | ||
| 103 | ubifs_prepare_node(c, auth, ubifs_auth_node_sz(c), 0); | ||
| 104 | |||
| 105 | err = 0; | ||
| 106 | out: | ||
| 107 | kfree(hash); | ||
| 108 | |||
| 109 | return err; | ||
| 110 | } | ||
| 111 | |||
| 112 | static struct shash_desc *ubifs_get_desc(const struct ubifs_info *c, | ||
| 113 | struct crypto_shash *tfm) | ||
| 114 | { | ||
| 115 | struct shash_desc *desc; | ||
| 116 | int err; | ||
| 117 | |||
| 118 | if (!ubifs_authenticated(c)) | ||
| 119 | return NULL; | ||
| 120 | |||
| 121 | desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); | ||
| 122 | if (!desc) | ||
| 123 | return ERR_PTR(-ENOMEM); | ||
| 124 | |||
| 125 | desc->tfm = tfm; | ||
| 126 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 127 | |||
| 128 | err = crypto_shash_init(desc); | ||
| 129 | if (err) { | ||
| 130 | kfree(desc); | ||
| 131 | return ERR_PTR(err); | ||
| 132 | } | ||
| 133 | |||
| 134 | return desc; | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * __ubifs_hash_get_desc - get a descriptor suitable for hashing a node | ||
| 139 | * @c: UBIFS file-system description object | ||
| 140 | * | ||
| 141 | * This function returns a descriptor suitable for hashing a node. Free after use | ||
| 142 | * with kfree. | ||
| 143 | */ | ||
| 144 | struct shash_desc *__ubifs_hash_get_desc(const struct ubifs_info *c) | ||
| 145 | { | ||
| 146 | return ubifs_get_desc(c, c->hash_tfm); | ||
| 147 | } | ||
| 148 | |||
| 149 | /** | ||
| 150 | * __ubifs_shash_final - finalize shash | ||
| 151 | * @c: UBIFS file-system description object | ||
| 152 | * @desc: the descriptor | ||
| 153 | * @out: the output hash | ||
| 154 | * | ||
| 155 | * Simple wrapper around crypto_shash_final(), safe to be called with | ||
| 156 | * disabled authentication. | ||
| 157 | */ | ||
| 158 | int __ubifs_shash_final(const struct ubifs_info *c, struct shash_desc *desc, | ||
| 159 | u8 *out) | ||
| 160 | { | ||
| 161 | if (ubifs_authenticated(c)) | ||
| 162 | return crypto_shash_final(desc, out); | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | /** | ||
| 168 | * ubifs_bad_hash - Report hash mismatches | ||
| 169 | * @c: UBIFS file-system description object | ||
| 170 | * @node: the node | ||
| 171 | * @hash: the expected hash | ||
| 172 | * @lnum: the LEB @node was read from | ||
| 173 | * @offs: offset in LEB @node was read from | ||
| 174 | * | ||
| 175 | * This function reports a hash mismatch when a node has a different hash than | ||
| 176 | * expected. | ||
| 177 | */ | ||
| 178 | void ubifs_bad_hash(const struct ubifs_info *c, const void *node, const u8 *hash, | ||
| 179 | int lnum, int offs) | ||
| 180 | { | ||
| 181 | int len = min(c->hash_len, 20); | ||
| 182 | int cropped = len != c->hash_len; | ||
| 183 | const char *cont = cropped ? "..." : ""; | ||
| 184 | |||
| 185 | u8 calc[UBIFS_HASH_ARR_SZ]; | ||
| 186 | |||
| 187 | __ubifs_node_calc_hash(c, node, calc); | ||
| 188 | |||
| 189 | ubifs_err(c, "hash mismatch on node at LEB %d:%d", lnum, offs); | ||
| 190 | ubifs_err(c, "hash expected: %*ph%s", len, hash, cont); | ||
| 191 | ubifs_err(c, "hash calculated: %*ph%s", len, calc, cont); | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * __ubifs_node_check_hash - check the hash of a node against given hash | ||
| 196 | * @c: UBIFS file-system description object | ||
| 197 | * @node: the node | ||
| 198 | * @expected: the expected hash | ||
| 199 | * | ||
| 200 | * This function calculates a hash over a node and compares it to the given hash. | ||
| 201 | * Returns 0 if both hashes are equal or authentication is disabled, otherwise a | ||
| 202 | * negative error code is returned. | ||
| 203 | */ | ||
| 204 | int __ubifs_node_check_hash(const struct ubifs_info *c, const void *node, | ||
| 205 | const u8 *expected) | ||
| 206 | { | ||
| 207 | u8 calc[UBIFS_HASH_ARR_SZ]; | ||
| 208 | int err; | ||
| 209 | |||
| 210 | err = __ubifs_node_calc_hash(c, node, calc); | ||
| 211 | if (err) | ||
| 212 | return err; | ||
| 213 | |||
| 214 | if (ubifs_check_hash(c, expected, calc)) | ||
| 215 | return -EPERM; | ||
| 216 | |||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | /** | ||
| 221 | * ubifs_init_authentication - initialize UBIFS authentication support | ||
| 222 | * @c: UBIFS file-system description object | ||
| 223 | * | ||
| 224 | * This function returns 0 for success or a negative error code otherwise. | ||
| 225 | */ | ||
| 226 | int ubifs_init_authentication(struct ubifs_info *c) | ||
| 227 | { | ||
| 228 | struct key *keyring_key; | ||
| 229 | const struct user_key_payload *ukp; | ||
| 230 | int err; | ||
| 231 | char hmac_name[CRYPTO_MAX_ALG_NAME]; | ||
| 232 | |||
| 233 | if (!c->auth_hash_name) { | ||
| 234 | ubifs_err(c, "authentication hash name needed with authentication"); | ||
| 235 | return -EINVAL; | ||
| 236 | } | ||
| 237 | |||
| 238 | c->auth_hash_algo = match_string(hash_algo_name, HASH_ALGO__LAST, | ||
| 239 | c->auth_hash_name); | ||
| 240 | if ((int)c->auth_hash_algo < 0) { | ||
| 241 | ubifs_err(c, "Unknown hash algo %s specified", | ||
| 242 | c->auth_hash_name); | ||
| 243 | return -EINVAL; | ||
| 244 | } | ||
| 245 | |||
| 246 | snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", | ||
| 247 | c->auth_hash_name); | ||
| 248 | |||
| 249 | keyring_key = request_key(&key_type_logon, c->auth_key_name, NULL); | ||
| 250 | |||
| 251 | if (IS_ERR(keyring_key)) { | ||
| 252 | ubifs_err(c, "Failed to request key: %ld", | ||
| 253 | PTR_ERR(keyring_key)); | ||
| 254 | return PTR_ERR(keyring_key); | ||
| 255 | } | ||
| 256 | |||
| 257 | down_read(&keyring_key->sem); | ||
| 258 | |||
| 259 | if (keyring_key->type != &key_type_logon) { | ||
| 260 | ubifs_err(c, "key type must be logon"); | ||
| 261 | err = -ENOKEY; | ||
| 262 | goto out; | ||
| 263 | } | ||
| 264 | |||
| 265 | ukp = user_key_payload_locked(keyring_key); | ||
| 266 | if (!ukp) { | ||
| 267 | /* key was revoked before we acquired its semaphore */ | ||
| 268 | err = -EKEYREVOKED; | ||
| 269 | goto out; | ||
| 270 | } | ||
| 271 | |||
| 272 | c->hash_tfm = crypto_alloc_shash(c->auth_hash_name, 0, | ||
| 273 | CRYPTO_ALG_ASYNC); | ||
| 274 | if (IS_ERR(c->hash_tfm)) { | ||
| 275 | err = PTR_ERR(c->hash_tfm); | ||
| 276 | ubifs_err(c, "Can not allocate %s: %d", | ||
| 277 | c->auth_hash_name, err); | ||
| 278 | goto out; | ||
| 279 | } | ||
| 280 | |||
| 281 | c->hash_len = crypto_shash_digestsize(c->hash_tfm); | ||
| 282 | if (c->hash_len > UBIFS_HASH_ARR_SZ) { | ||
| 283 | ubifs_err(c, "hash %s is bigger than maximum allowed hash size (%d > %d)", | ||
| 284 | c->auth_hash_name, c->hash_len, UBIFS_HASH_ARR_SZ); | ||
| 285 | err = -EINVAL; | ||
| 286 | goto out_free_hash; | ||
| 287 | } | ||
| 288 | |||
| 289 | c->hmac_tfm = crypto_alloc_shash(hmac_name, 0, CRYPTO_ALG_ASYNC); | ||
| 290 | if (IS_ERR(c->hmac_tfm)) { | ||
| 291 | err = PTR_ERR(c->hmac_tfm); | ||
| 292 | ubifs_err(c, "Can not allocate %s: %d", hmac_name, err); | ||
| 293 | goto out_free_hash; | ||
| 294 | } | ||
| 295 | |||
| 296 | c->hmac_desc_len = crypto_shash_digestsize(c->hmac_tfm); | ||
| 297 | if (c->hmac_desc_len > UBIFS_HMAC_ARR_SZ) { | ||
| 298 | ubifs_err(c, "hmac %s is bigger than maximum allowed hmac size (%d > %d)", | ||
| 299 | hmac_name, c->hmac_desc_len, UBIFS_HMAC_ARR_SZ); | ||
| 300 | err = -EINVAL; | ||
| 301 | goto out_free_hash; | ||
| 302 | } | ||
| 303 | |||
| 304 | err = crypto_shash_setkey(c->hmac_tfm, ukp->data, ukp->datalen); | ||
| 305 | if (err) | ||
| 306 | goto out_free_hmac; | ||
| 307 | |||
| 308 | c->authenticated = true; | ||
| 309 | |||
| 310 | c->log_hash = ubifs_hash_get_desc(c); | ||
| 311 | if (IS_ERR(c->log_hash)) | ||
| 312 | goto out_free_hmac; | ||
| 313 | |||
| 314 | err = 0; | ||
| 315 | |||
| 316 | out_free_hmac: | ||
| 317 | if (err) | ||
| 318 | crypto_free_shash(c->hmac_tfm); | ||
| 319 | out_free_hash: | ||
| 320 | if (err) | ||
| 321 | crypto_free_shash(c->hash_tfm); | ||
| 322 | out: | ||
| 323 | up_read(&keyring_key->sem); | ||
| 324 | key_put(keyring_key); | ||
| 325 | |||
| 326 | return err; | ||
| 327 | } | ||
| 328 | |||
| 329 | /** | ||
| 330 | * __ubifs_exit_authentication - release resource | ||
| 331 | * @c: UBIFS file-system description object | ||
| 332 | * | ||
| 333 | * This function releases the authentication related resources. | ||
| 334 | */ | ||
| 335 | void __ubifs_exit_authentication(struct ubifs_info *c) | ||
| 336 | { | ||
| 337 | if (!ubifs_authenticated(c)) | ||
| 338 | return; | ||
| 339 | |||
| 340 | crypto_free_shash(c->hmac_tfm); | ||
| 341 | crypto_free_shash(c->hash_tfm); | ||
| 342 | kfree(c->log_hash); | ||
| 343 | } | ||
| 344 | |||
| 345 | /** | ||
| 346 | * ubifs_node_calc_hmac - calculate the HMAC of a UBIFS node | ||
| 347 | * @c: UBIFS file-system description object | ||
| 348 | * @node: the node to insert a HMAC into. | ||
| 349 | * @len: the length of the node | ||
| 350 | * @ofs_hmac: the offset in the node where the HMAC is inserted | ||
| 351 | * @hmac: returned HMAC | ||
| 352 | * | ||
| 353 | * This function calculates a HMAC of a UBIFS node. The HMAC is expected to be | ||
| 354 | * embedded into the node, so this area is not covered by the HMAC. Also not | ||
| 355 | * covered is the UBIFS_NODE_MAGIC and the CRC of the node. | ||
| 356 | */ | ||
| 357 | static int ubifs_node_calc_hmac(const struct ubifs_info *c, const void *node, | ||
| 358 | int len, int ofs_hmac, void *hmac) | ||
| 359 | { | ||
| 360 | SHASH_DESC_ON_STACK(shash, c->hmac_tfm); | ||
| 361 | int hmac_len = c->hmac_desc_len; | ||
| 362 | int err; | ||
| 363 | |||
| 364 | ubifs_assert(c, ofs_hmac > 8); | ||
| 365 | ubifs_assert(c, ofs_hmac + hmac_len < len); | ||
| 366 | |||
| 367 | shash->tfm = c->hmac_tfm; | ||
| 368 | shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 369 | |||
| 370 | err = crypto_shash_init(shash); | ||
| 371 | if (err) | ||
| 372 | return err; | ||
| 373 | |||
| 374 | /* behind common node header CRC up to HMAC begin */ | ||
| 375 | err = crypto_shash_update(shash, node + 8, ofs_hmac - 8); | ||
| 376 | if (err < 0) | ||
| 377 | return err; | ||
| 378 | |||
| 379 | /* behind HMAC, if any */ | ||
| 380 | if (len - ofs_hmac - hmac_len > 0) { | ||
| 381 | err = crypto_shash_update(shash, node + ofs_hmac + hmac_len, | ||
| 382 | len - ofs_hmac - hmac_len); | ||
| 383 | if (err < 0) | ||
| 384 | return err; | ||
| 385 | } | ||
| 386 | |||
| 387 | return crypto_shash_final(shash, hmac); | ||
| 388 | } | ||
| 389 | |||
| 390 | /** | ||
| 391 | * __ubifs_node_insert_hmac - insert a HMAC into a UBIFS node | ||
| 392 | * @c: UBIFS file-system description object | ||
| 393 | * @node: the node to insert a HMAC into. | ||
| 394 | * @len: the length of the node | ||
| 395 | * @ofs_hmac: the offset in the node where the HMAC is inserted | ||
| 396 | * | ||
| 397 | * This function inserts a HMAC at offset @ofs_hmac into the node given in | ||
| 398 | * @node. | ||
| 399 | * | ||
| 400 | * This function returns 0 for success or a negative error code otherwise. | ||
| 401 | */ | ||
| 402 | int __ubifs_node_insert_hmac(const struct ubifs_info *c, void *node, int len, | ||
| 403 | int ofs_hmac) | ||
| 404 | { | ||
| 405 | return ubifs_node_calc_hmac(c, node, len, ofs_hmac, node + ofs_hmac); | ||
| 406 | } | ||
| 407 | |||
| 408 | /** | ||
| 409 | * __ubifs_node_verify_hmac - verify the HMAC of UBIFS node | ||
| 410 | * @c: UBIFS file-system description object | ||
| 411 | * @node: the node to insert a HMAC into. | ||
| 412 | * @len: the length of the node | ||
| 413 | * @ofs_hmac: the offset in the node where the HMAC is inserted | ||
| 414 | * | ||
| 415 | * This function verifies the HMAC at offset @ofs_hmac of the node given in | ||
| 416 | * @node. Returns 0 if successful or a negative error code otherwise. | ||
| 417 | */ | ||
| 418 | int __ubifs_node_verify_hmac(const struct ubifs_info *c, const void *node, | ||
| 419 | int len, int ofs_hmac) | ||
| 420 | { | ||
| 421 | int hmac_len = c->hmac_desc_len; | ||
| 422 | u8 *hmac; | ||
| 423 | int err; | ||
| 424 | |||
| 425 | hmac = kmalloc(hmac_len, GFP_NOFS); | ||
| 426 | if (!hmac) | ||
| 427 | return -ENOMEM; | ||
| 428 | |||
| 429 | err = ubifs_node_calc_hmac(c, node, len, ofs_hmac, hmac); | ||
| 430 | if (err) | ||
| 431 | return err; | ||
| 432 | |||
| 433 | err = crypto_memneq(hmac, node + ofs_hmac, hmac_len); | ||
| 434 | |||
| 435 | kfree(hmac); | ||
| 436 | |||
| 437 | if (!err) | ||
| 438 | return 0; | ||
| 439 | |||
| 440 | return -EPERM; | ||
| 441 | } | ||
| 442 | |||
| 443 | int __ubifs_shash_copy_state(const struct ubifs_info *c, struct shash_desc *src, | ||
| 444 | struct shash_desc *target) | ||
| 445 | { | ||
| 446 | u8 *state; | ||
| 447 | int err; | ||
| 448 | |||
| 449 | state = kmalloc(crypto_shash_descsize(src->tfm), GFP_NOFS); | ||
| 450 | if (!state) | ||
| 451 | return -ENOMEM; | ||
| 452 | |||
| 453 | err = crypto_shash_export(src, state); | ||
| 454 | if (err) | ||
| 455 | goto out; | ||
| 456 | |||
| 457 | err = crypto_shash_import(target, state); | ||
| 458 | |||
| 459 | out: | ||
| 460 | kfree(state); | ||
| 461 | |||
| 462 | return err; | ||
| 463 | } | ||
| 464 | |||
| 465 | /** | ||
| 466 | * ubifs_hmac_wkm - Create a HMAC of the well known message | ||
| 467 | * @c: UBIFS file-system description object | ||
| 468 | * @hmac: The HMAC of the well known message | ||
| 469 | * | ||
| 470 | * This function creates a HMAC of a well known message. This is used | ||
| 471 | * to check if the provided key is suitable to authenticate a UBIFS | ||
| 472 | * image. This is only a convenience to the user to provide a better | ||
| 473 | * error message when the wrong key is provided. | ||
| 474 | * | ||
| 475 | * This function returns 0 for success or a negative error code otherwise. | ||
| 476 | */ | ||
| 477 | int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac) | ||
| 478 | { | ||
| 479 | SHASH_DESC_ON_STACK(shash, c->hmac_tfm); | ||
| 480 | int err; | ||
| 481 | const char well_known_message[] = "UBIFS"; | ||
| 482 | |||
| 483 | if (!ubifs_authenticated(c)) | ||
| 484 | return 0; | ||
| 485 | |||
| 486 | shash->tfm = c->hmac_tfm; | ||
| 487 | shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 488 | |||
| 489 | err = crypto_shash_init(shash); | ||
| 490 | if (err) | ||
| 491 | return err; | ||
| 492 | |||
| 493 | err = crypto_shash_update(shash, well_known_message, | ||
| 494 | sizeof(well_known_message) - 1); | ||
| 495 | if (err < 0) | ||
| 496 | return err; | ||
| 497 | |||
| 498 | err = crypto_shash_final(shash, hmac); | ||
| 499 | if (err) | ||
| 500 | return err; | ||
| 501 | return 0; | ||
| 502 | } | ||
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 564e330d05b1..c49ff50fdceb 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
| @@ -165,6 +165,8 @@ const char *dbg_ntype(int type) | |||
| 165 | return "commit start node"; | 165 | return "commit start node"; |
| 166 | case UBIFS_ORPH_NODE: | 166 | case UBIFS_ORPH_NODE: |
| 167 | return "orphan node"; | 167 | return "orphan node"; |
| 168 | case UBIFS_AUTH_NODE: | ||
| 169 | return "auth node"; | ||
| 168 | default: | 170 | default: |
| 169 | return "unknown node"; | 171 | return "unknown node"; |
| 170 | } | 172 | } |
| @@ -542,6 +544,10 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node) | |||
| 542 | (unsigned long long)le64_to_cpu(orph->inos[i])); | 544 | (unsigned long long)le64_to_cpu(orph->inos[i])); |
| 543 | break; | 545 | break; |
| 544 | } | 546 | } |
| 547 | case UBIFS_AUTH_NODE: | ||
| 548 | { | ||
| 549 | break; | ||
| 550 | } | ||
| 545 | default: | 551 | default: |
| 546 | pr_err("node type %d was not recognized\n", | 552 | pr_err("node type %d was not recognized\n", |
| 547 | (int)ch->node_type); | 553 | (int)ch->node_type); |
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index d2680e0b4a36..bf75fdc76fc3 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c | |||
| @@ -254,7 +254,8 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 254 | snod->type == UBIFS_DATA_NODE || | 254 | snod->type == UBIFS_DATA_NODE || |
| 255 | snod->type == UBIFS_DENT_NODE || | 255 | snod->type == UBIFS_DENT_NODE || |
| 256 | snod->type == UBIFS_XENT_NODE || | 256 | snod->type == UBIFS_XENT_NODE || |
| 257 | snod->type == UBIFS_TRUN_NODE); | 257 | snod->type == UBIFS_TRUN_NODE || |
| 258 | snod->type == UBIFS_AUTH_NODE); | ||
| 258 | 259 | ||
| 259 | if (snod->type != UBIFS_INO_NODE && | 260 | if (snod->type != UBIFS_INO_NODE && |
| 260 | snod->type != UBIFS_DATA_NODE && | 261 | snod->type != UBIFS_DATA_NODE && |
| @@ -364,12 +365,13 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) | |||
| 364 | 365 | ||
| 365 | /* Write nodes to their new location. Use the first-fit strategy */ | 366 | /* Write nodes to their new location. Use the first-fit strategy */ |
| 366 | while (1) { | 367 | while (1) { |
| 367 | int avail; | 368 | int avail, moved = 0; |
| 368 | struct ubifs_scan_node *snod, *tmp; | 369 | struct ubifs_scan_node *snod, *tmp; |
| 369 | 370 | ||
| 370 | /* Move data nodes */ | 371 | /* Move data nodes */ |
| 371 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { | 372 | list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) { |
| 372 | avail = c->leb_size - wbuf->offs - wbuf->used; | 373 | avail = c->leb_size - wbuf->offs - wbuf->used - |
| 374 | ubifs_auth_node_sz(c); | ||
| 373 | if (snod->len > avail) | 375 | if (snod->len > avail) |
| 374 | /* | 376 | /* |
| 375 | * Do not skip data nodes in order to optimize | 377 | * Do not skip data nodes in order to optimize |
| @@ -377,14 +379,21 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) | |||
| 377 | */ | 379 | */ |
| 378 | break; | 380 | break; |
| 379 | 381 | ||
| 382 | err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, | ||
| 383 | snod->node, snod->len); | ||
| 384 | if (err) | ||
| 385 | goto out; | ||
| 386 | |||
| 380 | err = move_node(c, sleb, snod, wbuf); | 387 | err = move_node(c, sleb, snod, wbuf); |
| 381 | if (err) | 388 | if (err) |
| 382 | goto out; | 389 | goto out; |
| 390 | moved = 1; | ||
| 383 | } | 391 | } |
| 384 | 392 | ||
| 385 | /* Move non-data nodes */ | 393 | /* Move non-data nodes */ |
| 386 | list_for_each_entry_safe(snod, tmp, &nondata, list) { | 394 | list_for_each_entry_safe(snod, tmp, &nondata, list) { |
| 387 | avail = c->leb_size - wbuf->offs - wbuf->used; | 395 | avail = c->leb_size - wbuf->offs - wbuf->used - |
| 396 | ubifs_auth_node_sz(c); | ||
| 388 | if (avail < min) | 397 | if (avail < min) |
| 389 | break; | 398 | break; |
| 390 | 399 | ||
| @@ -402,9 +411,41 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) | |||
| 402 | continue; | 411 | continue; |
| 403 | } | 412 | } |
| 404 | 413 | ||
| 414 | err = ubifs_shash_update(c, c->jheads[GCHD].log_hash, | ||
| 415 | snod->node, snod->len); | ||
| 416 | if (err) | ||
| 417 | goto out; | ||
| 418 | |||
| 405 | err = move_node(c, sleb, snod, wbuf); | 419 | err = move_node(c, sleb, snod, wbuf); |
| 406 | if (err) | 420 | if (err) |
| 407 | goto out; | 421 | goto out; |
| 422 | moved = 1; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (ubifs_authenticated(c) && moved) { | ||
| 426 | struct ubifs_auth_node *auth; | ||
| 427 | |||
| 428 | auth = kmalloc(ubifs_auth_node_sz(c), GFP_NOFS); | ||
| 429 | if (!auth) { | ||
| 430 | err = -ENOMEM; | ||
| 431 | goto out; | ||
| 432 | } | ||
| 433 | |||
| 434 | err = ubifs_prepare_auth_node(c, auth, | ||
| 435 | c->jheads[GCHD].log_hash); | ||
| 436 | if (err) { | ||
| 437 | kfree(auth); | ||
| 438 | goto out; | ||
| 439 | } | ||
| 440 | |||
| 441 | err = ubifs_wbuf_write_nolock(wbuf, auth, | ||
| 442 | ubifs_auth_node_sz(c)); | ||
| 443 | if (err) { | ||
| 444 | kfree(auth); | ||
| 445 | goto out; | ||
| 446 | } | ||
| 447 | |||
| 448 | ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c)); | ||
| 408 | } | 449 | } |
| 409 | 450 | ||
| 410 | if (list_empty(&sleb->nodes) && list_empty(&nondata)) | 451 | if (list_empty(&sleb->nodes) && list_empty(&nondata)) |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 099bec94b820..d124117efd42 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
| @@ -365,20 +365,8 @@ static unsigned long long next_sqnum(struct ubifs_info *c) | |||
| 365 | return sqnum; | 365 | return sqnum; |
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | /** | 368 | void ubifs_init_node(struct ubifs_info *c, void *node, int len, int pad) |
| 369 | * ubifs_prepare_node - prepare node to be written to flash. | ||
| 370 | * @c: UBIFS file-system description object | ||
| 371 | * @node: the node to pad | ||
| 372 | * @len: node length | ||
| 373 | * @pad: if the buffer has to be padded | ||
| 374 | * | ||
| 375 | * This function prepares node at @node to be written to the media - it | ||
| 376 | * calculates node CRC, fills the common header, and adds proper padding up to | ||
| 377 | * the next minimum I/O unit if @pad is not zero. | ||
| 378 | */ | ||
| 379 | void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) | ||
| 380 | { | 369 | { |
| 381 | uint32_t crc; | ||
| 382 | struct ubifs_ch *ch = node; | 370 | struct ubifs_ch *ch = node; |
| 383 | unsigned long long sqnum = next_sqnum(c); | 371 | unsigned long long sqnum = next_sqnum(c); |
| 384 | 372 | ||
| @@ -389,8 +377,6 @@ void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) | |||
| 389 | ch->group_type = UBIFS_NO_NODE_GROUP; | 377 | ch->group_type = UBIFS_NO_NODE_GROUP; |
| 390 | ch->sqnum = cpu_to_le64(sqnum); | 378 | ch->sqnum = cpu_to_le64(sqnum); |
| 391 | ch->padding[0] = ch->padding[1] = 0; | 379 | ch->padding[0] = ch->padding[1] = 0; |
| 392 | crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8); | ||
| 393 | ch->crc = cpu_to_le32(crc); | ||
| 394 | 380 | ||
| 395 | if (pad) { | 381 | if (pad) { |
| 396 | len = ALIGN(len, 8); | 382 | len = ALIGN(len, 8); |
| @@ -399,6 +385,68 @@ void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) | |||
| 399 | } | 385 | } |
| 400 | } | 386 | } |
| 401 | 387 | ||
| 388 | void ubifs_crc_node(struct ubifs_info *c, void *node, int len) | ||
| 389 | { | ||
| 390 | struct ubifs_ch *ch = node; | ||
| 391 | uint32_t crc; | ||
| 392 | |||
| 393 | crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8); | ||
| 394 | ch->crc = cpu_to_le32(crc); | ||
| 395 | } | ||
| 396 | |||
| 397 | /** | ||
| 398 | * ubifs_prepare_node_hmac - prepare node to be written to flash. | ||
| 399 | * @c: UBIFS file-system description object | ||
| 400 | * @node: the node to pad | ||
| 401 | * @len: node length | ||
| 402 | * @hmac_offs: offset of the HMAC in the node | ||
| 403 | * @pad: if the buffer has to be padded | ||
| 404 | * | ||
| 405 | * This function prepares node at @node to be written to the media - it | ||
| 406 | * calculates node CRC, fills the common header, and adds proper padding up to | ||
| 407 | * the next minimum I/O unit if @pad is not zero. if @hmac_offs is positive then | ||
| 408 | * a HMAC is inserted into the node at the given offset. | ||
| 409 | * | ||
| 410 | * This function returns 0 for success or a negative error code otherwise. | ||
| 411 | */ | ||
| 412 | int ubifs_prepare_node_hmac(struct ubifs_info *c, void *node, int len, | ||
| 413 | int hmac_offs, int pad) | ||
| 414 | { | ||
| 415 | int err; | ||
| 416 | |||
| 417 | ubifs_init_node(c, node, len, pad); | ||
| 418 | |||
| 419 | if (hmac_offs > 0) { | ||
| 420 | err = ubifs_node_insert_hmac(c, node, len, hmac_offs); | ||
| 421 | if (err) | ||
| 422 | return err; | ||
| 423 | } | ||
| 424 | |||
| 425 | ubifs_crc_node(c, node, len); | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | /** | ||
| 431 | * ubifs_prepare_node - prepare node to be written to flash. | ||
| 432 | * @c: UBIFS file-system description object | ||
| 433 | * @node: the node to pad | ||
| 434 | * @len: node length | ||
| 435 | * @pad: if the buffer has to be padded | ||
| 436 | * | ||
| 437 | * This function prepares node at @node to be written to the media - it | ||
| 438 | * calculates node CRC, fills the common header, and adds proper padding up to | ||
| 439 | * the next minimum I/O unit if @pad is not zero. | ||
| 440 | */ | ||
| 441 | void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) | ||
| 442 | { | ||
| 443 | /* | ||
| 444 | * Deliberately ignore return value since this function can only fail | ||
| 445 | * when a hmac offset is given. | ||
| 446 | */ | ||
| 447 | ubifs_prepare_node_hmac(c, node, len, 0, pad); | ||
| 448 | } | ||
| 449 | |||
| 402 | /** | 450 | /** |
| 403 | * ubifs_prep_grp_node - prepare node of a group to be written to flash. | 451 | * ubifs_prep_grp_node - prepare node of a group to be written to flash. |
| 404 | * @c: UBIFS file-system description object | 452 | * @c: UBIFS file-system description object |
| @@ -849,12 +897,13 @@ out: | |||
| 849 | } | 897 | } |
| 850 | 898 | ||
| 851 | /** | 899 | /** |
| 852 | * ubifs_write_node - write node to the media. | 900 | * ubifs_write_node_hmac - write node to the media. |
| 853 | * @c: UBIFS file-system description object | 901 | * @c: UBIFS file-system description object |
| 854 | * @buf: the node to write | 902 | * @buf: the node to write |
| 855 | * @len: node length | 903 | * @len: node length |
| 856 | * @lnum: logical eraseblock number | 904 | * @lnum: logical eraseblock number |
| 857 | * @offs: offset within the logical eraseblock | 905 | * @offs: offset within the logical eraseblock |
| 906 | * @hmac_offs: offset of the HMAC within the node | ||
| 858 | * | 907 | * |
| 859 | * This function automatically fills node magic number, assigns sequence | 908 | * This function automatically fills node magic number, assigns sequence |
| 860 | * number, and calculates node CRC checksum. The length of the @buf buffer has | 909 | * number, and calculates node CRC checksum. The length of the @buf buffer has |
| @@ -862,8 +911,8 @@ out: | |||
| 862 | * appends padding node and padding bytes if needed. Returns zero in case of | 911 | * appends padding node and padding bytes if needed. Returns zero in case of |
| 863 | * success and a negative error code in case of failure. | 912 | * success and a negative error code in case of failure. |
| 864 | */ | 913 | */ |
| 865 | int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | 914 | int ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum, |
| 866 | int offs) | 915 | int offs, int hmac_offs) |
| 867 | { | 916 | { |
| 868 | int err, buf_len = ALIGN(len, c->min_io_size); | 917 | int err, buf_len = ALIGN(len, c->min_io_size); |
| 869 | 918 | ||
| @@ -878,7 +927,10 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | |||
| 878 | if (c->ro_error) | 927 | if (c->ro_error) |
| 879 | return -EROFS; | 928 | return -EROFS; |
| 880 | 929 | ||
| 881 | ubifs_prepare_node(c, buf, len, 1); | 930 | err = ubifs_prepare_node_hmac(c, buf, len, hmac_offs, 1); |
| 931 | if (err) | ||
| 932 | return err; | ||
| 933 | |||
| 882 | err = ubifs_leb_write(c, lnum, buf, offs, buf_len); | 934 | err = ubifs_leb_write(c, lnum, buf, offs, buf_len); |
| 883 | if (err) | 935 | if (err) |
| 884 | ubifs_dump_node(c, buf); | 936 | ubifs_dump_node(c, buf); |
| @@ -887,6 +939,26 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | |||
| 887 | } | 939 | } |
| 888 | 940 | ||
| 889 | /** | 941 | /** |
| 942 | * ubifs_write_node - write node to the media. | ||
| 943 | * @c: UBIFS file-system description object | ||
| 944 | * @buf: the node to write | ||
| 945 | * @len: node length | ||
| 946 | * @lnum: logical eraseblock number | ||
| 947 | * @offs: offset within the logical eraseblock | ||
| 948 | * | ||
| 949 | * This function automatically fills node magic number, assigns sequence | ||
| 950 | * number, and calculates node CRC checksum. The length of the @buf buffer has | ||
| 951 | * to be aligned to the minimal I/O unit size. This function automatically | ||
| 952 | * appends padding node and padding bytes if needed. Returns zero in case of | ||
| 953 | * success and a negative error code in case of failure. | ||
| 954 | */ | ||
| 955 | int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | ||
| 956 | int offs) | ||
| 957 | { | ||
| 958 | return ubifs_write_node_hmac(c, buf, len, lnum, offs, -1); | ||
| 959 | } | ||
| 960 | |||
| 961 | /** | ||
| 890 | * ubifs_read_node_wbuf - read node from the media or write-buffer. | 962 | * ubifs_read_node_wbuf - read node from the media or write-buffer. |
| 891 | * @wbuf: wbuf to check for un-written data | 963 | * @wbuf: wbuf to check for un-written data |
| 892 | * @buf: buffer to read to | 964 | * @buf: buffer to read to |
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 802565a17733..729dc76c83df 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c | |||
| @@ -90,6 +90,12 @@ static inline void zero_trun_node_unused(struct ubifs_trun_node *trun) | |||
| 90 | memset(trun->padding, 0, 12); | 90 | memset(trun->padding, 0, 12); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static void ubifs_add_auth_dirt(struct ubifs_info *c, int lnum) | ||
| 94 | { | ||
| 95 | if (ubifs_authenticated(c)) | ||
| 96 | ubifs_add_dirt(c, lnum, ubifs_auth_node_sz(c)); | ||
| 97 | } | ||
| 98 | |||
| 93 | /** | 99 | /** |
| 94 | * reserve_space - reserve space in the journal. | 100 | * reserve_space - reserve space in the journal. |
| 95 | * @c: UBIFS file-system description object | 101 | * @c: UBIFS file-system description object |
| @@ -228,34 +234,33 @@ out_return: | |||
| 228 | return err; | 234 | return err; |
| 229 | } | 235 | } |
| 230 | 236 | ||
| 231 | /** | 237 | static int ubifs_hash_nodes(struct ubifs_info *c, void *node, |
| 232 | * write_node - write node to a journal head. | 238 | int len, struct shash_desc *hash) |
| 233 | * @c: UBIFS file-system description object | ||
| 234 | * @jhead: journal head | ||
| 235 | * @node: node to write | ||
| 236 | * @len: node length | ||
| 237 | * @lnum: LEB number written is returned here | ||
| 238 | * @offs: offset written is returned here | ||
| 239 | * | ||
| 240 | * This function writes a node to reserved space of journal head @jhead. | ||
| 241 | * Returns zero in case of success and a negative error code in case of | ||
| 242 | * failure. | ||
| 243 | */ | ||
| 244 | static int write_node(struct ubifs_info *c, int jhead, void *node, int len, | ||
| 245 | int *lnum, int *offs) | ||
| 246 | { | 239 | { |
| 247 | struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf; | 240 | int auth_node_size = ubifs_auth_node_sz(c); |
| 241 | int err; | ||
| 248 | 242 | ||
| 249 | ubifs_assert(c, jhead != GCHD); | 243 | while (1) { |
| 244 | const struct ubifs_ch *ch = node; | ||
| 245 | int nodelen = le32_to_cpu(ch->len); | ||
| 250 | 246 | ||
| 251 | *lnum = c->jheads[jhead].wbuf.lnum; | 247 | ubifs_assert(c, len >= auth_node_size); |
| 252 | *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used; | ||
| 253 | 248 | ||
| 254 | dbg_jnl("jhead %s, LEB %d:%d, len %d", | 249 | if (len == auth_node_size) |
| 255 | dbg_jhead(jhead), *lnum, *offs, len); | 250 | break; |
| 256 | ubifs_prepare_node(c, node, len, 0); | 251 | |
| 252 | ubifs_assert(c, len > nodelen); | ||
| 253 | ubifs_assert(c, ch->magic == cpu_to_le32(UBIFS_NODE_MAGIC)); | ||
| 257 | 254 | ||
| 258 | return ubifs_wbuf_write_nolock(wbuf, node, len); | 255 | err = ubifs_shash_update(c, hash, (void *)node, nodelen); |
| 256 | if (err) | ||
| 257 | return err; | ||
| 258 | |||
| 259 | node += ALIGN(nodelen, 8); | ||
| 260 | len -= ALIGN(nodelen, 8); | ||
| 261 | } | ||
| 262 | |||
| 263 | return ubifs_prepare_auth_node(c, node, hash); | ||
| 259 | } | 264 | } |
| 260 | 265 | ||
| 261 | /** | 266 | /** |
| @@ -268,9 +273,9 @@ static int write_node(struct ubifs_info *c, int jhead, void *node, int len, | |||
| 268 | * @offs: offset written is returned here | 273 | * @offs: offset written is returned here |
| 269 | * @sync: non-zero if the write-buffer has to by synchronized | 274 | * @sync: non-zero if the write-buffer has to by synchronized |
| 270 | * | 275 | * |
| 271 | * This function is the same as 'write_node()' but it does not assume the | 276 | * This function writes data to the reserved space of journal head @jhead. |
| 272 | * buffer it is writing is a node, so it does not prepare it (which means | 277 | * Returns zero in case of success and a negative error code in case of |
| 273 | * initializing common header and calculating CRC). | 278 | * failure. |
| 274 | */ | 279 | */ |
| 275 | static int write_head(struct ubifs_info *c, int jhead, void *buf, int len, | 280 | static int write_head(struct ubifs_info *c, int jhead, void *buf, int len, |
| 276 | int *lnum, int *offs, int sync) | 281 | int *lnum, int *offs, int sync) |
| @@ -285,6 +290,12 @@ static int write_head(struct ubifs_info *c, int jhead, void *buf, int len, | |||
| 285 | dbg_jnl("jhead %s, LEB %d:%d, len %d", | 290 | dbg_jnl("jhead %s, LEB %d:%d, len %d", |
| 286 | dbg_jhead(jhead), *lnum, *offs, len); | 291 | dbg_jhead(jhead), *lnum, *offs, len); |
| 287 | 292 | ||
| 293 | if (ubifs_authenticated(c)) { | ||
| 294 | err = ubifs_hash_nodes(c, buf, len, c->jheads[jhead].log_hash); | ||
| 295 | if (err) | ||
| 296 | return err; | ||
| 297 | } | ||
| 298 | |||
| 288 | err = ubifs_wbuf_write_nolock(wbuf, buf, len); | 299 | err = ubifs_wbuf_write_nolock(wbuf, buf, len); |
| 289 | if (err) | 300 | if (err) |
| 290 | return err; | 301 | return err; |
| @@ -548,6 +559,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 548 | struct ubifs_dent_node *dent; | 559 | struct ubifs_dent_node *dent; |
| 549 | struct ubifs_ino_node *ino; | 560 | struct ubifs_ino_node *ino; |
| 550 | union ubifs_key dent_key, ino_key; | 561 | union ubifs_key dent_key, ino_key; |
| 562 | u8 hash_dent[UBIFS_HASH_ARR_SZ]; | ||
| 563 | u8 hash_ino[UBIFS_HASH_ARR_SZ]; | ||
| 564 | u8 hash_ino_host[UBIFS_HASH_ARR_SZ]; | ||
| 551 | 565 | ||
| 552 | ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex)); | 566 | ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex)); |
| 553 | 567 | ||
| @@ -570,7 +584,10 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 570 | 584 | ||
| 571 | len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ; | 585 | len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ; |
| 572 | /* Make sure to also account for extended attributes */ | 586 | /* Make sure to also account for extended attributes */ |
| 573 | len += host_ui->data_len; | 587 | if (ubifs_authenticated(c)) |
| 588 | len += ALIGN(host_ui->data_len, 8) + ubifs_auth_node_sz(c); | ||
| 589 | else | ||
| 590 | len += host_ui->data_len; | ||
| 574 | 591 | ||
| 575 | dent = kzalloc(len, GFP_NOFS); | 592 | dent = kzalloc(len, GFP_NOFS); |
| 576 | if (!dent) | 593 | if (!dent) |
| @@ -602,11 +619,21 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 602 | 619 | ||
| 603 | zero_dent_node_unused(dent); | 620 | zero_dent_node_unused(dent); |
| 604 | ubifs_prep_grp_node(c, dent, dlen, 0); | 621 | ubifs_prep_grp_node(c, dent, dlen, 0); |
| 622 | err = ubifs_node_calc_hash(c, dent, hash_dent); | ||
| 623 | if (err) | ||
| 624 | goto out_release; | ||
| 605 | 625 | ||
| 606 | ino = (void *)dent + aligned_dlen; | 626 | ino = (void *)dent + aligned_dlen; |
| 607 | pack_inode(c, ino, inode, 0); | 627 | pack_inode(c, ino, inode, 0); |
| 628 | err = ubifs_node_calc_hash(c, ino, hash_ino); | ||
| 629 | if (err) | ||
| 630 | goto out_release; | ||
| 631 | |||
| 608 | ino = (void *)ino + aligned_ilen; | 632 | ino = (void *)ino + aligned_ilen; |
| 609 | pack_inode(c, ino, dir, 1); | 633 | pack_inode(c, ino, dir, 1); |
| 634 | err = ubifs_node_calc_hash(c, ino, hash_ino_host); | ||
| 635 | if (err) | ||
| 636 | goto out_release; | ||
| 610 | 637 | ||
| 611 | if (last_reference) { | 638 | if (last_reference) { |
| 612 | err = ubifs_add_orphan(c, inode->i_ino); | 639 | err = ubifs_add_orphan(c, inode->i_ino); |
| @@ -628,6 +655,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 628 | } | 655 | } |
| 629 | release_head(c, BASEHD); | 656 | release_head(c, BASEHD); |
| 630 | kfree(dent); | 657 | kfree(dent); |
| 658 | ubifs_add_auth_dirt(c, lnum); | ||
| 631 | 659 | ||
| 632 | if (deletion) { | 660 | if (deletion) { |
| 633 | if (nm->hash) | 661 | if (nm->hash) |
| @@ -638,7 +666,8 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 638 | goto out_ro; | 666 | goto out_ro; |
| 639 | err = ubifs_add_dirt(c, lnum, dlen); | 667 | err = ubifs_add_dirt(c, lnum, dlen); |
| 640 | } else | 668 | } else |
| 641 | err = ubifs_tnc_add_nm(c, &dent_key, lnum, dent_offs, dlen, nm); | 669 | err = ubifs_tnc_add_nm(c, &dent_key, lnum, dent_offs, dlen, |
| 670 | hash_dent, nm); | ||
| 642 | if (err) | 671 | if (err) |
| 643 | goto out_ro; | 672 | goto out_ro; |
| 644 | 673 | ||
| @@ -650,14 +679,14 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, | |||
| 650 | */ | 679 | */ |
| 651 | ino_key_init(c, &ino_key, inode->i_ino); | 680 | ino_key_init(c, &ino_key, inode->i_ino); |
| 652 | ino_offs = dent_offs + aligned_dlen; | 681 | ino_offs = dent_offs + aligned_dlen; |
| 653 | err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, ilen); | 682 | err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, ilen, hash_ino); |
| 654 | if (err) | 683 | if (err) |
| 655 | goto out_ro; | 684 | goto out_ro; |
| 656 | 685 | ||
| 657 | ino_key_init(c, &ino_key, dir->i_ino); | 686 | ino_key_init(c, &ino_key, dir->i_ino); |
| 658 | ino_offs += aligned_ilen; | 687 | ino_offs += aligned_ilen; |
| 659 | err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, | 688 | err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, |
| 660 | UBIFS_INO_NODE_SZ + host_ui->data_len); | 689 | UBIFS_INO_NODE_SZ + host_ui->data_len, hash_ino_host); |
| 661 | if (err) | 690 | if (err) |
| 662 | goto out_ro; | 691 | goto out_ro; |
| 663 | 692 | ||
| @@ -706,10 +735,12 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, | |||
| 706 | const union ubifs_key *key, const void *buf, int len) | 735 | const union ubifs_key *key, const void *buf, int len) |
| 707 | { | 736 | { |
| 708 | struct ubifs_data_node *data; | 737 | struct ubifs_data_node *data; |
| 709 | int err, lnum, offs, compr_type, out_len, compr_len; | 738 | int err, lnum, offs, compr_type, out_len, compr_len, auth_len; |
| 710 | int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1; | 739 | int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1; |
| 740 | int write_len; | ||
| 711 | struct ubifs_inode *ui = ubifs_inode(inode); | 741 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 712 | bool encrypted = ubifs_crypt_is_encrypted(inode); | 742 | bool encrypted = ubifs_crypt_is_encrypted(inode); |
| 743 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 713 | 744 | ||
| 714 | dbg_jnlk(key, "ino %lu, blk %u, len %d, key ", | 745 | dbg_jnlk(key, "ino %lu, blk %u, len %d, key ", |
| 715 | (unsigned long)key_inum(c, key), key_block(c, key), len); | 746 | (unsigned long)key_inum(c, key), key_block(c, key), len); |
| @@ -718,7 +749,9 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, | |||
| 718 | if (encrypted) | 749 | if (encrypted) |
| 719 | dlen += UBIFS_CIPHER_BLOCK_SIZE; | 750 | dlen += UBIFS_CIPHER_BLOCK_SIZE; |
| 720 | 751 | ||
| 721 | data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN); | 752 | auth_len = ubifs_auth_node_sz(c); |
| 753 | |||
| 754 | data = kmalloc(dlen + auth_len, GFP_NOFS | __GFP_NOWARN); | ||
| 722 | if (!data) { | 755 | if (!data) { |
| 723 | /* | 756 | /* |
| 724 | * Fall-back to the write reserve buffer. Note, we might be | 757 | * Fall-back to the write reserve buffer. Note, we might be |
| @@ -757,20 +790,33 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, | |||
| 757 | } | 790 | } |
| 758 | 791 | ||
| 759 | dlen = UBIFS_DATA_NODE_SZ + out_len; | 792 | dlen = UBIFS_DATA_NODE_SZ + out_len; |
| 793 | if (ubifs_authenticated(c)) | ||
| 794 | write_len = ALIGN(dlen, 8) + auth_len; | ||
| 795 | else | ||
| 796 | write_len = dlen; | ||
| 797 | |||
| 760 | data->compr_type = cpu_to_le16(compr_type); | 798 | data->compr_type = cpu_to_le16(compr_type); |
| 761 | 799 | ||
| 762 | /* Make reservation before allocating sequence numbers */ | 800 | /* Make reservation before allocating sequence numbers */ |
| 763 | err = make_reservation(c, DATAHD, dlen); | 801 | err = make_reservation(c, DATAHD, write_len); |
| 764 | if (err) | 802 | if (err) |
| 765 | goto out_free; | 803 | goto out_free; |
| 766 | 804 | ||
| 767 | err = write_node(c, DATAHD, data, dlen, &lnum, &offs); | 805 | ubifs_prepare_node(c, data, dlen, 0); |
| 806 | err = write_head(c, DATAHD, data, write_len, &lnum, &offs, 0); | ||
| 807 | if (err) | ||
| 808 | goto out_release; | ||
| 809 | |||
| 810 | err = ubifs_node_calc_hash(c, data, hash); | ||
| 768 | if (err) | 811 | if (err) |
| 769 | goto out_release; | 812 | goto out_release; |
| 813 | |||
| 770 | ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf, key_inum(c, key)); | 814 | ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf, key_inum(c, key)); |
| 771 | release_head(c, DATAHD); | 815 | release_head(c, DATAHD); |
| 772 | 816 | ||
| 773 | err = ubifs_tnc_add(c, key, lnum, offs, dlen); | 817 | ubifs_add_auth_dirt(c, lnum); |
| 818 | |||
| 819 | err = ubifs_tnc_add(c, key, lnum, offs, dlen, hash); | ||
| 774 | if (err) | 820 | if (err) |
| 775 | goto out_ro; | 821 | goto out_ro; |
| 776 | 822 | ||
| @@ -808,7 +854,9 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) | |||
| 808 | int err, lnum, offs; | 854 | int err, lnum, offs; |
| 809 | struct ubifs_ino_node *ino; | 855 | struct ubifs_ino_node *ino; |
| 810 | struct ubifs_inode *ui = ubifs_inode(inode); | 856 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 811 | int sync = 0, len = UBIFS_INO_NODE_SZ, last_reference = !inode->i_nlink; | 857 | int sync = 0, write_len, ilen = UBIFS_INO_NODE_SZ; |
| 858 | int last_reference = !inode->i_nlink; | ||
| 859 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 812 | 860 | ||
| 813 | dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink); | 861 | dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink); |
| 814 | 862 | ||
| @@ -817,20 +865,30 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) | |||
| 817 | * need to synchronize the write-buffer either. | 865 | * need to synchronize the write-buffer either. |
| 818 | */ | 866 | */ |
| 819 | if (!last_reference) { | 867 | if (!last_reference) { |
| 820 | len += ui->data_len; | 868 | ilen += ui->data_len; |
| 821 | sync = IS_SYNC(inode); | 869 | sync = IS_SYNC(inode); |
| 822 | } | 870 | } |
| 823 | ino = kmalloc(len, GFP_NOFS); | 871 | |
| 872 | if (ubifs_authenticated(c)) | ||
| 873 | write_len = ALIGN(ilen, 8) + ubifs_auth_node_sz(c); | ||
| 874 | else | ||
| 875 | write_len = ilen; | ||
| 876 | |||
| 877 | ino = kmalloc(write_len, GFP_NOFS); | ||
| 824 | if (!ino) | 878 | if (!ino) |
| 825 | return -ENOMEM; | 879 | return -ENOMEM; |
| 826 | 880 | ||
| 827 | /* Make reservation before allocating sequence numbers */ | 881 | /* Make reservation before allocating sequence numbers */ |
| 828 | err = make_reservation(c, BASEHD, len); | 882 | err = make_reservation(c, BASEHD, write_len); |
| 829 | if (err) | 883 | if (err) |
| 830 | goto out_free; | 884 | goto out_free; |
| 831 | 885 | ||
| 832 | pack_inode(c, ino, inode, 1); | 886 | pack_inode(c, ino, inode, 1); |
| 833 | err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); | 887 | err = ubifs_node_calc_hash(c, ino, hash); |
| 888 | if (err) | ||
| 889 | goto out_release; | ||
| 890 | |||
| 891 | err = write_head(c, BASEHD, ino, write_len, &lnum, &offs, sync); | ||
| 834 | if (err) | 892 | if (err) |
| 835 | goto out_release; | 893 | goto out_release; |
| 836 | if (!sync) | 894 | if (!sync) |
| @@ -838,17 +896,19 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) | |||
| 838 | inode->i_ino); | 896 | inode->i_ino); |
| 839 | release_head(c, BASEHD); | 897 | release_head(c, BASEHD); |
| 840 | 898 | ||
| 899 | ubifs_add_auth_dirt(c, lnum); | ||
| 900 | |||
| 841 | if (last_reference) { | 901 | if (last_reference) { |
| 842 | err = ubifs_tnc_remove_ino(c, inode->i_ino); | 902 | err = ubifs_tnc_remove_ino(c, inode->i_ino); |
| 843 | if (err) | 903 | if (err) |
| 844 | goto out_ro; | 904 | goto out_ro; |
| 845 | ubifs_delete_orphan(c, inode->i_ino); | 905 | ubifs_delete_orphan(c, inode->i_ino); |
| 846 | err = ubifs_add_dirt(c, lnum, len); | 906 | err = ubifs_add_dirt(c, lnum, ilen); |
| 847 | } else { | 907 | } else { |
| 848 | union ubifs_key key; | 908 | union ubifs_key key; |
| 849 | 909 | ||
| 850 | ino_key_init(c, &key, inode->i_ino); | 910 | ino_key_init(c, &key, inode->i_ino); |
| 851 | err = ubifs_tnc_add(c, &key, lnum, offs, len); | 911 | err = ubifs_tnc_add(c, &key, lnum, offs, ilen, hash); |
| 852 | } | 912 | } |
| 853 | if (err) | 913 | if (err) |
| 854 | goto out_ro; | 914 | goto out_ro; |
| @@ -958,6 +1018,10 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, | |||
| 958 | int aligned_dlen1, aligned_dlen2; | 1018 | int aligned_dlen1, aligned_dlen2; |
| 959 | int twoparents = (fst_dir != snd_dir); | 1019 | int twoparents = (fst_dir != snd_dir); |
| 960 | void *p; | 1020 | void *p; |
| 1021 | u8 hash_dent1[UBIFS_HASH_ARR_SZ]; | ||
| 1022 | u8 hash_dent2[UBIFS_HASH_ARR_SZ]; | ||
| 1023 | u8 hash_p1[UBIFS_HASH_ARR_SZ]; | ||
| 1024 | u8 hash_p2[UBIFS_HASH_ARR_SZ]; | ||
| 961 | 1025 | ||
| 962 | ubifs_assert(c, ubifs_inode(fst_dir)->data_len == 0); | 1026 | ubifs_assert(c, ubifs_inode(fst_dir)->data_len == 0); |
| 963 | ubifs_assert(c, ubifs_inode(snd_dir)->data_len == 0); | 1027 | ubifs_assert(c, ubifs_inode(snd_dir)->data_len == 0); |
| @@ -973,6 +1037,8 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, | |||
| 973 | if (twoparents) | 1037 | if (twoparents) |
| 974 | len += plen; | 1038 | len += plen; |
| 975 | 1039 | ||
| 1040 | len += ubifs_auth_node_sz(c); | ||
| 1041 | |||
| 976 | dent1 = kzalloc(len, GFP_NOFS); | 1042 | dent1 = kzalloc(len, GFP_NOFS); |
| 977 | if (!dent1) | 1043 | if (!dent1) |
| 978 | return -ENOMEM; | 1044 | return -ENOMEM; |
| @@ -993,6 +1059,9 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, | |||
| 993 | set_dent_cookie(c, dent1); | 1059 | set_dent_cookie(c, dent1); |
| 994 | zero_dent_node_unused(dent1); | 1060 | zero_dent_node_unused(dent1); |
| 995 | ubifs_prep_grp_node(c, dent1, dlen1, 0); | 1061 | ubifs_prep_grp_node(c, dent1, dlen1, 0); |
| 1062 | err = ubifs_node_calc_hash(c, dent1, hash_dent1); | ||
| 1063 | if (err) | ||
| 1064 | goto out_release; | ||
| 996 | 1065 | ||
| 997 | /* Make new dent for 2nd entry */ | 1066 | /* Make new dent for 2nd entry */ |
| 998 | dent2 = (void *)dent1 + aligned_dlen1; | 1067 | dent2 = (void *)dent1 + aligned_dlen1; |
| @@ -1006,14 +1075,26 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, | |||
| 1006 | set_dent_cookie(c, dent2); | 1075 | set_dent_cookie(c, dent2); |
| 1007 | zero_dent_node_unused(dent2); | 1076 | zero_dent_node_unused(dent2); |
| 1008 | ubifs_prep_grp_node(c, dent2, dlen2, 0); | 1077 | ubifs_prep_grp_node(c, dent2, dlen2, 0); |
| 1078 | err = ubifs_node_calc_hash(c, dent2, hash_dent2); | ||
| 1079 | if (err) | ||
| 1080 | goto out_release; | ||
| 1009 | 1081 | ||
| 1010 | p = (void *)dent2 + aligned_dlen2; | 1082 | p = (void *)dent2 + aligned_dlen2; |
| 1011 | if (!twoparents) | 1083 | if (!twoparents) { |
| 1012 | pack_inode(c, p, fst_dir, 1); | 1084 | pack_inode(c, p, fst_dir, 1); |
| 1013 | else { | 1085 | err = ubifs_node_calc_hash(c, p, hash_p1); |
| 1086 | if (err) | ||
| 1087 | goto out_release; | ||
| 1088 | } else { | ||
| 1014 | pack_inode(c, p, fst_dir, 0); | 1089 | pack_inode(c, p, fst_dir, 0); |
| 1090 | err = ubifs_node_calc_hash(c, p, hash_p1); | ||
| 1091 | if (err) | ||
| 1092 | goto out_release; | ||
| 1015 | p += ALIGN(plen, 8); | 1093 | p += ALIGN(plen, 8); |
| 1016 | pack_inode(c, p, snd_dir, 1); | 1094 | pack_inode(c, p, snd_dir, 1); |
| 1095 | err = ubifs_node_calc_hash(c, p, hash_p2); | ||
| 1096 | if (err) | ||
| 1097 | goto out_release; | ||
| 1017 | } | 1098 | } |
| 1018 | 1099 | ||
| 1019 | err = write_head(c, BASEHD, dent1, len, &lnum, &offs, sync); | 1100 | err = write_head(c, BASEHD, dent1, len, &lnum, &offs, sync); |
| @@ -1027,28 +1108,30 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir, | |||
| 1027 | } | 1108 | } |
| 1028 | release_head(c, BASEHD); | 1109 | release_head(c, BASEHD); |
| 1029 | 1110 | ||
| 1111 | ubifs_add_auth_dirt(c, lnum); | ||
| 1112 | |||
| 1030 | dent_key_init(c, &key, snd_dir->i_ino, snd_nm); | 1113 | dent_key_init(c, &key, snd_dir->i_ino, snd_nm); |
| 1031 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, snd_nm); | 1114 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, hash_dent1, snd_nm); |
| 1032 | if (err) | 1115 | if (err) |
| 1033 | goto out_ro; | 1116 | goto out_ro; |
| 1034 | 1117 | ||
| 1035 | offs += aligned_dlen1; | 1118 | offs += aligned_dlen1; |
| 1036 | dent_key_init(c, &key, fst_dir->i_ino, fst_nm); | 1119 | dent_key_init(c, &key, fst_dir->i_ino, fst_nm); |
| 1037 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, fst_nm); | 1120 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, hash_dent2, fst_nm); |
| 1038 | if (err) | 1121 | if (err) |
| 1039 | goto out_ro; | 1122 | goto out_ro; |
| 1040 | 1123 | ||
| 1041 | offs += aligned_dlen2; | 1124 | offs += aligned_dlen2; |
| 1042 | 1125 | ||
| 1043 | ino_key_init(c, &key, fst_dir->i_ino); | 1126 | ino_key_init(c, &key, fst_dir->i_ino); |
| 1044 | err = ubifs_tnc_add(c, &key, lnum, offs, plen); | 1127 | err = ubifs_tnc_add(c, &key, lnum, offs, plen, hash_p1); |
| 1045 | if (err) | 1128 | if (err) |
| 1046 | goto out_ro; | 1129 | goto out_ro; |
| 1047 | 1130 | ||
| 1048 | if (twoparents) { | 1131 | if (twoparents) { |
| 1049 | offs += ALIGN(plen, 8); | 1132 | offs += ALIGN(plen, 8); |
| 1050 | ino_key_init(c, &key, snd_dir->i_ino); | 1133 | ino_key_init(c, &key, snd_dir->i_ino); |
| 1051 | err = ubifs_tnc_add(c, &key, lnum, offs, plen); | 1134 | err = ubifs_tnc_add(c, &key, lnum, offs, plen, hash_p2); |
| 1052 | if (err) | 1135 | if (err) |
| 1053 | goto out_ro; | 1136 | goto out_ro; |
| 1054 | } | 1137 | } |
| @@ -1101,6 +1184,11 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 1101 | int last_reference = !!(new_inode && new_inode->i_nlink == 0); | 1184 | int last_reference = !!(new_inode && new_inode->i_nlink == 0); |
| 1102 | int move = (old_dir != new_dir); | 1185 | int move = (old_dir != new_dir); |
| 1103 | struct ubifs_inode *uninitialized_var(new_ui); | 1186 | struct ubifs_inode *uninitialized_var(new_ui); |
| 1187 | u8 hash_old_dir[UBIFS_HASH_ARR_SZ]; | ||
| 1188 | u8 hash_new_dir[UBIFS_HASH_ARR_SZ]; | ||
| 1189 | u8 hash_new_inode[UBIFS_HASH_ARR_SZ]; | ||
| 1190 | u8 hash_dent1[UBIFS_HASH_ARR_SZ]; | ||
| 1191 | u8 hash_dent2[UBIFS_HASH_ARR_SZ]; | ||
| 1104 | 1192 | ||
| 1105 | ubifs_assert(c, ubifs_inode(old_dir)->data_len == 0); | 1193 | ubifs_assert(c, ubifs_inode(old_dir)->data_len == 0); |
| 1106 | ubifs_assert(c, ubifs_inode(new_dir)->data_len == 0); | 1194 | ubifs_assert(c, ubifs_inode(new_dir)->data_len == 0); |
| @@ -1123,6 +1211,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 1123 | len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8); | 1211 | len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8); |
| 1124 | if (move) | 1212 | if (move) |
| 1125 | len += plen; | 1213 | len += plen; |
| 1214 | |||
| 1215 | len += ubifs_auth_node_sz(c); | ||
| 1216 | |||
| 1126 | dent = kzalloc(len, GFP_NOFS); | 1217 | dent = kzalloc(len, GFP_NOFS); |
| 1127 | if (!dent) | 1218 | if (!dent) |
| 1128 | return -ENOMEM; | 1219 | return -ENOMEM; |
| @@ -1143,6 +1234,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 1143 | set_dent_cookie(c, dent); | 1234 | set_dent_cookie(c, dent); |
| 1144 | zero_dent_node_unused(dent); | 1235 | zero_dent_node_unused(dent); |
| 1145 | ubifs_prep_grp_node(c, dent, dlen1, 0); | 1236 | ubifs_prep_grp_node(c, dent, dlen1, 0); |
| 1237 | err = ubifs_node_calc_hash(c, dent, hash_dent1); | ||
| 1238 | if (err) | ||
| 1239 | goto out_release; | ||
| 1146 | 1240 | ||
| 1147 | dent2 = (void *)dent + aligned_dlen1; | 1241 | dent2 = (void *)dent + aligned_dlen1; |
| 1148 | dent2->ch.node_type = UBIFS_DENT_NODE; | 1242 | dent2->ch.node_type = UBIFS_DENT_NODE; |
| @@ -1162,19 +1256,36 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 1162 | set_dent_cookie(c, dent2); | 1256 | set_dent_cookie(c, dent2); |
| 1163 | zero_dent_node_unused(dent2); | 1257 | zero_dent_node_unused(dent2); |
| 1164 | ubifs_prep_grp_node(c, dent2, dlen2, 0); | 1258 | ubifs_prep_grp_node(c, dent2, dlen2, 0); |
| 1259 | err = ubifs_node_calc_hash(c, dent2, hash_dent2); | ||
| 1260 | if (err) | ||
| 1261 | goto out_release; | ||
| 1165 | 1262 | ||
| 1166 | p = (void *)dent2 + aligned_dlen2; | 1263 | p = (void *)dent2 + aligned_dlen2; |
| 1167 | if (new_inode) { | 1264 | if (new_inode) { |
| 1168 | pack_inode(c, p, new_inode, 0); | 1265 | pack_inode(c, p, new_inode, 0); |
| 1266 | err = ubifs_node_calc_hash(c, p, hash_new_inode); | ||
| 1267 | if (err) | ||
| 1268 | goto out_release; | ||
| 1269 | |||
| 1169 | p += ALIGN(ilen, 8); | 1270 | p += ALIGN(ilen, 8); |
| 1170 | } | 1271 | } |
| 1171 | 1272 | ||
| 1172 | if (!move) | 1273 | if (!move) { |
| 1173 | pack_inode(c, p, old_dir, 1); | 1274 | pack_inode(c, p, old_dir, 1); |
| 1174 | else { | 1275 | err = ubifs_node_calc_hash(c, p, hash_old_dir); |
| 1276 | if (err) | ||
| 1277 | goto out_release; | ||
| 1278 | } else { | ||
| 1175 | pack_inode(c, p, old_dir, 0); | 1279 | pack_inode(c, p, old_dir, 0); |
| 1280 | err = ubifs_node_calc_hash(c, p, hash_old_dir); | ||
| 1281 | if (err) | ||
| 1282 | goto out_release; | ||
| 1283 | |||
| 1176 | p += ALIGN(plen, 8); | 1284 | p += ALIGN(plen, 8); |
| 1177 | pack_inode(c, p, new_dir, 1); | 1285 | pack_inode(c, p, new_dir, 1); |
| 1286 | err = ubifs_node_calc_hash(c, p, hash_new_dir); | ||
| 1287 | if (err) | ||
| 1288 | goto out_release; | ||
| 1178 | } | 1289 | } |
| 1179 | 1290 | ||
| 1180 | if (last_reference) { | 1291 | if (last_reference) { |
| @@ -1200,15 +1311,17 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 1200 | } | 1311 | } |
| 1201 | release_head(c, BASEHD); | 1312 | release_head(c, BASEHD); |
| 1202 | 1313 | ||
| 1314 | ubifs_add_auth_dirt(c, lnum); | ||
| 1315 | |||
| 1203 | dent_key_init(c, &key, new_dir->i_ino, new_nm); | 1316 | dent_key_init(c, &key, new_dir->i_ino, new_nm); |
| 1204 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, new_nm); | 1317 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, hash_dent1, new_nm); |
| 1205 | if (err) | 1318 | if (err) |
| 1206 | goto out_ro; | 1319 | goto out_ro; |
| 1207 | 1320 | ||
| 1208 | offs += aligned_dlen1; | 1321 | offs += aligned_dlen1; |
| 1209 | if (whiteout) { | 1322 | if (whiteout) { |
| 1210 | dent_key_init(c, &key, old_dir->i_ino, old_nm); | 1323 | dent_key_init(c, &key, old_dir->i_ino, old_nm); |
| 1211 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, old_nm); | 1324 | err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, hash_dent2, old_nm); |
| 1212 | if (err) | 1325 | if (err) |
| 1213 | goto out_ro; | 1326 | goto out_ro; |
| 1214 | 1327 | ||
| @@ -1227,21 +1340,21 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, | |||
| 1227 | offs += aligned_dlen2; | 1340 | offs += aligned_dlen2; |
| 1228 | if (new_inode) { | 1341 | if (new_inode) { |
| 1229 | ino_key_init(c, &key, new_inode->i_ino); | 1342 | ino_key_init(c, &key, new_inode->i_ino); |
| 1230 | err = ubifs_tnc_add(c, &key, lnum, offs, ilen); | 1343 | err = ubifs_tnc_add(c, &key, lnum, offs, ilen, hash_new_inode); |
| 1231 | if (err) | 1344 | if (err) |
| 1232 | goto out_ro; | 1345 | goto out_ro; |
| 1233 | offs += ALIGN(ilen, 8); | 1346 | offs += ALIGN(ilen, 8); |
| 1234 | } | 1347 | } |
| 1235 | 1348 | ||
| 1236 | ino_key_init(c, &key, old_dir->i_ino); | 1349 | ino_key_init(c, &key, old_dir->i_ino); |
| 1237 | err = ubifs_tnc_add(c, &key, lnum, offs, plen); | 1350 | err = ubifs_tnc_add(c, &key, lnum, offs, plen, hash_old_dir); |
| 1238 | if (err) | 1351 | if (err) |
| 1239 | goto out_ro; | 1352 | goto out_ro; |
| 1240 | 1353 | ||
| 1241 | if (move) { | 1354 | if (move) { |
| 1242 | offs += ALIGN(plen, 8); | 1355 | offs += ALIGN(plen, 8); |
| 1243 | ino_key_init(c, &key, new_dir->i_ino); | 1356 | ino_key_init(c, &key, new_dir->i_ino); |
| 1244 | err = ubifs_tnc_add(c, &key, lnum, offs, plen); | 1357 | err = ubifs_tnc_add(c, &key, lnum, offs, plen, hash_new_dir); |
| 1245 | if (err) | 1358 | if (err) |
| 1246 | goto out_ro; | 1359 | goto out_ro; |
| 1247 | } | 1360 | } |
| @@ -1360,6 +1473,8 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, | |||
| 1360 | struct ubifs_inode *ui = ubifs_inode(inode); | 1473 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 1361 | ino_t inum = inode->i_ino; | 1474 | ino_t inum = inode->i_ino; |
| 1362 | unsigned int blk; | 1475 | unsigned int blk; |
| 1476 | u8 hash_ino[UBIFS_HASH_ARR_SZ]; | ||
| 1477 | u8 hash_dn[UBIFS_HASH_ARR_SZ]; | ||
| 1363 | 1478 | ||
| 1364 | dbg_jnl("ino %lu, size %lld -> %lld", | 1479 | dbg_jnl("ino %lu, size %lld -> %lld", |
| 1365 | (unsigned long)inum, old_size, new_size); | 1480 | (unsigned long)inum, old_size, new_size); |
| @@ -1369,6 +1484,9 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, | |||
| 1369 | 1484 | ||
| 1370 | sz = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ + | 1485 | sz = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ + |
| 1371 | UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR; | 1486 | UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR; |
| 1487 | |||
| 1488 | sz += ubifs_auth_node_sz(c); | ||
| 1489 | |||
| 1372 | ino = kmalloc(sz, GFP_NOFS); | 1490 | ino = kmalloc(sz, GFP_NOFS); |
| 1373 | if (!ino) | 1491 | if (!ino) |
| 1374 | return -ENOMEM; | 1492 | return -ENOMEM; |
| @@ -1414,16 +1532,28 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, | |||
| 1414 | 1532 | ||
| 1415 | /* Must make reservation before allocating sequence numbers */ | 1533 | /* Must make reservation before allocating sequence numbers */ |
| 1416 | len = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ; | 1534 | len = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ; |
| 1417 | if (dlen) | 1535 | |
| 1536 | if (ubifs_authenticated(c)) | ||
| 1537 | len += ALIGN(dlen, 8) + ubifs_auth_node_sz(c); | ||
| 1538 | else | ||
| 1418 | len += dlen; | 1539 | len += dlen; |
| 1540 | |||
| 1419 | err = make_reservation(c, BASEHD, len); | 1541 | err = make_reservation(c, BASEHD, len); |
| 1420 | if (err) | 1542 | if (err) |
| 1421 | goto out_free; | 1543 | goto out_free; |
| 1422 | 1544 | ||
| 1423 | pack_inode(c, ino, inode, 0); | 1545 | pack_inode(c, ino, inode, 0); |
| 1546 | err = ubifs_node_calc_hash(c, ino, hash_ino); | ||
| 1547 | if (err) | ||
| 1548 | goto out_release; | ||
| 1549 | |||
| 1424 | ubifs_prep_grp_node(c, trun, UBIFS_TRUN_NODE_SZ, dlen ? 0 : 1); | 1550 | ubifs_prep_grp_node(c, trun, UBIFS_TRUN_NODE_SZ, dlen ? 0 : 1); |
| 1425 | if (dlen) | 1551 | if (dlen) { |
| 1426 | ubifs_prep_grp_node(c, dn, dlen, 1); | 1552 | ubifs_prep_grp_node(c, dn, dlen, 1); |
| 1553 | err = ubifs_node_calc_hash(c, dn, hash_dn); | ||
| 1554 | if (err) | ||
| 1555 | goto out_release; | ||
| 1556 | } | ||
| 1427 | 1557 | ||
| 1428 | err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); | 1558 | err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); |
| 1429 | if (err) | 1559 | if (err) |
| @@ -1432,15 +1562,17 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, | |||
| 1432 | ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum); | 1562 | ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum); |
| 1433 | release_head(c, BASEHD); | 1563 | release_head(c, BASEHD); |
| 1434 | 1564 | ||
| 1565 | ubifs_add_auth_dirt(c, lnum); | ||
| 1566 | |||
| 1435 | if (dlen) { | 1567 | if (dlen) { |
| 1436 | sz = offs + UBIFS_INO_NODE_SZ + UBIFS_TRUN_NODE_SZ; | 1568 | sz = offs + UBIFS_INO_NODE_SZ + UBIFS_TRUN_NODE_SZ; |
| 1437 | err = ubifs_tnc_add(c, &key, lnum, sz, dlen); | 1569 | err = ubifs_tnc_add(c, &key, lnum, sz, dlen, hash_dn); |
| 1438 | if (err) | 1570 | if (err) |
| 1439 | goto out_ro; | 1571 | goto out_ro; |
| 1440 | } | 1572 | } |
| 1441 | 1573 | ||
| 1442 | ino_key_init(c, &key, inum); | 1574 | ino_key_init(c, &key, inum); |
| 1443 | err = ubifs_tnc_add(c, &key, lnum, offs, UBIFS_INO_NODE_SZ); | 1575 | err = ubifs_tnc_add(c, &key, lnum, offs, UBIFS_INO_NODE_SZ, hash_ino); |
| 1444 | if (err) | 1576 | if (err) |
| 1445 | goto out_ro; | 1577 | goto out_ro; |
| 1446 | 1578 | ||
| @@ -1495,12 +1627,13 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, | |||
| 1495 | const struct inode *inode, | 1627 | const struct inode *inode, |
| 1496 | const struct fscrypt_name *nm) | 1628 | const struct fscrypt_name *nm) |
| 1497 | { | 1629 | { |
| 1498 | int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen; | 1630 | int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen, write_len; |
| 1499 | struct ubifs_dent_node *xent; | 1631 | struct ubifs_dent_node *xent; |
| 1500 | struct ubifs_ino_node *ino; | 1632 | struct ubifs_ino_node *ino; |
| 1501 | union ubifs_key xent_key, key1, key2; | 1633 | union ubifs_key xent_key, key1, key2; |
| 1502 | int sync = IS_DIRSYNC(host); | 1634 | int sync = IS_DIRSYNC(host); |
| 1503 | struct ubifs_inode *host_ui = ubifs_inode(host); | 1635 | struct ubifs_inode *host_ui = ubifs_inode(host); |
| 1636 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 1504 | 1637 | ||
| 1505 | ubifs_assert(c, inode->i_nlink == 0); | 1638 | ubifs_assert(c, inode->i_nlink == 0); |
| 1506 | ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex)); | 1639 | ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex)); |
| @@ -1514,12 +1647,14 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, | |||
| 1514 | hlen = host_ui->data_len + UBIFS_INO_NODE_SZ; | 1647 | hlen = host_ui->data_len + UBIFS_INO_NODE_SZ; |
| 1515 | len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8); | 1648 | len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8); |
| 1516 | 1649 | ||
| 1517 | xent = kzalloc(len, GFP_NOFS); | 1650 | write_len = len + ubifs_auth_node_sz(c); |
| 1651 | |||
| 1652 | xent = kzalloc(write_len, GFP_NOFS); | ||
| 1518 | if (!xent) | 1653 | if (!xent) |
| 1519 | return -ENOMEM; | 1654 | return -ENOMEM; |
| 1520 | 1655 | ||
| 1521 | /* Make reservation before allocating sequence numbers */ | 1656 | /* Make reservation before allocating sequence numbers */ |
| 1522 | err = make_reservation(c, BASEHD, len); | 1657 | err = make_reservation(c, BASEHD, write_len); |
| 1523 | if (err) { | 1658 | if (err) { |
| 1524 | kfree(xent); | 1659 | kfree(xent); |
| 1525 | return err; | 1660 | return err; |
| @@ -1540,11 +1675,16 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, | |||
| 1540 | pack_inode(c, ino, inode, 0); | 1675 | pack_inode(c, ino, inode, 0); |
| 1541 | ino = (void *)ino + UBIFS_INO_NODE_SZ; | 1676 | ino = (void *)ino + UBIFS_INO_NODE_SZ; |
| 1542 | pack_inode(c, ino, host, 1); | 1677 | pack_inode(c, ino, host, 1); |
| 1678 | err = ubifs_node_calc_hash(c, ino, hash); | ||
| 1679 | if (err) | ||
| 1680 | goto out_release; | ||
| 1543 | 1681 | ||
| 1544 | err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync); | 1682 | err = write_head(c, BASEHD, xent, write_len, &lnum, &xent_offs, sync); |
| 1545 | if (!sync && !err) | 1683 | if (!sync && !err) |
| 1546 | ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino); | 1684 | ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino); |
| 1547 | release_head(c, BASEHD); | 1685 | release_head(c, BASEHD); |
| 1686 | |||
| 1687 | ubifs_add_auth_dirt(c, lnum); | ||
| 1548 | kfree(xent); | 1688 | kfree(xent); |
| 1549 | if (err) | 1689 | if (err) |
| 1550 | goto out_ro; | 1690 | goto out_ro; |
| @@ -1572,7 +1712,7 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, | |||
| 1572 | 1712 | ||
| 1573 | /* And update TNC with the new host inode position */ | 1713 | /* And update TNC with the new host inode position */ |
| 1574 | ino_key_init(c, &key1, host->i_ino); | 1714 | ino_key_init(c, &key1, host->i_ino); |
| 1575 | err = ubifs_tnc_add(c, &key1, lnum, xent_offs + len - hlen, hlen); | 1715 | err = ubifs_tnc_add(c, &key1, lnum, xent_offs + len - hlen, hlen, hash); |
| 1576 | if (err) | 1716 | if (err) |
| 1577 | goto out_ro; | 1717 | goto out_ro; |
| 1578 | 1718 | ||
| @@ -1583,6 +1723,9 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, | |||
| 1583 | mark_inode_clean(c, host_ui); | 1723 | mark_inode_clean(c, host_ui); |
| 1584 | return 0; | 1724 | return 0; |
| 1585 | 1725 | ||
| 1726 | out_release: | ||
| 1727 | kfree(xent); | ||
| 1728 | release_head(c, BASEHD); | ||
| 1586 | out_ro: | 1729 | out_ro: |
| 1587 | ubifs_ro_mode(c, err); | 1730 | ubifs_ro_mode(c, err); |
| 1588 | finish_reservation(c); | 1731 | finish_reservation(c); |
| @@ -1610,6 +1753,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1610 | struct ubifs_ino_node *ino; | 1753 | struct ubifs_ino_node *ino; |
| 1611 | union ubifs_key key; | 1754 | union ubifs_key key; |
| 1612 | int sync = IS_DIRSYNC(host); | 1755 | int sync = IS_DIRSYNC(host); |
| 1756 | u8 hash_host[UBIFS_HASH_ARR_SZ]; | ||
| 1757 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 1613 | 1758 | ||
| 1614 | dbg_jnl("ino %lu, ino %lu", host->i_ino, inode->i_ino); | 1759 | dbg_jnl("ino %lu, ino %lu", host->i_ino, inode->i_ino); |
| 1615 | ubifs_assert(c, host->i_nlink > 0); | 1760 | ubifs_assert(c, host->i_nlink > 0); |
| @@ -1621,6 +1766,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1621 | aligned_len1 = ALIGN(len1, 8); | 1766 | aligned_len1 = ALIGN(len1, 8); |
| 1622 | aligned_len = aligned_len1 + ALIGN(len2, 8); | 1767 | aligned_len = aligned_len1 + ALIGN(len2, 8); |
| 1623 | 1768 | ||
| 1769 | aligned_len += ubifs_auth_node_sz(c); | ||
| 1770 | |||
| 1624 | ino = kzalloc(aligned_len, GFP_NOFS); | 1771 | ino = kzalloc(aligned_len, GFP_NOFS); |
| 1625 | if (!ino) | 1772 | if (!ino) |
| 1626 | return -ENOMEM; | 1773 | return -ENOMEM; |
| @@ -1631,7 +1778,13 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1631 | goto out_free; | 1778 | goto out_free; |
| 1632 | 1779 | ||
| 1633 | pack_inode(c, ino, host, 0); | 1780 | pack_inode(c, ino, host, 0); |
| 1781 | err = ubifs_node_calc_hash(c, ino, hash_host); | ||
| 1782 | if (err) | ||
| 1783 | goto out_release; | ||
| 1634 | pack_inode(c, (void *)ino + aligned_len1, inode, 1); | 1784 | pack_inode(c, (void *)ino + aligned_len1, inode, 1); |
| 1785 | err = ubifs_node_calc_hash(c, (void *)ino + aligned_len1, hash); | ||
| 1786 | if (err) | ||
| 1787 | goto out_release; | ||
| 1635 | 1788 | ||
| 1636 | err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0); | 1789 | err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0); |
| 1637 | if (!sync && !err) { | 1790 | if (!sync && !err) { |
| @@ -1644,13 +1797,15 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1644 | if (err) | 1797 | if (err) |
| 1645 | goto out_ro; | 1798 | goto out_ro; |
| 1646 | 1799 | ||
| 1800 | ubifs_add_auth_dirt(c, lnum); | ||
| 1801 | |||
| 1647 | ino_key_init(c, &key, host->i_ino); | 1802 | ino_key_init(c, &key, host->i_ino); |
| 1648 | err = ubifs_tnc_add(c, &key, lnum, offs, len1); | 1803 | err = ubifs_tnc_add(c, &key, lnum, offs, len1, hash_host); |
| 1649 | if (err) | 1804 | if (err) |
| 1650 | goto out_ro; | 1805 | goto out_ro; |
| 1651 | 1806 | ||
| 1652 | ino_key_init(c, &key, inode->i_ino); | 1807 | ino_key_init(c, &key, inode->i_ino); |
| 1653 | err = ubifs_tnc_add(c, &key, lnum, offs + aligned_len1, len2); | 1808 | err = ubifs_tnc_add(c, &key, lnum, offs + aligned_len1, len2, hash); |
| 1654 | if (err) | 1809 | if (err) |
| 1655 | goto out_ro; | 1810 | goto out_ro; |
| 1656 | 1811 | ||
| @@ -1662,6 +1817,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, | |||
| 1662 | kfree(ino); | 1817 | kfree(ino); |
| 1663 | return 0; | 1818 | return 0; |
| 1664 | 1819 | ||
| 1820 | out_release: | ||
| 1821 | release_head(c, BASEHD); | ||
| 1665 | out_ro: | 1822 | out_ro: |
| 1666 | ubifs_ro_mode(c, err); | 1823 | ubifs_ro_mode(c, err); |
| 1667 | finish_reservation(c); | 1824 | finish_reservation(c); |
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index 86b0828f5499..15fd854149bb 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c | |||
| @@ -236,6 +236,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) | |||
| 236 | bud->lnum = lnum; | 236 | bud->lnum = lnum; |
| 237 | bud->start = offs; | 237 | bud->start = offs; |
| 238 | bud->jhead = jhead; | 238 | bud->jhead = jhead; |
| 239 | bud->log_hash = NULL; | ||
| 239 | 240 | ||
| 240 | ref->ch.node_type = UBIFS_REF_NODE; | 241 | ref->ch.node_type = UBIFS_REF_NODE; |
| 241 | ref->lnum = cpu_to_le32(bud->lnum); | 242 | ref->lnum = cpu_to_le32(bud->lnum); |
| @@ -275,6 +276,14 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) | |||
| 275 | if (err) | 276 | if (err) |
| 276 | goto out_unlock; | 277 | goto out_unlock; |
| 277 | 278 | ||
| 279 | err = ubifs_shash_update(c, c->log_hash, ref, UBIFS_REF_NODE_SZ); | ||
| 280 | if (err) | ||
| 281 | goto out_unlock; | ||
| 282 | |||
| 283 | err = ubifs_shash_copy_state(c, c->log_hash, c->jheads[jhead].log_hash); | ||
| 284 | if (err) | ||
| 285 | goto out_unlock; | ||
| 286 | |||
| 278 | c->lhead_offs += c->ref_node_alsz; | 287 | c->lhead_offs += c->ref_node_alsz; |
| 279 | 288 | ||
| 280 | ubifs_add_bud(c, bud); | 289 | ubifs_add_bud(c, bud); |
| @@ -377,6 +386,14 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum) | |||
| 377 | cs->cmt_no = cpu_to_le64(c->cmt_no); | 386 | cs->cmt_no = cpu_to_le64(c->cmt_no); |
| 378 | ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0); | 387 | ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0); |
| 379 | 388 | ||
| 389 | err = ubifs_shash_init(c, c->log_hash); | ||
| 390 | if (err) | ||
| 391 | goto out; | ||
| 392 | |||
| 393 | err = ubifs_shash_update(c, c->log_hash, cs, UBIFS_CS_NODE_SZ); | ||
| 394 | if (err < 0) | ||
| 395 | goto out; | ||
| 396 | |||
| 380 | /* | 397 | /* |
| 381 | * Note, we do not lock 'c->log_mutex' because this is the commit start | 398 | * Note, we do not lock 'c->log_mutex' because this is the commit start |
| 382 | * phase and we are exclusively using the log. And we do not lock | 399 | * phase and we are exclusively using the log. And we do not lock |
| @@ -402,6 +419,12 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum) | |||
| 402 | 419 | ||
| 403 | ubifs_prepare_node(c, ref, UBIFS_REF_NODE_SZ, 0); | 420 | ubifs_prepare_node(c, ref, UBIFS_REF_NODE_SZ, 0); |
| 404 | len += UBIFS_REF_NODE_SZ; | 421 | len += UBIFS_REF_NODE_SZ; |
| 422 | |||
| 423 | err = ubifs_shash_update(c, c->log_hash, ref, | ||
| 424 | UBIFS_REF_NODE_SZ); | ||
| 425 | if (err) | ||
| 426 | goto out; | ||
| 427 | ubifs_shash_copy_state(c, c->log_hash, c->jheads[i].log_hash); | ||
| 405 | } | 428 | } |
| 406 | 429 | ||
| 407 | ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len); | 430 | ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len); |
| @@ -516,6 +539,7 @@ int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum) | |||
| 516 | if (err) | 539 | if (err) |
| 517 | return err; | 540 | return err; |
| 518 | list_del(&bud->list); | 541 | list_del(&bud->list); |
| 542 | kfree(bud->log_hash); | ||
| 519 | kfree(bud); | 543 | kfree(bud); |
| 520 | } | 544 | } |
| 521 | mutex_lock(&c->log_mutex); | 545 | mutex_lock(&c->log_mutex); |
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index 31393370e334..d1d5e96350dd 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c | |||
| @@ -604,11 +604,12 @@ static int calc_pnode_num_from_parent(const struct ubifs_info *c, | |||
| 604 | * @lpt_first: LEB number of first LPT LEB | 604 | * @lpt_first: LEB number of first LPT LEB |
| 605 | * @lpt_lebs: number of LEBs for LPT is passed and returned here | 605 | * @lpt_lebs: number of LEBs for LPT is passed and returned here |
| 606 | * @big_lpt: use big LPT model is passed and returned here | 606 | * @big_lpt: use big LPT model is passed and returned here |
| 607 | * @hash: hash of the LPT is returned here | ||
| 607 | * | 608 | * |
| 608 | * This function returns %0 on success and a negative error code on failure. | 609 | * This function returns %0 on success and a negative error code on failure. |
| 609 | */ | 610 | */ |
| 610 | int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | 611 | int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, |
| 611 | int *lpt_lebs, int *big_lpt) | 612 | int *lpt_lebs, int *big_lpt, u8 *hash) |
| 612 | { | 613 | { |
| 613 | int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row; | 614 | int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row; |
| 614 | int blnum, boffs, bsz, bcnt; | 615 | int blnum, boffs, bsz, bcnt; |
| @@ -617,6 +618,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | |||
| 617 | void *buf = NULL, *p; | 618 | void *buf = NULL, *p; |
| 618 | struct ubifs_lpt_lprops *ltab = NULL; | 619 | struct ubifs_lpt_lprops *ltab = NULL; |
| 619 | int *lsave = NULL; | 620 | int *lsave = NULL; |
| 621 | struct shash_desc *desc; | ||
| 620 | 622 | ||
| 621 | err = calc_dflt_lpt_geom(c, main_lebs, big_lpt); | 623 | err = calc_dflt_lpt_geom(c, main_lebs, big_lpt); |
| 622 | if (err) | 624 | if (err) |
| @@ -630,6 +632,10 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | |||
| 630 | /* Needed by 'ubifs_pack_lsave()' */ | 632 | /* Needed by 'ubifs_pack_lsave()' */ |
| 631 | c->main_first = c->leb_cnt - *main_lebs; | 633 | c->main_first = c->leb_cnt - *main_lebs; |
| 632 | 634 | ||
| 635 | desc = ubifs_hash_get_desc(c); | ||
| 636 | if (IS_ERR(desc)) | ||
| 637 | return PTR_ERR(desc); | ||
| 638 | |||
| 633 | lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_KERNEL); | 639 | lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_KERNEL); |
| 634 | pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL); | 640 | pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL); |
| 635 | nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL); | 641 | nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL); |
| @@ -677,6 +683,10 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | |||
| 677 | 683 | ||
| 678 | /* Add first pnode */ | 684 | /* Add first pnode */ |
| 679 | ubifs_pack_pnode(c, p, pnode); | 685 | ubifs_pack_pnode(c, p, pnode); |
| 686 | err = ubifs_shash_update(c, desc, p, c->pnode_sz); | ||
| 687 | if (err) | ||
| 688 | goto out; | ||
| 689 | |||
| 680 | p += c->pnode_sz; | 690 | p += c->pnode_sz; |
| 681 | len = c->pnode_sz; | 691 | len = c->pnode_sz; |
| 682 | pnode->num += 1; | 692 | pnode->num += 1; |
| @@ -711,6 +721,10 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | |||
| 711 | len = 0; | 721 | len = 0; |
| 712 | } | 722 | } |
| 713 | ubifs_pack_pnode(c, p, pnode); | 723 | ubifs_pack_pnode(c, p, pnode); |
| 724 | err = ubifs_shash_update(c, desc, p, c->pnode_sz); | ||
| 725 | if (err) | ||
| 726 | goto out; | ||
| 727 | |||
| 714 | p += c->pnode_sz; | 728 | p += c->pnode_sz; |
| 715 | len += c->pnode_sz; | 729 | len += c->pnode_sz; |
| 716 | /* | 730 | /* |
| @@ -830,6 +844,10 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | |||
| 830 | if (err) | 844 | if (err) |
| 831 | goto out; | 845 | goto out; |
| 832 | 846 | ||
| 847 | err = ubifs_shash_final(c, desc, hash); | ||
| 848 | if (err) | ||
| 849 | goto out; | ||
| 850 | |||
| 833 | c->nhead_lnum = lnum; | 851 | c->nhead_lnum = lnum; |
| 834 | c->nhead_offs = ALIGN(len, c->min_io_size); | 852 | c->nhead_offs = ALIGN(len, c->min_io_size); |
| 835 | 853 | ||
| @@ -853,6 +871,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | |||
| 853 | dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); | 871 | dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); |
| 854 | out: | 872 | out: |
| 855 | c->ltab = NULL; | 873 | c->ltab = NULL; |
| 874 | kfree(desc); | ||
| 856 | kfree(lsave); | 875 | kfree(lsave); |
| 857 | vfree(ltab); | 876 | vfree(ltab); |
| 858 | vfree(buf); | 877 | vfree(buf); |
| @@ -1439,26 +1458,25 @@ struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c, | |||
| 1439 | } | 1458 | } |
| 1440 | 1459 | ||
| 1441 | /** | 1460 | /** |
| 1442 | * ubifs_lpt_lookup - lookup LEB properties in the LPT. | 1461 | * ubifs_pnode_lookup - lookup a pnode in the LPT. |
| 1443 | * @c: UBIFS file-system description object | 1462 | * @c: UBIFS file-system description object |
| 1444 | * @lnum: LEB number to lookup | 1463 | * @i: pnode number (0 to (main_lebs - 1) / UBIFS_LPT_FANOUT) |
| 1445 | * | 1464 | * |
| 1446 | * This function returns a pointer to the LEB properties on success or a | 1465 | * This function returns a pointer to the pnode on success or a negative |
| 1447 | * negative error code on failure. | 1466 | * error code on failure. |
| 1448 | */ | 1467 | */ |
| 1449 | struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum) | 1468 | struct ubifs_pnode *ubifs_pnode_lookup(struct ubifs_info *c, int i) |
| 1450 | { | 1469 | { |
| 1451 | int err, i, h, iip, shft; | 1470 | int err, h, iip, shft; |
| 1452 | struct ubifs_nnode *nnode; | 1471 | struct ubifs_nnode *nnode; |
| 1453 | struct ubifs_pnode *pnode; | ||
| 1454 | 1472 | ||
| 1455 | if (!c->nroot) { | 1473 | if (!c->nroot) { |
| 1456 | err = ubifs_read_nnode(c, NULL, 0); | 1474 | err = ubifs_read_nnode(c, NULL, 0); |
| 1457 | if (err) | 1475 | if (err) |
| 1458 | return ERR_PTR(err); | 1476 | return ERR_PTR(err); |
| 1459 | } | 1477 | } |
| 1478 | i <<= UBIFS_LPT_FANOUT_SHIFT; | ||
| 1460 | nnode = c->nroot; | 1479 | nnode = c->nroot; |
| 1461 | i = lnum - c->main_first; | ||
| 1462 | shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; | 1480 | shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; |
| 1463 | for (h = 1; h < c->lpt_hght; h++) { | 1481 | for (h = 1; h < c->lpt_hght; h++) { |
| 1464 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | 1482 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); |
| @@ -1468,7 +1486,24 @@ struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum) | |||
| 1468 | return ERR_CAST(nnode); | 1486 | return ERR_CAST(nnode); |
| 1469 | } | 1487 | } |
| 1470 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | 1488 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); |
| 1471 | pnode = ubifs_get_pnode(c, nnode, iip); | 1489 | return ubifs_get_pnode(c, nnode, iip); |
| 1490 | } | ||
| 1491 | |||
| 1492 | /** | ||
| 1493 | * ubifs_lpt_lookup - lookup LEB properties in the LPT. | ||
| 1494 | * @c: UBIFS file-system description object | ||
| 1495 | * @lnum: LEB number to lookup | ||
| 1496 | * | ||
| 1497 | * This function returns a pointer to the LEB properties on success or a | ||
| 1498 | * negative error code on failure. | ||
| 1499 | */ | ||
| 1500 | struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum) | ||
| 1501 | { | ||
| 1502 | int i, iip; | ||
| 1503 | struct ubifs_pnode *pnode; | ||
| 1504 | |||
| 1505 | i = lnum - c->main_first; | ||
| 1506 | pnode = ubifs_pnode_lookup(c, i >> UBIFS_LPT_FANOUT_SHIFT); | ||
| 1472 | if (IS_ERR(pnode)) | 1507 | if (IS_ERR(pnode)) |
| 1473 | return ERR_CAST(pnode); | 1508 | return ERR_CAST(pnode); |
| 1474 | iip = (i & (UBIFS_LPT_FANOUT - 1)); | 1509 | iip = (i & (UBIFS_LPT_FANOUT - 1)); |
| @@ -1620,6 +1655,131 @@ struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum) | |||
| 1620 | } | 1655 | } |
| 1621 | 1656 | ||
| 1622 | /** | 1657 | /** |
| 1658 | * ubifs_lpt_calc_hash - Calculate hash of the LPT pnodes | ||
| 1659 | * @c: UBIFS file-system description object | ||
| 1660 | * @hash: the returned hash of the LPT pnodes | ||
| 1661 | * | ||
| 1662 | * This function iterates over the LPT pnodes and creates a hash over them. | ||
| 1663 | * Returns 0 for success or a negative error code otherwise. | ||
| 1664 | */ | ||
| 1665 | int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash) | ||
| 1666 | { | ||
| 1667 | struct ubifs_nnode *nnode, *nn; | ||
| 1668 | struct ubifs_cnode *cnode; | ||
| 1669 | struct shash_desc *desc; | ||
| 1670 | int iip = 0, i; | ||
| 1671 | int bufsiz = max_t(int, c->nnode_sz, c->pnode_sz); | ||
| 1672 | void *buf; | ||
| 1673 | int err; | ||
| 1674 | |||
| 1675 | if (!ubifs_authenticated(c)) | ||
| 1676 | return 0; | ||
| 1677 | |||
| 1678 | desc = ubifs_hash_get_desc(c); | ||
| 1679 | if (IS_ERR(desc)) | ||
| 1680 | return PTR_ERR(desc); | ||
| 1681 | |||
| 1682 | buf = kmalloc(bufsiz, GFP_NOFS); | ||
| 1683 | if (!buf) { | ||
| 1684 | err = -ENOMEM; | ||
| 1685 | goto out; | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | if (!c->nroot) { | ||
| 1689 | err = ubifs_read_nnode(c, NULL, 0); | ||
| 1690 | if (err) | ||
| 1691 | return err; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | cnode = (struct ubifs_cnode *)c->nroot; | ||
| 1695 | |||
| 1696 | while (cnode) { | ||
| 1697 | nnode = cnode->parent; | ||
| 1698 | nn = (struct ubifs_nnode *)cnode; | ||
| 1699 | if (cnode->level > 1) { | ||
| 1700 | while (iip < UBIFS_LPT_FANOUT) { | ||
| 1701 | if (nn->nbranch[iip].lnum == 0) { | ||
| 1702 | /* Go right */ | ||
| 1703 | iip++; | ||
| 1704 | continue; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | nnode = ubifs_get_nnode(c, nn, iip); | ||
| 1708 | if (IS_ERR(nnode)) { | ||
| 1709 | err = PTR_ERR(nnode); | ||
| 1710 | goto out; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | /* Go down */ | ||
| 1714 | iip = 0; | ||
| 1715 | cnode = (struct ubifs_cnode *)nnode; | ||
| 1716 | break; | ||
| 1717 | } | ||
| 1718 | if (iip < UBIFS_LPT_FANOUT) | ||
| 1719 | continue; | ||
| 1720 | } else { | ||
| 1721 | struct ubifs_pnode *pnode; | ||
| 1722 | |||
| 1723 | for (i = 0; i < UBIFS_LPT_FANOUT; i++) { | ||
| 1724 | if (nn->nbranch[i].lnum == 0) | ||
| 1725 | continue; | ||
| 1726 | pnode = ubifs_get_pnode(c, nn, i); | ||
| 1727 | if (IS_ERR(pnode)) { | ||
| 1728 | err = PTR_ERR(pnode); | ||
| 1729 | goto out; | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | ubifs_pack_pnode(c, buf, pnode); | ||
| 1733 | err = ubifs_shash_update(c, desc, buf, | ||
| 1734 | c->pnode_sz); | ||
| 1735 | if (err) | ||
| 1736 | goto out; | ||
| 1737 | } | ||
| 1738 | } | ||
| 1739 | /* Go up and to the right */ | ||
| 1740 | iip = cnode->iip + 1; | ||
| 1741 | cnode = (struct ubifs_cnode *)nnode; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | err = ubifs_shash_final(c, desc, hash); | ||
| 1745 | out: | ||
| 1746 | kfree(desc); | ||
| 1747 | kfree(buf); | ||
| 1748 | |||
| 1749 | return err; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | /** | ||
| 1753 | * lpt_check_hash - check the hash of the LPT. | ||
| 1754 | * @c: UBIFS file-system description object | ||
| 1755 | * | ||
| 1756 | * This function calculates a hash over all pnodes in the LPT and compares it with | ||
| 1757 | * the hash stored in the master node. Returns %0 on success and a negative error | ||
| 1758 | * code on failure. | ||
| 1759 | */ | ||
| 1760 | static int lpt_check_hash(struct ubifs_info *c) | ||
| 1761 | { | ||
| 1762 | int err; | ||
| 1763 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 1764 | |||
| 1765 | if (!ubifs_authenticated(c)) | ||
| 1766 | return 0; | ||
| 1767 | |||
| 1768 | err = ubifs_lpt_calc_hash(c, hash); | ||
| 1769 | if (err) | ||
| 1770 | return err; | ||
| 1771 | |||
| 1772 | if (ubifs_check_hash(c, c->mst_node->hash_lpt, hash)) { | ||
| 1773 | err = -EPERM; | ||
| 1774 | ubifs_err(c, "Failed to authenticate LPT"); | ||
| 1775 | } else { | ||
| 1776 | err = 0; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | return err; | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | /** | ||
| 1623 | * lpt_init_rd - initialize the LPT for reading. | 1783 | * lpt_init_rd - initialize the LPT for reading. |
| 1624 | * @c: UBIFS file-system description object | 1784 | * @c: UBIFS file-system description object |
| 1625 | * | 1785 | * |
| @@ -1660,6 +1820,10 @@ static int lpt_init_rd(struct ubifs_info *c) | |||
| 1660 | if (err) | 1820 | if (err) |
| 1661 | return err; | 1821 | return err; |
| 1662 | 1822 | ||
| 1823 | err = lpt_check_hash(c); | ||
| 1824 | if (err) | ||
| 1825 | return err; | ||
| 1826 | |||
| 1663 | dbg_lp("space_bits %d", c->space_bits); | 1827 | dbg_lp("space_bits %d", c->space_bits); |
| 1664 | dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits); | 1828 | dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits); |
| 1665 | dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits); | 1829 | dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits); |
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 7ce30994bbba..1f88caffdf2a 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c | |||
| @@ -619,38 +619,6 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, | |||
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | /** | 621 | /** |
| 622 | * pnode_lookup - lookup a pnode in the LPT. | ||
| 623 | * @c: UBIFS file-system description object | ||
| 624 | * @i: pnode number (0 to (main_lebs - 1) / UBIFS_LPT_FANOUT)) | ||
| 625 | * | ||
| 626 | * This function returns a pointer to the pnode on success or a negative | ||
| 627 | * error code on failure. | ||
| 628 | */ | ||
| 629 | static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i) | ||
| 630 | { | ||
| 631 | int err, h, iip, shft; | ||
| 632 | struct ubifs_nnode *nnode; | ||
| 633 | |||
| 634 | if (!c->nroot) { | ||
| 635 | err = ubifs_read_nnode(c, NULL, 0); | ||
| 636 | if (err) | ||
| 637 | return ERR_PTR(err); | ||
| 638 | } | ||
| 639 | i <<= UBIFS_LPT_FANOUT_SHIFT; | ||
| 640 | nnode = c->nroot; | ||
| 641 | shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; | ||
| 642 | for (h = 1; h < c->lpt_hght; h++) { | ||
| 643 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | ||
| 644 | shft -= UBIFS_LPT_FANOUT_SHIFT; | ||
| 645 | nnode = ubifs_get_nnode(c, nnode, iip); | ||
| 646 | if (IS_ERR(nnode)) | ||
| 647 | return ERR_CAST(nnode); | ||
| 648 | } | ||
| 649 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | ||
| 650 | return ubifs_get_pnode(c, nnode, iip); | ||
| 651 | } | ||
| 652 | |||
| 653 | /** | ||
| 654 | * add_pnode_dirt - add dirty space to LPT LEB properties. | 622 | * add_pnode_dirt - add dirty space to LPT LEB properties. |
| 655 | * @c: UBIFS file-system description object | 623 | * @c: UBIFS file-system description object |
| 656 | * @pnode: pnode for which to add dirt | 624 | * @pnode: pnode for which to add dirt |
| @@ -702,7 +670,7 @@ static int make_tree_dirty(struct ubifs_info *c) | |||
| 702 | { | 670 | { |
| 703 | struct ubifs_pnode *pnode; | 671 | struct ubifs_pnode *pnode; |
| 704 | 672 | ||
| 705 | pnode = pnode_lookup(c, 0); | 673 | pnode = ubifs_pnode_lookup(c, 0); |
| 706 | if (IS_ERR(pnode)) | 674 | if (IS_ERR(pnode)) |
| 707 | return PTR_ERR(pnode); | 675 | return PTR_ERR(pnode); |
| 708 | 676 | ||
| @@ -956,7 +924,7 @@ static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum, | |||
| 956 | struct ubifs_pnode *pnode; | 924 | struct ubifs_pnode *pnode; |
| 957 | struct ubifs_nbranch *branch; | 925 | struct ubifs_nbranch *branch; |
| 958 | 926 | ||
| 959 | pnode = pnode_lookup(c, node_num); | 927 | pnode = ubifs_pnode_lookup(c, node_num); |
| 960 | if (IS_ERR(pnode)) | 928 | if (IS_ERR(pnode)) |
| 961 | return PTR_ERR(pnode); | 929 | return PTR_ERR(pnode); |
| 962 | branch = &pnode->parent->nbranch[pnode->iip]; | 930 | branch = &pnode->parent->nbranch[pnode->iip]; |
| @@ -1279,6 +1247,10 @@ int ubifs_lpt_start_commit(struct ubifs_info *c) | |||
| 1279 | if (err) | 1247 | if (err) |
| 1280 | goto out; | 1248 | goto out; |
| 1281 | 1249 | ||
| 1250 | err = ubifs_lpt_calc_hash(c, c->mst_node->hash_lpt); | ||
| 1251 | if (err) | ||
| 1252 | goto out; | ||
| 1253 | |||
| 1282 | /* Copy the LPT's own lprops for end commit to write */ | 1254 | /* Copy the LPT's own lprops for end commit to write */ |
| 1283 | memcpy(c->ltab_cmt, c->ltab, | 1255 | memcpy(c->ltab_cmt, c->ltab, |
| 1284 | sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); | 1256 | sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); |
| @@ -1558,7 +1530,7 @@ static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs) | |||
| 1558 | struct ubifs_nbranch *branch; | 1530 | struct ubifs_nbranch *branch; |
| 1559 | 1531 | ||
| 1560 | cond_resched(); | 1532 | cond_resched(); |
| 1561 | pnode = pnode_lookup(c, i); | 1533 | pnode = ubifs_pnode_lookup(c, i); |
| 1562 | if (IS_ERR(pnode)) | 1534 | if (IS_ERR(pnode)) |
| 1563 | return PTR_ERR(pnode); | 1535 | return PTR_ERR(pnode); |
| 1564 | branch = &pnode->parent->nbranch[pnode->iip]; | 1536 | branch = &pnode->parent->nbranch[pnode->iip]; |
| @@ -1710,7 +1682,7 @@ int dbg_check_ltab(struct ubifs_info *c) | |||
| 1710 | for (i = 0; i < cnt; i++) { | 1682 | for (i = 0; i < cnt; i++) { |
| 1711 | struct ubifs_pnode *pnode; | 1683 | struct ubifs_pnode *pnode; |
| 1712 | 1684 | ||
| 1713 | pnode = pnode_lookup(c, i); | 1685 | pnode = ubifs_pnode_lookup(c, i); |
| 1714 | if (IS_ERR(pnode)) | 1686 | if (IS_ERR(pnode)) |
| 1715 | return PTR_ERR(pnode); | 1687 | return PTR_ERR(pnode); |
| 1716 | cond_resched(); | 1688 | cond_resched(); |
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 9df4a41bba52..5ea51bbd14c7 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c | |||
| @@ -25,6 +25,42 @@ | |||
| 25 | #include "ubifs.h" | 25 | #include "ubifs.h" |
| 26 | 26 | ||
| 27 | /** | 27 | /** |
| 28 | * ubifs_compare_master_node - compare two UBIFS master nodes | ||
| 29 | * @c: UBIFS file-system description object | ||
| 30 | * @m1: the first node | ||
| 31 | * @m2: the second node | ||
| 32 | * | ||
| 33 | * This function compares two UBIFS master nodes. Returns 0 if they are equal | ||
| 34 | * and nonzero if not. | ||
| 35 | */ | ||
| 36 | int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2) | ||
| 37 | { | ||
| 38 | int ret; | ||
| 39 | int behind; | ||
| 40 | int hmac_offs = offsetof(struct ubifs_mst_node, hmac); | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Do not compare the common node header since the sequence number and | ||
| 44 | * hence the CRC are different. | ||
| 45 | */ | ||
| 46 | ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ, | ||
| 47 | hmac_offs - UBIFS_CH_SZ); | ||
| 48 | if (ret) | ||
| 49 | return ret; | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Do not compare the embedded HMAC aswell which also must be different | ||
| 53 | * due to the different common node header. | ||
| 54 | */ | ||
| 55 | behind = hmac_offs + UBIFS_MAX_HMAC_LEN; | ||
| 56 | |||
| 57 | if (UBIFS_MST_NODE_SZ > behind) | ||
| 58 | return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind); | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 28 | * scan_for_master - search the valid master node. | 64 | * scan_for_master - search the valid master node. |
| 29 | * @c: UBIFS file-system description object | 65 | * @c: UBIFS file-system description object |
| 30 | * | 66 | * |
| @@ -37,7 +73,7 @@ static int scan_for_master(struct ubifs_info *c) | |||
| 37 | { | 73 | { |
| 38 | struct ubifs_scan_leb *sleb; | 74 | struct ubifs_scan_leb *sleb; |
| 39 | struct ubifs_scan_node *snod; | 75 | struct ubifs_scan_node *snod; |
| 40 | int lnum, offs = 0, nodes_cnt; | 76 | int lnum, offs = 0, nodes_cnt, err; |
| 41 | 77 | ||
| 42 | lnum = UBIFS_MST_LNUM; | 78 | lnum = UBIFS_MST_LNUM; |
| 43 | 79 | ||
| @@ -69,12 +105,23 @@ static int scan_for_master(struct ubifs_info *c) | |||
| 69 | goto out_dump; | 105 | goto out_dump; |
| 70 | if (snod->offs != offs) | 106 | if (snod->offs != offs) |
| 71 | goto out; | 107 | goto out; |
| 72 | if (memcmp((void *)c->mst_node + UBIFS_CH_SZ, | 108 | if (ubifs_compare_master_node(c, c->mst_node, snod->node)) |
| 73 | (void *)snod->node + UBIFS_CH_SZ, | ||
| 74 | UBIFS_MST_NODE_SZ - UBIFS_CH_SZ)) | ||
| 75 | goto out; | 109 | goto out; |
| 110 | |||
| 76 | c->mst_offs = offs; | 111 | c->mst_offs = offs; |
| 77 | ubifs_scan_destroy(sleb); | 112 | ubifs_scan_destroy(sleb); |
| 113 | |||
| 114 | if (!ubifs_authenticated(c)) | ||
| 115 | return 0; | ||
| 116 | |||
| 117 | err = ubifs_node_verify_hmac(c, c->mst_node, | ||
| 118 | sizeof(struct ubifs_mst_node), | ||
| 119 | offsetof(struct ubifs_mst_node, hmac)); | ||
| 120 | if (err) { | ||
| 121 | ubifs_err(c, "Failed to verify master node HMAC"); | ||
| 122 | return -EPERM; | ||
| 123 | } | ||
| 124 | |||
| 78 | return 0; | 125 | return 0; |
| 79 | 126 | ||
| 80 | out: | 127 | out: |
| @@ -305,6 +352,8 @@ int ubifs_read_master(struct ubifs_info *c) | |||
| 305 | c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead); | 352 | c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead); |
| 306 | c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark); | 353 | c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark); |
| 307 | 354 | ||
| 355 | ubifs_copy_hash(c, c->mst_node->hash_root_idx, c->zroot.hash); | ||
| 356 | |||
| 308 | c->calc_idx_sz = c->bi.old_idx_sz; | 357 | c->calc_idx_sz = c->bi.old_idx_sz; |
| 309 | 358 | ||
| 310 | if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS)) | 359 | if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS)) |
| @@ -378,7 +427,9 @@ int ubifs_write_master(struct ubifs_info *c) | |||
| 378 | c->mst_offs = offs; | 427 | c->mst_offs = offs; |
| 379 | c->mst_node->highest_inum = cpu_to_le64(c->highest_inum); | 428 | c->mst_node->highest_inum = cpu_to_le64(c->highest_inum); |
| 380 | 429 | ||
| 381 | err = ubifs_write_node(c, c->mst_node, len, lnum, offs); | 430 | ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx); |
| 431 | err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs, | ||
| 432 | offsetof(struct ubifs_mst_node, hmac)); | ||
| 382 | if (err) | 433 | if (err) |
| 383 | return err; | 434 | return err; |
| 384 | 435 | ||
| @@ -389,7 +440,8 @@ int ubifs_write_master(struct ubifs_info *c) | |||
| 389 | if (err) | 440 | if (err) |
| 390 | return err; | 441 | return err; |
| 391 | } | 442 | } |
| 392 | err = ubifs_write_node(c, c->mst_node, len, lnum, offs); | 443 | err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs, |
| 444 | offsetof(struct ubifs_mst_node, hmac)); | ||
| 393 | 445 | ||
| 394 | return err; | 446 | return err; |
| 395 | } | 447 | } |
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 21d35d7dd975..6f87237fdbf4 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h | |||
| @@ -197,7 +197,8 @@ static inline int ubifs_return_leb(struct ubifs_info *c, int lnum) | |||
| 197 | */ | 197 | */ |
| 198 | static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt) | 198 | static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt) |
| 199 | { | 199 | { |
| 200 | return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt; | 200 | return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len + c->hash_len) |
| 201 | * child_cnt; | ||
| 201 | } | 202 | } |
| 202 | 203 | ||
| 203 | /** | 204 | /** |
| @@ -212,7 +213,7 @@ struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c, | |||
| 212 | int bnum) | 213 | int bnum) |
| 213 | { | 214 | { |
| 214 | return (struct ubifs_branch *)((void *)idx->branches + | 215 | return (struct ubifs_branch *)((void *)idx->branches + |
| 215 | (UBIFS_BRANCH_SZ + c->key_len) * bnum); | 216 | (UBIFS_BRANCH_SZ + c->key_len + c->hash_len) * bnum); |
| 216 | } | 217 | } |
| 217 | 218 | ||
| 218 | /** | 219 | /** |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 984e30e83c0b..8526b7ec4707 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
| @@ -212,7 +212,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c, | |||
| 212 | save_flags = mst->flags; | 212 | save_flags = mst->flags; |
| 213 | mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); | 213 | mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); |
| 214 | 214 | ||
| 215 | ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1); | 215 | err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ, |
| 216 | offsetof(struct ubifs_mst_node, hmac), 1); | ||
| 217 | if (err) | ||
| 218 | goto out; | ||
| 216 | err = ubifs_leb_change(c, lnum, mst, sz); | 219 | err = ubifs_leb_change(c, lnum, mst, sz); |
| 217 | if (err) | 220 | if (err) |
| 218 | goto out; | 221 | goto out; |
| @@ -264,9 +267,7 @@ int ubifs_recover_master_node(struct ubifs_info *c) | |||
| 264 | offs2 = (void *)mst2 - buf2; | 267 | offs2 = (void *)mst2 - buf2; |
| 265 | if (offs1 == offs2) { | 268 | if (offs1 == offs2) { |
| 266 | /* Same offset, so must be the same */ | 269 | /* Same offset, so must be the same */ |
| 267 | if (memcmp((void *)mst1 + UBIFS_CH_SZ, | 270 | if (ubifs_compare_master_node(c, mst1, mst2)) |
| 268 | (void *)mst2 + UBIFS_CH_SZ, | ||
| 269 | UBIFS_MST_NODE_SZ - UBIFS_CH_SZ)) | ||
| 270 | goto out_err; | 271 | goto out_err; |
| 271 | mst = mst1; | 272 | mst = mst1; |
| 272 | } else if (offs2 + sz == offs1) { | 273 | } else if (offs2 + sz == offs1) { |
| @@ -1462,15 +1463,81 @@ out: | |||
| 1462 | } | 1463 | } |
| 1463 | 1464 | ||
| 1464 | /** | 1465 | /** |
| 1466 | * inode_fix_size - fix inode size | ||
| 1467 | * @c: UBIFS file-system description object | ||
| 1468 | * @e: inode size information for recovery | ||
| 1469 | */ | ||
| 1470 | static int inode_fix_size(struct ubifs_info *c, struct size_entry *e) | ||
| 1471 | { | ||
| 1472 | struct inode *inode; | ||
| 1473 | struct ubifs_inode *ui; | ||
| 1474 | int err; | ||
| 1475 | |||
| 1476 | if (c->ro_mount) | ||
| 1477 | ubifs_assert(c, !e->inode); | ||
| 1478 | |||
| 1479 | if (e->inode) { | ||
| 1480 | /* Remounting rw, pick up inode we stored earlier */ | ||
| 1481 | inode = e->inode; | ||
| 1482 | } else { | ||
| 1483 | inode = ubifs_iget(c->vfs_sb, e->inum); | ||
| 1484 | if (IS_ERR(inode)) | ||
| 1485 | return PTR_ERR(inode); | ||
| 1486 | |||
| 1487 | if (inode->i_size >= e->d_size) { | ||
| 1488 | /* | ||
| 1489 | * The original inode in the index already has a size | ||
| 1490 | * big enough, nothing to do | ||
| 1491 | */ | ||
| 1492 | iput(inode); | ||
| 1493 | return 0; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | dbg_rcvry("ino %lu size %lld -> %lld", | ||
| 1497 | (unsigned long)e->inum, | ||
| 1498 | inode->i_size, e->d_size); | ||
| 1499 | |||
| 1500 | ui = ubifs_inode(inode); | ||
| 1501 | |||
| 1502 | inode->i_size = e->d_size; | ||
| 1503 | ui->ui_size = e->d_size; | ||
| 1504 | ui->synced_i_size = e->d_size; | ||
| 1505 | |||
| 1506 | e->inode = inode; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | /* | ||
| 1510 | * In readonly mode just keep the inode pinned in memory until we go | ||
| 1511 | * readwrite. In readwrite mode write the inode to the journal with the | ||
| 1512 | * fixed size. | ||
| 1513 | */ | ||
| 1514 | if (c->ro_mount) | ||
| 1515 | return 0; | ||
| 1516 | |||
| 1517 | err = ubifs_jnl_write_inode(c, inode); | ||
| 1518 | |||
| 1519 | iput(inode); | ||
| 1520 | |||
| 1521 | if (err) | ||
| 1522 | return err; | ||
| 1523 | |||
| 1524 | rb_erase(&e->rb, &c->size_tree); | ||
| 1525 | kfree(e); | ||
| 1526 | |||
| 1527 | return 0; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | /** | ||
| 1465 | * ubifs_recover_size - recover inode size. | 1531 | * ubifs_recover_size - recover inode size. |
| 1466 | * @c: UBIFS file-system description object | 1532 | * @c: UBIFS file-system description object |
| 1533 | * @in_place: If true, do a in-place size fixup | ||
| 1467 | * | 1534 | * |
| 1468 | * This function attempts to fix inode size discrepancies identified by the | 1535 | * This function attempts to fix inode size discrepancies identified by the |
| 1469 | * 'ubifs_recover_size_accum()' function. | 1536 | * 'ubifs_recover_size_accum()' function. |
| 1470 | * | 1537 | * |
| 1471 | * This functions returns %0 on success and a negative error code on failure. | 1538 | * This functions returns %0 on success and a negative error code on failure. |
| 1472 | */ | 1539 | */ |
| 1473 | int ubifs_recover_size(struct ubifs_info *c) | 1540 | int ubifs_recover_size(struct ubifs_info *c, bool in_place) |
| 1474 | { | 1541 | { |
| 1475 | struct rb_node *this = rb_first(&c->size_tree); | 1542 | struct rb_node *this = rb_first(&c->size_tree); |
| 1476 | 1543 | ||
| @@ -1479,6 +1546,9 @@ int ubifs_recover_size(struct ubifs_info *c) | |||
| 1479 | int err; | 1546 | int err; |
| 1480 | 1547 | ||
| 1481 | e = rb_entry(this, struct size_entry, rb); | 1548 | e = rb_entry(this, struct size_entry, rb); |
| 1549 | |||
| 1550 | this = rb_next(this); | ||
| 1551 | |||
| 1482 | if (!e->exists) { | 1552 | if (!e->exists) { |
| 1483 | union ubifs_key key; | 1553 | union ubifs_key key; |
| 1484 | 1554 | ||
| @@ -1502,40 +1572,26 @@ int ubifs_recover_size(struct ubifs_info *c) | |||
| 1502 | } | 1572 | } |
| 1503 | 1573 | ||
| 1504 | if (e->exists && e->i_size < e->d_size) { | 1574 | if (e->exists && e->i_size < e->d_size) { |
| 1505 | if (c->ro_mount) { | 1575 | ubifs_assert(c, !(c->ro_mount && in_place)); |
| 1506 | /* Fix the inode size and pin it in memory */ | 1576 | |
| 1507 | struct inode *inode; | 1577 | /* |
| 1508 | struct ubifs_inode *ui; | 1578 | * We found data that is outside the found inode size, |
| 1509 | 1579 | * fixup the inode size | |
| 1510 | ubifs_assert(c, !e->inode); | 1580 | */ |
| 1511 | 1581 | ||
| 1512 | inode = ubifs_iget(c->vfs_sb, e->inum); | 1582 | if (in_place) { |
| 1513 | if (IS_ERR(inode)) | ||
| 1514 | return PTR_ERR(inode); | ||
| 1515 | |||
| 1516 | ui = ubifs_inode(inode); | ||
| 1517 | if (inode->i_size < e->d_size) { | ||
| 1518 | dbg_rcvry("ino %lu size %lld -> %lld", | ||
| 1519 | (unsigned long)e->inum, | ||
| 1520 | inode->i_size, e->d_size); | ||
| 1521 | inode->i_size = e->d_size; | ||
| 1522 | ui->ui_size = e->d_size; | ||
| 1523 | ui->synced_i_size = e->d_size; | ||
| 1524 | e->inode = inode; | ||
| 1525 | this = rb_next(this); | ||
| 1526 | continue; | ||
| 1527 | } | ||
| 1528 | iput(inode); | ||
| 1529 | } else { | ||
| 1530 | /* Fix the size in place */ | ||
| 1531 | err = fix_size_in_place(c, e); | 1583 | err = fix_size_in_place(c, e); |
| 1532 | if (err) | 1584 | if (err) |
| 1533 | return err; | 1585 | return err; |
| 1534 | iput(e->inode); | 1586 | iput(e->inode); |
| 1587 | } else { | ||
| 1588 | err = inode_fix_size(c, e); | ||
| 1589 | if (err) | ||
| 1590 | return err; | ||
| 1591 | continue; | ||
| 1535 | } | 1592 | } |
| 1536 | } | 1593 | } |
| 1537 | 1594 | ||
| 1538 | this = rb_next(this); | ||
| 1539 | rb_erase(&e->rb, &c->size_tree); | 1595 | rb_erase(&e->rb, &c->size_tree); |
| 1540 | kfree(e); | 1596 | kfree(e); |
| 1541 | } | 1597 | } |
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 4844538eb926..75f961c4c044 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | 34 | ||
| 35 | #include "ubifs.h" | 35 | #include "ubifs.h" |
| 36 | #include <linux/list_sort.h> | 36 | #include <linux/list_sort.h> |
| 37 | #include <crypto/hash.h> | ||
| 38 | #include <crypto/algapi.h> | ||
| 37 | 39 | ||
| 38 | /** | 40 | /** |
| 39 | * struct replay_entry - replay list entry. | 41 | * struct replay_entry - replay list entry. |
| @@ -56,6 +58,7 @@ struct replay_entry { | |||
| 56 | int lnum; | 58 | int lnum; |
| 57 | int offs; | 59 | int offs; |
| 58 | int len; | 60 | int len; |
| 61 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 59 | unsigned int deletion:1; | 62 | unsigned int deletion:1; |
| 60 | unsigned long long sqnum; | 63 | unsigned long long sqnum; |
| 61 | struct list_head list; | 64 | struct list_head list; |
| @@ -228,7 +231,7 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r) | |||
| 228 | err = ubifs_tnc_remove_nm(c, &r->key, &r->nm); | 231 | err = ubifs_tnc_remove_nm(c, &r->key, &r->nm); |
| 229 | else | 232 | else |
| 230 | err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs, | 233 | err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs, |
| 231 | r->len, &r->nm); | 234 | r->len, r->hash, &r->nm); |
| 232 | } else { | 235 | } else { |
| 233 | if (r->deletion) | 236 | if (r->deletion) |
| 234 | switch (key_type(c, &r->key)) { | 237 | switch (key_type(c, &r->key)) { |
| @@ -248,7 +251,7 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r) | |||
| 248 | } | 251 | } |
| 249 | else | 252 | else |
| 250 | err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs, | 253 | err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs, |
| 251 | r->len); | 254 | r->len, r->hash); |
| 252 | if (err) | 255 | if (err) |
| 253 | return err; | 256 | return err; |
| 254 | 257 | ||
| @@ -352,9 +355,9 @@ static void destroy_replay_list(struct ubifs_info *c) | |||
| 352 | * in case of success and a negative error code in case of failure. | 355 | * in case of success and a negative error code in case of failure. |
| 353 | */ | 356 | */ |
| 354 | static int insert_node(struct ubifs_info *c, int lnum, int offs, int len, | 357 | static int insert_node(struct ubifs_info *c, int lnum, int offs, int len, |
| 355 | union ubifs_key *key, unsigned long long sqnum, | 358 | const u8 *hash, union ubifs_key *key, |
| 356 | int deletion, int *used, loff_t old_size, | 359 | unsigned long long sqnum, int deletion, int *used, |
| 357 | loff_t new_size) | 360 | loff_t old_size, loff_t new_size) |
| 358 | { | 361 | { |
| 359 | struct replay_entry *r; | 362 | struct replay_entry *r; |
| 360 | 363 | ||
| @@ -372,6 +375,7 @@ static int insert_node(struct ubifs_info *c, int lnum, int offs, int len, | |||
| 372 | r->lnum = lnum; | 375 | r->lnum = lnum; |
| 373 | r->offs = offs; | 376 | r->offs = offs; |
| 374 | r->len = len; | 377 | r->len = len; |
| 378 | ubifs_copy_hash(c, hash, r->hash); | ||
| 375 | r->deletion = !!deletion; | 379 | r->deletion = !!deletion; |
| 376 | r->sqnum = sqnum; | 380 | r->sqnum = sqnum; |
| 377 | key_copy(c, key, &r->key); | 381 | key_copy(c, key, &r->key); |
| @@ -400,8 +404,9 @@ static int insert_node(struct ubifs_info *c, int lnum, int offs, int len, | |||
| 400 | * negative error code in case of failure. | 404 | * negative error code in case of failure. |
| 401 | */ | 405 | */ |
| 402 | static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len, | 406 | static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len, |
| 403 | union ubifs_key *key, const char *name, int nlen, | 407 | const u8 *hash, union ubifs_key *key, |
| 404 | unsigned long long sqnum, int deletion, int *used) | 408 | const char *name, int nlen, unsigned long long sqnum, |
| 409 | int deletion, int *used) | ||
| 405 | { | 410 | { |
| 406 | struct replay_entry *r; | 411 | struct replay_entry *r; |
| 407 | char *nbuf; | 412 | char *nbuf; |
| @@ -425,6 +430,7 @@ static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len, | |||
| 425 | r->lnum = lnum; | 430 | r->lnum = lnum; |
| 426 | r->offs = offs; | 431 | r->offs = offs; |
| 427 | r->len = len; | 432 | r->len = len; |
| 433 | ubifs_copy_hash(c, hash, r->hash); | ||
| 428 | r->deletion = !!deletion; | 434 | r->deletion = !!deletion; |
| 429 | r->sqnum = sqnum; | 435 | r->sqnum = sqnum; |
| 430 | key_copy(c, key, &r->key); | 436 | key_copy(c, key, &r->key); |
| @@ -528,6 +534,105 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud) | |||
| 528 | } | 534 | } |
| 529 | 535 | ||
| 530 | /** | 536 | /** |
| 537 | * authenticate_sleb - authenticate one scan LEB | ||
| 538 | * @c: UBIFS file-system description object | ||
| 539 | * @sleb: the scan LEB to authenticate | ||
| 540 | * @log_hash: | ||
| 541 | * @is_last: if true, this is is the last LEB | ||
| 542 | * | ||
| 543 | * This function iterates over the buds of a single LEB authenticating all buds | ||
| 544 | * with the authentication nodes on this LEB. Authentication nodes are written | ||
| 545 | * after some buds and contain a HMAC covering the authentication node itself | ||
| 546 | * and the buds between the last authentication node and the current | ||
| 547 | * authentication node. It can happen that the last buds cannot be authenticated | ||
| 548 | * because a powercut happened when some nodes were written but not the | ||
| 549 | * corresponding authentication node. This function returns the number of nodes | ||
| 550 | * that could be authenticated or a negative error code. | ||
| 551 | */ | ||
| 552 | static int authenticate_sleb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | ||
| 553 | struct shash_desc *log_hash, int is_last) | ||
| 554 | { | ||
| 555 | int n_not_auth = 0; | ||
| 556 | struct ubifs_scan_node *snod; | ||
| 557 | int n_nodes = 0; | ||
| 558 | int err; | ||
| 559 | u8 *hash, *hmac; | ||
| 560 | |||
| 561 | if (!ubifs_authenticated(c)) | ||
| 562 | return sleb->nodes_cnt; | ||
| 563 | |||
| 564 | hash = kmalloc(crypto_shash_descsize(c->hash_tfm), GFP_NOFS); | ||
| 565 | hmac = kmalloc(c->hmac_desc_len, GFP_NOFS); | ||
| 566 | if (!hash || !hmac) { | ||
| 567 | err = -ENOMEM; | ||
| 568 | goto out; | ||
| 569 | } | ||
| 570 | |||
| 571 | list_for_each_entry(snod, &sleb->nodes, list) { | ||
| 572 | |||
| 573 | n_nodes++; | ||
| 574 | |||
| 575 | if (snod->type == UBIFS_AUTH_NODE) { | ||
| 576 | struct ubifs_auth_node *auth = snod->node; | ||
| 577 | SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm); | ||
| 578 | SHASH_DESC_ON_STACK(hmac_desc, c->hmac_tfm); | ||
| 579 | |||
| 580 | hash_desc->tfm = c->hash_tfm; | ||
| 581 | hash_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 582 | |||
| 583 | ubifs_shash_copy_state(c, log_hash, hash_desc); | ||
| 584 | err = crypto_shash_final(hash_desc, hash); | ||
| 585 | if (err) | ||
| 586 | goto out; | ||
| 587 | |||
| 588 | hmac_desc->tfm = c->hmac_tfm; | ||
| 589 | hmac_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
| 590 | err = crypto_shash_digest(hmac_desc, hash, c->hash_len, | ||
| 591 | hmac); | ||
| 592 | if (err) | ||
| 593 | goto out; | ||
| 594 | |||
| 595 | err = ubifs_check_hmac(c, auth->hmac, hmac); | ||
| 596 | if (err) { | ||
| 597 | err = -EPERM; | ||
| 598 | goto out; | ||
| 599 | } | ||
| 600 | n_not_auth = 0; | ||
| 601 | } else { | ||
| 602 | err = crypto_shash_update(log_hash, snod->node, | ||
| 603 | snod->len); | ||
| 604 | if (err) | ||
| 605 | goto out; | ||
| 606 | n_not_auth++; | ||
| 607 | } | ||
| 608 | } | ||
| 609 | |||
| 610 | /* | ||
| 611 | * A powercut can happen when some nodes were written, but not yet | ||
| 612 | * the corresponding authentication node. This may only happen on | ||
| 613 | * the last bud though. | ||
| 614 | */ | ||
| 615 | if (n_not_auth) { | ||
| 616 | if (is_last) { | ||
| 617 | dbg_mnt("%d unauthenticated nodes found on LEB %d, Ignoring them", | ||
| 618 | n_not_auth, sleb->lnum); | ||
| 619 | err = 0; | ||
| 620 | } else { | ||
| 621 | dbg_mnt("%d unauthenticated nodes found on non-last LEB %d", | ||
| 622 | n_not_auth, sleb->lnum); | ||
| 623 | err = -EPERM; | ||
| 624 | } | ||
| 625 | } else { | ||
| 626 | err = 0; | ||
| 627 | } | ||
| 628 | out: | ||
| 629 | kfree(hash); | ||
| 630 | kfree(hmac); | ||
| 631 | |||
| 632 | return err ? err : n_nodes - n_not_auth; | ||
| 633 | } | ||
| 634 | |||
| 635 | /** | ||
| 531 | * replay_bud - replay a bud logical eraseblock. | 636 | * replay_bud - replay a bud logical eraseblock. |
| 532 | * @c: UBIFS file-system description object | 637 | * @c: UBIFS file-system description object |
| 533 | * @b: bud entry which describes the bud | 638 | * @b: bud entry which describes the bud |
| @@ -540,6 +645,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 540 | { | 645 | { |
| 541 | int is_last = is_last_bud(c, b->bud); | 646 | int is_last = is_last_bud(c, b->bud); |
| 542 | int err = 0, used = 0, lnum = b->bud->lnum, offs = b->bud->start; | 647 | int err = 0, used = 0, lnum = b->bud->lnum, offs = b->bud->start; |
| 648 | int n_nodes, n = 0; | ||
| 543 | struct ubifs_scan_leb *sleb; | 649 | struct ubifs_scan_leb *sleb; |
| 544 | struct ubifs_scan_node *snod; | 650 | struct ubifs_scan_node *snod; |
| 545 | 651 | ||
| @@ -559,6 +665,15 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 559 | if (IS_ERR(sleb)) | 665 | if (IS_ERR(sleb)) |
| 560 | return PTR_ERR(sleb); | 666 | return PTR_ERR(sleb); |
| 561 | 667 | ||
| 668 | n_nodes = authenticate_sleb(c, sleb, b->bud->log_hash, is_last); | ||
| 669 | if (n_nodes < 0) { | ||
| 670 | err = n_nodes; | ||
| 671 | goto out; | ||
| 672 | } | ||
| 673 | |||
| 674 | ubifs_shash_copy_state(c, b->bud->log_hash, | ||
| 675 | c->jheads[b->bud->jhead].log_hash); | ||
| 676 | |||
| 562 | /* | 677 | /* |
| 563 | * The bud does not have to start from offset zero - the beginning of | 678 | * The bud does not have to start from offset zero - the beginning of |
| 564 | * the 'lnum' LEB may contain previously committed data. One of the | 679 | * the 'lnum' LEB may contain previously committed data. One of the |
| @@ -582,6 +697,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 582 | */ | 697 | */ |
| 583 | 698 | ||
| 584 | list_for_each_entry(snod, &sleb->nodes, list) { | 699 | list_for_each_entry(snod, &sleb->nodes, list) { |
| 700 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 585 | int deletion = 0; | 701 | int deletion = 0; |
| 586 | 702 | ||
| 587 | cond_resched(); | 703 | cond_resched(); |
| @@ -591,6 +707,8 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 591 | goto out_dump; | 707 | goto out_dump; |
| 592 | } | 708 | } |
| 593 | 709 | ||
| 710 | ubifs_node_calc_hash(c, snod->node, hash); | ||
| 711 | |||
| 594 | if (snod->sqnum > c->max_sqnum) | 712 | if (snod->sqnum > c->max_sqnum) |
| 595 | c->max_sqnum = snod->sqnum; | 713 | c->max_sqnum = snod->sqnum; |
| 596 | 714 | ||
| @@ -602,7 +720,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 602 | 720 | ||
| 603 | if (le32_to_cpu(ino->nlink) == 0) | 721 | if (le32_to_cpu(ino->nlink) == 0) |
| 604 | deletion = 1; | 722 | deletion = 1; |
| 605 | err = insert_node(c, lnum, snod->offs, snod->len, | 723 | err = insert_node(c, lnum, snod->offs, snod->len, hash, |
| 606 | &snod->key, snod->sqnum, deletion, | 724 | &snod->key, snod->sqnum, deletion, |
| 607 | &used, 0, new_size); | 725 | &used, 0, new_size); |
| 608 | break; | 726 | break; |
| @@ -614,7 +732,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 614 | key_block(c, &snod->key) * | 732 | key_block(c, &snod->key) * |
| 615 | UBIFS_BLOCK_SIZE; | 733 | UBIFS_BLOCK_SIZE; |
| 616 | 734 | ||
| 617 | err = insert_node(c, lnum, snod->offs, snod->len, | 735 | err = insert_node(c, lnum, snod->offs, snod->len, hash, |
| 618 | &snod->key, snod->sqnum, deletion, | 736 | &snod->key, snod->sqnum, deletion, |
| 619 | &used, 0, new_size); | 737 | &used, 0, new_size); |
| 620 | break; | 738 | break; |
| @@ -628,7 +746,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 628 | if (err) | 746 | if (err) |
| 629 | goto out_dump; | 747 | goto out_dump; |
| 630 | 748 | ||
| 631 | err = insert_dent(c, lnum, snod->offs, snod->len, | 749 | err = insert_dent(c, lnum, snod->offs, snod->len, hash, |
| 632 | &snod->key, dent->name, | 750 | &snod->key, dent->name, |
| 633 | le16_to_cpu(dent->nlen), snod->sqnum, | 751 | le16_to_cpu(dent->nlen), snod->sqnum, |
| 634 | !le64_to_cpu(dent->inum), &used); | 752 | !le64_to_cpu(dent->inum), &used); |
| @@ -654,11 +772,13 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 654 | * functions which expect nodes to have keys. | 772 | * functions which expect nodes to have keys. |
| 655 | */ | 773 | */ |
| 656 | trun_key_init(c, &key, le32_to_cpu(trun->inum)); | 774 | trun_key_init(c, &key, le32_to_cpu(trun->inum)); |
| 657 | err = insert_node(c, lnum, snod->offs, snod->len, | 775 | err = insert_node(c, lnum, snod->offs, snod->len, hash, |
| 658 | &key, snod->sqnum, 1, &used, | 776 | &key, snod->sqnum, 1, &used, |
| 659 | old_size, new_size); | 777 | old_size, new_size); |
| 660 | break; | 778 | break; |
| 661 | } | 779 | } |
| 780 | case UBIFS_AUTH_NODE: | ||
| 781 | break; | ||
| 662 | default: | 782 | default: |
| 663 | ubifs_err(c, "unexpected node type %d in bud LEB %d:%d", | 783 | ubifs_err(c, "unexpected node type %d in bud LEB %d:%d", |
| 664 | snod->type, lnum, snod->offs); | 784 | snod->type, lnum, snod->offs); |
| @@ -667,6 +787,10 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) | |||
| 667 | } | 787 | } |
| 668 | if (err) | 788 | if (err) |
| 669 | goto out; | 789 | goto out; |
| 790 | |||
| 791 | n++; | ||
| 792 | if (n == n_nodes) | ||
| 793 | break; | ||
| 670 | } | 794 | } |
| 671 | 795 | ||
| 672 | ubifs_assert(c, ubifs_search_bud(c, lnum)); | 796 | ubifs_assert(c, ubifs_search_bud(c, lnum)); |
| @@ -745,6 +869,7 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, | |||
| 745 | { | 869 | { |
| 746 | struct ubifs_bud *bud; | 870 | struct ubifs_bud *bud; |
| 747 | struct bud_entry *b; | 871 | struct bud_entry *b; |
| 872 | int err; | ||
| 748 | 873 | ||
| 749 | dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead); | 874 | dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead); |
| 750 | 875 | ||
| @@ -754,13 +879,21 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, | |||
| 754 | 879 | ||
| 755 | b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL); | 880 | b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL); |
| 756 | if (!b) { | 881 | if (!b) { |
| 757 | kfree(bud); | 882 | err = -ENOMEM; |
| 758 | return -ENOMEM; | 883 | goto out; |
| 759 | } | 884 | } |
| 760 | 885 | ||
| 761 | bud->lnum = lnum; | 886 | bud->lnum = lnum; |
| 762 | bud->start = offs; | 887 | bud->start = offs; |
| 763 | bud->jhead = jhead; | 888 | bud->jhead = jhead; |
| 889 | bud->log_hash = ubifs_hash_get_desc(c); | ||
| 890 | if (IS_ERR(bud->log_hash)) { | ||
| 891 | err = PTR_ERR(bud->log_hash); | ||
| 892 | goto out; | ||
| 893 | } | ||
| 894 | |||
| 895 | ubifs_shash_copy_state(c, c->log_hash, bud->log_hash); | ||
| 896 | |||
| 764 | ubifs_add_bud(c, bud); | 897 | ubifs_add_bud(c, bud); |
| 765 | 898 | ||
| 766 | b->bud = bud; | 899 | b->bud = bud; |
| @@ -768,6 +901,11 @@ static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, | |||
| 768 | list_add_tail(&b->list, &c->replay_buds); | 901 | list_add_tail(&b->list, &c->replay_buds); |
| 769 | 902 | ||
| 770 | return 0; | 903 | return 0; |
| 904 | out: | ||
| 905 | kfree(bud); | ||
| 906 | kfree(b); | ||
| 907 | |||
| 908 | return err; | ||
| 771 | } | 909 | } |
| 772 | 910 | ||
| 773 | /** | 911 | /** |
| @@ -873,6 +1011,14 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) | |||
| 873 | 1011 | ||
| 874 | c->cs_sqnum = le64_to_cpu(node->ch.sqnum); | 1012 | c->cs_sqnum = le64_to_cpu(node->ch.sqnum); |
| 875 | dbg_mnt("commit start sqnum %llu", c->cs_sqnum); | 1013 | dbg_mnt("commit start sqnum %llu", c->cs_sqnum); |
| 1014 | |||
| 1015 | err = ubifs_shash_init(c, c->log_hash); | ||
| 1016 | if (err) | ||
| 1017 | goto out; | ||
| 1018 | |||
| 1019 | err = ubifs_shash_update(c, c->log_hash, node, UBIFS_CS_NODE_SZ); | ||
| 1020 | if (err < 0) | ||
| 1021 | goto out; | ||
| 876 | } | 1022 | } |
| 877 | 1023 | ||
| 878 | if (snod->sqnum < c->cs_sqnum) { | 1024 | if (snod->sqnum < c->cs_sqnum) { |
| @@ -920,6 +1066,11 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) | |||
| 920 | if (err) | 1066 | if (err) |
| 921 | goto out_dump; | 1067 | goto out_dump; |
| 922 | 1068 | ||
| 1069 | err = ubifs_shash_update(c, c->log_hash, ref, | ||
| 1070 | UBIFS_REF_NODE_SZ); | ||
| 1071 | if (err) | ||
| 1072 | goto out; | ||
| 1073 | |||
| 923 | err = add_replay_bud(c, le32_to_cpu(ref->lnum), | 1074 | err = add_replay_bud(c, le32_to_cpu(ref->lnum), |
| 924 | le32_to_cpu(ref->offs), | 1075 | le32_to_cpu(ref->offs), |
| 925 | le32_to_cpu(ref->jhead), | 1076 | le32_to_cpu(ref->jhead), |
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index bf17f58908ff..75a69dd26d6e 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c | |||
| @@ -82,10 +82,13 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 82 | int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first; | 82 | int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first; |
| 83 | int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0; | 83 | int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0; |
| 84 | int min_leb_cnt = UBIFS_MIN_LEB_CNT; | 84 | int min_leb_cnt = UBIFS_MIN_LEB_CNT; |
| 85 | int idx_node_size; | ||
| 85 | long long tmp64, main_bytes; | 86 | long long tmp64, main_bytes; |
| 86 | __le64 tmp_le64; | 87 | __le64 tmp_le64; |
| 87 | __le32 tmp_le32; | 88 | __le32 tmp_le32; |
| 88 | struct timespec64 ts; | 89 | struct timespec64 ts; |
| 90 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 91 | u8 hash_lpt[UBIFS_HASH_ARR_SZ]; | ||
| 89 | 92 | ||
| 90 | /* Some functions called from here depend on the @c->key_len filed */ | 93 | /* Some functions called from here depend on the @c->key_len filed */ |
| 91 | c->key_len = UBIFS_SK_LEN; | 94 | c->key_len = UBIFS_SK_LEN; |
| @@ -147,7 +150,7 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 147 | c->lsave_cnt = DEFAULT_LSAVE_CNT; | 150 | c->lsave_cnt = DEFAULT_LSAVE_CNT; |
| 148 | c->max_leb_cnt = c->leb_cnt; | 151 | c->max_leb_cnt = c->leb_cnt; |
| 149 | err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs, | 152 | err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs, |
| 150 | &big_lpt); | 153 | &big_lpt, hash_lpt); |
| 151 | if (err) | 154 | if (err) |
| 152 | return err; | 155 | return err; |
| 153 | 156 | ||
| @@ -156,17 +159,35 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 156 | 159 | ||
| 157 | main_first = c->leb_cnt - main_lebs; | 160 | main_first = c->leb_cnt - main_lebs; |
| 158 | 161 | ||
| 162 | sup = kzalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_KERNEL); | ||
| 163 | mst = kzalloc(c->mst_node_alsz, GFP_KERNEL); | ||
| 164 | idx_node_size = ubifs_idx_node_sz(c, 1); | ||
| 165 | idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL); | ||
| 166 | ino = kzalloc(ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size), GFP_KERNEL); | ||
| 167 | cs = kzalloc(ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size), GFP_KERNEL); | ||
| 168 | |||
| 169 | if (!sup || !mst || !idx || !ino || !cs) { | ||
| 170 | err = -ENOMEM; | ||
| 171 | goto out; | ||
| 172 | } | ||
| 173 | |||
| 159 | /* Create default superblock */ | 174 | /* Create default superblock */ |
| 160 | tmp = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); | ||
| 161 | sup = kzalloc(tmp, GFP_KERNEL); | ||
| 162 | if (!sup) | ||
| 163 | return -ENOMEM; | ||
| 164 | 175 | ||
| 165 | tmp64 = (long long)max_buds * c->leb_size; | 176 | tmp64 = (long long)max_buds * c->leb_size; |
| 166 | if (big_lpt) | 177 | if (big_lpt) |
| 167 | sup_flags |= UBIFS_FLG_BIGLPT; | 178 | sup_flags |= UBIFS_FLG_BIGLPT; |
| 168 | sup_flags |= UBIFS_FLG_DOUBLE_HASH; | 179 | sup_flags |= UBIFS_FLG_DOUBLE_HASH; |
| 169 | 180 | ||
| 181 | if (ubifs_authenticated(c)) { | ||
| 182 | sup_flags |= UBIFS_FLG_AUTHENTICATION; | ||
| 183 | sup->hash_algo = cpu_to_le16(c->auth_hash_algo); | ||
| 184 | err = ubifs_hmac_wkm(c, sup->hmac_wkm); | ||
| 185 | if (err) | ||
| 186 | goto out; | ||
| 187 | } else { | ||
| 188 | sup->hash_algo = 0xffff; | ||
| 189 | } | ||
| 190 | |||
| 170 | sup->ch.node_type = UBIFS_SB_NODE; | 191 | sup->ch.node_type = UBIFS_SB_NODE; |
| 171 | sup->key_hash = UBIFS_KEY_HASH_R5; | 192 | sup->key_hash = UBIFS_KEY_HASH_R5; |
| 172 | sup->flags = cpu_to_le32(sup_flags); | 193 | sup->flags = cpu_to_le32(sup_flags); |
| @@ -197,17 +218,9 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 197 | sup->rp_size = cpu_to_le64(tmp64); | 218 | sup->rp_size = cpu_to_le64(tmp64); |
| 198 | sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION); | 219 | sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION); |
| 199 | 220 | ||
| 200 | err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0); | ||
| 201 | kfree(sup); | ||
| 202 | if (err) | ||
| 203 | return err; | ||
| 204 | |||
| 205 | dbg_gen("default superblock created at LEB 0:0"); | 221 | dbg_gen("default superblock created at LEB 0:0"); |
| 206 | 222 | ||
| 207 | /* Create default master node */ | 223 | /* Create default master node */ |
| 208 | mst = kzalloc(c->mst_node_alsz, GFP_KERNEL); | ||
| 209 | if (!mst) | ||
| 210 | return -ENOMEM; | ||
| 211 | 224 | ||
| 212 | mst->ch.node_type = UBIFS_MST_NODE; | 225 | mst->ch.node_type = UBIFS_MST_NODE; |
| 213 | mst->log_lnum = cpu_to_le32(UBIFS_LOG_LNUM); | 226 | mst->log_lnum = cpu_to_le32(UBIFS_LOG_LNUM); |
| @@ -233,6 +246,7 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 233 | mst->empty_lebs = cpu_to_le32(main_lebs - 2); | 246 | mst->empty_lebs = cpu_to_le32(main_lebs - 2); |
| 234 | mst->idx_lebs = cpu_to_le32(1); | 247 | mst->idx_lebs = cpu_to_le32(1); |
| 235 | mst->leb_cnt = cpu_to_le32(c->leb_cnt); | 248 | mst->leb_cnt = cpu_to_le32(c->leb_cnt); |
| 249 | ubifs_copy_hash(c, hash_lpt, mst->hash_lpt); | ||
| 236 | 250 | ||
| 237 | /* Calculate lprops statistics */ | 251 | /* Calculate lprops statistics */ |
| 238 | tmp64 = main_bytes; | 252 | tmp64 = main_bytes; |
| @@ -253,24 +267,9 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 253 | 267 | ||
| 254 | mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); | 268 | mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); |
| 255 | 269 | ||
| 256 | err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0); | ||
| 257 | if (err) { | ||
| 258 | kfree(mst); | ||
| 259 | return err; | ||
| 260 | } | ||
| 261 | err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, | ||
| 262 | 0); | ||
| 263 | kfree(mst); | ||
| 264 | if (err) | ||
| 265 | return err; | ||
| 266 | |||
| 267 | dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM); | 270 | dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM); |
| 268 | 271 | ||
| 269 | /* Create the root indexing node */ | 272 | /* Create the root indexing node */ |
| 270 | tmp = ubifs_idx_node_sz(c, 1); | ||
| 271 | idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL); | ||
| 272 | if (!idx) | ||
| 273 | return -ENOMEM; | ||
| 274 | 273 | ||
| 275 | c->key_fmt = UBIFS_SIMPLE_KEY_FMT; | 274 | c->key_fmt = UBIFS_SIMPLE_KEY_FMT; |
| 276 | c->key_hash = key_r5_hash; | 275 | c->key_hash = key_r5_hash; |
| @@ -282,19 +281,11 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 282 | key_write_idx(c, &key, &br->key); | 281 | key_write_idx(c, &key, &br->key); |
| 283 | br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB); | 282 | br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB); |
| 284 | br->len = cpu_to_le32(UBIFS_INO_NODE_SZ); | 283 | br->len = cpu_to_le32(UBIFS_INO_NODE_SZ); |
| 285 | err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0); | ||
| 286 | kfree(idx); | ||
| 287 | if (err) | ||
| 288 | return err; | ||
| 289 | 284 | ||
| 290 | dbg_gen("default root indexing node created LEB %d:0", | 285 | dbg_gen("default root indexing node created LEB %d:0", |
| 291 | main_first + DEFAULT_IDX_LEB); | 286 | main_first + DEFAULT_IDX_LEB); |
| 292 | 287 | ||
| 293 | /* Create default root inode */ | 288 | /* Create default root inode */ |
| 294 | tmp = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size); | ||
| 295 | ino = kzalloc(tmp, GFP_KERNEL); | ||
| 296 | if (!ino) | ||
| 297 | return -ENOMEM; | ||
| 298 | 289 | ||
| 299 | ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO); | 290 | ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO); |
| 300 | ino->ch.node_type = UBIFS_INO_NODE; | 291 | ino->ch.node_type = UBIFS_INO_NODE; |
| @@ -317,12 +308,6 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 317 | /* Set compression enabled by default */ | 308 | /* Set compression enabled by default */ |
| 318 | ino->flags = cpu_to_le32(UBIFS_COMPR_FL); | 309 | ino->flags = cpu_to_le32(UBIFS_COMPR_FL); |
| 319 | 310 | ||
| 320 | err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ, | ||
| 321 | main_first + DEFAULT_DATA_LEB, 0); | ||
| 322 | kfree(ino); | ||
| 323 | if (err) | ||
| 324 | return err; | ||
| 325 | |||
| 326 | dbg_gen("root inode created at LEB %d:0", | 311 | dbg_gen("root inode created at LEB %d:0", |
| 327 | main_first + DEFAULT_DATA_LEB); | 312 | main_first + DEFAULT_DATA_LEB); |
| 328 | 313 | ||
| @@ -331,19 +316,54 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
| 331 | * always the case during normal file-system operation. Write a fake | 316 | * always the case during normal file-system operation. Write a fake |
| 332 | * commit start node to the log. | 317 | * commit start node to the log. |
| 333 | */ | 318 | */ |
| 334 | tmp = ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size); | ||
| 335 | cs = kzalloc(tmp, GFP_KERNEL); | ||
| 336 | if (!cs) | ||
| 337 | return -ENOMEM; | ||
| 338 | 319 | ||
| 339 | cs->ch.node_type = UBIFS_CS_NODE; | 320 | cs->ch.node_type = UBIFS_CS_NODE; |
| 321 | |||
| 322 | err = ubifs_write_node_hmac(c, sup, UBIFS_SB_NODE_SZ, 0, 0, | ||
| 323 | offsetof(struct ubifs_sb_node, hmac)); | ||
| 324 | if (err) | ||
| 325 | goto out; | ||
| 326 | |||
| 327 | err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ, | ||
| 328 | main_first + DEFAULT_DATA_LEB, 0); | ||
| 329 | if (err) | ||
| 330 | goto out; | ||
| 331 | |||
| 332 | ubifs_node_calc_hash(c, ino, hash); | ||
| 333 | ubifs_copy_hash(c, hash, ubifs_branch_hash(c, br)); | ||
| 334 | |||
| 335 | err = ubifs_write_node(c, idx, idx_node_size, main_first + DEFAULT_IDX_LEB, 0); | ||
| 336 | if (err) | ||
| 337 | goto out; | ||
| 338 | |||
| 339 | ubifs_node_calc_hash(c, idx, hash); | ||
| 340 | ubifs_copy_hash(c, hash, mst->hash_root_idx); | ||
| 341 | |||
| 342 | err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0, | ||
| 343 | offsetof(struct ubifs_mst_node, hmac)); | ||
| 344 | if (err) | ||
| 345 | goto out; | ||
| 346 | |||
| 347 | err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, | ||
| 348 | 0, offsetof(struct ubifs_mst_node, hmac)); | ||
| 349 | if (err) | ||
| 350 | goto out; | ||
| 351 | |||
| 340 | err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0); | 352 | err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0); |
| 341 | kfree(cs); | ||
| 342 | if (err) | 353 | if (err) |
| 343 | return err; | 354 | goto out; |
| 344 | 355 | ||
| 345 | ubifs_msg(c, "default file-system created"); | 356 | ubifs_msg(c, "default file-system created"); |
| 346 | return 0; | 357 | |
| 358 | err = 0; | ||
| 359 | out: | ||
| 360 | kfree(sup); | ||
| 361 | kfree(mst); | ||
| 362 | kfree(idx); | ||
| 363 | kfree(ino); | ||
| 364 | kfree(cs); | ||
| 365 | |||
| 366 | return err; | ||
| 347 | } | 367 | } |
| 348 | 368 | ||
| 349 | /** | 369 | /** |
| @@ -498,7 +518,7 @@ failed: | |||
| 498 | * code. Note, the user of this function is responsible of kfree()'ing the | 518 | * code. Note, the user of this function is responsible of kfree()'ing the |
| 499 | * returned superblock buffer. | 519 | * returned superblock buffer. |
| 500 | */ | 520 | */ |
| 501 | struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) | 521 | static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) |
| 502 | { | 522 | { |
| 503 | struct ubifs_sb_node *sup; | 523 | struct ubifs_sb_node *sup; |
| 504 | int err; | 524 | int err; |
| @@ -517,6 +537,65 @@ struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) | |||
| 517 | return sup; | 537 | return sup; |
| 518 | } | 538 | } |
| 519 | 539 | ||
| 540 | static int authenticate_sb_node(struct ubifs_info *c, | ||
| 541 | const struct ubifs_sb_node *sup) | ||
| 542 | { | ||
| 543 | unsigned int sup_flags = le32_to_cpu(sup->flags); | ||
| 544 | u8 hmac_wkm[UBIFS_HMAC_ARR_SZ]; | ||
| 545 | int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION); | ||
| 546 | int hash_algo; | ||
| 547 | int err; | ||
| 548 | |||
| 549 | if (c->authenticated && !authenticated) { | ||
| 550 | ubifs_err(c, "authenticated FS forced, but found FS without authentication"); | ||
| 551 | return -EINVAL; | ||
| 552 | } | ||
| 553 | |||
| 554 | if (!c->authenticated && authenticated) { | ||
| 555 | ubifs_err(c, "authenticated FS found, but no key given"); | ||
| 556 | return -EINVAL; | ||
| 557 | } | ||
| 558 | |||
| 559 | ubifs_msg(c, "Mounting in %sauthenticated mode", | ||
| 560 | c->authenticated ? "" : "un"); | ||
| 561 | |||
| 562 | if (!c->authenticated) | ||
| 563 | return 0; | ||
| 564 | |||
| 565 | if (!IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) | ||
| 566 | return -EOPNOTSUPP; | ||
| 567 | |||
| 568 | hash_algo = le16_to_cpu(sup->hash_algo); | ||
| 569 | if (hash_algo >= HASH_ALGO__LAST) { | ||
| 570 | ubifs_err(c, "superblock uses unknown hash algo %d", | ||
| 571 | hash_algo); | ||
| 572 | return -EINVAL; | ||
| 573 | } | ||
| 574 | |||
| 575 | if (strcmp(hash_algo_name[hash_algo], c->auth_hash_name)) { | ||
| 576 | ubifs_err(c, "This filesystem uses %s for hashing," | ||
| 577 | " but %s is specified", hash_algo_name[hash_algo], | ||
| 578 | c->auth_hash_name); | ||
| 579 | return -EINVAL; | ||
| 580 | } | ||
| 581 | |||
| 582 | err = ubifs_hmac_wkm(c, hmac_wkm); | ||
| 583 | if (err) | ||
| 584 | return err; | ||
| 585 | |||
| 586 | if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) { | ||
| 587 | ubifs_err(c, "provided key does not fit"); | ||
| 588 | return -ENOKEY; | ||
| 589 | } | ||
| 590 | |||
| 591 | err = ubifs_node_verify_hmac(c, sup, sizeof(*sup), | ||
| 592 | offsetof(struct ubifs_sb_node, hmac)); | ||
| 593 | if (err) | ||
| 594 | ubifs_err(c, "Failed to authenticate superblock: %d", err); | ||
| 595 | |||
| 596 | return err; | ||
| 597 | } | ||
| 598 | |||
| 520 | /** | 599 | /** |
| 521 | * ubifs_write_sb_node - write superblock node. | 600 | * ubifs_write_sb_node - write superblock node. |
| 522 | * @c: UBIFS file-system description object | 601 | * @c: UBIFS file-system description object |
| @@ -527,8 +606,13 @@ struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) | |||
| 527 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) | 606 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) |
| 528 | { | 607 | { |
| 529 | int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); | 608 | int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); |
| 609 | int err; | ||
| 610 | |||
| 611 | err = ubifs_prepare_node_hmac(c, sup, UBIFS_SB_NODE_SZ, | ||
| 612 | offsetof(struct ubifs_sb_node, hmac), 1); | ||
| 613 | if (err) | ||
| 614 | return err; | ||
| 530 | 615 | ||
| 531 | ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1); | ||
| 532 | return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len); | 616 | return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len); |
| 533 | } | 617 | } |
| 534 | 618 | ||
| @@ -555,6 +639,8 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 555 | if (IS_ERR(sup)) | 639 | if (IS_ERR(sup)) |
| 556 | return PTR_ERR(sup); | 640 | return PTR_ERR(sup); |
| 557 | 641 | ||
| 642 | c->sup_node = sup; | ||
| 643 | |||
| 558 | c->fmt_version = le32_to_cpu(sup->fmt_version); | 644 | c->fmt_version = le32_to_cpu(sup->fmt_version); |
| 559 | c->ro_compat_version = le32_to_cpu(sup->ro_compat_version); | 645 | c->ro_compat_version = le32_to_cpu(sup->ro_compat_version); |
| 560 | 646 | ||
| @@ -603,7 +689,7 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 603 | c->key_hash = key_test_hash; | 689 | c->key_hash = key_test_hash; |
| 604 | c->key_hash_type = UBIFS_KEY_HASH_TEST; | 690 | c->key_hash_type = UBIFS_KEY_HASH_TEST; |
| 605 | break; | 691 | break; |
| 606 | }; | 692 | } |
| 607 | 693 | ||
| 608 | c->key_fmt = sup->key_fmt; | 694 | c->key_fmt = sup->key_fmt; |
| 609 | 695 | ||
| @@ -640,6 +726,10 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 640 | c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH); | 726 | c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH); |
| 641 | c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION); | 727 | c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION); |
| 642 | 728 | ||
| 729 | err = authenticate_sb_node(c, sup); | ||
| 730 | if (err) | ||
| 731 | goto out; | ||
| 732 | |||
| 643 | if ((sup_flags & ~UBIFS_FLG_MASK) != 0) { | 733 | if ((sup_flags & ~UBIFS_FLG_MASK) != 0) { |
| 644 | ubifs_err(c, "Unknown feature flags found: %#x", | 734 | ubifs_err(c, "Unknown feature flags found: %#x", |
| 645 | sup_flags & ~UBIFS_FLG_MASK); | 735 | sup_flags & ~UBIFS_FLG_MASK); |
| @@ -686,7 +776,6 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 686 | 776 | ||
| 687 | err = validate_sb(c, sup); | 777 | err = validate_sb(c, sup); |
| 688 | out: | 778 | out: |
| 689 | kfree(sup); | ||
| 690 | return err; | 779 | return err; |
| 691 | } | 780 | } |
| 692 | 781 | ||
| @@ -815,7 +904,7 @@ out: | |||
| 815 | int ubifs_fixup_free_space(struct ubifs_info *c) | 904 | int ubifs_fixup_free_space(struct ubifs_info *c) |
| 816 | { | 905 | { |
| 817 | int err; | 906 | int err; |
| 818 | struct ubifs_sb_node *sup; | 907 | struct ubifs_sb_node *sup = c->sup_node; |
| 819 | 908 | ||
| 820 | ubifs_assert(c, c->space_fixup); | 909 | ubifs_assert(c, c->space_fixup); |
| 821 | ubifs_assert(c, !c->ro_mount); | 910 | ubifs_assert(c, !c->ro_mount); |
| @@ -826,16 +915,11 @@ int ubifs_fixup_free_space(struct ubifs_info *c) | |||
| 826 | if (err) | 915 | if (err) |
| 827 | return err; | 916 | return err; |
| 828 | 917 | ||
| 829 | sup = ubifs_read_sb_node(c); | ||
| 830 | if (IS_ERR(sup)) | ||
| 831 | return PTR_ERR(sup); | ||
| 832 | |||
| 833 | /* Free-space fixup is no longer required */ | 918 | /* Free-space fixup is no longer required */ |
| 834 | c->space_fixup = 0; | 919 | c->space_fixup = 0; |
| 835 | sup->flags &= cpu_to_le32(~UBIFS_FLG_SPACE_FIXUP); | 920 | sup->flags &= cpu_to_le32(~UBIFS_FLG_SPACE_FIXUP); |
| 836 | 921 | ||
| 837 | err = ubifs_write_sb_node(c, sup); | 922 | err = ubifs_write_sb_node(c, sup); |
| 838 | kfree(sup); | ||
| 839 | if (err) | 923 | if (err) |
| 840 | return err; | 924 | return err; |
| 841 | 925 | ||
| @@ -846,7 +930,7 @@ int ubifs_fixup_free_space(struct ubifs_info *c) | |||
| 846 | int ubifs_enable_encryption(struct ubifs_info *c) | 930 | int ubifs_enable_encryption(struct ubifs_info *c) |
| 847 | { | 931 | { |
| 848 | int err; | 932 | int err; |
| 849 | struct ubifs_sb_node *sup; | 933 | struct ubifs_sb_node *sup = c->sup_node; |
| 850 | 934 | ||
| 851 | if (c->encrypted) | 935 | if (c->encrypted) |
| 852 | return 0; | 936 | return 0; |
| @@ -859,16 +943,11 @@ int ubifs_enable_encryption(struct ubifs_info *c) | |||
| 859 | return -EINVAL; | 943 | return -EINVAL; |
| 860 | } | 944 | } |
| 861 | 945 | ||
| 862 | sup = ubifs_read_sb_node(c); | ||
| 863 | if (IS_ERR(sup)) | ||
| 864 | return PTR_ERR(sup); | ||
| 865 | |||
| 866 | sup->flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION); | 946 | sup->flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION); |
| 867 | 947 | ||
| 868 | err = ubifs_write_sb_node(c, sup); | 948 | err = ubifs_write_sb_node(c, sup); |
| 869 | if (!err) | 949 | if (!err) |
| 870 | c->encrypted = 1; | 950 | c->encrypted = 1; |
| 871 | kfree(sup); | ||
| 872 | 951 | ||
| 873 | return err; | 952 | return err; |
| 874 | } | 953 | } |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index fec62e9dfbe6..1fac1133dadd 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -579,6 +579,9 @@ static int init_constants_early(struct ubifs_info *c) | |||
| 579 | c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; | 579 | c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; |
| 580 | c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; | 580 | c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; |
| 581 | c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; | 581 | c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; |
| 582 | c->ranges[UBIFS_AUTH_NODE].min_len = UBIFS_AUTH_NODE_SZ; | ||
| 583 | c->ranges[UBIFS_AUTH_NODE].max_len = UBIFS_AUTH_NODE_SZ + | ||
| 584 | UBIFS_MAX_HMAC_LEN; | ||
| 582 | 585 | ||
| 583 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; | 586 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; |
| 584 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; | 587 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; |
| @@ -816,6 +819,9 @@ static int alloc_wbufs(struct ubifs_info *c) | |||
| 816 | c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback; | 819 | c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback; |
| 817 | c->jheads[i].wbuf.jhead = i; | 820 | c->jheads[i].wbuf.jhead = i; |
| 818 | c->jheads[i].grouped = 1; | 821 | c->jheads[i].grouped = 1; |
| 822 | c->jheads[i].log_hash = ubifs_hash_get_desc(c); | ||
| 823 | if (IS_ERR(c->jheads[i].log_hash)) | ||
| 824 | goto out; | ||
| 819 | } | 825 | } |
| 820 | 826 | ||
| 821 | /* | 827 | /* |
| @@ -826,6 +832,12 @@ static int alloc_wbufs(struct ubifs_info *c) | |||
| 826 | c->jheads[GCHD].grouped = 0; | 832 | c->jheads[GCHD].grouped = 0; |
| 827 | 833 | ||
| 828 | return 0; | 834 | return 0; |
| 835 | |||
| 836 | out: | ||
| 837 | while (i--) | ||
| 838 | kfree(c->jheads[i].log_hash); | ||
| 839 | |||
| 840 | return err; | ||
| 829 | } | 841 | } |
| 830 | 842 | ||
| 831 | /** | 843 | /** |
| @@ -840,6 +852,7 @@ static void free_wbufs(struct ubifs_info *c) | |||
| 840 | for (i = 0; i < c->jhead_cnt; i++) { | 852 | for (i = 0; i < c->jhead_cnt; i++) { |
| 841 | kfree(c->jheads[i].wbuf.buf); | 853 | kfree(c->jheads[i].wbuf.buf); |
| 842 | kfree(c->jheads[i].wbuf.inodes); | 854 | kfree(c->jheads[i].wbuf.inodes); |
| 855 | kfree(c->jheads[i].log_hash); | ||
| 843 | } | 856 | } |
| 844 | kfree(c->jheads); | 857 | kfree(c->jheads); |
| 845 | c->jheads = NULL; | 858 | c->jheads = NULL; |
| @@ -924,6 +937,8 @@ static int check_volume_empty(struct ubifs_info *c) | |||
| 924 | * Opt_no_chk_data_crc: do not check CRCs when reading data nodes | 937 | * Opt_no_chk_data_crc: do not check CRCs when reading data nodes |
| 925 | * Opt_override_compr: override default compressor | 938 | * Opt_override_compr: override default compressor |
| 926 | * Opt_assert: set ubifs_assert() action | 939 | * Opt_assert: set ubifs_assert() action |
| 940 | * Opt_auth_key: The key name used for authentication | ||
| 941 | * Opt_auth_hash_name: The hash type used for authentication | ||
| 927 | * Opt_err: just end of array marker | 942 | * Opt_err: just end of array marker |
| 928 | */ | 943 | */ |
| 929 | enum { | 944 | enum { |
| @@ -935,6 +950,8 @@ enum { | |||
| 935 | Opt_no_chk_data_crc, | 950 | Opt_no_chk_data_crc, |
| 936 | Opt_override_compr, | 951 | Opt_override_compr, |
| 937 | Opt_assert, | 952 | Opt_assert, |
| 953 | Opt_auth_key, | ||
| 954 | Opt_auth_hash_name, | ||
| 938 | Opt_ignore, | 955 | Opt_ignore, |
| 939 | Opt_err, | 956 | Opt_err, |
| 940 | }; | 957 | }; |
| @@ -947,6 +964,8 @@ static const match_table_t tokens = { | |||
| 947 | {Opt_chk_data_crc, "chk_data_crc"}, | 964 | {Opt_chk_data_crc, "chk_data_crc"}, |
| 948 | {Opt_no_chk_data_crc, "no_chk_data_crc"}, | 965 | {Opt_no_chk_data_crc, "no_chk_data_crc"}, |
| 949 | {Opt_override_compr, "compr=%s"}, | 966 | {Opt_override_compr, "compr=%s"}, |
| 967 | {Opt_auth_key, "auth_key=%s"}, | ||
| 968 | {Opt_auth_hash_name, "auth_hash_name=%s"}, | ||
| 950 | {Opt_ignore, "ubi=%s"}, | 969 | {Opt_ignore, "ubi=%s"}, |
| 951 | {Opt_ignore, "vol=%s"}, | 970 | {Opt_ignore, "vol=%s"}, |
| 952 | {Opt_assert, "assert=%s"}, | 971 | {Opt_assert, "assert=%s"}, |
| @@ -1070,6 +1089,16 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
| 1070 | kfree(act); | 1089 | kfree(act); |
| 1071 | break; | 1090 | break; |
| 1072 | } | 1091 | } |
| 1092 | case Opt_auth_key: | ||
| 1093 | c->auth_key_name = kstrdup(args[0].from, GFP_KERNEL); | ||
| 1094 | if (!c->auth_key_name) | ||
| 1095 | return -ENOMEM; | ||
| 1096 | break; | ||
| 1097 | case Opt_auth_hash_name: | ||
| 1098 | c->auth_hash_name = kstrdup(args[0].from, GFP_KERNEL); | ||
| 1099 | if (!c->auth_hash_name) | ||
| 1100 | return -ENOMEM; | ||
| 1101 | break; | ||
| 1073 | case Opt_ignore: | 1102 | case Opt_ignore: |
| 1074 | break; | 1103 | break; |
| 1075 | default: | 1104 | default: |
| @@ -1249,6 +1278,19 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1249 | 1278 | ||
| 1250 | c->mounting = 1; | 1279 | c->mounting = 1; |
| 1251 | 1280 | ||
| 1281 | if (c->auth_key_name) { | ||
| 1282 | if (IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) { | ||
| 1283 | err = ubifs_init_authentication(c); | ||
| 1284 | if (err) | ||
| 1285 | goto out_free; | ||
| 1286 | } else { | ||
| 1287 | ubifs_err(c, "auth_key_name, but UBIFS is built without" | ||
| 1288 | " authentication support"); | ||
| 1289 | err = -EINVAL; | ||
| 1290 | goto out_free; | ||
| 1291 | } | ||
| 1292 | } | ||
| 1293 | |||
| 1252 | err = ubifs_read_superblock(c); | 1294 | err = ubifs_read_superblock(c); |
| 1253 | if (err) | 1295 | if (err) |
| 1254 | goto out_free; | 1296 | goto out_free; |
| @@ -1367,12 +1409,21 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1367 | } | 1409 | } |
| 1368 | 1410 | ||
| 1369 | if (c->need_recovery) { | 1411 | if (c->need_recovery) { |
| 1370 | err = ubifs_recover_size(c); | 1412 | if (!ubifs_authenticated(c)) { |
| 1371 | if (err) | 1413 | err = ubifs_recover_size(c, true); |
| 1372 | goto out_orphans; | 1414 | if (err) |
| 1415 | goto out_orphans; | ||
| 1416 | } | ||
| 1417 | |||
| 1373 | err = ubifs_rcvry_gc_commit(c); | 1418 | err = ubifs_rcvry_gc_commit(c); |
| 1374 | if (err) | 1419 | if (err) |
| 1375 | goto out_orphans; | 1420 | goto out_orphans; |
| 1421 | |||
| 1422 | if (ubifs_authenticated(c)) { | ||
| 1423 | err = ubifs_recover_size(c, false); | ||
| 1424 | if (err) | ||
| 1425 | goto out_orphans; | ||
| 1426 | } | ||
| 1376 | } else { | 1427 | } else { |
| 1377 | err = take_gc_lnum(c); | 1428 | err = take_gc_lnum(c); |
| 1378 | if (err) | 1429 | if (err) |
| @@ -1391,7 +1442,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1391 | if (err) | 1442 | if (err) |
| 1392 | goto out_orphans; | 1443 | goto out_orphans; |
| 1393 | } else if (c->need_recovery) { | 1444 | } else if (c->need_recovery) { |
| 1394 | err = ubifs_recover_size(c); | 1445 | err = ubifs_recover_size(c, false); |
| 1395 | if (err) | 1446 | if (err) |
| 1396 | goto out_orphans; | 1447 | goto out_orphans; |
| 1397 | } else { | 1448 | } else { |
| @@ -1557,7 +1608,10 @@ static void ubifs_umount(struct ubifs_info *c) | |||
| 1557 | free_wbufs(c); | 1608 | free_wbufs(c); |
| 1558 | free_orphans(c); | 1609 | free_orphans(c); |
| 1559 | ubifs_lpt_free(c, 0); | 1610 | ubifs_lpt_free(c, 0); |
| 1611 | ubifs_exit_authentication(c); | ||
| 1560 | 1612 | ||
| 1613 | kfree(c->auth_key_name); | ||
| 1614 | kfree(c->auth_hash_name); | ||
| 1561 | kfree(c->cbuf); | 1615 | kfree(c->cbuf); |
| 1562 | kfree(c->rcvrd_mst_node); | 1616 | kfree(c->rcvrd_mst_node); |
| 1563 | kfree(c->mst_node); | 1617 | kfree(c->mst_node); |
| @@ -1605,16 +1659,10 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
| 1605 | goto out; | 1659 | goto out; |
| 1606 | 1660 | ||
| 1607 | if (c->old_leb_cnt != c->leb_cnt) { | 1661 | if (c->old_leb_cnt != c->leb_cnt) { |
| 1608 | struct ubifs_sb_node *sup; | 1662 | struct ubifs_sb_node *sup = c->sup_node; |
| 1609 | 1663 | ||
| 1610 | sup = ubifs_read_sb_node(c); | ||
| 1611 | if (IS_ERR(sup)) { | ||
| 1612 | err = PTR_ERR(sup); | ||
| 1613 | goto out; | ||
| 1614 | } | ||
| 1615 | sup->leb_cnt = cpu_to_le32(c->leb_cnt); | 1664 | sup->leb_cnt = cpu_to_le32(c->leb_cnt); |
| 1616 | err = ubifs_write_sb_node(c, sup); | 1665 | err = ubifs_write_sb_node(c, sup); |
| 1617 | kfree(sup); | ||
| 1618 | if (err) | 1666 | if (err) |
| 1619 | goto out; | 1667 | goto out; |
| 1620 | } | 1668 | } |
| @@ -1624,9 +1672,11 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
| 1624 | err = ubifs_write_rcvrd_mst_node(c); | 1672 | err = ubifs_write_rcvrd_mst_node(c); |
| 1625 | if (err) | 1673 | if (err) |
| 1626 | goto out; | 1674 | goto out; |
| 1627 | err = ubifs_recover_size(c); | 1675 | if (!ubifs_authenticated(c)) { |
| 1628 | if (err) | 1676 | err = ubifs_recover_size(c, true); |
| 1629 | goto out; | 1677 | if (err) |
| 1678 | goto out; | ||
| 1679 | } | ||
| 1630 | err = ubifs_clean_lebs(c, c->sbuf); | 1680 | err = ubifs_clean_lebs(c, c->sbuf); |
| 1631 | if (err) | 1681 | if (err) |
| 1632 | goto out; | 1682 | goto out; |
| @@ -1692,10 +1742,19 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
| 1692 | goto out; | 1742 | goto out; |
| 1693 | } | 1743 | } |
| 1694 | 1744 | ||
| 1695 | if (c->need_recovery) | 1745 | if (c->need_recovery) { |
| 1696 | err = ubifs_rcvry_gc_commit(c); | 1746 | err = ubifs_rcvry_gc_commit(c); |
| 1697 | else | 1747 | if (err) |
| 1748 | goto out; | ||
| 1749 | |||
| 1750 | if (ubifs_authenticated(c)) { | ||
| 1751 | err = ubifs_recover_size(c, false); | ||
| 1752 | if (err) | ||
| 1753 | goto out; | ||
| 1754 | } | ||
| 1755 | } else { | ||
| 1698 | err = ubifs_leb_unmap(c, c->gc_lnum); | 1756 | err = ubifs_leb_unmap(c, c->gc_lnum); |
| 1757 | } | ||
| 1699 | if (err) | 1758 | if (err) |
| 1700 | goto out; | 1759 | goto out; |
| 1701 | 1760 | ||
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index bf416e512743..25572ffea163 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | #include "ubifs.h" | 35 | #include "ubifs.h" |
| 36 | 36 | ||
| 37 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, | 37 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, |
| 38 | int len, int lnum, int offs); | 38 | struct ubifs_zbranch *zbr); |
| 39 | static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, | 39 | static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, |
| 40 | struct ubifs_zbranch *zbr, void *node); | 40 | struct ubifs_zbranch *zbr, void *node); |
| 41 | 41 | ||
| @@ -433,9 +433,7 @@ static int tnc_read_hashed_node(struct ubifs_info *c, struct ubifs_zbranch *zbr, | |||
| 433 | * @c: UBIFS file-system description object | 433 | * @c: UBIFS file-system description object |
| 434 | * @buf: buffer to read to | 434 | * @buf: buffer to read to |
| 435 | * @type: node type | 435 | * @type: node type |
| 436 | * @len: node length (not aligned) | 436 | * @zbr: the zbranch describing the node to read |
| 437 | * @lnum: LEB number of node to read | ||
| 438 | * @offs: offset of node to read | ||
| 439 | * | 437 | * |
| 440 | * This function tries to read a node of known type and length, checks it and | 438 | * This function tries to read a node of known type and length, checks it and |
| 441 | * stores it in @buf. This function returns %1 if a node is present and %0 if | 439 | * stores it in @buf. This function returns %1 if a node is present and %0 if |
| @@ -453,8 +451,11 @@ static int tnc_read_hashed_node(struct ubifs_info *c, struct ubifs_zbranch *zbr, | |||
| 453 | * journal nodes may potentially be corrupted, so checking is required. | 451 | * journal nodes may potentially be corrupted, so checking is required. |
| 454 | */ | 452 | */ |
| 455 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, | 453 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, |
| 456 | int len, int lnum, int offs) | 454 | struct ubifs_zbranch *zbr) |
| 457 | { | 455 | { |
| 456 | int len = zbr->len; | ||
| 457 | int lnum = zbr->lnum; | ||
| 458 | int offs = zbr->offs; | ||
| 458 | int err, node_len; | 459 | int err, node_len; |
| 459 | struct ubifs_ch *ch = buf; | 460 | struct ubifs_ch *ch = buf; |
| 460 | uint32_t crc, node_crc; | 461 | uint32_t crc, node_crc; |
| @@ -487,6 +488,12 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, | |||
| 487 | if (crc != node_crc) | 488 | if (crc != node_crc) |
| 488 | return 0; | 489 | return 0; |
| 489 | 490 | ||
| 491 | err = ubifs_node_check_hash(c, buf, zbr->hash); | ||
| 492 | if (err) { | ||
| 493 | ubifs_bad_hash(c, buf, zbr->hash, lnum, offs); | ||
| 494 | return 0; | ||
| 495 | } | ||
| 496 | |||
| 490 | return 1; | 497 | return 1; |
| 491 | } | 498 | } |
| 492 | 499 | ||
| @@ -507,8 +514,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, | |||
| 507 | 514 | ||
| 508 | dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs); | 515 | dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs); |
| 509 | 516 | ||
| 510 | ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum, | 517 | ret = try_read_node(c, node, key_type(c, key), zbr); |
| 511 | zbr->offs); | ||
| 512 | if (ret == 1) { | 518 | if (ret == 1) { |
| 513 | union ubifs_key node_key; | 519 | union ubifs_key node_key; |
| 514 | struct ubifs_dent_node *dent = node; | 520 | struct ubifs_dent_node *dent = node; |
| @@ -1713,6 +1719,12 @@ static int validate_data_node(struct ubifs_info *c, void *buf, | |||
| 1713 | goto out; | 1719 | goto out; |
| 1714 | } | 1720 | } |
| 1715 | 1721 | ||
| 1722 | err = ubifs_node_check_hash(c, buf, zbr->hash); | ||
| 1723 | if (err) { | ||
| 1724 | ubifs_bad_hash(c, buf, zbr->hash, zbr->lnum, zbr->offs); | ||
| 1725 | return err; | ||
| 1726 | } | ||
| 1727 | |||
| 1716 | len = le32_to_cpu(ch->len); | 1728 | len = le32_to_cpu(ch->len); |
| 1717 | if (len != zbr->len) { | 1729 | if (len != zbr->len) { |
| 1718 | ubifs_err(c, "bad node length %d, expected %d", len, zbr->len); | 1730 | ubifs_err(c, "bad node length %d, expected %d", len, zbr->len); |
| @@ -2260,13 +2272,14 @@ do_split: | |||
| 2260 | * @lnum: LEB number of node | 2272 | * @lnum: LEB number of node |
| 2261 | * @offs: node offset | 2273 | * @offs: node offset |
| 2262 | * @len: node length | 2274 | * @len: node length |
| 2275 | * @hash: The hash over the node | ||
| 2263 | * | 2276 | * |
| 2264 | * This function adds a node with key @key to TNC. The node may be new or it may | 2277 | * This function adds a node with key @key to TNC. The node may be new or it may |
| 2265 | * obsolete some existing one. Returns %0 on success or negative error code on | 2278 | * obsolete some existing one. Returns %0 on success or negative error code on |
| 2266 | * failure. | 2279 | * failure. |
| 2267 | */ | 2280 | */ |
| 2268 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, | 2281 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, |
| 2269 | int offs, int len) | 2282 | int offs, int len, const u8 *hash) |
| 2270 | { | 2283 | { |
| 2271 | int found, n, err = 0; | 2284 | int found, n, err = 0; |
| 2272 | struct ubifs_znode *znode; | 2285 | struct ubifs_znode *znode; |
| @@ -2281,6 +2294,7 @@ int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, | |||
| 2281 | zbr.lnum = lnum; | 2294 | zbr.lnum = lnum; |
| 2282 | zbr.offs = offs; | 2295 | zbr.offs = offs; |
| 2283 | zbr.len = len; | 2296 | zbr.len = len; |
| 2297 | ubifs_copy_hash(c, hash, zbr.hash); | ||
| 2284 | key_copy(c, key, &zbr.key); | 2298 | key_copy(c, key, &zbr.key); |
| 2285 | err = tnc_insert(c, znode, &zbr, n + 1); | 2299 | err = tnc_insert(c, znode, &zbr, n + 1); |
| 2286 | } else if (found == 1) { | 2300 | } else if (found == 1) { |
| @@ -2291,6 +2305,7 @@ int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, | |||
| 2291 | zbr->lnum = lnum; | 2305 | zbr->lnum = lnum; |
| 2292 | zbr->offs = offs; | 2306 | zbr->offs = offs; |
| 2293 | zbr->len = len; | 2307 | zbr->len = len; |
| 2308 | ubifs_copy_hash(c, hash, zbr->hash); | ||
| 2294 | } else | 2309 | } else |
| 2295 | err = found; | 2310 | err = found; |
| 2296 | if (!err) | 2311 | if (!err) |
| @@ -2392,13 +2407,14 @@ out_unlock: | |||
| 2392 | * @lnum: LEB number of node | 2407 | * @lnum: LEB number of node |
| 2393 | * @offs: node offset | 2408 | * @offs: node offset |
| 2394 | * @len: node length | 2409 | * @len: node length |
| 2410 | * @hash: The hash over the node | ||
| 2395 | * @nm: node name | 2411 | * @nm: node name |
| 2396 | * | 2412 | * |
| 2397 | * This is the same as 'ubifs_tnc_add()' but it should be used with keys which | 2413 | * This is the same as 'ubifs_tnc_add()' but it should be used with keys which |
| 2398 | * may have collisions, like directory entry keys. | 2414 | * may have collisions, like directory entry keys. |
| 2399 | */ | 2415 | */ |
| 2400 | int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, | 2416 | int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, |
| 2401 | int lnum, int offs, int len, | 2417 | int lnum, int offs, int len, const u8 *hash, |
| 2402 | const struct fscrypt_name *nm) | 2418 | const struct fscrypt_name *nm) |
| 2403 | { | 2419 | { |
| 2404 | int found, n, err = 0; | 2420 | int found, n, err = 0; |
| @@ -2441,6 +2457,7 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, | |||
| 2441 | zbr->lnum = lnum; | 2457 | zbr->lnum = lnum; |
| 2442 | zbr->offs = offs; | 2458 | zbr->offs = offs; |
| 2443 | zbr->len = len; | 2459 | zbr->len = len; |
| 2460 | ubifs_copy_hash(c, hash, zbr->hash); | ||
| 2444 | goto out_unlock; | 2461 | goto out_unlock; |
| 2445 | } | 2462 | } |
| 2446 | } | 2463 | } |
| @@ -2452,6 +2469,7 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, | |||
| 2452 | zbr.lnum = lnum; | 2469 | zbr.lnum = lnum; |
| 2453 | zbr.offs = offs; | 2470 | zbr.offs = offs; |
| 2454 | zbr.len = len; | 2471 | zbr.len = len; |
| 2472 | ubifs_copy_hash(c, hash, zbr.hash); | ||
| 2455 | key_copy(c, key, &zbr.key); | 2473 | key_copy(c, key, &zbr.key); |
| 2456 | err = tnc_insert(c, znode, &zbr, n + 1); | 2474 | err = tnc_insert(c, znode, &zbr, n + 1); |
| 2457 | if (err) | 2475 | if (err) |
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index dba87d09b989..dbcd2c350b65 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c | |||
| @@ -38,6 +38,7 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, | |||
| 38 | struct ubifs_znode *znode, int lnum, int offs, int len) | 38 | struct ubifs_znode *znode, int lnum, int offs, int len) |
| 39 | { | 39 | { |
| 40 | struct ubifs_znode *zp; | 40 | struct ubifs_znode *zp; |
| 41 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 41 | int i, err; | 42 | int i, err; |
| 42 | 43 | ||
| 43 | /* Make index node */ | 44 | /* Make index node */ |
| @@ -52,6 +53,7 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, | |||
| 52 | br->lnum = cpu_to_le32(zbr->lnum); | 53 | br->lnum = cpu_to_le32(zbr->lnum); |
| 53 | br->offs = cpu_to_le32(zbr->offs); | 54 | br->offs = cpu_to_le32(zbr->offs); |
| 54 | br->len = cpu_to_le32(zbr->len); | 55 | br->len = cpu_to_le32(zbr->len); |
| 56 | ubifs_copy_hash(c, zbr->hash, ubifs_branch_hash(c, br)); | ||
| 55 | if (!zbr->lnum || !zbr->len) { | 57 | if (!zbr->lnum || !zbr->len) { |
| 56 | ubifs_err(c, "bad ref in znode"); | 58 | ubifs_err(c, "bad ref in znode"); |
| 57 | ubifs_dump_znode(c, znode); | 59 | ubifs_dump_znode(c, znode); |
| @@ -62,6 +64,7 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, | |||
| 62 | } | 64 | } |
| 63 | } | 65 | } |
| 64 | ubifs_prepare_node(c, idx, len, 0); | 66 | ubifs_prepare_node(c, idx, len, 0); |
| 67 | ubifs_node_calc_hash(c, idx, hash); | ||
| 65 | 68 | ||
| 66 | znode->lnum = lnum; | 69 | znode->lnum = lnum; |
| 67 | znode->offs = offs; | 70 | znode->offs = offs; |
| @@ -78,10 +81,12 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, | |||
| 78 | zbr->lnum = lnum; | 81 | zbr->lnum = lnum; |
| 79 | zbr->offs = offs; | 82 | zbr->offs = offs; |
| 80 | zbr->len = len; | 83 | zbr->len = len; |
| 84 | ubifs_copy_hash(c, hash, zbr->hash); | ||
| 81 | } else { | 85 | } else { |
| 82 | c->zroot.lnum = lnum; | 86 | c->zroot.lnum = lnum; |
| 83 | c->zroot.offs = offs; | 87 | c->zroot.offs = offs; |
| 84 | c->zroot.len = len; | 88 | c->zroot.len = len; |
| 89 | ubifs_copy_hash(c, hash, c->zroot.hash); | ||
| 85 | } | 90 | } |
| 86 | c->calc_idx_sz += ALIGN(len, 8); | 91 | c->calc_idx_sz += ALIGN(len, 8); |
| 87 | 92 | ||
| @@ -647,6 +652,8 @@ static int get_znodes_to_commit(struct ubifs_info *c) | |||
| 647 | znode->cnext = c->cnext; | 652 | znode->cnext = c->cnext; |
| 648 | break; | 653 | break; |
| 649 | } | 654 | } |
| 655 | znode->cparent = znode->parent; | ||
| 656 | znode->ciip = znode->iip; | ||
| 650 | znode->cnext = cnext; | 657 | znode->cnext = cnext; |
| 651 | znode = cnext; | 658 | znode = cnext; |
| 652 | cnt += 1; | 659 | cnt += 1; |
| @@ -840,6 +847,8 @@ static int write_index(struct ubifs_info *c) | |||
| 840 | } | 847 | } |
| 841 | 848 | ||
| 842 | while (1) { | 849 | while (1) { |
| 850 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 851 | |||
| 843 | cond_resched(); | 852 | cond_resched(); |
| 844 | 853 | ||
| 845 | znode = cnext; | 854 | znode = cnext; |
| @@ -857,6 +866,7 @@ static int write_index(struct ubifs_info *c) | |||
| 857 | br->lnum = cpu_to_le32(zbr->lnum); | 866 | br->lnum = cpu_to_le32(zbr->lnum); |
| 858 | br->offs = cpu_to_le32(zbr->offs); | 867 | br->offs = cpu_to_le32(zbr->offs); |
| 859 | br->len = cpu_to_le32(zbr->len); | 868 | br->len = cpu_to_le32(zbr->len); |
| 869 | ubifs_copy_hash(c, zbr->hash, ubifs_branch_hash(c, br)); | ||
| 860 | if (!zbr->lnum || !zbr->len) { | 870 | if (!zbr->lnum || !zbr->len) { |
| 861 | ubifs_err(c, "bad ref in znode"); | 871 | ubifs_err(c, "bad ref in znode"); |
| 862 | ubifs_dump_znode(c, znode); | 872 | ubifs_dump_znode(c, znode); |
| @@ -868,6 +878,23 @@ static int write_index(struct ubifs_info *c) | |||
| 868 | } | 878 | } |
| 869 | len = ubifs_idx_node_sz(c, znode->child_cnt); | 879 | len = ubifs_idx_node_sz(c, znode->child_cnt); |
| 870 | ubifs_prepare_node(c, idx, len, 0); | 880 | ubifs_prepare_node(c, idx, len, 0); |
| 881 | ubifs_node_calc_hash(c, idx, hash); | ||
| 882 | |||
| 883 | mutex_lock(&c->tnc_mutex); | ||
| 884 | |||
| 885 | if (znode->cparent) | ||
| 886 | ubifs_copy_hash(c, hash, | ||
| 887 | znode->cparent->zbranch[znode->ciip].hash); | ||
| 888 | |||
| 889 | if (znode->parent) { | ||
| 890 | if (!ubifs_zn_obsolete(znode)) | ||
| 891 | ubifs_copy_hash(c, hash, | ||
| 892 | znode->parent->zbranch[znode->iip].hash); | ||
| 893 | } else { | ||
| 894 | ubifs_copy_hash(c, hash, c->zroot.hash); | ||
| 895 | } | ||
| 896 | |||
| 897 | mutex_unlock(&c->tnc_mutex); | ||
| 871 | 898 | ||
| 872 | /* Determine the index node position */ | 899 | /* Determine the index node position */ |
| 873 | if (lnum == -1) { | 900 | if (lnum == -1) { |
diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c index d90ee01076a9..d1815e959007 100644 --- a/fs/ubifs/tnc_misc.c +++ b/fs/ubifs/tnc_misc.c | |||
| @@ -265,9 +265,7 @@ long ubifs_destroy_tnc_subtree(const struct ubifs_info *c, | |||
| 265 | /** | 265 | /** |
| 266 | * read_znode - read an indexing node from flash and fill znode. | 266 | * read_znode - read an indexing node from flash and fill znode. |
| 267 | * @c: UBIFS file-system description object | 267 | * @c: UBIFS file-system description object |
| 268 | * @lnum: LEB of the indexing node to read | 268 | * @zzbr: the zbranch describing the node to read |
| 269 | * @offs: node offset | ||
| 270 | * @len: node length | ||
| 271 | * @znode: znode to read to | 269 | * @znode: znode to read to |
| 272 | * | 270 | * |
| 273 | * This function reads an indexing node from the flash media and fills znode | 271 | * This function reads an indexing node from the flash media and fills znode |
| @@ -276,9 +274,12 @@ long ubifs_destroy_tnc_subtree(const struct ubifs_info *c, | |||
| 276 | * is wrong with it, this function prints complaint messages and returns | 274 | * is wrong with it, this function prints complaint messages and returns |
| 277 | * %-EINVAL. | 275 | * %-EINVAL. |
| 278 | */ | 276 | */ |
| 279 | static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, | 277 | static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr, |
| 280 | struct ubifs_znode *znode) | 278 | struct ubifs_znode *znode) |
| 281 | { | 279 | { |
| 280 | int lnum = zzbr->lnum; | ||
| 281 | int offs = zzbr->offs; | ||
| 282 | int len = zzbr->len; | ||
| 282 | int i, err, type, cmp; | 283 | int i, err, type, cmp; |
| 283 | struct ubifs_idx_node *idx; | 284 | struct ubifs_idx_node *idx; |
| 284 | 285 | ||
| @@ -292,6 +293,12 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, | |||
| 292 | return err; | 293 | return err; |
| 293 | } | 294 | } |
| 294 | 295 | ||
| 296 | err = ubifs_node_check_hash(c, idx, zzbr->hash); | ||
| 297 | if (err) { | ||
| 298 | ubifs_bad_hash(c, idx, zzbr->hash, lnum, offs); | ||
| 299 | return err; | ||
| 300 | } | ||
| 301 | |||
| 295 | znode->child_cnt = le16_to_cpu(idx->child_cnt); | 302 | znode->child_cnt = le16_to_cpu(idx->child_cnt); |
| 296 | znode->level = le16_to_cpu(idx->level); | 303 | znode->level = le16_to_cpu(idx->level); |
| 297 | 304 | ||
| @@ -308,13 +315,14 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, | |||
| 308 | } | 315 | } |
| 309 | 316 | ||
| 310 | for (i = 0; i < znode->child_cnt; i++) { | 317 | for (i = 0; i < znode->child_cnt; i++) { |
| 311 | const struct ubifs_branch *br = ubifs_idx_branch(c, idx, i); | 318 | struct ubifs_branch *br = ubifs_idx_branch(c, idx, i); |
| 312 | struct ubifs_zbranch *zbr = &znode->zbranch[i]; | 319 | struct ubifs_zbranch *zbr = &znode->zbranch[i]; |
| 313 | 320 | ||
| 314 | key_read(c, &br->key, &zbr->key); | 321 | key_read(c, &br->key, &zbr->key); |
| 315 | zbr->lnum = le32_to_cpu(br->lnum); | 322 | zbr->lnum = le32_to_cpu(br->lnum); |
| 316 | zbr->offs = le32_to_cpu(br->offs); | 323 | zbr->offs = le32_to_cpu(br->offs); |
| 317 | zbr->len = le32_to_cpu(br->len); | 324 | zbr->len = le32_to_cpu(br->len); |
| 325 | ubifs_copy_hash(c, ubifs_branch_hash(c, br), zbr->hash); | ||
| 318 | zbr->znode = NULL; | 326 | zbr->znode = NULL; |
| 319 | 327 | ||
| 320 | /* Validate branch */ | 328 | /* Validate branch */ |
| @@ -425,7 +433,7 @@ struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c, | |||
| 425 | if (!znode) | 433 | if (!znode) |
| 426 | return ERR_PTR(-ENOMEM); | 434 | return ERR_PTR(-ENOMEM); |
| 427 | 435 | ||
| 428 | err = read_znode(c, zbr->lnum, zbr->offs, zbr->len, znode); | 436 | err = read_znode(c, zbr, znode); |
| 429 | if (err) | 437 | if (err) |
| 430 | goto out; | 438 | goto out; |
| 431 | 439 | ||
| @@ -496,5 +504,11 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr, | |||
| 496 | return -EINVAL; | 504 | return -EINVAL; |
| 497 | } | 505 | } |
| 498 | 506 | ||
| 507 | err = ubifs_node_check_hash(c, node, zbr->hash); | ||
| 508 | if (err) { | ||
| 509 | ubifs_bad_hash(c, node, zbr->hash, zbr->lnum, zbr->offs); | ||
| 510 | return err; | ||
| 511 | } | ||
| 512 | |||
| 499 | return 0; | 513 | return 0; |
| 500 | } | 514 | } |
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index e8c23c9d4f4a..8b7c1844014f 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h | |||
| @@ -286,6 +286,7 @@ enum { | |||
| 286 | #define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node) | 286 | #define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node) |
| 287 | #define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) | 287 | #define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) |
| 288 | #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) | 288 | #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) |
| 289 | #define UBIFS_AUTH_NODE_SZ sizeof(struct ubifs_auth_node) | ||
| 289 | /* Extended attribute entry nodes are identical to directory entry nodes */ | 290 | /* Extended attribute entry nodes are identical to directory entry nodes */ |
| 290 | #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ | 291 | #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ |
| 291 | /* Only this does not have to be multiple of 8 bytes */ | 292 | /* Only this does not have to be multiple of 8 bytes */ |
| @@ -300,6 +301,12 @@ enum { | |||
| 300 | /* The largest UBIFS node */ | 301 | /* The largest UBIFS node */ |
| 301 | #define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ | 302 | #define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ |
| 302 | 303 | ||
| 304 | /* The maxmimum size of a hash, enough for sha512 */ | ||
| 305 | #define UBIFS_MAX_HASH_LEN 64 | ||
| 306 | |||
| 307 | /* The maxmimum size of a hmac, enough for hmac(sha512) */ | ||
| 308 | #define UBIFS_MAX_HMAC_LEN 64 | ||
| 309 | |||
| 303 | /* | 310 | /* |
| 304 | * xattr name of UBIFS encryption context, we don't use a prefix | 311 | * xattr name of UBIFS encryption context, we don't use a prefix |
| 305 | * nor a long name to not waste space on the flash. | 312 | * nor a long name to not waste space on the flash. |
| @@ -365,6 +372,7 @@ enum { | |||
| 365 | * UBIFS_IDX_NODE: index node | 372 | * UBIFS_IDX_NODE: index node |
| 366 | * UBIFS_CS_NODE: commit start node | 373 | * UBIFS_CS_NODE: commit start node |
| 367 | * UBIFS_ORPH_NODE: orphan node | 374 | * UBIFS_ORPH_NODE: orphan node |
| 375 | * UBIFS_AUTH_NODE: authentication node | ||
| 368 | * UBIFS_NODE_TYPES_CNT: count of supported node types | 376 | * UBIFS_NODE_TYPES_CNT: count of supported node types |
| 369 | * | 377 | * |
| 370 | * Note, we index arrays by these numbers, so keep them low and contiguous. | 378 | * Note, we index arrays by these numbers, so keep them low and contiguous. |
| @@ -384,6 +392,7 @@ enum { | |||
| 384 | UBIFS_IDX_NODE, | 392 | UBIFS_IDX_NODE, |
| 385 | UBIFS_CS_NODE, | 393 | UBIFS_CS_NODE, |
| 386 | UBIFS_ORPH_NODE, | 394 | UBIFS_ORPH_NODE, |
| 395 | UBIFS_AUTH_NODE, | ||
| 387 | UBIFS_NODE_TYPES_CNT, | 396 | UBIFS_NODE_TYPES_CNT, |
| 388 | }; | 397 | }; |
| 389 | 398 | ||
| @@ -421,15 +430,19 @@ enum { | |||
| 421 | * UBIFS_FLG_DOUBLE_HASH: store a 32bit cookie in directory entry nodes to | 430 | * UBIFS_FLG_DOUBLE_HASH: store a 32bit cookie in directory entry nodes to |
| 422 | * support 64bit cookies for lookups by hash | 431 | * support 64bit cookies for lookups by hash |
| 423 | * UBIFS_FLG_ENCRYPTION: this filesystem contains encrypted files | 432 | * UBIFS_FLG_ENCRYPTION: this filesystem contains encrypted files |
| 433 | * UBIFS_FLG_AUTHENTICATION: this filesystem contains hashes for authentication | ||
| 424 | */ | 434 | */ |
| 425 | enum { | 435 | enum { |
| 426 | UBIFS_FLG_BIGLPT = 0x02, | 436 | UBIFS_FLG_BIGLPT = 0x02, |
| 427 | UBIFS_FLG_SPACE_FIXUP = 0x04, | 437 | UBIFS_FLG_SPACE_FIXUP = 0x04, |
| 428 | UBIFS_FLG_DOUBLE_HASH = 0x08, | 438 | UBIFS_FLG_DOUBLE_HASH = 0x08, |
| 429 | UBIFS_FLG_ENCRYPTION = 0x10, | 439 | UBIFS_FLG_ENCRYPTION = 0x10, |
| 440 | UBIFS_FLG_AUTHENTICATION = 0x20, | ||
| 430 | }; | 441 | }; |
| 431 | 442 | ||
| 432 | #define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT|UBIFS_FLG_SPACE_FIXUP|UBIFS_FLG_DOUBLE_HASH|UBIFS_FLG_ENCRYPTION) | 443 | #define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT | UBIFS_FLG_SPACE_FIXUP | \ |
| 444 | UBIFS_FLG_DOUBLE_HASH | UBIFS_FLG_ENCRYPTION | \ | ||
| 445 | UBIFS_FLG_AUTHENTICATION) | ||
| 433 | 446 | ||
| 434 | /** | 447 | /** |
| 435 | * struct ubifs_ch - common header node. | 448 | * struct ubifs_ch - common header node. |
| @@ -633,6 +646,10 @@ struct ubifs_pad_node { | |||
| 633 | * @time_gran: time granularity in nanoseconds | 646 | * @time_gran: time granularity in nanoseconds |
| 634 | * @uuid: UUID generated when the file system image was created | 647 | * @uuid: UUID generated when the file system image was created |
| 635 | * @ro_compat_version: UBIFS R/O compatibility version | 648 | * @ro_compat_version: UBIFS R/O compatibility version |
| 649 | * @hmac: HMAC to authenticate the superblock node | ||
| 650 | * @hmac_wkm: HMAC of a well known message (the string "UBIFS") as a convenience | ||
| 651 | * to the user to check if the correct key is passed. | ||
| 652 | * @hash_algo: The hash algo used for this filesystem (one of enum hash_algo) | ||
| 636 | */ | 653 | */ |
| 637 | struct ubifs_sb_node { | 654 | struct ubifs_sb_node { |
| 638 | struct ubifs_ch ch; | 655 | struct ubifs_ch ch; |
| @@ -660,7 +677,10 @@ struct ubifs_sb_node { | |||
| 660 | __le32 time_gran; | 677 | __le32 time_gran; |
| 661 | __u8 uuid[16]; | 678 | __u8 uuid[16]; |
| 662 | __le32 ro_compat_version; | 679 | __le32 ro_compat_version; |
| 663 | __u8 padding2[3968]; | 680 | __u8 hmac[UBIFS_MAX_HMAC_LEN]; |
| 681 | __u8 hmac_wkm[UBIFS_MAX_HMAC_LEN]; | ||
| 682 | __le16 hash_algo; | ||
| 683 | __u8 padding2[3838]; | ||
| 664 | } __packed; | 684 | } __packed; |
| 665 | 685 | ||
| 666 | /** | 686 | /** |
| @@ -695,6 +715,9 @@ struct ubifs_sb_node { | |||
| 695 | * @empty_lebs: number of empty logical eraseblocks | 715 | * @empty_lebs: number of empty logical eraseblocks |
| 696 | * @idx_lebs: number of indexing logical eraseblocks | 716 | * @idx_lebs: number of indexing logical eraseblocks |
| 697 | * @leb_cnt: count of LEBs used by file-system | 717 | * @leb_cnt: count of LEBs used by file-system |
| 718 | * @hash_root_idx: the hash of the root index node | ||
| 719 | * @hash_lpt: the hash of the LPT | ||
| 720 | * @hmac: HMAC to authenticate the master node | ||
| 698 | * @padding: reserved for future, zeroes | 721 | * @padding: reserved for future, zeroes |
| 699 | */ | 722 | */ |
| 700 | struct ubifs_mst_node { | 723 | struct ubifs_mst_node { |
| @@ -727,7 +750,10 @@ struct ubifs_mst_node { | |||
| 727 | __le32 empty_lebs; | 750 | __le32 empty_lebs; |
| 728 | __le32 idx_lebs; | 751 | __le32 idx_lebs; |
| 729 | __le32 leb_cnt; | 752 | __le32 leb_cnt; |
| 730 | __u8 padding[344]; | 753 | __u8 hash_root_idx[UBIFS_MAX_HASH_LEN]; |
| 754 | __u8 hash_lpt[UBIFS_MAX_HASH_LEN]; | ||
| 755 | __u8 hmac[UBIFS_MAX_HMAC_LEN]; | ||
| 756 | __u8 padding[152]; | ||
| 731 | } __packed; | 757 | } __packed; |
| 732 | 758 | ||
| 733 | /** | 759 | /** |
| @@ -747,11 +773,25 @@ struct ubifs_ref_node { | |||
| 747 | } __packed; | 773 | } __packed; |
| 748 | 774 | ||
| 749 | /** | 775 | /** |
| 776 | * struct ubifs_auth_node - node for authenticating other nodes | ||
| 777 | * @ch: common header | ||
| 778 | * @hmac: The HMAC | ||
| 779 | */ | ||
| 780 | struct ubifs_auth_node { | ||
| 781 | struct ubifs_ch ch; | ||
| 782 | __u8 hmac[]; | ||
| 783 | } __packed; | ||
| 784 | |||
| 785 | /** | ||
| 750 | * struct ubifs_branch - key/reference/length branch | 786 | * struct ubifs_branch - key/reference/length branch |
| 751 | * @lnum: LEB number of the target node | 787 | * @lnum: LEB number of the target node |
| 752 | * @offs: offset within @lnum | 788 | * @offs: offset within @lnum |
| 753 | * @len: target node length | 789 | * @len: target node length |
| 754 | * @key: key | 790 | * @key: key |
| 791 | * | ||
| 792 | * In an authenticated UBIFS we have the hash of the referenced node after @key. | ||
| 793 | * This can't be added to the struct type definition because @key is a | ||
| 794 | * dynamically sized element already. | ||
| 755 | */ | 795 | */ |
| 756 | struct ubifs_branch { | 796 | struct ubifs_branch { |
| 757 | __le32 lnum; | 797 | __le32 lnum; |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 4368cde476b0..38401adaa00d 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -39,6 +39,9 @@ | |||
| 39 | #include <linux/security.h> | 39 | #include <linux/security.h> |
| 40 | #include <linux/xattr.h> | 40 | #include <linux/xattr.h> |
| 41 | #include <linux/random.h> | 41 | #include <linux/random.h> |
| 42 | #include <crypto/hash_info.h> | ||
| 43 | #include <crypto/hash.h> | ||
| 44 | #include <crypto/algapi.h> | ||
| 42 | 45 | ||
| 43 | #define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION) | 46 | #define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_UBIFS_FS_ENCRYPTION) |
| 44 | #include <linux/fscrypt.h> | 47 | #include <linux/fscrypt.h> |
| @@ -157,6 +160,14 @@ | |||
| 157 | /* Maximum number of data nodes to bulk-read */ | 160 | /* Maximum number of data nodes to bulk-read */ |
| 158 | #define UBIFS_MAX_BULK_READ 32 | 161 | #define UBIFS_MAX_BULK_READ 32 |
| 159 | 162 | ||
| 163 | #ifdef CONFIG_UBIFS_FS_AUTHENTICATION | ||
| 164 | #define UBIFS_HASH_ARR_SZ UBIFS_MAX_HASH_LEN | ||
| 165 | #define UBIFS_HMAC_ARR_SZ UBIFS_MAX_HMAC_LEN | ||
| 166 | #else | ||
| 167 | #define UBIFS_HASH_ARR_SZ 0 | ||
| 168 | #define UBIFS_HMAC_ARR_SZ 0 | ||
| 169 | #endif | ||
| 170 | |||
| 160 | /* | 171 | /* |
| 161 | * Lockdep classes for UBIFS inode @ui_mutex. | 172 | * Lockdep classes for UBIFS inode @ui_mutex. |
| 162 | */ | 173 | */ |
| @@ -706,6 +717,7 @@ struct ubifs_wbuf { | |||
| 706 | * @jhead: journal head number this bud belongs to | 717 | * @jhead: journal head number this bud belongs to |
| 707 | * @list: link in the list buds belonging to the same journal head | 718 | * @list: link in the list buds belonging to the same journal head |
| 708 | * @rb: link in the tree of all buds | 719 | * @rb: link in the tree of all buds |
| 720 | * @log_hash: the log hash from the commit start node up to this bud | ||
| 709 | */ | 721 | */ |
| 710 | struct ubifs_bud { | 722 | struct ubifs_bud { |
| 711 | int lnum; | 723 | int lnum; |
| @@ -713,6 +725,7 @@ struct ubifs_bud { | |||
| 713 | int jhead; | 725 | int jhead; |
| 714 | struct list_head list; | 726 | struct list_head list; |
| 715 | struct rb_node rb; | 727 | struct rb_node rb; |
| 728 | struct shash_desc *log_hash; | ||
| 716 | }; | 729 | }; |
| 717 | 730 | ||
| 718 | /** | 731 | /** |
| @@ -720,6 +733,7 @@ struct ubifs_bud { | |||
| 720 | * @wbuf: head's write-buffer | 733 | * @wbuf: head's write-buffer |
| 721 | * @buds_list: list of bud LEBs belonging to this journal head | 734 | * @buds_list: list of bud LEBs belonging to this journal head |
| 722 | * @grouped: non-zero if UBIFS groups nodes when writing to this journal head | 735 | * @grouped: non-zero if UBIFS groups nodes when writing to this journal head |
| 736 | * @log_hash: the log hash from the commit start node up to this journal head | ||
| 723 | * | 737 | * |
| 724 | * Note, the @buds list is protected by the @c->buds_lock. | 738 | * Note, the @buds list is protected by the @c->buds_lock. |
| 725 | */ | 739 | */ |
| @@ -727,6 +741,7 @@ struct ubifs_jhead { | |||
| 727 | struct ubifs_wbuf wbuf; | 741 | struct ubifs_wbuf wbuf; |
| 728 | struct list_head buds_list; | 742 | struct list_head buds_list; |
| 729 | unsigned int grouped:1; | 743 | unsigned int grouped:1; |
| 744 | struct shash_desc *log_hash; | ||
| 730 | }; | 745 | }; |
| 731 | 746 | ||
| 732 | /** | 747 | /** |
| @@ -736,6 +751,7 @@ struct ubifs_jhead { | |||
| 736 | * @lnum: LEB number of the target node (indexing node or data node) | 751 | * @lnum: LEB number of the target node (indexing node or data node) |
| 737 | * @offs: target node offset within @lnum | 752 | * @offs: target node offset within @lnum |
| 738 | * @len: target node length | 753 | * @len: target node length |
| 754 | * @hash: the hash of the target node | ||
| 739 | */ | 755 | */ |
| 740 | struct ubifs_zbranch { | 756 | struct ubifs_zbranch { |
| 741 | union ubifs_key key; | 757 | union ubifs_key key; |
| @@ -746,12 +762,15 @@ struct ubifs_zbranch { | |||
| 746 | int lnum; | 762 | int lnum; |
| 747 | int offs; | 763 | int offs; |
| 748 | int len; | 764 | int len; |
| 765 | u8 hash[UBIFS_HASH_ARR_SZ]; | ||
| 749 | }; | 766 | }; |
| 750 | 767 | ||
| 751 | /** | 768 | /** |
| 752 | * struct ubifs_znode - in-memory representation of an indexing node. | 769 | * struct ubifs_znode - in-memory representation of an indexing node. |
| 753 | * @parent: parent znode or NULL if it is the root | 770 | * @parent: parent znode or NULL if it is the root |
| 754 | * @cnext: next znode to commit | 771 | * @cnext: next znode to commit |
| 772 | * @cparent: parent node for this commit | ||
| 773 | * @ciip: index in cparent's zbranch array | ||
| 755 | * @flags: znode flags (%DIRTY_ZNODE, %COW_ZNODE or %OBSOLETE_ZNODE) | 774 | * @flags: znode flags (%DIRTY_ZNODE, %COW_ZNODE or %OBSOLETE_ZNODE) |
| 756 | * @time: last access time (seconds) | 775 | * @time: last access time (seconds) |
| 757 | * @level: level of the entry in the TNC tree | 776 | * @level: level of the entry in the TNC tree |
| @@ -769,6 +788,8 @@ struct ubifs_zbranch { | |||
| 769 | struct ubifs_znode { | 788 | struct ubifs_znode { |
| 770 | struct ubifs_znode *parent; | 789 | struct ubifs_znode *parent; |
| 771 | struct ubifs_znode *cnext; | 790 | struct ubifs_znode *cnext; |
| 791 | struct ubifs_znode *cparent; | ||
| 792 | int ciip; | ||
| 772 | unsigned long flags; | 793 | unsigned long flags; |
| 773 | time64_t time; | 794 | time64_t time; |
| 774 | int level; | 795 | int level; |
| @@ -983,6 +1004,7 @@ struct ubifs_debug_info; | |||
| 983 | * struct ubifs_info - UBIFS file-system description data structure | 1004 | * struct ubifs_info - UBIFS file-system description data structure |
| 984 | * (per-superblock). | 1005 | * (per-superblock). |
| 985 | * @vfs_sb: VFS @struct super_block object | 1006 | * @vfs_sb: VFS @struct super_block object |
| 1007 | * @sup_node: The super block node as read from the device | ||
| 986 | * | 1008 | * |
| 987 | * @highest_inum: highest used inode number | 1009 | * @highest_inum: highest used inode number |
| 988 | * @max_sqnum: current global sequence number | 1010 | * @max_sqnum: current global sequence number |
| @@ -1028,6 +1050,7 @@ struct ubifs_debug_info; | |||
| 1028 | * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc) | 1050 | * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc) |
| 1029 | * @rw_incompat: the media is not R/W compatible | 1051 | * @rw_incompat: the media is not R/W compatible |
| 1030 | * @assert_action: action to take when a ubifs_assert() fails | 1052 | * @assert_action: action to take when a ubifs_assert() fails |
| 1053 | * @authenticated: flag indigating the FS is mounted in authenticated mode | ||
| 1031 | * | 1054 | * |
| 1032 | * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and | 1055 | * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and |
| 1033 | * @calc_idx_sz | 1056 | * @calc_idx_sz |
| @@ -1075,6 +1098,7 @@ struct ubifs_debug_info; | |||
| 1075 | * @key_hash: direntry key hash function | 1098 | * @key_hash: direntry key hash function |
| 1076 | * @key_fmt: key format | 1099 | * @key_fmt: key format |
| 1077 | * @key_len: key length | 1100 | * @key_len: key length |
| 1101 | * @hash_len: The length of the index node hashes | ||
| 1078 | * @fanout: fanout of the index tree (number of links per indexing node) | 1102 | * @fanout: fanout of the index tree (number of links per indexing node) |
| 1079 | * | 1103 | * |
| 1080 | * @min_io_size: minimal input/output unit size | 1104 | * @min_io_size: minimal input/output unit size |
| @@ -1210,6 +1234,15 @@ struct ubifs_debug_info; | |||
| 1210 | * @rp_uid: reserved pool user ID | 1234 | * @rp_uid: reserved pool user ID |
| 1211 | * @rp_gid: reserved pool group ID | 1235 | * @rp_gid: reserved pool group ID |
| 1212 | * | 1236 | * |
| 1237 | * @hash_tfm: the hash transformation used for hashing nodes | ||
| 1238 | * @hmac_tfm: the HMAC transformation for this filesystem | ||
| 1239 | * @hmac_desc_len: length of the HMAC used for authentication | ||
| 1240 | * @auth_key_name: the authentication key name | ||
| 1241 | * @auth_hash_name: the name of the hash algorithm used for authentication | ||
| 1242 | * @auth_hash_algo: the authentication hash used for this fs | ||
| 1243 | * @log_hash: the log hash from the commit start node up to the latest reference | ||
| 1244 | * node. | ||
| 1245 | * | ||
| 1213 | * @empty: %1 if the UBI device is empty | 1246 | * @empty: %1 if the UBI device is empty |
| 1214 | * @need_recovery: %1 if the file-system needs recovery | 1247 | * @need_recovery: %1 if the file-system needs recovery |
| 1215 | * @replaying: %1 during journal replay | 1248 | * @replaying: %1 during journal replay |
| @@ -1230,6 +1263,7 @@ struct ubifs_debug_info; | |||
| 1230 | */ | 1263 | */ |
| 1231 | struct ubifs_info { | 1264 | struct ubifs_info { |
| 1232 | struct super_block *vfs_sb; | 1265 | struct super_block *vfs_sb; |
| 1266 | struct ubifs_sb_node *sup_node; | ||
| 1233 | 1267 | ||
| 1234 | ino_t highest_inum; | 1268 | ino_t highest_inum; |
| 1235 | unsigned long long max_sqnum; | 1269 | unsigned long long max_sqnum; |
| @@ -1270,6 +1304,7 @@ struct ubifs_info { | |||
| 1270 | unsigned int default_compr:2; | 1304 | unsigned int default_compr:2; |
| 1271 | unsigned int rw_incompat:1; | 1305 | unsigned int rw_incompat:1; |
| 1272 | unsigned int assert_action:2; | 1306 | unsigned int assert_action:2; |
| 1307 | unsigned int authenticated:1; | ||
| 1273 | 1308 | ||
| 1274 | struct mutex tnc_mutex; | 1309 | struct mutex tnc_mutex; |
| 1275 | struct ubifs_zbranch zroot; | 1310 | struct ubifs_zbranch zroot; |
| @@ -1314,6 +1349,7 @@ struct ubifs_info { | |||
| 1314 | uint32_t (*key_hash)(const char *str, int len); | 1349 | uint32_t (*key_hash)(const char *str, int len); |
| 1315 | int key_fmt; | 1350 | int key_fmt; |
| 1316 | int key_len; | 1351 | int key_len; |
| 1352 | int hash_len; | ||
| 1317 | int fanout; | 1353 | int fanout; |
| 1318 | 1354 | ||
| 1319 | int min_io_size; | 1355 | int min_io_size; |
| @@ -1441,6 +1477,15 @@ struct ubifs_info { | |||
| 1441 | kuid_t rp_uid; | 1477 | kuid_t rp_uid; |
| 1442 | kgid_t rp_gid; | 1478 | kgid_t rp_gid; |
| 1443 | 1479 | ||
| 1480 | struct crypto_shash *hash_tfm; | ||
| 1481 | struct crypto_shash *hmac_tfm; | ||
| 1482 | int hmac_desc_len; | ||
| 1483 | char *auth_key_name; | ||
| 1484 | char *auth_hash_name; | ||
| 1485 | enum hash_algo auth_hash_algo; | ||
| 1486 | |||
| 1487 | struct shash_desc *log_hash; | ||
| 1488 | |||
| 1444 | /* The below fields are used only during mounting and re-mounting */ | 1489 | /* The below fields are used only during mounting and re-mounting */ |
| 1445 | unsigned int empty:1; | 1490 | unsigned int empty:1; |
| 1446 | unsigned int need_recovery:1; | 1491 | unsigned int need_recovery:1; |
| @@ -1471,6 +1516,195 @@ extern const struct inode_operations ubifs_dir_inode_operations; | |||
| 1471 | extern const struct inode_operations ubifs_symlink_inode_operations; | 1516 | extern const struct inode_operations ubifs_symlink_inode_operations; |
| 1472 | extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; | 1517 | extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; |
| 1473 | 1518 | ||
| 1519 | /* auth.c */ | ||
| 1520 | static inline int ubifs_authenticated(const struct ubifs_info *c) | ||
| 1521 | { | ||
| 1522 | return (IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) && c->authenticated; | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | struct shash_desc *__ubifs_hash_get_desc(const struct ubifs_info *c); | ||
| 1526 | static inline struct shash_desc *ubifs_hash_get_desc(const struct ubifs_info *c) | ||
| 1527 | { | ||
| 1528 | return ubifs_authenticated(c) ? __ubifs_hash_get_desc(c) : NULL; | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | static inline int ubifs_shash_init(const struct ubifs_info *c, | ||
| 1532 | struct shash_desc *desc) | ||
| 1533 | { | ||
| 1534 | if (ubifs_authenticated(c)) | ||
| 1535 | return crypto_shash_init(desc); | ||
| 1536 | else | ||
| 1537 | return 0; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | static inline int ubifs_shash_update(const struct ubifs_info *c, | ||
| 1541 | struct shash_desc *desc, const void *buf, | ||
| 1542 | unsigned int len) | ||
| 1543 | { | ||
| 1544 | int err = 0; | ||
| 1545 | |||
| 1546 | if (ubifs_authenticated(c)) { | ||
| 1547 | err = crypto_shash_update(desc, buf, len); | ||
| 1548 | if (err < 0) | ||
| 1549 | return err; | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | return 0; | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | static inline int ubifs_shash_final(const struct ubifs_info *c, | ||
| 1556 | struct shash_desc *desc, u8 *out) | ||
| 1557 | { | ||
| 1558 | return ubifs_authenticated(c) ? crypto_shash_final(desc, out) : 0; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | int __ubifs_node_calc_hash(const struct ubifs_info *c, const void *buf, | ||
| 1562 | u8 *hash); | ||
| 1563 | static inline int ubifs_node_calc_hash(const struct ubifs_info *c, | ||
| 1564 | const void *buf, u8 *hash) | ||
| 1565 | { | ||
| 1566 | if (ubifs_authenticated(c)) | ||
| 1567 | return __ubifs_node_calc_hash(c, buf, hash); | ||
| 1568 | else | ||
| 1569 | return 0; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | int ubifs_prepare_auth_node(struct ubifs_info *c, void *node, | ||
| 1573 | struct shash_desc *inhash); | ||
| 1574 | |||
| 1575 | /** | ||
| 1576 | * ubifs_check_hash - compare two hashes | ||
| 1577 | * @c: UBIFS file-system description object | ||
| 1578 | * @expected: first hash | ||
| 1579 | * @got: second hash | ||
| 1580 | * | ||
| 1581 | * Compare two hashes @expected and @got. Returns 0 when they are equal, a | ||
| 1582 | * negative error code otherwise. | ||
| 1583 | */ | ||
| 1584 | static inline int ubifs_check_hash(const struct ubifs_info *c, | ||
| 1585 | const u8 *expected, const u8 *got) | ||
| 1586 | { | ||
| 1587 | return crypto_memneq(expected, got, c->hash_len); | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | /** | ||
| 1591 | * ubifs_check_hmac - compare two HMACs | ||
| 1592 | * @c: UBIFS file-system description object | ||
| 1593 | * @expected: first HMAC | ||
| 1594 | * @got: second HMAC | ||
| 1595 | * | ||
| 1596 | * Compare two hashes @expected and @got. Returns 0 when they are equal, a | ||
| 1597 | * negative error code otherwise. | ||
| 1598 | */ | ||
| 1599 | static inline int ubifs_check_hmac(const struct ubifs_info *c, | ||
| 1600 | const u8 *expected, const u8 *got) | ||
| 1601 | { | ||
| 1602 | return crypto_memneq(expected, got, c->hmac_desc_len); | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | void ubifs_bad_hash(const struct ubifs_info *c, const void *node, | ||
| 1606 | const u8 *hash, int lnum, int offs); | ||
| 1607 | |||
| 1608 | int __ubifs_node_check_hash(const struct ubifs_info *c, const void *buf, | ||
| 1609 | const u8 *expected); | ||
| 1610 | static inline int ubifs_node_check_hash(const struct ubifs_info *c, | ||
| 1611 | const void *buf, const u8 *expected) | ||
| 1612 | { | ||
| 1613 | if (ubifs_authenticated(c)) | ||
| 1614 | return __ubifs_node_check_hash(c, buf, expected); | ||
| 1615 | else | ||
| 1616 | return 0; | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | int ubifs_init_authentication(struct ubifs_info *c); | ||
| 1620 | void __ubifs_exit_authentication(struct ubifs_info *c); | ||
| 1621 | static inline void ubifs_exit_authentication(struct ubifs_info *c) | ||
| 1622 | { | ||
| 1623 | if (ubifs_authenticated(c)) | ||
| 1624 | __ubifs_exit_authentication(c); | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | /** | ||
| 1628 | * ubifs_branch_hash - returns a pointer to the hash of a branch | ||
| 1629 | * @c: UBIFS file-system description object | ||
| 1630 | * @br: branch to get the hash from | ||
| 1631 | * | ||
| 1632 | * This returns a pointer to the hash of a branch. Since the key already is a | ||
| 1633 | * dynamically sized object we cannot use a struct member here. | ||
| 1634 | */ | ||
| 1635 | static inline u8 *ubifs_branch_hash(struct ubifs_info *c, | ||
| 1636 | struct ubifs_branch *br) | ||
| 1637 | { | ||
| 1638 | return (void *)br + sizeof(*br) + c->key_len; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | /** | ||
| 1642 | * ubifs_copy_hash - copy a hash | ||
| 1643 | * @c: UBIFS file-system description object | ||
| 1644 | * @from: source hash | ||
| 1645 | * @to: destination hash | ||
| 1646 | * | ||
| 1647 | * With authentication this copies a hash, otherwise does nothing. | ||
| 1648 | */ | ||
| 1649 | static inline void ubifs_copy_hash(const struct ubifs_info *c, const u8 *from, | ||
| 1650 | u8 *to) | ||
| 1651 | { | ||
| 1652 | if (ubifs_authenticated(c)) | ||
| 1653 | memcpy(to, from, c->hash_len); | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | int __ubifs_node_insert_hmac(const struct ubifs_info *c, void *buf, | ||
| 1657 | int len, int ofs_hmac); | ||
| 1658 | static inline int ubifs_node_insert_hmac(const struct ubifs_info *c, void *buf, | ||
| 1659 | int len, int ofs_hmac) | ||
| 1660 | { | ||
| 1661 | if (ubifs_authenticated(c)) | ||
| 1662 | return __ubifs_node_insert_hmac(c, buf, len, ofs_hmac); | ||
| 1663 | else | ||
| 1664 | return 0; | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | int __ubifs_node_verify_hmac(const struct ubifs_info *c, const void *buf, | ||
| 1668 | int len, int ofs_hmac); | ||
| 1669 | static inline int ubifs_node_verify_hmac(const struct ubifs_info *c, | ||
| 1670 | const void *buf, int len, int ofs_hmac) | ||
| 1671 | { | ||
| 1672 | if (ubifs_authenticated(c)) | ||
| 1673 | return __ubifs_node_verify_hmac(c, buf, len, ofs_hmac); | ||
| 1674 | else | ||
| 1675 | return 0; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | /** | ||
| 1679 | * ubifs_auth_node_sz - returns the size of an authentication node | ||
| 1680 | * @c: UBIFS file-system description object | ||
| 1681 | * | ||
| 1682 | * This function returns the size of an authentication node which can | ||
| 1683 | * be 0 for unauthenticated filesystems or the real size of an auth node | ||
| 1684 | * authentication is enabled. | ||
| 1685 | */ | ||
| 1686 | static inline int ubifs_auth_node_sz(const struct ubifs_info *c) | ||
| 1687 | { | ||
| 1688 | if (ubifs_authenticated(c)) | ||
| 1689 | return sizeof(struct ubifs_auth_node) + c->hmac_desc_len; | ||
| 1690 | else | ||
| 1691 | return 0; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac); | ||
| 1695 | |||
| 1696 | int __ubifs_shash_copy_state(const struct ubifs_info *c, struct shash_desc *src, | ||
| 1697 | struct shash_desc *target); | ||
| 1698 | static inline int ubifs_shash_copy_state(const struct ubifs_info *c, | ||
| 1699 | struct shash_desc *src, | ||
| 1700 | struct shash_desc *target) | ||
| 1701 | { | ||
| 1702 | if (ubifs_authenticated(c)) | ||
| 1703 | return __ubifs_shash_copy_state(c, src, target); | ||
| 1704 | else | ||
| 1705 | return 0; | ||
| 1706 | } | ||
| 1707 | |||
| 1474 | /* io.c */ | 1708 | /* io.c */ |
| 1475 | void ubifs_ro_mode(struct ubifs_info *c, int err); | 1709 | void ubifs_ro_mode(struct ubifs_info *c, int err); |
| 1476 | int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs, | 1710 | int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs, |
| @@ -1490,9 +1724,15 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, | |||
| 1490 | int lnum, int offs); | 1724 | int lnum, int offs); |
| 1491 | int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, | 1725 | int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, |
| 1492 | int offs); | 1726 | int offs); |
| 1727 | int ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum, | ||
| 1728 | int offs, int hmac_offs); | ||
| 1493 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | 1729 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, |
| 1494 | int offs, int quiet, int must_chk_crc); | 1730 | int offs, int quiet, int must_chk_crc); |
| 1731 | void ubifs_init_node(struct ubifs_info *c, void *buf, int len, int pad); | ||
| 1732 | void ubifs_crc_node(struct ubifs_info *c, void *buf, int len); | ||
| 1495 | void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); | 1733 | void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); |
| 1734 | int ubifs_prepare_node_hmac(struct ubifs_info *c, void *node, int len, | ||
| 1735 | int hmac_offs, int pad); | ||
| 1496 | void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); | 1736 | void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); |
| 1497 | int ubifs_io_init(struct ubifs_info *c); | 1737 | int ubifs_io_init(struct ubifs_info *c); |
| 1498 | void ubifs_pad(const struct ubifs_info *c, void *buf, int pad); | 1738 | void ubifs_pad(const struct ubifs_info *c, void *buf, int pad); |
| @@ -1592,11 +1832,12 @@ int ubifs_tnc_lookup_dh(struct ubifs_info *c, const union ubifs_key *key, | |||
| 1592 | int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, | 1832 | int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, |
| 1593 | void *node, int *lnum, int *offs); | 1833 | void *node, int *lnum, int *offs); |
| 1594 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, | 1834 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, |
| 1595 | int offs, int len); | 1835 | int offs, int len, const u8 *hash); |
| 1596 | int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key, | 1836 | int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key, |
| 1597 | int old_lnum, int old_offs, int lnum, int offs, int len); | 1837 | int old_lnum, int old_offs, int lnum, int offs, int len); |
| 1598 | int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, | 1838 | int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, |
| 1599 | int lnum, int offs, int len, const struct fscrypt_name *nm); | 1839 | int lnum, int offs, int len, const u8 *hash, |
| 1840 | const struct fscrypt_name *nm); | ||
| 1600 | int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key); | 1841 | int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key); |
| 1601 | int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key, | 1842 | int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key, |
| 1602 | const struct fscrypt_name *nm); | 1843 | const struct fscrypt_name *nm); |
| @@ -1659,12 +1900,12 @@ int ubifs_gc_should_commit(struct ubifs_info *c); | |||
| 1659 | void ubifs_wait_for_commit(struct ubifs_info *c); | 1900 | void ubifs_wait_for_commit(struct ubifs_info *c); |
| 1660 | 1901 | ||
| 1661 | /* master.c */ | 1902 | /* master.c */ |
| 1903 | int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2); | ||
| 1662 | int ubifs_read_master(struct ubifs_info *c); | 1904 | int ubifs_read_master(struct ubifs_info *c); |
| 1663 | int ubifs_write_master(struct ubifs_info *c); | 1905 | int ubifs_write_master(struct ubifs_info *c); |
| 1664 | 1906 | ||
| 1665 | /* sb.c */ | 1907 | /* sb.c */ |
| 1666 | int ubifs_read_superblock(struct ubifs_info *c); | 1908 | int ubifs_read_superblock(struct ubifs_info *c); |
| 1667 | struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c); | ||
| 1668 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup); | 1909 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup); |
| 1669 | int ubifs_fixup_free_space(struct ubifs_info *c); | 1910 | int ubifs_fixup_free_space(struct ubifs_info *c); |
| 1670 | int ubifs_enable_encryption(struct ubifs_info *c); | 1911 | int ubifs_enable_encryption(struct ubifs_info *c); |
| @@ -1693,7 +1934,7 @@ int ubifs_clear_orphans(struct ubifs_info *c); | |||
| 1693 | /* lpt.c */ | 1934 | /* lpt.c */ |
| 1694 | int ubifs_calc_lpt_geom(struct ubifs_info *c); | 1935 | int ubifs_calc_lpt_geom(struct ubifs_info *c); |
| 1695 | int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, | 1936 | int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, |
| 1696 | int *lpt_lebs, int *big_lpt); | 1937 | int *lpt_lebs, int *big_lpt, u8 *hash); |
| 1697 | int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr); | 1938 | int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr); |
| 1698 | struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum); | 1939 | struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum); |
| 1699 | struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum); | 1940 | struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum); |
| @@ -1712,6 +1953,7 @@ struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c, | |||
| 1712 | struct ubifs_nnode *parent, int iip); | 1953 | struct ubifs_nnode *parent, int iip); |
| 1713 | struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c, | 1954 | struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c, |
| 1714 | struct ubifs_nnode *parent, int iip); | 1955 | struct ubifs_nnode *parent, int iip); |
| 1956 | struct ubifs_pnode *ubifs_pnode_lookup(struct ubifs_info *c, int i); | ||
| 1715 | int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip); | 1957 | int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip); |
| 1716 | void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty); | 1958 | void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty); |
| 1717 | void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode); | 1959 | void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode); |
| @@ -1720,6 +1962,7 @@ struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght); | |||
| 1720 | /* Needed only in debugging code in lpt_commit.c */ | 1962 | /* Needed only in debugging code in lpt_commit.c */ |
| 1721 | int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf, | 1963 | int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf, |
| 1722 | struct ubifs_nnode *nnode); | 1964 | struct ubifs_nnode *nnode); |
| 1965 | int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash); | ||
| 1723 | 1966 | ||
| 1724 | /* lpt_commit.c */ | 1967 | /* lpt_commit.c */ |
| 1725 | int ubifs_lpt_start_commit(struct ubifs_info *c); | 1968 | int ubifs_lpt_start_commit(struct ubifs_info *c); |
| @@ -1807,7 +2050,7 @@ int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf); | |||
| 1807 | int ubifs_rcvry_gc_commit(struct ubifs_info *c); | 2050 | int ubifs_rcvry_gc_commit(struct ubifs_info *c); |
| 1808 | int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, | 2051 | int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, |
| 1809 | int deletion, loff_t new_size); | 2052 | int deletion, loff_t new_size); |
| 1810 | int ubifs_recover_size(struct ubifs_info *c); | 2053 | int ubifs_recover_size(struct ubifs_info *c, bool in_place); |
| 1811 | void ubifs_destroy_size_tree(struct ubifs_info *c); | 2054 | void ubifs_destroy_size_tree(struct ubifs_info *c); |
| 1812 | 2055 | ||
| 1813 | /* ioctl.c */ | 2056 | /* ioctl.c */ |
