aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2021-02-13 11:54:58 -0500
committerTheodore Ts'o <tytso@mit.edu>2021-02-13 11:54:58 -0500
commitff9b039b1f6c86b144686d5baf57dbce14998285 (patch)
tree94f66240d610f9531c74f859dd692de04c7d5890
parent28e22540e24fd2a70b8adf805fad4961f5234d21 (diff)
downloade2fsprogs-ff9b039b1f6c86b144686d5baf57dbce14998285.tar.gz
debugfs: clamp journal s_maxlen value when dumping the journal log
Addresses-Coverity-Bug: 1432478 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--debugfs/logdump.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/debugfs/logdump.c b/debugfs/logdump.c
index 6826b2507..ea01db7a7 100644
--- a/debugfs/logdump.c
+++ b/debugfs/logdump.c
@@ -56,7 +56,7 @@ static void dump_journal(char *, FILE *, struct journal_source *);
static void dump_descriptor_block(FILE *, struct journal_source *,
char *, journal_superblock_t *,
- unsigned int *, int, tid_t);
+ unsigned int *, int, __u32, tid_t);
static void dump_revoke_block(FILE *, char *, journal_superblock_t *,
unsigned int, int, tid_t);
@@ -71,10 +71,9 @@ static void dump_fc_block(FILE *out_file, char *buf, int blocksize,
static void do_hexdump (FILE *, char *, int);
-#define WRAP(jsb, blocknr) \
- if (blocknr >= be32_to_cpu((jsb)->s_maxlen)) \
- blocknr -= (be32_to_cpu((jsb)->s_maxlen) - \
- be32_to_cpu((jsb)->s_first));
+#define WRAP(jsb, blocknr, maxlen) \
+ if (blocknr >= (maxlen)) \
+ blocknr -= (maxlen - be32_to_cpu((jsb)->s_first));
void do_logdump(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
void *infop EXT2FS_ATTR((unused)))
@@ -359,6 +358,8 @@ static void dump_journal(char *cmdname, FILE *out_file,
tid_t transaction;
unsigned int blocknr = 0;
int fc_done;
+ __u64 total_len;
+ __u32 maxlen;
/* First, check to see if there's an ext2 superblock header */
retval = read_journal_block(cmdname, source, 0, buf, 2048);
@@ -417,6 +418,25 @@ static void dump_journal(char *cmdname, FILE *out_file,
}
transaction = be32_to_cpu(jsb->s_sequence);
blocknr = be32_to_cpu(jsb->s_start);
+ if (source->where == JOURNAL_IS_INTERNAL) {
+ retval = ext2fs_file_get_lsize(source->file, &total_len);
+ if (retval) {
+ stat_err:
+ com_err("dump_journal", retval,
+ "while getting journal inode size");
+ return;
+ }
+ total_len /= blocksize;
+ } else {
+ struct stat st;
+
+ if (fstat(source->fd, &st) < 0)
+ goto stat_err;
+ total_len = st.st_size / blocksize;
+ }
+ maxlen = be32_to_cpu(jsb->s_maxlen);
+ if (maxlen > total_len)
+ maxlen = total_len;
fprintf(out_file, "Journal starts at block %u, transaction %u\n",
blocknr, transaction);
@@ -466,14 +486,14 @@ static void dump_journal(char *cmdname, FILE *out_file,
switch (blocktype) {
case JBD2_DESCRIPTOR_BLOCK:
dump_descriptor_block(out_file, source, buf, jsb,
- &blocknr, blocksize,
+ &blocknr, blocksize, maxlen,
transaction);
continue;
case JBD2_COMMIT_BLOCK:
transaction++;
blocknr++;
- WRAP(jsb, blocknr);
+ WRAP(jsb, blocknr, maxlen);
continue;
case JBD2_REVOKE_BLOCK:
@@ -481,7 +501,7 @@ static void dump_journal(char *cmdname, FILE *out_file,
blocknr, blocksize,
transaction);
blocknr++;
- WRAP(jsb, blocknr);
+ WRAP(jsb, blocknr, maxlen);
continue;
default:
@@ -492,8 +512,8 @@ static void dump_journal(char *cmdname, FILE *out_file,
}
fc:
- blocknr = be32_to_cpu(jsb->s_maxlen) - jbd2_journal_get_num_fc_blks(jsb) + 1;
- while (blocknr <= be32_to_cpu(jsb->s_maxlen)) {
+ blocknr = maxlen - jbd2_journal_get_num_fc_blks(jsb) + 1;
+ while (blocknr <= maxlen) {
retval = read_journal_block(cmdname, source,
((ext2_loff_t) blocknr) * blocksize,
buf, blocksize);
@@ -622,6 +642,7 @@ static void dump_descriptor_block(FILE *out_file,
char *buf,
journal_superblock_t *jsb,
unsigned int *blockp, int blocksize,
+ __u32 maxlen,
tid_t transaction)
{
int offset, tag_size, csum_size = 0;
@@ -644,7 +665,7 @@ static void dump_descriptor_block(FILE *out_file,
"block %u:\n", transaction, blocknr);
++blocknr;
- WRAP(jsb, blocknr);
+ WRAP(jsb, blocknr, maxlen);
do {
/* Work out the location of the current tag, and skip to
@@ -669,7 +690,7 @@ static void dump_descriptor_block(FILE *out_file,
transaction);
++blocknr;
- WRAP(jsb, blocknr);
+ WRAP(jsb, blocknr, maxlen);
} while (!(tag_flags & JBD2_FLAG_LAST_TAG));