Patch "jbd2: fix r_count overflows leading to buffer overflow in journal recovery" has been added to the 4.0-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
jbd2: fix r_count overflows leading to buffer overflow in journal recovery
to the 4.0-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
jbd2-fix-r_count-overflows-leading-to-buffer-overflow-in-journal-recovery.patch
and it can be found in the queue-4.0 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
e531d0bceb402e643a4499de40dd3fa39d8d2e43Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <[email protected]>
Date: Thu, 14 May 2015 19:11:50 -0400
Subject: jbd2: fix r_count overflows leading to buffer overflow in journal recovery
From: "Darrick J. Wong" <[email protected]>
commit e531d0bceb402e643a4499de40dd3fa39d8d2e43 upstream.
The journal revoke block recovery code does not check r_count for sanity, which means that an evil value of r_count could result in the kernel reading off the end of the revoke table and into whatever garbage lies beyond. This could crash the kernel, so fix that.
However, in testing this fix, I discovered that the code to write out the revoke tables also was not correctly checking to see if the block was full -- the current offset check is fine so long as the revoke table space size is a multiple of the record size, but this is not true when either journal_csum_v[23] are set.
--- fs/jbd2/recovery.c | 10 +++++++++- fs/jbd2/revoke.c | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-)
fs/jbd2/recovery.c +9 -1
@@ -842,15 +842,23 @@ static int scan_revoke_records(journal_t {jbd2_journal_revoke_header_t *header;int offset, max; +int csum_size =0 ; +__u32 rcount;int record_len =4 ; header = (jbd2_journal_revoke_header_t *) bh->b_data; offset =sizeof (jbd2_journal_revoke_header_t); - max =be32_to_cpu (header->r_count); + rcount =be32_to_cpu (header->r_count);if (!jbd2_revoke_block_csum_verify (journal, header))return -EINVAL ; +if (jbd2_journal_has_csum_v2or3 (journal)) + csum_size =sizeof (struct jbd2_journal_revoke_tail ); +if (rcount > journal->j_blocksize - csum_size) +return -EINVAL ; + max = rcount; +if (JBD2_HAS_INCOMPAT_FEATURE (journal,JBD2_FEATURE_INCOMPAT_64BIT )) record_len =8 ;
fs/jbd2/revoke.c +10 -8
@@ -577,7 +577,7 @@ static void write_one_revoke_record(jour {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
@@ -594,9 +594,14 @@ static void write_one_revoke_record(jourif (jbd2_journal_has_csum_v2or3 (journal)) csum_size =sizeof (struct jbd2_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 ; }
@@ -619,16 +624,13 @@ static void write_one_revoke_record(jour *descriptorp = descriptor; } -if (JBD2_HAS_INCOMPAT_FEATURE (journal,JBD2_FEATURE_INCOMPAT_64BIT )) { +if (JBD2_HAS_INCOMPAT_FEATURE (journal,JBD2_FEATURE_INCOMPAT_64BIT )) * ((__be64 *)(&descriptor->b_data[offset])) =cpu_to_be64 (record->blocknr); - offset +=8 ; - - }else { +else * ((__be32 *)(&descriptor->b_data[offset])) =cpu_to_be32 (record->blocknr); - offset +=4 ; - } + offset += sz; *offsetp = offset; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.0/jbd2-fix-r_count-overflows-leading-to-buffer-overflow-in-journal-recovery.patch