diff options
author | Stefan Brüns <stefan.bruens@rwth-aachen.de> | 2016-09-06 04:36:41 +0200 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-09-23 09:02:34 -0400 |
commit | 76a29519ff87dd6a014d841a3a6e501d3b2f5153 (patch) | |
tree | 8eeafae000b8748dc274ac574b9ec2091fd6204b /fs/ext4/ext4_write.c | |
parent | 011bc3342a485345f7136eed20e0477b8cd5580f (diff) | |
download | u-boot-76a29519ff87dd6a014d841a3a6e501d3b2f5153.tar.gz u-boot-76a29519ff87dd6a014d841a3a6e501d3b2f5153.tar.bz2 u-boot-76a29519ff87dd6a014d841a3a6e501d3b2f5153.zip |
ext4: fix possible crash on directory traversal, ignore deleted entries
The following command triggers a segfault in search_dir:
./sandbox/u-boot -c 'host bind 0 ./sandbox/test/fs/3GB.ext4.img ;
ext4write host 0 0 /./foo 0x10'
The following command triggers a segfault in check_filename:
./sandbox/u-boot -c 'host bind 0 ./sandbox/test/fs/3GB.ext4.img ;
ext4write host 0 0 /. 0x10'
"." is the first entry in the directory, thus previous_dir is NULL. The
whole previous_dir block in search_dir seems to be a bad copy from
check_filename(...). As the changed data is not written to disk, the
statement is mostly harmless, save the possible NULL-ptr reference.
Typically a file is unlinked by extending the direntlen of the previous
entry. If the entry is the first entry in the directory block, it is
invalidated by setting inode=0.
The inode==0 case is hard to trigger without crafted filesystems. It only
hits if the first entry in a directory block is deleted and later a lookup
for the entry (by name) is done.
Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majewski@samsung.com>
Diffstat (limited to 'fs/ext4/ext4_write.c')
-rw-r--r-- | fs/ext4/ext4_write.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index fac3222ef8..9200c4727e 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -882,7 +882,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer, if (ext4fs_iget(parent_inodeno, g_parent_inode)) goto fail; /* check if the filename is already present in root */ - existing_file_inodeno = ext4fs_filename_check(filename); + existing_file_inodeno = ext4fs_filename_unlink(filename); if (existing_file_inodeno != -1) { ret = ext4fs_delete_file(existing_file_inodeno); fs->first_pass_bbmap = 0; |