e2fsck: fix buffer overrun in revoke block scanning

Check the value of r_count to ensure that we never try to read revoke
records past the end of the revoke block.  It turns out that the
journal writing code in debugfs was also playing fast and loose with
the r_count, so fix that as well.

The Coverity bug was 1297508.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
debian
Darrick J. Wong 2015-05-16 20:50:21 -04:00 committed by Theodore Ts'o
parent f008143cf5
commit 04c66cb25f
7 changed files with 51 additions and 21 deletions

View File

@ -175,7 +175,7 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
void *buf;
size_t i, offset;
blk64_t curr_blk;
int csum_size = 0;
int sz, csum_size = 0;
struct buffer_head *bh;
errcode_t err;
@ -204,9 +204,15 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid);
offset = sizeof(*jrb);
if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
JFS_FEATURE_INCOMPAT_64BIT))
sz = 8;
else
sz = 4;
for (i = 0; i < revoke_len; i++) {
/* Block full, write to journal */
if (offset > trans->journal->j_blocksize - csum_size) {
if (offset + sz > trans->journal->j_blocksize - csum_size) {
jrb->r_count = ext2fs_cpu_to_be32(offset);
jbd2_revoke_csum_set(trans->journal, bh);
@ -233,16 +239,13 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
}
if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
JFS_FEATURE_INCOMPAT_64BIT)) {
JFS_FEATURE_INCOMPAT_64BIT))
*((__u64 *)(&((char *)buf)[offset])) =
ext2fs_cpu_to_be64(revoke_list[i]);
offset += 8;
} else {
else
*((__u32 *)(&((char *)buf)[offset])) =
ext2fs_cpu_to_be32(revoke_list[i]);
offset += 4;
}
offset += sz;
}
if (offset > 0) {

View File

@ -839,15 +839,23 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
{
journal_revoke_header_t *header;
int offset, max;
int csum_size = 0;
__u32 rcount;
int record_len = 4;
header = (journal_revoke_header_t *) bh->b_data;
offset = sizeof(journal_revoke_header_t);
max = ext2fs_be32_to_cpu(header->r_count);
rcount = ext2fs_be32_to_cpu(header->r_count);
if (!jbd2_revoke_block_csum_verify(journal, header))
return -EINVAL;
if (journal_has_csum_v2or3(journal))
csum_size = sizeof(struct journal_revoke_tail);
if (rcount > journal->j_blocksize - csum_size)
return -EINVAL;
max = rcount;
if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
record_len = 8;

View File

@ -583,7 +583,7 @@ static void write_one_revoke_record(journal_t *journal,
{
int csum_size = 0;
struct buffer_head *descriptor;
int offset;
int sz, offset;
journal_header_t *header;
/* If we are already aborting, this all becomes a noop. We
@ -600,9 +600,14 @@ static void write_one_revoke_record(journal_t *journal,
if (journal_has_csum_v2or3(journal))
csum_size = sizeof(struct journal_revoke_tail);
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
sz = 8;
else
sz = 4;
/* Make sure we have a descriptor with space left for the record */
if (descriptor) {
if (offset >= journal->j_blocksize - csum_size) {
if (offset + sz > journal->j_blocksize - csum_size) {
flush_descriptor(journal, descriptor, offset, write_op);
descriptor = NULL;
}
@ -625,16 +630,13 @@ static void write_one_revoke_record(journal_t *journal,
*descriptorp = descriptor;
}
if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT)) {
* ((__u64 *)(&descriptor->b_data[offset])) =
ext2fs_cpu_to_be64(record->blocknr);
offset += 8;
} else {
* ((__u32 *)(&descriptor->b_data[offset])) =
ext2fs_cpu_to_be32(record->blocknr);
offset += 4;
}
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) {
* ((__be64 *)(&descriptor->b_data[offset])) =
cpu_to_be64(record->blocknr);
else
* ((__be32 *)(&descriptor->b_data[offset])) =
cpu_to_be32(record->blocknr);
offset += sz;
*offsetp = offset;
}

View File

@ -0,0 +1,8 @@
test_filesys: recovering journal
../e2fsck/e2fsck: Invalid argument while recovering ext3 journal of test_filesys
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: ********** WARNING: Filesystem still has errors **********
Exit status is 12

View File

@ -0,0 +1,8 @@
test_filesys: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: 11/512 files (9.1% non-contiguous), 1066/2048 blocks
Exit status is 0

Binary file not shown.

View File

@ -0,0 +1 @@
corrupt revoke r_count buffer overflow