Skip to content

Commit

Permalink
Fix possible UDF deadlock and memory corruption (CVE-2006-4145)
Browse files Browse the repository at this point in the history
UDF code is not really ready to handle extents larger that 1GB. This is
the easy way to forbid creating those.

Also truncation code did not count with the case when there are no
extents in the file and we are extending the file.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Jan Kara authored and Greg Kroah-Hartman committed Aug 22, 2006
1 parent c164a9b commit 00a2b0f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 26 deletions.
2 changes: 1 addition & 1 deletion fs/udf/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
iput(inode);
goto error_out;
}
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_maxbytes = 1<<30;
return 0;

error_out:
Expand Down
64 changes: 39 additions & 25 deletions fs/udf/truncate.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,37 +239,51 @@ void udf_truncate_extents(struct inode * inode)
{
if (offset)
{
extoffset -= adsize;
etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
{
extoffset -= adsize;
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
/*
* OK, there is not extent covering inode->i_size and
* no extent above inode->i_size => truncate is
* extending the file by 'offset'.
*/
if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
(bh && extoffset == sizeof(struct allocExtDesc))) {
/* File has no extents at all! */
memset(&eloc, 0x00, sizeof(kernel_lb_addr));
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
{
kernel_lb_addr neloc = { 0, 0 };
else {
extoffset -= adsize;
nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
((elen + offset + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
}
else
{
if (elen & (inode->i_sb->s_blocksize - 1))
etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
{
extoffset -= adsize;
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
}
else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
{
kernel_lb_addr neloc = { 0, 0 };
extoffset -= adsize;
elen = EXT_RECORDED_ALLOCATED |
((elen + inode->i_sb->s_blocksize - 1) &
nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
((elen + offset + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
}
else
{
if (elen & (inode->i_sb->s_blocksize - 1))
{
extoffset -= adsize;
elen = EXT_RECORDED_ALLOCATED |
((elen + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
}
memset(&eloc, 0x00, sizeof(kernel_lb_addr));
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
memset(&eloc, 0x00, sizeof(kernel_lb_addr));
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
}
}
Expand Down

0 comments on commit 00a2b0f

Please sign in to comment.