.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * This file is part of UBIFS. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2006-2008 Nokia Corporation. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
8 | | - * the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License along with |
---|
16 | | - * this program; if not, write to the Free Software Foundation, Inc., 51 |
---|
17 | | - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
---|
18 | 6 | * |
---|
19 | 7 | * Authors: Adrian Hunter |
---|
20 | 8 | * Artem Bityutskiy (Битюцкий Артём) |
---|
.. | .. |
---|
35 | 23 | #include "ubifs.h" |
---|
36 | 24 | |
---|
37 | 25 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, |
---|
38 | | - int len, int lnum, int offs); |
---|
| 26 | + struct ubifs_zbranch *zbr); |
---|
39 | 27 | static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, |
---|
40 | 28 | struct ubifs_zbranch *zbr, void *node); |
---|
41 | 29 | |
---|
.. | .. |
---|
55 | 43 | NAME_GREATER = 2, |
---|
56 | 44 | NOT_ON_MEDIA = 3, |
---|
57 | 45 | }; |
---|
| 46 | + |
---|
| 47 | +static void do_insert_old_idx(struct ubifs_info *c, |
---|
| 48 | + struct ubifs_old_idx *old_idx) |
---|
| 49 | +{ |
---|
| 50 | + struct ubifs_old_idx *o; |
---|
| 51 | + struct rb_node **p, *parent = NULL; |
---|
| 52 | + |
---|
| 53 | + p = &c->old_idx.rb_node; |
---|
| 54 | + while (*p) { |
---|
| 55 | + parent = *p; |
---|
| 56 | + o = rb_entry(parent, struct ubifs_old_idx, rb); |
---|
| 57 | + if (old_idx->lnum < o->lnum) |
---|
| 58 | + p = &(*p)->rb_left; |
---|
| 59 | + else if (old_idx->lnum > o->lnum) |
---|
| 60 | + p = &(*p)->rb_right; |
---|
| 61 | + else if (old_idx->offs < o->offs) |
---|
| 62 | + p = &(*p)->rb_left; |
---|
| 63 | + else if (old_idx->offs > o->offs) |
---|
| 64 | + p = &(*p)->rb_right; |
---|
| 65 | + else { |
---|
| 66 | + ubifs_err(c, "old idx added twice!"); |
---|
| 67 | + kfree(old_idx); |
---|
| 68 | + } |
---|
| 69 | + } |
---|
| 70 | + rb_link_node(&old_idx->rb, parent, p); |
---|
| 71 | + rb_insert_color(&old_idx->rb, &c->old_idx); |
---|
| 72 | +} |
---|
58 | 73 | |
---|
59 | 74 | /** |
---|
60 | 75 | * insert_old_idx - record an index node obsoleted since the last commit start. |
---|
.. | .. |
---|
81 | 96 | */ |
---|
82 | 97 | static int insert_old_idx(struct ubifs_info *c, int lnum, int offs) |
---|
83 | 98 | { |
---|
84 | | - struct ubifs_old_idx *old_idx, *o; |
---|
85 | | - struct rb_node **p, *parent = NULL; |
---|
| 99 | + struct ubifs_old_idx *old_idx; |
---|
86 | 100 | |
---|
87 | 101 | old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS); |
---|
88 | 102 | if (unlikely(!old_idx)) |
---|
89 | 103 | return -ENOMEM; |
---|
90 | 104 | old_idx->lnum = lnum; |
---|
91 | 105 | old_idx->offs = offs; |
---|
| 106 | + do_insert_old_idx(c, old_idx); |
---|
92 | 107 | |
---|
93 | | - p = &c->old_idx.rb_node; |
---|
94 | | - while (*p) { |
---|
95 | | - parent = *p; |
---|
96 | | - o = rb_entry(parent, struct ubifs_old_idx, rb); |
---|
97 | | - if (lnum < o->lnum) |
---|
98 | | - p = &(*p)->rb_left; |
---|
99 | | - else if (lnum > o->lnum) |
---|
100 | | - p = &(*p)->rb_right; |
---|
101 | | - else if (offs < o->offs) |
---|
102 | | - p = &(*p)->rb_left; |
---|
103 | | - else if (offs > o->offs) |
---|
104 | | - p = &(*p)->rb_right; |
---|
105 | | - else { |
---|
106 | | - ubifs_err(c, "old idx added twice!"); |
---|
107 | | - kfree(old_idx); |
---|
108 | | - return 0; |
---|
109 | | - } |
---|
110 | | - } |
---|
111 | | - rb_link_node(&old_idx->rb, parent, p); |
---|
112 | | - rb_insert_color(&old_idx->rb, &c->old_idx); |
---|
113 | 108 | return 0; |
---|
114 | 109 | } |
---|
115 | 110 | |
---|
.. | .. |
---|
211 | 206 | __set_bit(DIRTY_ZNODE, &zn->flags); |
---|
212 | 207 | __clear_bit(COW_ZNODE, &zn->flags); |
---|
213 | 208 | |
---|
214 | | - ubifs_assert(c, !ubifs_zn_obsolete(znode)); |
---|
215 | | - __set_bit(OBSOLETE_ZNODE, &znode->flags); |
---|
216 | | - |
---|
217 | | - if (znode->level != 0) { |
---|
218 | | - int i; |
---|
219 | | - const int n = zn->child_cnt; |
---|
220 | | - |
---|
221 | | - /* The children now have new parent */ |
---|
222 | | - for (i = 0; i < n; i++) { |
---|
223 | | - struct ubifs_zbranch *zbr = &zn->zbranch[i]; |
---|
224 | | - |
---|
225 | | - if (zbr->znode) |
---|
226 | | - zbr->znode->parent = zn; |
---|
227 | | - } |
---|
228 | | - } |
---|
229 | | - |
---|
230 | | - atomic_long_inc(&c->dirty_zn_cnt); |
---|
231 | 209 | return zn; |
---|
232 | 210 | } |
---|
233 | 211 | |
---|
.. | .. |
---|
243 | 221 | { |
---|
244 | 222 | c->calc_idx_sz -= ALIGN(dirt, 8); |
---|
245 | 223 | return ubifs_add_dirt(c, lnum, dirt); |
---|
| 224 | +} |
---|
| 225 | + |
---|
| 226 | +/** |
---|
| 227 | + * replace_znode - replace old znode with new znode. |
---|
| 228 | + * @c: UBIFS file-system description object |
---|
| 229 | + * @new_zn: new znode |
---|
| 230 | + * @old_zn: old znode |
---|
| 231 | + * @zbr: the branch of parent znode |
---|
| 232 | + * |
---|
| 233 | + * Replace old znode with new znode in TNC. |
---|
| 234 | + */ |
---|
| 235 | +static void replace_znode(struct ubifs_info *c, struct ubifs_znode *new_zn, |
---|
| 236 | + struct ubifs_znode *old_zn, struct ubifs_zbranch *zbr) |
---|
| 237 | +{ |
---|
| 238 | + ubifs_assert(c, !ubifs_zn_obsolete(old_zn)); |
---|
| 239 | + __set_bit(OBSOLETE_ZNODE, &old_zn->flags); |
---|
| 240 | + |
---|
| 241 | + if (old_zn->level != 0) { |
---|
| 242 | + int i; |
---|
| 243 | + const int n = new_zn->child_cnt; |
---|
| 244 | + |
---|
| 245 | + /* The children now have new parent */ |
---|
| 246 | + for (i = 0; i < n; i++) { |
---|
| 247 | + struct ubifs_zbranch *child = &new_zn->zbranch[i]; |
---|
| 248 | + |
---|
| 249 | + if (child->znode) |
---|
| 250 | + child->znode->parent = new_zn; |
---|
| 251 | + } |
---|
| 252 | + } |
---|
| 253 | + |
---|
| 254 | + zbr->znode = new_zn; |
---|
| 255 | + zbr->lnum = 0; |
---|
| 256 | + zbr->offs = 0; |
---|
| 257 | + zbr->len = 0; |
---|
| 258 | + |
---|
| 259 | + atomic_long_inc(&c->dirty_zn_cnt); |
---|
246 | 260 | } |
---|
247 | 261 | |
---|
248 | 262 | /** |
---|
.. | .. |
---|
277 | 291 | return zn; |
---|
278 | 292 | |
---|
279 | 293 | if (zbr->len) { |
---|
280 | | - err = insert_old_idx(c, zbr->lnum, zbr->offs); |
---|
281 | | - if (unlikely(err)) |
---|
282 | | - return ERR_PTR(err); |
---|
| 294 | + struct ubifs_old_idx *old_idx; |
---|
| 295 | + |
---|
| 296 | + old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS); |
---|
| 297 | + if (unlikely(!old_idx)) { |
---|
| 298 | + err = -ENOMEM; |
---|
| 299 | + goto out; |
---|
| 300 | + } |
---|
| 301 | + old_idx->lnum = zbr->lnum; |
---|
| 302 | + old_idx->offs = zbr->offs; |
---|
| 303 | + |
---|
283 | 304 | err = add_idx_dirt(c, zbr->lnum, zbr->len); |
---|
284 | | - } else |
---|
285 | | - err = 0; |
---|
| 305 | + if (err) { |
---|
| 306 | + kfree(old_idx); |
---|
| 307 | + goto out; |
---|
| 308 | + } |
---|
286 | 309 | |
---|
287 | | - zbr->znode = zn; |
---|
288 | | - zbr->lnum = 0; |
---|
289 | | - zbr->offs = 0; |
---|
290 | | - zbr->len = 0; |
---|
| 310 | + do_insert_old_idx(c, old_idx); |
---|
| 311 | + } |
---|
291 | 312 | |
---|
292 | | - if (unlikely(err)) |
---|
293 | | - return ERR_PTR(err); |
---|
| 313 | + replace_znode(c, zn, znode, zbr); |
---|
| 314 | + |
---|
294 | 315 | return zn; |
---|
| 316 | + |
---|
| 317 | +out: |
---|
| 318 | + kfree(zn); |
---|
| 319 | + return ERR_PTR(err); |
---|
295 | 320 | } |
---|
296 | 321 | |
---|
297 | 322 | /** |
---|
.. | .. |
---|
372 | 397 | /** |
---|
373 | 398 | * lnc_free - remove a leaf node from the leaf node cache. |
---|
374 | 399 | * @zbr: zbranch of leaf node |
---|
375 | | - * @node: leaf node |
---|
376 | 400 | */ |
---|
377 | 401 | static void lnc_free(struct ubifs_zbranch *zbr) |
---|
378 | 402 | { |
---|
.. | .. |
---|
433 | 457 | * @c: UBIFS file-system description object |
---|
434 | 458 | * @buf: buffer to read to |
---|
435 | 459 | * @type: node type |
---|
436 | | - * @len: node length (not aligned) |
---|
437 | | - * @lnum: LEB number of node to read |
---|
438 | | - * @offs: offset of node to read |
---|
| 460 | + * @zbr: the zbranch describing the node to read |
---|
439 | 461 | * |
---|
440 | 462 | * This function tries to read a node of known type and length, checks it and |
---|
441 | 463 | * stores it in @buf. This function returns %1 if a node is present and %0 if |
---|
.. | .. |
---|
453 | 475 | * journal nodes may potentially be corrupted, so checking is required. |
---|
454 | 476 | */ |
---|
455 | 477 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, |
---|
456 | | - int len, int lnum, int offs) |
---|
| 478 | + struct ubifs_zbranch *zbr) |
---|
457 | 479 | { |
---|
| 480 | + int len = zbr->len; |
---|
| 481 | + int lnum = zbr->lnum; |
---|
| 482 | + int offs = zbr->offs; |
---|
458 | 483 | int err, node_len; |
---|
459 | 484 | struct ubifs_ch *ch = buf; |
---|
460 | 485 | uint32_t crc, node_crc; |
---|
.. | .. |
---|
478 | 503 | if (node_len != len) |
---|
479 | 504 | return 0; |
---|
480 | 505 | |
---|
481 | | - if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting && |
---|
482 | | - !c->remounting_rw) |
---|
483 | | - return 1; |
---|
| 506 | + if (type != UBIFS_DATA_NODE || !c->no_chk_data_crc || c->mounting || |
---|
| 507 | + c->remounting_rw) { |
---|
| 508 | + crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
---|
| 509 | + node_crc = le32_to_cpu(ch->crc); |
---|
| 510 | + if (crc != node_crc) |
---|
| 511 | + return 0; |
---|
| 512 | + } |
---|
484 | 513 | |
---|
485 | | - crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
---|
486 | | - node_crc = le32_to_cpu(ch->crc); |
---|
487 | | - if (crc != node_crc) |
---|
| 514 | + err = ubifs_node_check_hash(c, buf, zbr->hash); |
---|
| 515 | + if (err) { |
---|
| 516 | + ubifs_bad_hash(c, buf, zbr->hash, lnum, offs); |
---|
488 | 517 | return 0; |
---|
| 518 | + } |
---|
489 | 519 | |
---|
490 | 520 | return 1; |
---|
491 | 521 | } |
---|
.. | .. |
---|
507 | 537 | |
---|
508 | 538 | dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs); |
---|
509 | 539 | |
---|
510 | | - ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum, |
---|
511 | | - zbr->offs); |
---|
| 540 | + ret = try_read_node(c, node, key_type(c, key), zbr); |
---|
512 | 541 | if (ret == 1) { |
---|
513 | 542 | union ubifs_key node_key; |
---|
514 | 543 | struct ubifs_dent_node *dent = node; |
---|
.. | .. |
---|
899 | 928 | int adding) |
---|
900 | 929 | { |
---|
901 | 930 | struct ubifs_znode *o_znode = NULL, *znode = *zn; |
---|
902 | | - int uninitialized_var(o_n), err, cmp, unsure = 0, nn = *n; |
---|
| 931 | + int o_n, err, cmp, unsure = 0, nn = *n; |
---|
903 | 932 | |
---|
904 | 933 | cmp = fallible_matches_name(c, &znode->zbranch[nn], nm); |
---|
905 | 934 | if (unlikely(cmp < 0)) |
---|
.. | .. |
---|
1521 | 1550 | */ |
---|
1522 | 1551 | int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) |
---|
1523 | 1552 | { |
---|
1524 | | - int n, err = 0, lnum = -1, uninitialized_var(offs); |
---|
1525 | | - int uninitialized_var(len); |
---|
| 1553 | + int n, err = 0, lnum = -1, offs; |
---|
| 1554 | + int len; |
---|
1526 | 1555 | unsigned int block = key_block(c, &bu->key); |
---|
1527 | 1556 | struct ubifs_znode *znode; |
---|
1528 | 1557 | |
---|
.. | .. |
---|
1711 | 1740 | if (err) { |
---|
1712 | 1741 | ubifs_err(c, "expected node type %d", UBIFS_DATA_NODE); |
---|
1713 | 1742 | goto out; |
---|
| 1743 | + } |
---|
| 1744 | + |
---|
| 1745 | + err = ubifs_node_check_hash(c, buf, zbr->hash); |
---|
| 1746 | + if (err) { |
---|
| 1747 | + ubifs_bad_hash(c, buf, zbr->hash, zbr->lnum, zbr->offs); |
---|
| 1748 | + return err; |
---|
1714 | 1749 | } |
---|
1715 | 1750 | |
---|
1716 | 1751 | len = le32_to_cpu(ch->len); |
---|
.. | .. |
---|
2266 | 2301 | * @lnum: LEB number of node |
---|
2267 | 2302 | * @offs: node offset |
---|
2268 | 2303 | * @len: node length |
---|
| 2304 | + * @hash: The hash over the node |
---|
2269 | 2305 | * |
---|
2270 | 2306 | * This function adds a node with key @key to TNC. The node may be new or it may |
---|
2271 | 2307 | * obsolete some existing one. Returns %0 on success or negative error code on |
---|
2272 | 2308 | * failure. |
---|
2273 | 2309 | */ |
---|
2274 | 2310 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, |
---|
2275 | | - int offs, int len) |
---|
| 2311 | + int offs, int len, const u8 *hash) |
---|
2276 | 2312 | { |
---|
2277 | 2313 | int found, n, err = 0; |
---|
2278 | 2314 | struct ubifs_znode *znode; |
---|
.. | .. |
---|
2287 | 2323 | zbr.lnum = lnum; |
---|
2288 | 2324 | zbr.offs = offs; |
---|
2289 | 2325 | zbr.len = len; |
---|
| 2326 | + ubifs_copy_hash(c, hash, zbr.hash); |
---|
2290 | 2327 | key_copy(c, key, &zbr.key); |
---|
2291 | 2328 | err = tnc_insert(c, znode, &zbr, n + 1); |
---|
2292 | 2329 | } else if (found == 1) { |
---|
.. | .. |
---|
2297 | 2334 | zbr->lnum = lnum; |
---|
2298 | 2335 | zbr->offs = offs; |
---|
2299 | 2336 | zbr->len = len; |
---|
| 2337 | + ubifs_copy_hash(c, hash, zbr->hash); |
---|
2300 | 2338 | } else |
---|
2301 | 2339 | err = found; |
---|
2302 | 2340 | if (!err) |
---|
.. | .. |
---|
2398 | 2436 | * @lnum: LEB number of node |
---|
2399 | 2437 | * @offs: node offset |
---|
2400 | 2438 | * @len: node length |
---|
| 2439 | + * @hash: The hash over the node |
---|
2401 | 2440 | * @nm: node name |
---|
2402 | 2441 | * |
---|
2403 | 2442 | * This is the same as 'ubifs_tnc_add()' but it should be used with keys which |
---|
2404 | 2443 | * may have collisions, like directory entry keys. |
---|
2405 | 2444 | */ |
---|
2406 | 2445 | int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, |
---|
2407 | | - int lnum, int offs, int len, |
---|
| 2446 | + int lnum, int offs, int len, const u8 *hash, |
---|
2408 | 2447 | const struct fscrypt_name *nm) |
---|
2409 | 2448 | { |
---|
2410 | 2449 | int found, n, err = 0; |
---|
.. | .. |
---|
2447 | 2486 | zbr->lnum = lnum; |
---|
2448 | 2487 | zbr->offs = offs; |
---|
2449 | 2488 | zbr->len = len; |
---|
| 2489 | + ubifs_copy_hash(c, hash, zbr->hash); |
---|
2450 | 2490 | goto out_unlock; |
---|
2451 | 2491 | } |
---|
2452 | 2492 | } |
---|
.. | .. |
---|
2458 | 2498 | zbr.lnum = lnum; |
---|
2459 | 2499 | zbr.offs = offs; |
---|
2460 | 2500 | zbr.len = len; |
---|
| 2501 | + ubifs_copy_hash(c, hash, zbr.hash); |
---|
2461 | 2502 | key_copy(c, key, &zbr.key); |
---|
2462 | 2503 | err = tnc_insert(c, znode, &zbr, n + 1); |
---|
2463 | 2504 | if (err) |
---|
.. | .. |
---|
2880 | 2921 | err = PTR_ERR(xent); |
---|
2881 | 2922 | if (err == -ENOENT) |
---|
2882 | 2923 | break; |
---|
| 2924 | + kfree(pxent); |
---|
2883 | 2925 | return err; |
---|
2884 | 2926 | } |
---|
2885 | 2927 | |
---|
.. | .. |
---|
2893 | 2935 | fname_len(&nm) = le16_to_cpu(xent->nlen); |
---|
2894 | 2936 | err = ubifs_tnc_remove_nm(c, &key1, &nm); |
---|
2895 | 2937 | if (err) { |
---|
| 2938 | + kfree(pxent); |
---|
2896 | 2939 | kfree(xent); |
---|
2897 | 2940 | return err; |
---|
2898 | 2941 | } |
---|
.. | .. |
---|
2901 | 2944 | highest_ino_key(c, &key2, xattr_inum); |
---|
2902 | 2945 | err = ubifs_tnc_remove_range(c, &key1, &key2); |
---|
2903 | 2946 | if (err) { |
---|
| 2947 | + kfree(pxent); |
---|
2904 | 2948 | kfree(xent); |
---|
2905 | 2949 | return err; |
---|
2906 | 2950 | } |
---|
.. | .. |
---|
3046 | 3090 | cnext = cnext->cnext; |
---|
3047 | 3091 | if (ubifs_zn_obsolete(znode)) |
---|
3048 | 3092 | kfree(znode); |
---|
| 3093 | + else if (!ubifs_zn_cow(znode)) { |
---|
| 3094 | + /* |
---|
| 3095 | + * Don't forget to update clean znode count after |
---|
| 3096 | + * committing failed, because ubifs will check this |
---|
| 3097 | + * count while closing tnc. Non-obsolete znode could |
---|
| 3098 | + * be re-dirtied during committing process, so dirty |
---|
| 3099 | + * flag is untrustable. The flag 'COW_ZNODE' is set |
---|
| 3100 | + * for each dirty znode before committing, and it is |
---|
| 3101 | + * cleared as long as the znode become clean, so we |
---|
| 3102 | + * can statistic clean znode count according to this |
---|
| 3103 | + * flag. |
---|
| 3104 | + */ |
---|
| 3105 | + atomic_long_inc(&c->clean_zn_cnt); |
---|
| 3106 | + atomic_long_inc(&ubifs_clean_zn_cnt); |
---|
| 3107 | + } |
---|
3049 | 3108 | } while (cnext && cnext != c->cnext); |
---|
3050 | 3109 | } |
---|
3051 | 3110 | |
---|
.. | .. |
---|
3461 | 3520 | /** |
---|
3462 | 3521 | * dbg_check_inode_size - check if inode size is correct. |
---|
3463 | 3522 | * @c: UBIFS file-system description object |
---|
3464 | | - * @inum: inode number |
---|
| 3523 | + * @inode: inode to check |
---|
3465 | 3524 | * @size: inode size |
---|
3466 | 3525 | * |
---|
3467 | 3526 | * This function makes sure that the inode size (@size) is correct and it does |
---|