Skip to content

Commit

Permalink
erofs: support superblock checksum
Browse files Browse the repository at this point in the history
Introduce superblock checksum feature in order to
check at mounting time.

Note that the first 1024 bytes are ignore for x86
boot sectors and other oddities.

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Pratik Shinde <[email protected]>
Reviewed-by: Chao Yu <[email protected]>
Cc: Dan Carpenter <[email protected]>
Signed-off-by: Gao Xiang <[email protected]>
  • Loading branch information
Pratik32 authored and Gao Xiang committed Nov 24, 2019
1 parent a93f8c3 commit b858a48
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 3 deletions.
1 change: 1 addition & 0 deletions fs/erofs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
config EROFS_FS
tristate "EROFS filesystem support"
depends on BLOCK
select LIBCRC32C
help
EROFS (Enhanced Read-Only File System) is a lightweight
read-only file system with modern designs (eg. page-sized
Expand Down
3 changes: 2 additions & 1 deletion fs/erofs/erofs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#define EROFS_SUPER_OFFSET 1024

#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001

/*
* Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should
* be incompatible with this kernel version.
Expand All @@ -37,7 +39,6 @@ struct erofs_super_block {
__u8 uuid[16]; /* 128-bit uuid for volume */
__u8 volume_name[16]; /* volume name */
__le32 feature_incompat;

__u8 reserved2[44];
};

Expand Down
1 change: 1 addition & 0 deletions fs/erofs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct erofs_sb_info {

u8 uuid[16]; /* 128-bit uuid for volume */
u8 volume_name[16]; /* volume name */
u32 feature_compat;
u32 feature_incompat;

unsigned int mount_opt;
Expand Down
36 changes: 34 additions & 2 deletions fs/erofs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/statfs.h>
#include <linux/parser.h>
#include <linux/seq_file.h>
#include <linux/crc32c.h>
#include "xattr.h"

#define CREATE_TRACE_POINTS
Expand Down Expand Up @@ -46,6 +47,30 @@ void _erofs_info(struct super_block *sb, const char *function,
va_end(args);
}

static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
{
struct erofs_super_block *dsb;
u32 expected_crc, crc;

dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET,
EROFS_BLKSIZ - EROFS_SUPER_OFFSET, GFP_KERNEL);
if (!dsb)
return -ENOMEM;

expected_crc = le32_to_cpu(dsb->checksum);
dsb->checksum = 0;
/* to allow for x86 boot sectors and other oddities. */
crc = crc32c(~0, dsb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET);
kfree(dsb);

if (crc != expected_crc) {
erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected",
crc, expected_crc);
return -EBADMSG;
}
return 0;
}

static void erofs_inode_init_once(void *ptr)
{
struct erofs_inode *vi = ptr;
Expand Down Expand Up @@ -112,7 +137,7 @@ static int erofs_read_superblock(struct super_block *sb)

sbi = EROFS_SB(sb);

data = kmap_atomic(page);
data = kmap(page);
dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET);

ret = -EINVAL;
Expand All @@ -121,6 +146,13 @@ static int erofs_read_superblock(struct super_block *sb)
goto out;
}

sbi->feature_compat = le32_to_cpu(dsb->feature_compat);
if (sbi->feature_compat & EROFS_FEATURE_COMPAT_SB_CHKSUM) {
ret = erofs_superblock_csum_verify(sb, data);
if (ret)
goto out;
}

blkszbits = dsb->blkszbits;
/* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
if (blkszbits != LOG_BLOCK_SIZE) {
Expand Down Expand Up @@ -155,7 +187,7 @@ static int erofs_read_superblock(struct super_block *sb)
}
ret = 0;
out:
kunmap_atomic(data);
kunmap(page);
put_page(page);
return ret;
}
Expand Down

0 comments on commit b858a48

Please sign in to comment.