Fix possible UDF deadlock and memory corruption (CVE-2006-4145)
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>
This commit is contained in:
parent
c164a9ba0a
commit
00a2b0f6dd
2 changed files with 43 additions and 29 deletions
|
@ -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:
|
||||
|
|
|
@ -239,38 +239,52 @@ 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);
|
||||
}
|
||||
else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
|
||||
{
|
||||
kernel_lb_addr neloc = { 0, 0 };
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
/*
|
||||
* 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 {
|
||||
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);
|
||||
}
|
||||
else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
|
||||
{
|
||||
kernel_lb_addr neloc = { 0, 0 };
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UDF_I_LENEXTENTS(inode) = inode->i_size;
|
||||
|
|
Loading…
Reference in a new issue