diff options
| -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 | |||
