Commit 00a2b0f6 authored by Jan Kara's avatar Jan Kara Committed by Greg Kroah-Hartman

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: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c164a9ba
...@@ -1659,7 +1659,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -1659,7 +1659,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
iput(inode); iput(inode);
goto error_out; goto error_out;
} }
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_maxbytes = 1<<30;
return 0; return 0;
error_out: error_out:
......
...@@ -239,37 +239,51 @@ void udf_truncate_extents(struct inode * inode) ...@@ -239,37 +239,51 @@ void udf_truncate_extents(struct inode * inode)
{ {
if (offset) if (offset)
{ {
extoffset -= adsize; /*
etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1); * OK, there is not extent covering inode->i_size and
if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) * no extent above inode->i_size => truncate is
{ * extending the file by 'offset'.
extoffset -= adsize; */
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset); if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); (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)) else {
{
kernel_lb_addr neloc = { 0, 0 };
extoffset -= adsize; extoffset -= adsize;
nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
((elen + offset + inode->i_sb->s_blocksize - 1) & if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
~(inode->i_sb->s_blocksize - 1)); {
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); extoffset -= adsize;
udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
} udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
else }
{ else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
if (elen & (inode->i_sb->s_blocksize - 1))
{ {
kernel_lb_addr neloc = { 0, 0 };
extoffset -= adsize; extoffset -= adsize;
elen = EXT_RECORDED_ALLOCATED | nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
((elen + inode->i_sb->s_blocksize - 1) & ((elen + offset + inode->i_sb->s_blocksize - 1) &
~(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);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment