All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] jbd2: fix r_count overflows leading to buffer overflow in journal recovery
@ 2015-05-13 18:56 Darrick J. Wong
  2015-05-14 12:19 ` Jan Kara
  0 siblings, 1 reply; 3+ messages in thread
From: Darrick J. Wong @ 2015-05-13 18:56 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4

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.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/jbd2/recovery.c |   10 +++++++++-
 fs/jbd2/revoke.c   |   18 ++++++++++--------
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index b5128c6..a9079d0 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -842,15 +842,23 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 {
 	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;
 
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index c6cbaef..fd9969d 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -577,7 +577,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
@@ -594,9 +594,14 @@ static void write_one_revoke_record(journal_t *journal,
 	if (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(journal_t *journal,
 		*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;

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] jbd2: fix r_count overflows leading to buffer overflow in journal recovery
  2015-05-13 18:56 [PATCH] jbd2: fix r_count overflows leading to buffer overflow in journal recovery Darrick J. Wong
@ 2015-05-14 12:19 ` Jan Kara
  2015-05-14 18:09   ` Darrick J. Wong
  0 siblings, 1 reply; 3+ messages in thread
From: Jan Kara @ 2015-05-14 12:19 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: tytso, linux-ext4

On Wed 13-05-15 11:56:46, Darrick J. Wong wrote:
> 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.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
...
> @@ -594,9 +594,14 @@ static void write_one_revoke_record(journal_t *journal,
>  	if (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) {
  Hum, but we can have strict inequality here, can't we? Otherwise the
patch looks good to me.

								Honza


-- 
Jan Kara <jack@suse.cz>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] jbd2: fix r_count overflows leading to buffer overflow in journal recovery
  2015-05-14 12:19 ` Jan Kara
@ 2015-05-14 18:09   ` Darrick J. Wong
  0 siblings, 0 replies; 3+ messages in thread
From: Darrick J. Wong @ 2015-05-14 18:09 UTC (permalink / raw)
  To: Jan Kara; +Cc: tytso, linux-ext4

On Thu, May 14, 2015 at 02:19:40PM +0200, Jan Kara wrote:
> On Wed 13-05-15 11:56:46, Darrick J. Wong wrote:
> > 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.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ...
> > @@ -594,9 +594,14 @@ static void write_one_revoke_record(journal_t *journal,
> >  	if (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) {
>   Hum, but we can have strict inequality here, can't we? Otherwise the
> patch looks good to me.

You're right, it could be greater-than here.  Will respin this and the
corresponding e2fsprogs patch.

--D

> 
> 								Honza
> 
> 
> -- 
> Jan Kara <jack@suse.cz>
> SUSE Labs, CR
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-05-14 18:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-13 18:56 [PATCH] jbd2: fix r_count overflows leading to buffer overflow in journal recovery Darrick J. Wong
2015-05-14 12:19 ` Jan Kara
2015-05-14 18:09   ` Darrick J. Wong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.