Commit a20d1ceb authored by Theodore Ts'o's avatar Theodore Ts'o

jbd2: fix portability problems caused by unaligned accesses

This commit applies the e2fsck/recovery.c portions of commit
1e0c8ca7c08a ("e2fsck: fix portability problems caused by unaligned
accesses) from the e2fsprogs git tree.

The on-disk format for the ext4 journal can have unaigned 32-bit
integers.  This can happen when replaying a journal using a obsolete
checksum format (which was never popularly used, since the v3 format
replaced v2 while the metadata checksum feature was being stablized).
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 877ba3f7
...@@ -196,7 +196,7 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf) ...@@ -196,7 +196,7 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
static int count_tags(journal_t *journal, struct buffer_head *bh) static int count_tags(journal_t *journal, struct buffer_head *bh)
{ {
char * tagp; char * tagp;
journal_block_tag_t * tag; journal_block_tag_t tag;
int nr = 0, size = journal->j_blocksize; int nr = 0, size = journal->j_blocksize;
int tag_bytes = journal_tag_bytes(journal); int tag_bytes = journal_tag_bytes(journal);
...@@ -206,14 +206,14 @@ static int count_tags(journal_t *journal, struct buffer_head *bh) ...@@ -206,14 +206,14 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
tagp = &bh->b_data[sizeof(journal_header_t)]; tagp = &bh->b_data[sizeof(journal_header_t)];
while ((tagp - bh->b_data + tag_bytes) <= size) { while ((tagp - bh->b_data + tag_bytes) <= size) {
tag = (journal_block_tag_t *) tagp; memcpy(&tag, tagp, sizeof(tag));
nr++; nr++;
tagp += tag_bytes; tagp += tag_bytes;
if (!(tag->t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID))) if (!(tag.t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
tagp += 16; tagp += 16;
if (tag->t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG)) if (tag.t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
break; break;
} }
...@@ -433,9 +433,9 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) ...@@ -433,9 +433,9 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
} }
static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
journal_block_tag3_t *tag3,
void *buf, __u32 sequence) void *buf, __u32 sequence)
{ {
journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
__u32 csum32; __u32 csum32;
__be32 seq; __be32 seq;
...@@ -496,7 +496,7 @@ static int do_one_pass(journal_t *journal, ...@@ -496,7 +496,7 @@ static int do_one_pass(journal_t *journal,
while (1) { while (1) {
int flags; int flags;
char * tagp; char * tagp;
journal_block_tag_t * tag; journal_block_tag_t tag;
struct buffer_head * obh; struct buffer_head * obh;
struct buffer_head * nbh; struct buffer_head * nbh;
...@@ -613,8 +613,8 @@ static int do_one_pass(journal_t *journal, ...@@ -613,8 +613,8 @@ static int do_one_pass(journal_t *journal,
<= journal->j_blocksize - descr_csum_size) { <= journal->j_blocksize - descr_csum_size) {
unsigned long io_block; unsigned long io_block;
tag = (journal_block_tag_t *) tagp; memcpy(&tag, tagp, sizeof(tag));
flags = be16_to_cpu(tag->t_flags); flags = be16_to_cpu(tag.t_flags);
io_block = next_log_block++; io_block = next_log_block++;
wrap(journal, next_log_block); wrap(journal, next_log_block);
...@@ -632,7 +632,7 @@ static int do_one_pass(journal_t *journal, ...@@ -632,7 +632,7 @@ static int do_one_pass(journal_t *journal,
J_ASSERT(obh != NULL); J_ASSERT(obh != NULL);
blocknr = read_tag_block(journal, blocknr = read_tag_block(journal,
tag); &tag);
/* If the block has been /* If the block has been
* revoked, then we're all done * revoked, then we're all done
...@@ -647,8 +647,8 @@ static int do_one_pass(journal_t *journal, ...@@ -647,8 +647,8 @@ static int do_one_pass(journal_t *journal,
/* Look for block corruption */ /* Look for block corruption */
if (!jbd2_block_tag_csum_verify( if (!jbd2_block_tag_csum_verify(
journal, tag, obh->b_data, journal, &tag, (journal_block_tag3_t *)tagp,
be32_to_cpu(tmp->h_sequence))) { obh->b_data, be32_to_cpu(tmp->h_sequence))) {
brelse(obh); brelse(obh);
success = -EFSBADCRC; success = -EFSBADCRC;
printk(KERN_ERR "JBD2: Invalid " printk(KERN_ERR "JBD2: Invalid "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment