diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-14 20:24:12 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-14 20:24:12 -0400 |
| commit | a318423b61e8c67aa5c0a428540c58439a20baac (patch) | |
| tree | 5834b93378b01bde412c49aacdb7aa1021c701ca | |
| parent | f2772a0e4833d1af1901b6f1a38136fb71d1350c (diff) | |
| parent | 8009ce956c3d28022af6b122e50213ad830fc902 (diff) | |
Merge tag 'upstream-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs
Pull UBIFS updates from Richard Weinberger:
- Support for zstd compression
- Support for offline signed filesystems
- Various fixes for regressions
* tag 'upstream-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
ubifs: Don't leak orphans on memory during commit
ubifs: Check link count of inodes when killing orphans.
ubifs: Add support for zstd compression.
ubifs: support offline signed images
ubifs: remove unnecessary check in ubifs_log_start_commit
ubifs: Fix typo of output in get_cs_sqnum
ubifs: Simplify redundant code
ubifs: Correctly use tnc_next() in search_dh_cookie()
| -rw-r--r-- | fs/ubifs/Kconfig | 13 | ||||
| -rw-r--r-- | fs/ubifs/auth.c | 86 | ||||
| -rw-r--r-- | fs/ubifs/compress.c | 27 | ||||
| -rw-r--r-- | fs/ubifs/log.c | 5 | ||||
| -rw-r--r-- | fs/ubifs/master.c | 53 | ||||
| -rw-r--r-- | fs/ubifs/orphan.c | 94 | ||||
| -rw-r--r-- | fs/ubifs/recovery.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/sb.c | 52 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 46 | ||||
| -rw-r--r-- | fs/ubifs/tnc.c | 16 | ||||
| -rw-r--r-- | fs/ubifs/ubifs-media.h | 30 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 6 |
12 files changed, 338 insertions, 92 deletions
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index 06c35c64162b..69932bcfa920 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig | |||
| @@ -6,8 +6,10 @@ config UBIFS_FS | |||
| 6 | select CRYPTO if UBIFS_FS_ADVANCED_COMPR | 6 | select CRYPTO if UBIFS_FS_ADVANCED_COMPR |
| 7 | select CRYPTO if UBIFS_FS_LZO | 7 | select CRYPTO if UBIFS_FS_LZO |
| 8 | select CRYPTO if UBIFS_FS_ZLIB | 8 | select CRYPTO if UBIFS_FS_ZLIB |
| 9 | select CRYPTO if UBIFS_FS_ZSTD | ||
| 9 | select CRYPTO_LZO if UBIFS_FS_LZO | 10 | select CRYPTO_LZO if UBIFS_FS_LZO |
| 10 | select CRYPTO_DEFLATE if UBIFS_FS_ZLIB | 11 | select CRYPTO_DEFLATE if UBIFS_FS_ZLIB |
| 12 | select CRYPTO_ZSTD if UBIFS_FS_ZSTD | ||
| 11 | select CRYPTO_HASH_INFO | 13 | select CRYPTO_HASH_INFO |
| 12 | select UBIFS_FS_XATTR if FS_ENCRYPTION | 14 | select UBIFS_FS_XATTR if FS_ENCRYPTION |
| 13 | depends on MTD_UBI | 15 | depends on MTD_UBI |
| @@ -38,6 +40,14 @@ config UBIFS_FS_ZLIB | |||
| 38 | help | 40 | help |
| 39 | Zlib compresses better than LZO but it is slower. Say 'Y' if unsure. | 41 | Zlib compresses better than LZO but it is slower. Say 'Y' if unsure. |
| 40 | 42 | ||
| 43 | config UBIFS_FS_ZSTD | ||
| 44 | bool "ZSTD compression support" if UBIFS_FS_ADVANCED_COMPR | ||
| 45 | depends on UBIFS_FS | ||
| 46 | default y | ||
| 47 | help | ||
| 48 | ZSTD compresses is a big win in speed over Zlib and | ||
| 49 | in compression ratio over LZO. Say 'Y' if unsure. | ||
| 50 | |||
| 41 | config UBIFS_ATIME_SUPPORT | 51 | config UBIFS_ATIME_SUPPORT |
| 42 | bool "Access time support" | 52 | bool "Access time support" |
| 43 | default n | 53 | default n |
| @@ -77,8 +87,9 @@ config UBIFS_FS_SECURITY | |||
| 77 | 87 | ||
| 78 | config UBIFS_FS_AUTHENTICATION | 88 | config UBIFS_FS_AUTHENTICATION |
| 79 | bool "UBIFS authentication support" | 89 | bool "UBIFS authentication support" |
| 80 | depends on KEYS | 90 | select KEYS |
| 81 | select CRYPTO_HMAC | 91 | select CRYPTO_HMAC |
| 92 | select SYSTEM_DATA_VERIFICATION | ||
| 82 | help | 93 | help |
| 83 | Enable authentication support for UBIFS. This feature offers protection | 94 | Enable authentication support for UBIFS. This feature offers protection |
| 84 | against offline changes for both data and metadata of the filesystem. | 95 | against offline changes for both data and metadata of the filesystem. |
diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c index 60f43b93d06e..d9af2de9084a 100644 --- a/fs/ubifs/auth.c +++ b/fs/ubifs/auth.c | |||
| @@ -10,10 +10,12 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
| 13 | #include <linux/verification.h> | ||
| 13 | #include <crypto/hash.h> | 14 | #include <crypto/hash.h> |
| 14 | #include <crypto/sha.h> | 15 | #include <crypto/sha.h> |
| 15 | #include <crypto/algapi.h> | 16 | #include <crypto/algapi.h> |
| 16 | #include <keys/user-type.h> | 17 | #include <keys/user-type.h> |
| 18 | #include <keys/asymmetric-type.h> | ||
| 17 | 19 | ||
| 18 | #include "ubifs.h" | 20 | #include "ubifs.h" |
| 19 | 21 | ||
| @@ -199,6 +201,77 @@ int __ubifs_node_check_hash(const struct ubifs_info *c, const void *node, | |||
| 199 | } | 201 | } |
| 200 | 202 | ||
| 201 | /** | 203 | /** |
| 204 | * ubifs_sb_verify_signature - verify the signature of a superblock | ||
| 205 | * @c: UBIFS file-system description object | ||
| 206 | * @sup: The superblock node | ||
| 207 | * | ||
| 208 | * To support offline signed images the superblock can be signed with a | ||
| 209 | * PKCS#7 signature. The signature is placed directly behind the superblock | ||
| 210 | * node in an ubifs_sig_node. | ||
| 211 | * | ||
| 212 | * Returns 0 when the signature can be successfully verified or a negative | ||
| 213 | * error code if not. | ||
| 214 | */ | ||
| 215 | int ubifs_sb_verify_signature(struct ubifs_info *c, | ||
| 216 | const struct ubifs_sb_node *sup) | ||
| 217 | { | ||
| 218 | int err; | ||
| 219 | struct ubifs_scan_leb *sleb; | ||
| 220 | struct ubifs_scan_node *snod; | ||
| 221 | const struct ubifs_sig_node *signode; | ||
| 222 | |||
| 223 | sleb = ubifs_scan(c, UBIFS_SB_LNUM, UBIFS_SB_NODE_SZ, c->sbuf, 0); | ||
| 224 | if (IS_ERR(sleb)) { | ||
| 225 | err = PTR_ERR(sleb); | ||
| 226 | return err; | ||
| 227 | } | ||
| 228 | |||
| 229 | if (sleb->nodes_cnt == 0) { | ||
| 230 | ubifs_err(c, "Unable to find signature node"); | ||
| 231 | err = -EINVAL; | ||
| 232 | goto out_destroy; | ||
| 233 | } | ||
| 234 | |||
| 235 | snod = list_first_entry(&sleb->nodes, struct ubifs_scan_node, list); | ||
| 236 | |||
| 237 | if (snod->type != UBIFS_SIG_NODE) { | ||
| 238 | ubifs_err(c, "Signature node is of wrong type"); | ||
| 239 | err = -EINVAL; | ||
| 240 | goto out_destroy; | ||
| 241 | } | ||
| 242 | |||
| 243 | signode = snod->node; | ||
| 244 | |||
| 245 | if (le32_to_cpu(signode->len) > snod->len + sizeof(struct ubifs_sig_node)) { | ||
| 246 | ubifs_err(c, "invalid signature len %d", le32_to_cpu(signode->len)); | ||
| 247 | err = -EINVAL; | ||
| 248 | goto out_destroy; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (le32_to_cpu(signode->type) != UBIFS_SIGNATURE_TYPE_PKCS7) { | ||
| 252 | ubifs_err(c, "Signature type %d is not supported\n", | ||
| 253 | le32_to_cpu(signode->type)); | ||
| 254 | err = -EINVAL; | ||
| 255 | goto out_destroy; | ||
| 256 | } | ||
| 257 | |||
| 258 | err = verify_pkcs7_signature(sup, sizeof(struct ubifs_sb_node), | ||
| 259 | signode->sig, le32_to_cpu(signode->len), | ||
| 260 | NULL, VERIFYING_UNSPECIFIED_SIGNATURE, | ||
| 261 | NULL, NULL); | ||
| 262 | |||
| 263 | if (err) | ||
| 264 | ubifs_err(c, "Failed to verify signature"); | ||
| 265 | else | ||
| 266 | ubifs_msg(c, "Successfully verified super block signature"); | ||
| 267 | |||
| 268 | out_destroy: | ||
| 269 | ubifs_scan_destroy(sleb); | ||
| 270 | |||
| 271 | return err; | ||
| 272 | } | ||
| 273 | |||
| 274 | /** | ||
| 202 | * ubifs_init_authentication - initialize UBIFS authentication support | 275 | * ubifs_init_authentication - initialize UBIFS authentication support |
| 203 | * @c: UBIFS file-system description object | 276 | * @c: UBIFS file-system description object |
| 204 | * | 277 | * |
| @@ -478,3 +551,16 @@ int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac) | |||
| 478 | return err; | 551 | return err; |
| 479 | return 0; | 552 | return 0; |
| 480 | } | 553 | } |
| 554 | |||
| 555 | /* | ||
| 556 | * ubifs_hmac_zero - test if a HMAC is zero | ||
| 557 | * @c: UBIFS file-system description object | ||
| 558 | * @hmac: the HMAC to test | ||
| 559 | * | ||
| 560 | * This function tests if a HMAC is zero and returns true if it is | ||
| 561 | * and false otherwise. | ||
| 562 | */ | ||
| 563 | bool ubifs_hmac_zero(struct ubifs_info *c, const u8 *hmac) | ||
| 564 | { | ||
| 565 | return !memchr_inv(hmac, 0, c->hmac_desc_len); | ||
| 566 | } | ||
diff --git a/fs/ubifs/compress.c b/fs/ubifs/compress.c index 99c53ad11e93..3a92e6af69b2 100644 --- a/fs/ubifs/compress.c +++ b/fs/ubifs/compress.c | |||
| @@ -59,6 +59,24 @@ static struct ubifs_compressor zlib_compr = { | |||
| 59 | }; | 59 | }; |
| 60 | #endif | 60 | #endif |
| 61 | 61 | ||
| 62 | #ifdef CONFIG_UBIFS_FS_ZSTD | ||
| 63 | static DEFINE_MUTEX(zstd_enc_mutex); | ||
| 64 | static DEFINE_MUTEX(zstd_dec_mutex); | ||
| 65 | |||
| 66 | static struct ubifs_compressor zstd_compr = { | ||
| 67 | .compr_type = UBIFS_COMPR_ZSTD, | ||
| 68 | .comp_mutex = &zstd_enc_mutex, | ||
| 69 | .decomp_mutex = &zstd_dec_mutex, | ||
| 70 | .name = "zstd", | ||
| 71 | .capi_name = "zstd", | ||
| 72 | }; | ||
| 73 | #else | ||
| 74 | static struct ubifs_compressor zstd_compr = { | ||
| 75 | .compr_type = UBIFS_COMPR_ZSTD, | ||
| 76 | .name = "zstd", | ||
| 77 | }; | ||
| 78 | #endif | ||
| 79 | |||
| 62 | /* All UBIFS compressors */ | 80 | /* All UBIFS compressors */ |
| 63 | struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; | 81 | struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; |
| 64 | 82 | ||
| @@ -216,13 +234,19 @@ int __init ubifs_compressors_init(void) | |||
| 216 | if (err) | 234 | if (err) |
| 217 | return err; | 235 | return err; |
| 218 | 236 | ||
| 219 | err = compr_init(&zlib_compr); | 237 | err = compr_init(&zstd_compr); |
| 220 | if (err) | 238 | if (err) |
| 221 | goto out_lzo; | 239 | goto out_lzo; |
| 222 | 240 | ||
| 241 | err = compr_init(&zlib_compr); | ||
| 242 | if (err) | ||
| 243 | goto out_zstd; | ||
| 244 | |||
| 223 | ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr; | 245 | ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr; |
| 224 | return 0; | 246 | return 0; |
| 225 | 247 | ||
| 248 | out_zstd: | ||
| 249 | compr_exit(&zstd_compr); | ||
| 226 | out_lzo: | 250 | out_lzo: |
| 227 | compr_exit(&lzo_compr); | 251 | compr_exit(&lzo_compr); |
| 228 | return err; | 252 | return err; |
| @@ -235,4 +259,5 @@ void ubifs_compressors_exit(void) | |||
| 235 | { | 259 | { |
| 236 | compr_exit(&lzo_compr); | 260 | compr_exit(&lzo_compr); |
| 237 | compr_exit(&zlib_compr); | 261 | compr_exit(&zlib_compr); |
| 262 | compr_exit(&zstd_compr); | ||
| 238 | } | 263 | } |
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index cd85d7d4c515..b6ac9c4281ef 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c | |||
| @@ -438,10 +438,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum) | |||
| 438 | *ltail_lnum = c->lhead_lnum; | 438 | *ltail_lnum = c->lhead_lnum; |
| 439 | 439 | ||
| 440 | c->lhead_offs += len; | 440 | c->lhead_offs += len; |
| 441 | if (c->lhead_offs == c->leb_size) { | 441 | ubifs_assert(c, c->lhead_offs < c->leb_size); |
| 442 | c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum); | ||
| 443 | c->lhead_offs = 0; | ||
| 444 | } | ||
| 445 | 442 | ||
| 446 | remove_buds(c); | 443 | remove_buds(c); |
| 447 | 444 | ||
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index b42a768709c0..52a85c01397e 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c | |||
| @@ -48,6 +48,39 @@ int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2) | |||
| 48 | return 0; | 48 | return 0; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | /* mst_node_check_hash - Check hash of a master node | ||
| 52 | * @c: UBIFS file-system description object | ||
| 53 | * @mst: The master node | ||
| 54 | * @expected: The expected hash of the master node | ||
| 55 | * | ||
| 56 | * This checks the hash of a master node against a given expected hash. | ||
| 57 | * Note that we have two master nodes on a UBIFS image which have different | ||
| 58 | * sequence numbers and consequently different CRCs. To be able to match | ||
| 59 | * both master nodes we exclude the common node header containing the sequence | ||
| 60 | * number and CRC from the hash. | ||
| 61 | * | ||
| 62 | * Returns 0 if the hashes are equal, a negative error code otherwise. | ||
| 63 | */ | ||
| 64 | static int mst_node_check_hash(const struct ubifs_info *c, | ||
| 65 | const struct ubifs_mst_node *mst, | ||
| 66 | const u8 *expected) | ||
| 67 | { | ||
| 68 | u8 calc[UBIFS_MAX_HASH_LEN]; | ||
| 69 | const void *node = mst; | ||
| 70 | |||
| 71 | SHASH_DESC_ON_STACK(shash, c->hash_tfm); | ||
| 72 | |||
| 73 | shash->tfm = c->hash_tfm; | ||
| 74 | |||
| 75 | crypto_shash_digest(shash, node + sizeof(struct ubifs_ch), | ||
| 76 | UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch), calc); | ||
| 77 | |||
| 78 | if (ubifs_check_hash(c, expected, calc)) | ||
| 79 | return -EPERM; | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 51 | /** | 84 | /** |
| 52 | * scan_for_master - search the valid master node. | 85 | * scan_for_master - search the valid master node. |
| 53 | * @c: UBIFS file-system description object | 86 | * @c: UBIFS file-system description object |
| @@ -102,14 +135,22 @@ static int scan_for_master(struct ubifs_info *c) | |||
| 102 | if (!ubifs_authenticated(c)) | 135 | if (!ubifs_authenticated(c)) |
| 103 | return 0; | 136 | return 0; |
| 104 | 137 | ||
| 105 | err = ubifs_node_verify_hmac(c, c->mst_node, | 138 | if (ubifs_hmac_zero(c, c->mst_node->hmac)) { |
| 106 | sizeof(struct ubifs_mst_node), | 139 | err = mst_node_check_hash(c, c->mst_node, |
| 107 | offsetof(struct ubifs_mst_node, hmac)); | 140 | c->sup_node->hash_mst); |
| 108 | if (err) { | 141 | if (err) |
| 109 | ubifs_err(c, "Failed to verify master node HMAC"); | 142 | ubifs_err(c, "Failed to verify master node hash"); |
| 110 | return -EPERM; | 143 | } else { |
| 144 | err = ubifs_node_verify_hmac(c, c->mst_node, | ||
| 145 | sizeof(struct ubifs_mst_node), | ||
| 146 | offsetof(struct ubifs_mst_node, hmac)); | ||
| 147 | if (err) | ||
| 148 | ubifs_err(c, "Failed to verify master node HMAC"); | ||
| 111 | } | 149 | } |
| 112 | 150 | ||
| 151 | if (err) | ||
| 152 | return -EPERM; | ||
| 153 | |||
| 113 | return 0; | 154 | return 0; |
| 114 | 155 | ||
| 115 | out: | 156 | out: |
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index cb72688032cd..b52624e28fa1 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c | |||
| @@ -126,25 +126,11 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o) | |||
| 126 | kfree(o); | 126 | kfree(o); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static void orphan_delete(struct ubifs_info *c, ino_t inum) | 129 | static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) |
| 130 | { | 130 | { |
| 131 | struct ubifs_orphan *orph, *child_orph, *tmp_o; | ||
| 132 | |||
| 133 | spin_lock(&c->orphan_lock); | ||
| 134 | |||
| 135 | orph = lookup_orphan(c, inum); | ||
| 136 | if (!orph) { | ||
| 137 | spin_unlock(&c->orphan_lock); | ||
| 138 | ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum); | ||
| 139 | dump_stack(); | ||
| 140 | |||
| 141 | return; | ||
| 142 | } | ||
| 143 | |||
| 144 | if (orph->del) { | 131 | if (orph->del) { |
| 145 | spin_unlock(&c->orphan_lock); | 132 | spin_unlock(&c->orphan_lock); |
| 146 | dbg_gen("deleted twice ino %lu", | 133 | dbg_gen("deleted twice ino %lu", orph->inum); |
| 147 | (unsigned long)inum); | ||
| 148 | return; | 134 | return; |
| 149 | } | 135 | } |
| 150 | 136 | ||
| @@ -153,19 +139,11 @@ static void orphan_delete(struct ubifs_info *c, ino_t inum) | |||
| 153 | orph->dnext = c->orph_dnext; | 139 | orph->dnext = c->orph_dnext; |
| 154 | c->orph_dnext = orph; | 140 | c->orph_dnext = orph; |
| 155 | spin_unlock(&c->orphan_lock); | 141 | spin_unlock(&c->orphan_lock); |
| 156 | dbg_gen("delete later ino %lu", | 142 | dbg_gen("delete later ino %lu", orph->inum); |
| 157 | (unsigned long)inum); | ||
| 158 | return; | 143 | return; |
| 159 | } | 144 | } |
| 160 | 145 | ||
| 161 | list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) { | ||
| 162 | list_del(&child_orph->child_list); | ||
| 163 | __orphan_drop(c, child_orph); | ||
| 164 | } | ||
| 165 | |||
| 166 | __orphan_drop(c, orph); | 146 | __orphan_drop(c, orph); |
| 167 | |||
| 168 | spin_unlock(&c->orphan_lock); | ||
| 169 | } | 147 | } |
| 170 | 148 | ||
| 171 | /** | 149 | /** |
| @@ -223,7 +201,27 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) | |||
| 223 | */ | 201 | */ |
| 224 | void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) | 202 | void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) |
| 225 | { | 203 | { |
| 226 | orphan_delete(c, inum); | 204 | struct ubifs_orphan *orph, *child_orph, *tmp_o; |
| 205 | |||
| 206 | spin_lock(&c->orphan_lock); | ||
| 207 | |||
| 208 | orph = lookup_orphan(c, inum); | ||
| 209 | if (!orph) { | ||
| 210 | spin_unlock(&c->orphan_lock); | ||
| 211 | ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum); | ||
| 212 | dump_stack(); | ||
| 213 | |||
| 214 | return; | ||
| 215 | } | ||
| 216 | |||
| 217 | list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) { | ||
| 218 | list_del(&child_orph->child_list); | ||
| 219 | orphan_delete(c, child_orph); | ||
| 220 | } | ||
| 221 | |||
| 222 | orphan_delete(c, orph); | ||
| 223 | |||
| 224 | spin_unlock(&c->orphan_lock); | ||
| 227 | } | 225 | } |
| 228 | 226 | ||
| 229 | /** | 227 | /** |
| @@ -630,6 +628,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 630 | { | 628 | { |
| 631 | struct ubifs_scan_node *snod; | 629 | struct ubifs_scan_node *snod; |
| 632 | struct ubifs_orph_node *orph; | 630 | struct ubifs_orph_node *orph; |
| 631 | struct ubifs_ino_node *ino = NULL; | ||
| 633 | unsigned long long cmt_no; | 632 | unsigned long long cmt_no; |
| 634 | ino_t inum; | 633 | ino_t inum; |
| 635 | int i, n, err, first = 1; | 634 | int i, n, err, first = 1; |
| @@ -676,23 +675,40 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 676 | if (first) | 675 | if (first) |
| 677 | first = 0; | 676 | first = 0; |
| 678 | 677 | ||
| 678 | ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); | ||
| 679 | if (!ino) | ||
| 680 | return -ENOMEM; | ||
| 681 | |||
| 679 | n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; | 682 | n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; |
| 680 | for (i = 0; i < n; i++) { | 683 | for (i = 0; i < n; i++) { |
| 681 | union ubifs_key key1, key2; | 684 | union ubifs_key key1, key2; |
| 682 | 685 | ||
| 683 | inum = le64_to_cpu(orph->inos[i]); | 686 | inum = le64_to_cpu(orph->inos[i]); |
| 684 | dbg_rcvry("deleting orphaned inode %lu", | ||
| 685 | (unsigned long)inum); | ||
| 686 | |||
| 687 | lowest_ino_key(c, &key1, inum); | ||
| 688 | highest_ino_key(c, &key2, inum); | ||
| 689 | 687 | ||
| 690 | err = ubifs_tnc_remove_range(c, &key1, &key2); | 688 | ino_key_init(c, &key1, inum); |
| 689 | err = ubifs_tnc_lookup(c, &key1, ino); | ||
| 691 | if (err) | 690 | if (err) |
| 692 | return err; | 691 | goto out_free; |
| 692 | |||
| 693 | /* | ||
| 694 | * Check whether an inode can really get deleted. | ||
| 695 | * linkat() with O_TMPFILE allows rebirth of an inode. | ||
| 696 | */ | ||
| 697 | if (ino->nlink == 0) { | ||
| 698 | dbg_rcvry("deleting orphaned inode %lu", | ||
| 699 | (unsigned long)inum); | ||
| 700 | |||
| 701 | lowest_ino_key(c, &key1, inum); | ||
| 702 | highest_ino_key(c, &key2, inum); | ||
| 703 | |||
| 704 | err = ubifs_tnc_remove_range(c, &key1, &key2); | ||
| 705 | if (err) | ||
| 706 | goto out_ro; | ||
| 707 | } | ||
| 708 | |||
| 693 | err = insert_dead_orphan(c, inum); | 709 | err = insert_dead_orphan(c, inum); |
| 694 | if (err) | 710 | if (err) |
| 695 | return err; | 711 | goto out_free; |
| 696 | } | 712 | } |
| 697 | 713 | ||
| 698 | *last_cmt_no = cmt_no; | 714 | *last_cmt_no = cmt_no; |
| @@ -704,7 +720,15 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 704 | *last_flagged = 0; | 720 | *last_flagged = 0; |
| 705 | } | 721 | } |
| 706 | 722 | ||
| 707 | return 0; | 723 | err = 0; |
| 724 | out_free: | ||
| 725 | kfree(ino); | ||
| 726 | return err; | ||
| 727 | |||
| 728 | out_ro: | ||
| 729 | ubifs_ro_mode(c, err); | ||
| 730 | kfree(ino); | ||
| 731 | return err; | ||
| 708 | } | 732 | } |
| 709 | 733 | ||
| 710 | /** | 734 | /** |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 3fc589881825..f116f7b3f9e5 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
| @@ -818,7 +818,7 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, | |||
| 818 | goto out_err; | 818 | goto out_err; |
| 819 | } | 819 | } |
| 820 | if (cs_node->ch.node_type != UBIFS_CS_NODE) { | 820 | if (cs_node->ch.node_type != UBIFS_CS_NODE) { |
| 821 | ubifs_err(c, "Node a CS node, type is %d", cs_node->ch.node_type); | 821 | ubifs_err(c, "Not a CS node, type is %d", cs_node->ch.node_type); |
| 822 | goto out_err; | 822 | goto out_err; |
| 823 | } | 823 | } |
| 824 | if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { | 824 | if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { |
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 12c2afdb5804..a551eb3e9b89 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c | |||
| @@ -578,17 +578,26 @@ static int authenticate_sb_node(struct ubifs_info *c, | |||
| 578 | return -EINVAL; | 578 | return -EINVAL; |
| 579 | } | 579 | } |
| 580 | 580 | ||
| 581 | err = ubifs_hmac_wkm(c, hmac_wkm); | 581 | /* |
| 582 | if (err) | 582 | * The super block node can either be authenticated by a HMAC or |
| 583 | return err; | 583 | * by a signature in a ubifs_sig_node directly following the |
| 584 | 584 | * super block node to support offline image creation. | |
| 585 | if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) { | 585 | */ |
| 586 | ubifs_err(c, "provided key does not fit"); | 586 | if (ubifs_hmac_zero(c, sup->hmac)) { |
| 587 | return -ENOKEY; | 587 | err = ubifs_sb_verify_signature(c, sup); |
| 588 | } else { | ||
| 589 | err = ubifs_hmac_wkm(c, hmac_wkm); | ||
| 590 | if (err) | ||
| 591 | return err; | ||
| 592 | if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) { | ||
| 593 | ubifs_err(c, "provided key does not fit"); | ||
| 594 | return -ENOKEY; | ||
| 595 | } | ||
| 596 | err = ubifs_node_verify_hmac(c, sup, sizeof(*sup), | ||
| 597 | offsetof(struct ubifs_sb_node, | ||
| 598 | hmac)); | ||
| 588 | } | 599 | } |
| 589 | 600 | ||
| 590 | err = ubifs_node_verify_hmac(c, sup, sizeof(*sup), | ||
| 591 | offsetof(struct ubifs_sb_node, hmac)); | ||
| 592 | if (err) | 601 | if (err) |
| 593 | ubifs_err(c, "Failed to authenticate superblock: %d", err); | 602 | ubifs_err(c, "Failed to authenticate superblock: %d", err); |
| 594 | 603 | ||
| @@ -744,21 +753,16 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 744 | } | 753 | } |
| 745 | 754 | ||
| 746 | /* Automatically increase file system size to the maximum size */ | 755 | /* Automatically increase file system size to the maximum size */ |
| 747 | c->old_leb_cnt = c->leb_cnt; | ||
| 748 | if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { | 756 | if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { |
| 757 | int old_leb_cnt = c->leb_cnt; | ||
| 758 | |||
| 749 | c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); | 759 | c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); |
| 750 | if (c->ro_mount) | 760 | sup->leb_cnt = cpu_to_le32(c->leb_cnt); |
| 751 | dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs", | 761 | |
| 752 | c->old_leb_cnt, c->leb_cnt); | 762 | c->superblock_need_write = 1; |
| 753 | else { | 763 | |
| 754 | dbg_mnt("Auto resizing (sb) from %d LEBs to %d LEBs", | 764 | dbg_mnt("Auto resizing from %d LEBs to %d LEBs", |
| 755 | c->old_leb_cnt, c->leb_cnt); | 765 | old_leb_cnt, c->leb_cnt); |
| 756 | sup->leb_cnt = cpu_to_le32(c->leb_cnt); | ||
| 757 | err = ubifs_write_sb_node(c, sup); | ||
| 758 | if (err) | ||
| 759 | goto out; | ||
| 760 | c->old_leb_cnt = c->leb_cnt; | ||
| 761 | } | ||
| 762 | } | 766 | } |
| 763 | 767 | ||
| 764 | c->log_bytes = (long long)c->log_lebs * c->leb_size; | 768 | c->log_bytes = (long long)c->log_lebs * c->leb_size; |
| @@ -916,9 +920,7 @@ int ubifs_fixup_free_space(struct ubifs_info *c) | |||
| 916 | c->space_fixup = 0; | 920 | c->space_fixup = 0; |
| 917 | sup->flags &= cpu_to_le32(~UBIFS_FLG_SPACE_FIXUP); | 921 | sup->flags &= cpu_to_le32(~UBIFS_FLG_SPACE_FIXUP); |
| 918 | 922 | ||
| 919 | err = ubifs_write_sb_node(c, sup); | 923 | c->superblock_need_write = 1; |
| 920 | if (err) | ||
| 921 | return err; | ||
| 922 | 924 | ||
| 923 | ubifs_msg(c, "free space fixup complete"); | 925 | ubifs_msg(c, "free space fixup complete"); |
| 924 | return err; | 926 | return err; |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index fd1977b568f0..2c0803b0ac3a 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -566,6 +566,8 @@ static int init_constants_early(struct ubifs_info *c) | |||
| 566 | c->ranges[UBIFS_AUTH_NODE].min_len = UBIFS_AUTH_NODE_SZ; | 566 | c->ranges[UBIFS_AUTH_NODE].min_len = UBIFS_AUTH_NODE_SZ; |
| 567 | c->ranges[UBIFS_AUTH_NODE].max_len = UBIFS_AUTH_NODE_SZ + | 567 | c->ranges[UBIFS_AUTH_NODE].max_len = UBIFS_AUTH_NODE_SZ + |
| 568 | UBIFS_MAX_HMAC_LEN; | 568 | UBIFS_MAX_HMAC_LEN; |
| 569 | c->ranges[UBIFS_SIG_NODE].min_len = UBIFS_SIG_NODE_SZ; | ||
| 570 | c->ranges[UBIFS_SIG_NODE].max_len = c->leb_size - UBIFS_SB_NODE_SZ; | ||
| 569 | 571 | ||
| 570 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; | 572 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; |
| 571 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; | 573 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; |
| @@ -1043,6 +1045,8 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
| 1043 | c->mount_opts.compr_type = UBIFS_COMPR_LZO; | 1045 | c->mount_opts.compr_type = UBIFS_COMPR_LZO; |
| 1044 | else if (!strcmp(name, "zlib")) | 1046 | else if (!strcmp(name, "zlib")) |
| 1045 | c->mount_opts.compr_type = UBIFS_COMPR_ZLIB; | 1047 | c->mount_opts.compr_type = UBIFS_COMPR_ZLIB; |
| 1048 | else if (!strcmp(name, "zstd")) | ||
| 1049 | c->mount_opts.compr_type = UBIFS_COMPR_ZSTD; | ||
| 1046 | else { | 1050 | else { |
| 1047 | ubifs_err(c, "unknown compressor \"%s\"", name); //FIXME: is c ready? | 1051 | ubifs_err(c, "unknown compressor \"%s\"", name); //FIXME: is c ready? |
| 1048 | kfree(name); | 1052 | kfree(name); |
| @@ -1296,8 +1300,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1296 | if (err) | 1300 | if (err) |
| 1297 | goto out_free; | 1301 | goto out_free; |
| 1298 | 1302 | ||
| 1299 | sz = ALIGN(c->max_idx_node_sz, c->min_io_size); | 1303 | sz = ALIGN(c->max_idx_node_sz, c->min_io_size) * 2; |
| 1300 | sz = ALIGN(sz + c->max_idx_node_sz, c->min_io_size); | ||
| 1301 | c->cbuf = kmalloc(sz, GFP_NOFS); | 1304 | c->cbuf = kmalloc(sz, GFP_NOFS); |
| 1302 | if (!c->cbuf) { | 1305 | if (!c->cbuf) { |
| 1303 | err = -ENOMEM; | 1306 | err = -ENOMEM; |
| @@ -1360,6 +1363,26 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1360 | goto out_lpt; | 1363 | goto out_lpt; |
| 1361 | } | 1364 | } |
| 1362 | 1365 | ||
| 1366 | /* | ||
| 1367 | * Handle offline signed images: Now that the master node is | ||
| 1368 | * written and its validation no longer depends on the hash | ||
| 1369 | * in the superblock, we can update the offline signed | ||
| 1370 | * superblock with a HMAC version, | ||
| 1371 | */ | ||
| 1372 | if (ubifs_authenticated(c) && ubifs_hmac_zero(c, c->sup_node->hmac)) { | ||
| 1373 | err = ubifs_hmac_wkm(c, c->sup_node->hmac_wkm); | ||
| 1374 | if (err) | ||
| 1375 | goto out_lpt; | ||
| 1376 | c->superblock_need_write = 1; | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | if (!c->ro_mount && c->superblock_need_write) { | ||
| 1380 | err = ubifs_write_sb_node(c, c->sup_node); | ||
| 1381 | if (err) | ||
| 1382 | goto out_lpt; | ||
| 1383 | c->superblock_need_write = 0; | ||
| 1384 | } | ||
| 1385 | |||
| 1363 | err = dbg_check_idx_size(c, c->bi.old_idx_sz); | 1386 | err = dbg_check_idx_size(c, c->bi.old_idx_sz); |
| 1364 | if (err) | 1387 | if (err) |
| 1365 | goto out_lpt; | 1388 | goto out_lpt; |
| @@ -1642,15 +1665,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
| 1642 | if (err) | 1665 | if (err) |
| 1643 | goto out; | 1666 | goto out; |
| 1644 | 1667 | ||
| 1645 | if (c->old_leb_cnt != c->leb_cnt) { | ||
| 1646 | struct ubifs_sb_node *sup = c->sup_node; | ||
| 1647 | |||
| 1648 | sup->leb_cnt = cpu_to_le32(c->leb_cnt); | ||
| 1649 | err = ubifs_write_sb_node(c, sup); | ||
| 1650 | if (err) | ||
| 1651 | goto out; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | if (c->need_recovery) { | 1668 | if (c->need_recovery) { |
| 1655 | ubifs_msg(c, "completing deferred recovery"); | 1669 | ubifs_msg(c, "completing deferred recovery"); |
| 1656 | err = ubifs_write_rcvrd_mst_node(c); | 1670 | err = ubifs_write_rcvrd_mst_node(c); |
| @@ -1682,6 +1696,16 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
| 1682 | goto out; | 1696 | goto out; |
| 1683 | } | 1697 | } |
| 1684 | 1698 | ||
| 1699 | if (c->superblock_need_write) { | ||
| 1700 | struct ubifs_sb_node *sup = c->sup_node; | ||
| 1701 | |||
| 1702 | err = ubifs_write_sb_node(c, sup); | ||
| 1703 | if (err) | ||
| 1704 | goto out; | ||
| 1705 | |||
| 1706 | c->superblock_need_write = 0; | ||
| 1707 | } | ||
| 1708 | |||
| 1685 | c->ileb_buf = vmalloc(c->leb_size); | 1709 | c->ileb_buf = vmalloc(c->leb_size); |
| 1686 | if (!c->ileb_buf) { | 1710 | if (!c->ileb_buf) { |
| 1687 | err = -ENOMEM; | 1711 | err = -ENOMEM; |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index f5a823cb0e43..e8e7b0e9532e 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
| @@ -1158,8 +1158,8 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c, | |||
| 1158 | * o exact match, i.e. the found zero-level znode contains key @key, then %1 | 1158 | * o exact match, i.e. the found zero-level znode contains key @key, then %1 |
| 1159 | * is returned and slot number of the matched branch is stored in @n; | 1159 | * is returned and slot number of the matched branch is stored in @n; |
| 1160 | * o not exact match, which means that zero-level znode does not contain | 1160 | * o not exact match, which means that zero-level znode does not contain |
| 1161 | * @key, then %0 is returned and slot number of the closest branch is stored | 1161 | * @key, then %0 is returned and slot number of the closest branch or %-1 |
| 1162 | * in @n; | 1162 | * is stored in @n; In this case calling tnc_next() is mandatory. |
| 1163 | * o @key is so small that it is even less than the lowest key of the | 1163 | * o @key is so small that it is even less than the lowest key of the |
| 1164 | * leftmost zero-level node, then %0 is returned and %0 is stored in @n. | 1164 | * leftmost zero-level node, then %0 is returned and %0 is stored in @n. |
| 1165 | * | 1165 | * |
| @@ -1882,13 +1882,19 @@ int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, | |||
| 1882 | 1882 | ||
| 1883 | static int search_dh_cookie(struct ubifs_info *c, const union ubifs_key *key, | 1883 | static int search_dh_cookie(struct ubifs_info *c, const union ubifs_key *key, |
| 1884 | struct ubifs_dent_node *dent, uint32_t cookie, | 1884 | struct ubifs_dent_node *dent, uint32_t cookie, |
| 1885 | struct ubifs_znode **zn, int *n) | 1885 | struct ubifs_znode **zn, int *n, int exact) |
| 1886 | { | 1886 | { |
| 1887 | int err; | 1887 | int err; |
| 1888 | struct ubifs_znode *znode = *zn; | 1888 | struct ubifs_znode *znode = *zn; |
| 1889 | struct ubifs_zbranch *zbr; | 1889 | struct ubifs_zbranch *zbr; |
| 1890 | union ubifs_key *dkey; | 1890 | union ubifs_key *dkey; |
| 1891 | 1891 | ||
| 1892 | if (!exact) { | ||
| 1893 | err = tnc_next(c, &znode, n); | ||
| 1894 | if (err) | ||
| 1895 | return err; | ||
| 1896 | } | ||
| 1897 | |||
| 1892 | for (;;) { | 1898 | for (;;) { |
| 1893 | zbr = &znode->zbranch[*n]; | 1899 | zbr = &znode->zbranch[*n]; |
| 1894 | dkey = &zbr->key; | 1900 | dkey = &zbr->key; |
| @@ -1930,7 +1936,7 @@ static int do_lookup_dh(struct ubifs_info *c, const union ubifs_key *key, | |||
| 1930 | if (unlikely(err < 0)) | 1936 | if (unlikely(err < 0)) |
| 1931 | goto out_unlock; | 1937 | goto out_unlock; |
| 1932 | 1938 | ||
| 1933 | err = search_dh_cookie(c, key, dent, cookie, &znode, &n); | 1939 | err = search_dh_cookie(c, key, dent, cookie, &znode, &n, err); |
| 1934 | 1940 | ||
| 1935 | out_unlock: | 1941 | out_unlock: |
| 1936 | mutex_unlock(&c->tnc_mutex); | 1942 | mutex_unlock(&c->tnc_mutex); |
| @@ -2723,7 +2729,7 @@ int ubifs_tnc_remove_dh(struct ubifs_info *c, const union ubifs_key *key, | |||
| 2723 | if (unlikely(err < 0)) | 2729 | if (unlikely(err < 0)) |
| 2724 | goto out_free; | 2730 | goto out_free; |
| 2725 | 2731 | ||
| 2726 | err = search_dh_cookie(c, key, dent, cookie, &znode, &n); | 2732 | err = search_dh_cookie(c, key, dent, cookie, &znode, &n, err); |
| 2727 | if (err) | 2733 | if (err) |
| 2728 | goto out_free; | 2734 | goto out_free; |
| 2729 | } | 2735 | } |
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index 86f0f2be116c..3c9792cbb6ff 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h | |||
| @@ -275,6 +275,8 @@ enum { | |||
| 275 | #define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) | 275 | #define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) |
| 276 | #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) | 276 | #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) |
| 277 | #define UBIFS_AUTH_NODE_SZ sizeof(struct ubifs_auth_node) | 277 | #define UBIFS_AUTH_NODE_SZ sizeof(struct ubifs_auth_node) |
| 278 | #define UBIFS_SIG_NODE_SZ sizeof(struct ubifs_sig_node) | ||
| 279 | |||
| 278 | /* Extended attribute entry nodes are identical to directory entry nodes */ | 280 | /* Extended attribute entry nodes are identical to directory entry nodes */ |
| 279 | #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ | 281 | #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ |
| 280 | /* Only this does not have to be multiple of 8 bytes */ | 282 | /* Only this does not have to be multiple of 8 bytes */ |
| @@ -301,6 +303,8 @@ enum { | |||
| 301 | */ | 303 | */ |
| 302 | #define UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT "c" | 304 | #define UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT "c" |
| 303 | 305 | ||
| 306 | /* Type field in ubifs_sig_node */ | ||
| 307 | #define UBIFS_SIGNATURE_TYPE_PKCS7 1 | ||
| 304 | 308 | ||
| 305 | /* | 309 | /* |
| 306 | * On-flash inode flags. | 310 | * On-flash inode flags. |
| @@ -336,12 +340,14 @@ enum { | |||
| 336 | * UBIFS_COMPR_NONE: no compression | 340 | * UBIFS_COMPR_NONE: no compression |
| 337 | * UBIFS_COMPR_LZO: LZO compression | 341 | * UBIFS_COMPR_LZO: LZO compression |
| 338 | * UBIFS_COMPR_ZLIB: ZLIB compression | 342 | * UBIFS_COMPR_ZLIB: ZLIB compression |
| 343 | * UBIFS_COMPR_ZSTD: ZSTD compression | ||
| 339 | * UBIFS_COMPR_TYPES_CNT: count of supported compression types | 344 | * UBIFS_COMPR_TYPES_CNT: count of supported compression types |
| 340 | */ | 345 | */ |
| 341 | enum { | 346 | enum { |
| 342 | UBIFS_COMPR_NONE, | 347 | UBIFS_COMPR_NONE, |
| 343 | UBIFS_COMPR_LZO, | 348 | UBIFS_COMPR_LZO, |
| 344 | UBIFS_COMPR_ZLIB, | 349 | UBIFS_COMPR_ZLIB, |
| 350 | UBIFS_COMPR_ZSTD, | ||
| 345 | UBIFS_COMPR_TYPES_CNT, | 351 | UBIFS_COMPR_TYPES_CNT, |
| 346 | }; | 352 | }; |
| 347 | 353 | ||
| @@ -361,6 +367,7 @@ enum { | |||
| 361 | * UBIFS_CS_NODE: commit start node | 367 | * UBIFS_CS_NODE: commit start node |
| 362 | * UBIFS_ORPH_NODE: orphan node | 368 | * UBIFS_ORPH_NODE: orphan node |
| 363 | * UBIFS_AUTH_NODE: authentication node | 369 | * UBIFS_AUTH_NODE: authentication node |
| 370 | * UBIFS_SIG_NODE: signature node | ||
| 364 | * UBIFS_NODE_TYPES_CNT: count of supported node types | 371 | * UBIFS_NODE_TYPES_CNT: count of supported node types |
| 365 | * | 372 | * |
| 366 | * Note, we index arrays by these numbers, so keep them low and contiguous. | 373 | * Note, we index arrays by these numbers, so keep them low and contiguous. |
| @@ -381,6 +388,7 @@ enum { | |||
| 381 | UBIFS_CS_NODE, | 388 | UBIFS_CS_NODE, |
| 382 | UBIFS_ORPH_NODE, | 389 | UBIFS_ORPH_NODE, |
| 383 | UBIFS_AUTH_NODE, | 390 | UBIFS_AUTH_NODE, |
| 391 | UBIFS_SIG_NODE, | ||
| 384 | UBIFS_NODE_TYPES_CNT, | 392 | UBIFS_NODE_TYPES_CNT, |
| 385 | }; | 393 | }; |
| 386 | 394 | ||
| @@ -638,6 +646,8 @@ struct ubifs_pad_node { | |||
| 638 | * @hmac_wkm: HMAC of a well known message (the string "UBIFS") as a convenience | 646 | * @hmac_wkm: HMAC of a well known message (the string "UBIFS") as a convenience |
| 639 | * to the user to check if the correct key is passed. | 647 | * to the user to check if the correct key is passed. |
| 640 | * @hash_algo: The hash algo used for this filesystem (one of enum hash_algo) | 648 | * @hash_algo: The hash algo used for this filesystem (one of enum hash_algo) |
| 649 | * @hash_mst: hash of the master node, only valid for signed images in which the | ||
| 650 | * master node does not contain a hmac | ||
| 641 | */ | 651 | */ |
| 642 | struct ubifs_sb_node { | 652 | struct ubifs_sb_node { |
| 643 | struct ubifs_ch ch; | 653 | struct ubifs_ch ch; |
| @@ -668,7 +678,8 @@ struct ubifs_sb_node { | |||
| 668 | __u8 hmac[UBIFS_MAX_HMAC_LEN]; | 678 | __u8 hmac[UBIFS_MAX_HMAC_LEN]; |
| 669 | __u8 hmac_wkm[UBIFS_MAX_HMAC_LEN]; | 679 | __u8 hmac_wkm[UBIFS_MAX_HMAC_LEN]; |
| 670 | __le16 hash_algo; | 680 | __le16 hash_algo; |
| 671 | __u8 padding2[3838]; | 681 | __u8 hash_mst[UBIFS_MAX_HASH_LEN]; |
| 682 | __u8 padding2[3774]; | ||
| 672 | } __packed; | 683 | } __packed; |
| 673 | 684 | ||
| 674 | /** | 685 | /** |
| @@ -771,6 +782,23 @@ struct ubifs_auth_node { | |||
| 771 | } __packed; | 782 | } __packed; |
| 772 | 783 | ||
| 773 | /** | 784 | /** |
| 785 | * struct ubifs_sig_node - node for signing other nodes | ||
| 786 | * @ch: common header | ||
| 787 | * @type: type of the signature, currently only UBIFS_SIGNATURE_TYPE_PKCS7 | ||
| 788 | * supported | ||
| 789 | * @len: The length of the signature data | ||
| 790 | * @padding: reserved for future, zeroes | ||
| 791 | * @sig: The signature data | ||
| 792 | */ | ||
| 793 | struct ubifs_sig_node { | ||
| 794 | struct ubifs_ch ch; | ||
| 795 | __le32 type; | ||
| 796 | __le32 len; | ||
| 797 | __u8 padding[32]; | ||
| 798 | __u8 sig[]; | ||
| 799 | } __packed; | ||
| 800 | |||
| 801 | /** | ||
| 774 | * struct ubifs_branch - key/reference/length branch | 802 | * struct ubifs_branch - key/reference/length branch |
| 775 | * @lnum: LEB number of the target node | 803 | * @lnum: LEB number of the target node |
| 776 | * @offs: offset within @lnum | 804 | * @offs: offset within @lnum |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 745b23e5b406..c55f212dcb75 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -1104,7 +1104,6 @@ struct ubifs_debug_info; | |||
| 1104 | * used to store indexing nodes (@leb_size - @max_idx_node_sz) | 1104 | * used to store indexing nodes (@leb_size - @max_idx_node_sz) |
| 1105 | * @leb_cnt: count of logical eraseblocks | 1105 | * @leb_cnt: count of logical eraseblocks |
| 1106 | * @max_leb_cnt: maximum count of logical eraseblocks | 1106 | * @max_leb_cnt: maximum count of logical eraseblocks |
| 1107 | * @old_leb_cnt: count of logical eraseblocks before re-size | ||
| 1108 | * @ro_media: the underlying UBI volume is read-only | 1107 | * @ro_media: the underlying UBI volume is read-only |
| 1109 | * @ro_mount: the file-system was mounted as read-only | 1108 | * @ro_mount: the file-system was mounted as read-only |
| 1110 | * @ro_error: UBIFS switched to R/O mode because an error happened | 1109 | * @ro_error: UBIFS switched to R/O mode because an error happened |
| @@ -1295,6 +1294,7 @@ struct ubifs_info { | |||
| 1295 | unsigned int rw_incompat:1; | 1294 | unsigned int rw_incompat:1; |
| 1296 | unsigned int assert_action:2; | 1295 | unsigned int assert_action:2; |
| 1297 | unsigned int authenticated:1; | 1296 | unsigned int authenticated:1; |
| 1297 | unsigned int superblock_need_write:1; | ||
| 1298 | 1298 | ||
| 1299 | struct mutex tnc_mutex; | 1299 | struct mutex tnc_mutex; |
| 1300 | struct ubifs_zbranch zroot; | 1300 | struct ubifs_zbranch zroot; |
| @@ -1352,7 +1352,6 @@ struct ubifs_info { | |||
| 1352 | int idx_leb_size; | 1352 | int idx_leb_size; |
| 1353 | int leb_cnt; | 1353 | int leb_cnt; |
| 1354 | int max_leb_cnt; | 1354 | int max_leb_cnt; |
| 1355 | int old_leb_cnt; | ||
| 1356 | unsigned int ro_media:1; | 1355 | unsigned int ro_media:1; |
| 1357 | unsigned int ro_mount:1; | 1356 | unsigned int ro_mount:1; |
| 1358 | unsigned int ro_error:1; | 1357 | unsigned int ro_error:1; |
| @@ -1680,6 +1679,9 @@ static inline int ubifs_auth_node_sz(const struct ubifs_info *c) | |||
| 1680 | else | 1679 | else |
| 1681 | return 0; | 1680 | return 0; |
| 1682 | } | 1681 | } |
| 1682 | int ubifs_sb_verify_signature(struct ubifs_info *c, | ||
| 1683 | const struct ubifs_sb_node *sup); | ||
| 1684 | bool ubifs_hmac_zero(struct ubifs_info *c, const u8 *hmac); | ||
| 1683 | 1685 | ||
| 1684 | int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac); | 1686 | int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac); |
| 1685 | 1687 | ||
