Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fd5ea43 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Theodore Ts'o
Browse files

jbd2: checksum journal superblock



Calculate and verify a checksum covering the journal superblock.

Signed-off-by: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 01b5adce
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -106,6 +106,34 @@ int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
	return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
}

static __u32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
{
	__u32 csum, old_csum;

	old_csum = sb->s_checksum;
	sb->s_checksum = 0;
	csum = jbd2_chksum(j, ~0, (char *)sb, sizeof(journal_superblock_t));
	sb->s_checksum = old_csum;

	return cpu_to_be32(csum);
}

int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
{
	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
		return 1;

	return sb->s_checksum == jbd2_superblock_csum(j, sb);
}

void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
{
	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
		return;

	sb->s_checksum = jbd2_superblock_csum(j, sb);
}

/*
 * Helper function used to manage commit timeouts
 */
@@ -1357,6 +1385,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)
	jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
		  journal->j_errno);
	sb->s_errno    = cpu_to_be32(journal->j_errno);
	jbd2_superblock_csum_set(journal, sb);
	read_unlock(&journal->j_state_lock);

	jbd2_write_superblock(journal, WRITE_SYNC);
@@ -1449,6 +1478,17 @@ static int journal_get_superblock(journal_t *journal)
		}
	}

	/* Check superblock checksum */
	if (!jbd2_superblock_csum_verify(journal, sb)) {
		printk(KERN_ERR "JBD: journal checksum error\n");
		goto out;
	}

	/* Precompute checksum seed for all metadata */
	if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
		journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
						   sizeof(sb->s_uuid));

	set_buffer_verified(bh);

	return 0;
@@ -1732,6 +1772,13 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
				return 0;
			}
		}

		/* Precompute checksum seed for all metadata */
		if (JBD2_HAS_INCOMPAT_FEATURE(journal,
					      JBD2_FEATURE_INCOMPAT_CSUM_V2))
			journal->j_csum_seed = jbd2_chksum(journal, ~0,
							   sb->s_uuid,
							   sizeof(sb->s_uuid));
	}

	/* If enabling v1 checksums, downgrade superblock */
+3 −0
Original line number Diff line number Diff line
@@ -969,6 +969,9 @@ struct journal_s

	/* Reference to checksum algorithm driver via cryptoapi */
	struct crypto_shash *j_chksum_driver;

	/* Precomputed journal UUID checksum for seeding other checksums */
	__u32 j_csum_seed;
};

/*