| .. | .. |
|---|
| 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 | |
|---|
| .. | .. |
|---|
| 372 | 360 | /** |
|---|
| 373 | 361 | * lnc_free - remove a leaf node from the leaf node cache. |
|---|
| 374 | 362 | * @zbr: zbranch of leaf node |
|---|
| 375 | | - * @node: leaf node |
|---|
| 376 | 363 | */ |
|---|
| 377 | 364 | static void lnc_free(struct ubifs_zbranch *zbr) |
|---|
| 378 | 365 | { |
|---|
| .. | .. |
|---|
| 433 | 420 | * @c: UBIFS file-system description object |
|---|
| 434 | 421 | * @buf: buffer to read to |
|---|
| 435 | 422 | * @type: node type |
|---|
| 436 | | - * @len: node length (not aligned) |
|---|
| 437 | | - * @lnum: LEB number of node to read |
|---|
| 438 | | - * @offs: offset of node to read |
|---|
| 423 | + * @zbr: the zbranch describing the node to read |
|---|
| 439 | 424 | * |
|---|
| 440 | 425 | * This function tries to read a node of known type and length, checks it and |
|---|
| 441 | 426 | * stores it in @buf. This function returns %1 if a node is present and %0 if |
|---|
| .. | .. |
|---|
| 453 | 438 | * journal nodes may potentially be corrupted, so checking is required. |
|---|
| 454 | 439 | */ |
|---|
| 455 | 440 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, |
|---|
| 456 | | - int len, int lnum, int offs) |
|---|
| 441 | + struct ubifs_zbranch *zbr) |
|---|
| 457 | 442 | { |
|---|
| 443 | + int len = zbr->len; |
|---|
| 444 | + int lnum = zbr->lnum; |
|---|
| 445 | + int offs = zbr->offs; |
|---|
| 458 | 446 | int err, node_len; |
|---|
| 459 | 447 | struct ubifs_ch *ch = buf; |
|---|
| 460 | 448 | uint32_t crc, node_crc; |
|---|
| .. | .. |
|---|
| 478 | 466 | if (node_len != len) |
|---|
| 479 | 467 | return 0; |
|---|
| 480 | 468 | |
|---|
| 481 | | - if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting && |
|---|
| 482 | | - !c->remounting_rw) |
|---|
| 483 | | - return 1; |
|---|
| 469 | + if (type != UBIFS_DATA_NODE || !c->no_chk_data_crc || c->mounting || |
|---|
| 470 | + c->remounting_rw) { |
|---|
| 471 | + crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
|---|
| 472 | + node_crc = le32_to_cpu(ch->crc); |
|---|
| 473 | + if (crc != node_crc) |
|---|
| 474 | + return 0; |
|---|
| 475 | + } |
|---|
| 484 | 476 | |
|---|
| 485 | | - crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
|---|
| 486 | | - node_crc = le32_to_cpu(ch->crc); |
|---|
| 487 | | - if (crc != node_crc) |
|---|
| 477 | + err = ubifs_node_check_hash(c, buf, zbr->hash); |
|---|
| 478 | + if (err) { |
|---|
| 479 | + ubifs_bad_hash(c, buf, zbr->hash, lnum, offs); |
|---|
| 488 | 480 | return 0; |
|---|
| 481 | + } |
|---|
| 489 | 482 | |
|---|
| 490 | 483 | return 1; |
|---|
| 491 | 484 | } |
|---|
| .. | .. |
|---|
| 507 | 500 | |
|---|
| 508 | 501 | dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs); |
|---|
| 509 | 502 | |
|---|
| 510 | | - ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum, |
|---|
| 511 | | - zbr->offs); |
|---|
| 503 | + ret = try_read_node(c, node, key_type(c, key), zbr); |
|---|
| 512 | 504 | if (ret == 1) { |
|---|
| 513 | 505 | union ubifs_key node_key; |
|---|
| 514 | 506 | struct ubifs_dent_node *dent = node; |
|---|
| .. | .. |
|---|
| 899 | 891 | int adding) |
|---|
| 900 | 892 | { |
|---|
| 901 | 893 | struct ubifs_znode *o_znode = NULL, *znode = *zn; |
|---|
| 902 | | - int uninitialized_var(o_n), err, cmp, unsure = 0, nn = *n; |
|---|
| 894 | + int o_n, err, cmp, unsure = 0, nn = *n; |
|---|
| 903 | 895 | |
|---|
| 904 | 896 | cmp = fallible_matches_name(c, &znode->zbranch[nn], nm); |
|---|
| 905 | 897 | if (unlikely(cmp < 0)) |
|---|
| .. | .. |
|---|
| 1521 | 1513 | */ |
|---|
| 1522 | 1514 | int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) |
|---|
| 1523 | 1515 | { |
|---|
| 1524 | | - int n, err = 0, lnum = -1, uninitialized_var(offs); |
|---|
| 1525 | | - int uninitialized_var(len); |
|---|
| 1516 | + int n, err = 0, lnum = -1, offs; |
|---|
| 1517 | + int len; |
|---|
| 1526 | 1518 | unsigned int block = key_block(c, &bu->key); |
|---|
| 1527 | 1519 | struct ubifs_znode *znode; |
|---|
| 1528 | 1520 | |
|---|
| .. | .. |
|---|
| 1711 | 1703 | if (err) { |
|---|
| 1712 | 1704 | ubifs_err(c, "expected node type %d", UBIFS_DATA_NODE); |
|---|
| 1713 | 1705 | goto out; |
|---|
| 1706 | + } |
|---|
| 1707 | + |
|---|
| 1708 | + err = ubifs_node_check_hash(c, buf, zbr->hash); |
|---|
| 1709 | + if (err) { |
|---|
| 1710 | + ubifs_bad_hash(c, buf, zbr->hash, zbr->lnum, zbr->offs); |
|---|
| 1711 | + return err; |
|---|
| 1714 | 1712 | } |
|---|
| 1715 | 1713 | |
|---|
| 1716 | 1714 | len = le32_to_cpu(ch->len); |
|---|
| .. | .. |
|---|
| 2266 | 2264 | * @lnum: LEB number of node |
|---|
| 2267 | 2265 | * @offs: node offset |
|---|
| 2268 | 2266 | * @len: node length |
|---|
| 2267 | + * @hash: The hash over the node |
|---|
| 2269 | 2268 | * |
|---|
| 2270 | 2269 | * This function adds a node with key @key to TNC. The node may be new or it may |
|---|
| 2271 | 2270 | * obsolete some existing one. Returns %0 on success or negative error code on |
|---|
| 2272 | 2271 | * failure. |
|---|
| 2273 | 2272 | */ |
|---|
| 2274 | 2273 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, |
|---|
| 2275 | | - int offs, int len) |
|---|
| 2274 | + int offs, int len, const u8 *hash) |
|---|
| 2276 | 2275 | { |
|---|
| 2277 | 2276 | int found, n, err = 0; |
|---|
| 2278 | 2277 | struct ubifs_znode *znode; |
|---|
| .. | .. |
|---|
| 2287 | 2286 | zbr.lnum = lnum; |
|---|
| 2288 | 2287 | zbr.offs = offs; |
|---|
| 2289 | 2288 | zbr.len = len; |
|---|
| 2289 | + ubifs_copy_hash(c, hash, zbr.hash); |
|---|
| 2290 | 2290 | key_copy(c, key, &zbr.key); |
|---|
| 2291 | 2291 | err = tnc_insert(c, znode, &zbr, n + 1); |
|---|
| 2292 | 2292 | } else if (found == 1) { |
|---|
| .. | .. |
|---|
| 2297 | 2297 | zbr->lnum = lnum; |
|---|
| 2298 | 2298 | zbr->offs = offs; |
|---|
| 2299 | 2299 | zbr->len = len; |
|---|
| 2300 | + ubifs_copy_hash(c, hash, zbr->hash); |
|---|
| 2300 | 2301 | } else |
|---|
| 2301 | 2302 | err = found; |
|---|
| 2302 | 2303 | if (!err) |
|---|
| .. | .. |
|---|
| 2398 | 2399 | * @lnum: LEB number of node |
|---|
| 2399 | 2400 | * @offs: node offset |
|---|
| 2400 | 2401 | * @len: node length |
|---|
| 2402 | + * @hash: The hash over the node |
|---|
| 2401 | 2403 | * @nm: node name |
|---|
| 2402 | 2404 | * |
|---|
| 2403 | 2405 | * This is the same as 'ubifs_tnc_add()' but it should be used with keys which |
|---|
| 2404 | 2406 | * may have collisions, like directory entry keys. |
|---|
| 2405 | 2407 | */ |
|---|
| 2406 | 2408 | int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key, |
|---|
| 2407 | | - int lnum, int offs, int len, |
|---|
| 2409 | + int lnum, int offs, int len, const u8 *hash, |
|---|
| 2408 | 2410 | const struct fscrypt_name *nm) |
|---|
| 2409 | 2411 | { |
|---|
| 2410 | 2412 | int found, n, err = 0; |
|---|
| .. | .. |
|---|
| 2447 | 2449 | zbr->lnum = lnum; |
|---|
| 2448 | 2450 | zbr->offs = offs; |
|---|
| 2449 | 2451 | zbr->len = len; |
|---|
| 2452 | + ubifs_copy_hash(c, hash, zbr->hash); |
|---|
| 2450 | 2453 | goto out_unlock; |
|---|
| 2451 | 2454 | } |
|---|
| 2452 | 2455 | } |
|---|
| .. | .. |
|---|
| 2458 | 2461 | zbr.lnum = lnum; |
|---|
| 2459 | 2462 | zbr.offs = offs; |
|---|
| 2460 | 2463 | zbr.len = len; |
|---|
| 2464 | + ubifs_copy_hash(c, hash, zbr.hash); |
|---|
| 2461 | 2465 | key_copy(c, key, &zbr.key); |
|---|
| 2462 | 2466 | err = tnc_insert(c, znode, &zbr, n + 1); |
|---|
| 2463 | 2467 | if (err) |
|---|
| .. | .. |
|---|
| 2880 | 2884 | err = PTR_ERR(xent); |
|---|
| 2881 | 2885 | if (err == -ENOENT) |
|---|
| 2882 | 2886 | break; |
|---|
| 2887 | + kfree(pxent); |
|---|
| 2883 | 2888 | return err; |
|---|
| 2884 | 2889 | } |
|---|
| 2885 | 2890 | |
|---|
| .. | .. |
|---|
| 2893 | 2898 | fname_len(&nm) = le16_to_cpu(xent->nlen); |
|---|
| 2894 | 2899 | err = ubifs_tnc_remove_nm(c, &key1, &nm); |
|---|
| 2895 | 2900 | if (err) { |
|---|
| 2901 | + kfree(pxent); |
|---|
| 2896 | 2902 | kfree(xent); |
|---|
| 2897 | 2903 | return err; |
|---|
| 2898 | 2904 | } |
|---|
| .. | .. |
|---|
| 2901 | 2907 | highest_ino_key(c, &key2, xattr_inum); |
|---|
| 2902 | 2908 | err = ubifs_tnc_remove_range(c, &key1, &key2); |
|---|
| 2903 | 2909 | if (err) { |
|---|
| 2910 | + kfree(pxent); |
|---|
| 2904 | 2911 | kfree(xent); |
|---|
| 2905 | 2912 | return err; |
|---|
| 2906 | 2913 | } |
|---|
| .. | .. |
|---|
| 3461 | 3468 | /** |
|---|
| 3462 | 3469 | * dbg_check_inode_size - check if inode size is correct. |
|---|
| 3463 | 3470 | * @c: UBIFS file-system description object |
|---|
| 3464 | | - * @inum: inode number |
|---|
| 3471 | + * @inode: inode to check |
|---|
| 3465 | 3472 | * @size: inode size |
|---|
| 3466 | 3473 | * |
|---|
| 3467 | 3474 | * This function makes sure that the inode size (@size) is correct and it does |
|---|