diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-01-27 09:12:31 -0500 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-01-27 09:25:10 -0500 |
commit | 6f7ab6d458bbfc2f55d295fa3e6b9e69cdb1d517 (patch) | |
tree | 7d07f5ff88d205a652998c2fd281e7123ba9a112 | |
parent | 6ba87c9b920bea8c2703308d31eb7de925242c30 (diff) |
UBIFS: fix no_chk_data_crc
When data CRC checking is disabled, UBIFS returns incorrect return
code from the 'try_read_node()' function (0 instead of 1, which means
CRC error), which make the caller re-read the data node again, but using
a different code patch, so the second read is fine. Thus, we read the
same node twice. And the result of this is that UBIFS is slower
with no_chk_data_crc option than it is with chk_data_crc option.
This patches fixes the problem.
Reported-by: Reuben Dowle <Reuben.Dowle@navico.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r-- | fs/ubifs/io.c | 22 | ||||
-rw-r--r-- | fs/ubifs/tnc.c | 12 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 2 |
3 files changed, 23 insertions, 13 deletions
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 01682713af69..e8e632a1dcdf 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
@@ -29,7 +29,7 @@ | |||
29 | * would have been wasted for padding to the nearest minimal I/O unit boundary. | 29 | * would have been wasted for padding to the nearest minimal I/O unit boundary. |
30 | * Instead, data first goes to the write-buffer and is flushed when the | 30 | * Instead, data first goes to the write-buffer and is flushed when the |
31 | * buffer is full or when it is not used for some time (by timer). This is | 31 | * buffer is full or when it is not used for some time (by timer). This is |
32 | * similarto the mechanism is used by JFFS2. | 32 | * similar to the mechanism is used by JFFS2. |
33 | * | 33 | * |
34 | * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by | 34 | * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by |
35 | * mutexes defined inside these objects. Since sometimes upper-level code | 35 | * mutexes defined inside these objects. Since sometimes upper-level code |
@@ -75,7 +75,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) | |||
75 | * @lnum: logical eraseblock number | 75 | * @lnum: logical eraseblock number |
76 | * @offs: offset within the logical eraseblock | 76 | * @offs: offset within the logical eraseblock |
77 | * @quiet: print no messages | 77 | * @quiet: print no messages |
78 | * @chk_crc: indicates whether to always check the CRC | 78 | * @must_chk_crc: indicates whether to always check the CRC |
79 | * | 79 | * |
80 | * This function checks node magic number and CRC checksum. This function also | 80 | * This function checks node magic number and CRC checksum. This function also |
81 | * validates node length to prevent UBIFS from becoming crazy when an attacker | 81 | * validates node length to prevent UBIFS from becoming crazy when an attacker |
@@ -83,11 +83,17 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) | |||
83 | * node length in the common header could cause UBIFS to read memory outside of | 83 | * node length in the common header could cause UBIFS to read memory outside of |
84 | * allocated buffer when checking the CRC checksum. | 84 | * allocated buffer when checking the CRC checksum. |
85 | * | 85 | * |
86 | * This function returns zero in case of success %-EUCLEAN in case of bad CRC | 86 | * This function may skip data nodes CRC checking if @c->no_chk_data_crc is |
87 | * or magic. | 87 | * true, which is controlled by corresponding UBIFS mount option. However, if |
88 | * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is | ||
89 | * checked. Similarly, if @c->always_chk_crc is true, @c->no_chk_data_crc is | ||
90 | * ignored and CRC is checked. | ||
91 | * | ||
92 | * This function returns zero in case of success and %-EUCLEAN in case of bad | ||
93 | * CRC or magic. | ||
88 | */ | 94 | */ |
89 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | 95 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, |
90 | int offs, int quiet, int chk_crc) | 96 | int offs, int quiet, int must_chk_crc) |
91 | { | 97 | { |
92 | int err = -EINVAL, type, node_len; | 98 | int err = -EINVAL, type, node_len; |
93 | uint32_t crc, node_crc, magic; | 99 | uint32_t crc, node_crc, magic; |
@@ -123,9 +129,9 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | |||
123 | node_len > c->ranges[type].max_len) | 129 | node_len > c->ranges[type].max_len) |
124 | goto out_len; | 130 | goto out_len; |
125 | 131 | ||
126 | if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc) | 132 | if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc && |
127 | if (c->no_chk_data_crc) | 133 | c->no_chk_data_crc) |
128 | return 0; | 134 | return 0; |
129 | 135 | ||
130 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); | 136 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
131 | node_crc = le32_to_cpu(ch->crc); | 137 | node_crc = le32_to_cpu(ch->crc); |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index f7e36f545527..fa28a84c6a1b 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
@@ -443,6 +443,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr, | |||
443 | * This function performs that same function as ubifs_read_node except that | 443 | * This function performs that same function as ubifs_read_node except that |
444 | * it does not require that there is actually a node present and instead | 444 | * it does not require that there is actually a node present and instead |
445 | * the return code indicates if a node was read. | 445 | * the return code indicates if a node was read. |
446 | * | ||
447 | * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc | ||
448 | * is true (it is controlled by corresponding mount option). However, if | ||
449 | * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always | ||
450 | * checked. | ||
446 | */ | 451 | */ |
447 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, | 452 | static int try_read_node(const struct ubifs_info *c, void *buf, int type, |
448 | int len, int lnum, int offs) | 453 | int len, int lnum, int offs) |
@@ -470,9 +475,8 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, | |||
470 | if (node_len != len) | 475 | if (node_len != len) |
471 | return 0; | 476 | return 0; |
472 | 477 | ||
473 | if (type == UBIFS_DATA_NODE && !c->always_chk_crc) | 478 | if (type == UBIFS_DATA_NODE && !c->always_chk_crc && c->no_chk_data_crc) |
474 | if (c->no_chk_data_crc) | 479 | return 1; |
475 | return 0; | ||
476 | 480 | ||
477 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); | 481 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
478 | node_crc = le32_to_cpu(ch->crc); | 482 | node_crc = le32_to_cpu(ch->crc); |
@@ -1506,7 +1510,7 @@ out: | |||
1506 | * | 1510 | * |
1507 | * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function | 1511 | * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function |
1508 | * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares | 1512 | * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares |
1509 | * maxumum possible amount of nodes for bulk-read. | 1513 | * maximum possible amount of nodes for bulk-read. |
1510 | */ | 1514 | */ |
1511 | int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) | 1515 | int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) |
1512 | { | 1516 | { |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 9999ff0aaa43..29dfa816077b 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -1428,7 +1428,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, | |||
1428 | int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, | 1428 | int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, |
1429 | int offs, int dtype); | 1429 | int offs, int dtype); |
1430 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | 1430 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, |
1431 | int offs, int quiet, int chk_crc); | 1431 | int offs, int quiet, int must_chk_crc); |
1432 | void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); | 1432 | void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); |
1433 | void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); | 1433 | void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); |
1434 | int ubifs_io_init(struct ubifs_info *c); | 1434 | int ubifs_io_init(struct ubifs_info *c); |