Message ID | 1509452190-12368-3-git-send-email-martyn.welch@collabora.co.uk |
---|---|
State | Superseded |
Delegated to: | Stefano Babic |
Headers | show |
Series | Add support for GE PPD | expand |
On Tue, Oct 31, 2017 at 12:16:25PM +0000, Martyn Welch wrote: > From: Ian Ray <ian.ray@ge.com> > > Some fixes when reading EXT files and directory entries were identified > after using e2fuzz to corrupt an EXT3 filesystem: > > - Stop reading directory entries if the offset becomes badly aligned. > > - Avoid overwriting memory by clamping the length used to zero the buffer > in ext4fs_read_file. Also sanity check blocksize. > > Signed-off-by: Ian Ray <ian.ray@ge.com> > Signed-off-by: Martyn Welch <martyn.welch@collabora.co.uk> > --- > fs/ext4/ext4_common.c | 10 ++++++++++ > fs/ext4/ext4fs.c | 10 +++++++++- > 2 files changed, 19 insertions(+), 1 deletion(-) > > diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c > index 31952f4..dac9545 100644 > --- a/fs/ext4/ext4_common.c > +++ b/fs/ext4/ext4_common.c > @@ -660,6 +660,11 @@ static int search_dir(struct ext2_inode *parent_inode, char *dirname) > > offset = 0; > do { > + if (offset & 3) { > + printf("Badly aligned ext2_dirent\n"); > + break; > + } > + > dir = (struct ext2_dirent *)(block_buffer + offset); > direntname = (char*)(dir) + sizeof(struct ext2_dirent); > > @@ -880,6 +885,11 @@ static int unlink_filename(char *filename, unsigned int blknr) > > offset = 0; > do { > + if (offset & 3) { > + printf("Badly aligned ext2_dirent\n"); > + break; > + } > + > previous_dir = dir; > dir = (struct ext2_dirent *)(block_buffer + offset); > direntname = (char *)(dir) + sizeof(struct ext2_dirent); > diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c > index b0c7303..9ee2caf 100644 > --- a/fs/ext4/ext4fs.c > +++ b/fs/ext4/ext4fs.c > @@ -64,6 +64,9 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, > char *delayed_buf = NULL; > short status; > > + if (blocksize <= 0) > + return -1; > + > /* Adjust len so it we can't read past the end of the file. */ > if (len + pos > filesize) > len = (filesize - pos); > @@ -127,6 +130,7 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, > (blockend >> log2blksz); > } > } else { > + int n; > if (previous_block_number != -1) { > /* spill */ > status = ext4fs_devread(delayed_start, > @@ -137,7 +141,11 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, > return -1; > previous_block_number = -1; > } > - memset(buf, 0, blocksize - skipfirst); > + /* Zero no more than `len' bytes. */ > + n = blocksize - skipfirst; > + if (n > len) > + n = len; > + memset(buf, 0, n); > } > buf += blocksize - skipfirst; > } Stefan, do you have any comments on this? Thanks!
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 31952f4..dac9545 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -660,6 +660,11 @@ static int search_dir(struct ext2_inode *parent_inode, char *dirname) offset = 0; do { + if (offset & 3) { + printf("Badly aligned ext2_dirent\n"); + break; + } + dir = (struct ext2_dirent *)(block_buffer + offset); direntname = (char*)(dir) + sizeof(struct ext2_dirent); @@ -880,6 +885,11 @@ static int unlink_filename(char *filename, unsigned int blknr) offset = 0; do { + if (offset & 3) { + printf("Badly aligned ext2_dirent\n"); + break; + } + previous_dir = dir; dir = (struct ext2_dirent *)(block_buffer + offset); direntname = (char *)(dir) + sizeof(struct ext2_dirent); diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index b0c7303..9ee2caf 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -64,6 +64,9 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, char *delayed_buf = NULL; short status; + if (blocksize <= 0) + return -1; + /* Adjust len so it we can't read past the end of the file. */ if (len + pos > filesize) len = (filesize - pos); @@ -127,6 +130,7 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, (blockend >> log2blksz); } } else { + int n; if (previous_block_number != -1) { /* spill */ status = ext4fs_devread(delayed_start, @@ -137,7 +141,11 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, return -1; previous_block_number = -1; } - memset(buf, 0, blocksize - skipfirst); + /* Zero no more than `len' bytes. */ + n = blocksize - skipfirst; + if (n > len) + n = len; + memset(buf, 0, n); } buf += blocksize - skipfirst; }