Beispiel #1
0
static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
				      void *buf, __u32 sequence)
{
	__u32 provided, calculated;

	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
		return 1;

	sequence = cpu_to_be32(sequence);
	calculated = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence,
				 sizeof(sequence));
	calculated = jbd2_chksum(j, calculated, buf, j->j_blocksize);
	provided = be32_to_cpu(tag->t_checksum);

	return provided == cpu_to_be32(calculated);
}
Beispiel #2
0
static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
				      void *buf, __u32 sequence)
{
	journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
	__u32 csum32;
	__u32 seq;

	if (!journal_has_csum_v2or3(j))
		return 1;

	seq = ext2fs_cpu_to_be32(sequence);
	csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
	csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize);

	if (jfs_has_feature_csum3(j))
		return tag3->t_checksum == ext2fs_cpu_to_be32(csum32);

	return tag->t_checksum == ext2fs_cpu_to_be16(csum32);
}
Beispiel #3
0
void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
			     struct buffer_head *bh, __u32 sequence)
{
	journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
	__u32 csum32;
	__be32 seq;

	if (!journal_has_csum_v2or3(j))
		return;

	seq = ext2fs_cpu_to_be32(sequence);
	csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
	csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size);

	if (jfs_has_feature_csum3(j))
		tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
	else
		tag->t_checksum = ext2fs_cpu_to_be16(csum32);
}
Beispiel #4
0
static void update_journal_csum(journal_t *journal, int ver)
{
	journal_superblock_t *jsb;

	if (journal->j_format_version < 2)
		return;

	if (journal->j_tail != 0 ||
	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
				      EXT3_FEATURE_INCOMPAT_RECOVER)) {
		printf("Journal needs recovery, will not add csums.\n");
		return;
	}

	/* metadata_csum implies journal csum v3 */
	jsb = journal->j_superblock;
	if (EXT2_HAS_RO_COMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
		printf("Setting csum v%d\n", ver);
		switch (ver) {
		case 2:
			journal->j_superblock->s_feature_incompat &=
				ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V3);
			journal->j_superblock->s_feature_incompat |=
				ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2);
			journal->j_superblock->s_feature_compat &=
				ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
			break;
		case 3:
			journal->j_superblock->s_feature_incompat &=
				ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V2);
			journal->j_superblock->s_feature_incompat |=
				ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3);
			journal->j_superblock->s_feature_compat &=
				ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
			break;
		default:
			printf("Unknown checksum v%d\n", ver);
			break;
		}
		journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM;
		journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
						   sizeof(jsb->s_uuid));
	} else {
		journal->j_superblock->s_feature_compat |=
			ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_CHECKSUM);
		journal->j_superblock->s_feature_incompat &=
			ext2fs_cpu_to_be32(~(JFS_FEATURE_INCOMPAT_CSUM_V2 |
					     JFS_FEATURE_INCOMPAT_CSUM_V3));
	}
}
Beispiel #5
0
void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh)
{
	struct journal_block_tail *tail;
	__u32 csum;

	if (!journal_has_csum_v2or3(j))
		return;

	tail = (struct journal_block_tail *)(bh->b_data + j->j_blocksize -
			sizeof(struct journal_block_tail));
	tail->t_checksum = 0;
	csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
	tail->t_checksum = ext2fs_cpu_to_be32(csum);
}
Beispiel #6
0
void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh)
{
	struct commit_header *h;
	__u32 csum;

	if (!journal_has_csum_v2or3(j))
		return;

	h = (struct commit_header *)(bh->b_data);
	h->h_chksum_type = 0;
	h->h_chksum_size = 0;
	h->h_chksum[0] = 0;
	csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
	h->h_chksum[0] = ext2fs_cpu_to_be32(csum);
}
Beispiel #7
0
static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
{
	struct commit_header *h;
	__u32 provided;
	__u32 calculated;

	if (!journal_has_csum_v2or3(j))
		return 1;

	h = buf;
	provided = h->h_chksum[0];
	h->h_chksum[0] = 0;
	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
	h->h_chksum[0] = provided;

	return provided == ext2fs_cpu_to_be32(calculated);
}
Beispiel #8
0
static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
{
	struct commit_header *h;
	__u32 provided, calculated;

	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
		return 1;

	h = buf;
	provided = h->h_chksum[0];
	h->h_chksum[0] = 0;
	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
	h->h_chksum[0] = provided;

	provided = be32_to_cpu(provided);
	return provided == calculated;
}
Beispiel #9
0
static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
{
	struct jbd2_journal_block_tail *tail;
	__be32 provided;
	__u32 calculated;

	if (!jbd2_journal_has_csum_v2or3(j))
		return 1;

	tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize -
			sizeof(struct jbd2_journal_block_tail));
	provided = tail->t_checksum;
	tail->t_checksum = 0;
	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
	tail->t_checksum = provided;

	return provided == cpu_to_be32(calculated);
}
Beispiel #10
0
static int jbd2_revoke_block_csum_verify(journal_t *j,
					 void *buf)
{
	struct jbd2_journal_revoke_tail *tail;
	__u32 provided, calculated;

	if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
		return 1;

	tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize -
			sizeof(struct jbd2_journal_revoke_tail));
	provided = tail->r_checksum;
	tail->r_checksum = 0;
	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
	tail->r_checksum = provided;

	provided = be32_to_cpu(provided);
	return provided == calculated;
}
Beispiel #11
0
static errcode_t e2fsck_journal_load(journal_t *journal)
{
	e2fsck_t ctx = journal->j_dev->k_ctx;
	journal_superblock_t *jsb;
	struct buffer_head *jbh = journal->j_sb_buffer;
	struct problem_context pctx;

	clear_problem_context(&pctx);

	ll_rw_block(READ, 1, &jbh);
	if (jbh->b_err) {
		com_err(ctx->device_name, jbh->b_err, "%s",
			_("reading journal superblock\n"));
		return jbh->b_err;
	}

	jsb = journal->j_superblock;
	/* If we don't even have JFS_MAGIC, we probably have a wrong inode */
	if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
		return e2fsck_journal_fix_bad_inode(ctx, &pctx);

	switch (ntohl(jsb->s_header.h_blocktype)) {
	case JFS_SUPERBLOCK_V1:
		journal->j_format_version = 1;
		if (jsb->s_feature_compat ||
		    jsb->s_feature_incompat ||
		    jsb->s_feature_ro_compat ||
		    jsb->s_nr_users)
			clear_v2_journal_fields(journal);
		break;

	case JFS_SUPERBLOCK_V2:
		journal->j_format_version = 2;
		if (ntohl(jsb->s_nr_users) > 1 &&
		    uuid_is_null(ctx->fs->super->s_journal_uuid))
			clear_v2_journal_fields(journal);
		if (ntohl(jsb->s_nr_users) > 1) {
			fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
			return EXT2_ET_JOURNAL_UNSUPP_VERSION;
		}
		break;

	/*
	 * These should never appear in a journal super block, so if
	 * they do, the journal is badly corrupted.
	 */
	case JFS_DESCRIPTOR_BLOCK:
	case JFS_COMMIT_BLOCK:
	case JFS_REVOKE_BLOCK:
		return EXT2_ET_CORRUPT_SUPERBLOCK;

	/* If we don't understand the superblock major type, but there
	 * is a magic number, then it is likely to be a new format we
	 * just don't understand, so leave it alone. */
	default:
		return EXT2_ET_JOURNAL_UNSUPP_VERSION;
	}

	if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
		return EXT2_ET_UNSUPP_FEATURE;

	if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
		return EXT2_ET_RO_UNSUPP_FEATURE;

	/* Checksum v1-3 are mutually exclusive features. */
	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
	    JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
		return EXT2_ET_CORRUPT_SUPERBLOCK;

	if (journal_has_csum_v2or3(journal) &&
	    JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
		return EXT2_ET_CORRUPT_SUPERBLOCK;

	if (!e2fsck_journal_verify_csum_type(journal, jsb) ||
	    !e2fsck_journal_sb_csum_verify(journal, jsb))
		return EXT2_ET_CORRUPT_SUPERBLOCK;

	if (journal_has_csum_v2or3(journal))
		journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
						   sizeof(jsb->s_uuid));

	/* We have now checked whether we know enough about the journal
	 * format to be able to proceed safely, so any other checks that
	 * fail we should attempt to recover from. */
	if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
		com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
			_("%s: no valid journal superblock found\n"),
			ctx->device_name);
		return EXT2_ET_CORRUPT_SUPERBLOCK;
	}

	if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
		journal->j_maxlen = ntohl(jsb->s_maxlen);
	else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
		com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
			_("%s: journal too short\n"),
			ctx->device_name);
		return EXT2_ET_CORRUPT_SUPERBLOCK;
	}

	journal->j_tail_sequence = ntohl(jsb->s_sequence);
	journal->j_transaction_sequence = journal->j_tail_sequence;
	journal->j_tail = ntohl(jsb->s_start);
	journal->j_first = ntohl(jsb->s_first);
	journal->j_last = ntohl(jsb->s_maxlen);

	return 0;
}