Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#2 60-character symlinks corrupt generated filesystem

open
nobody
None
5
2014-07-09
2011-03-17
Steve Lemke
No

Running genext2fs to build a filesystem that contains symlinks that are exactly 60 characters long result in those symlinks getting created (incorrectly) as "fast" symlinks where the data is stored within the inode.

Running e2fsck on the generated filesystem reports invalid symlinks, and from there things only get worse.

I noticed that all of the invalid symlinks were 60 bytes long and then ran across the following ext2 documentation:

From http://www.mjmwired.net/kernel/Documentation/filesystems/ext2.txt#189
Symbolic links are also filesystem objects with inodes. They deserve
special mention because the data for them is stored within the inode
itself if the symlink is less than 60 bytes long. It uses the fields
which would normally be used to store the pointers to data blocks.
This is a worthwhile optimisation as it we avoid allocating a full
block for the symlink, and most symlinks are less than 60 characters long.

Upon looking at the genext2fs v1.4.1 source, I found the following test in mklink_fs():
if(size <= 4 * (EXT2_TIND_BLOCK+1))

Elsewhere in the source, I found that EXT2_TIND_BLOCK is 14, hence the test is for <= 60.

Changing this to instead test for "size < 4 * ...", re-building, re-generating my filesystem image, and re-running e2fsck now reports no corruption.

Discussion

  • Steve Lemke
    Steve Lemke
    2011-03-17

    Looks like a corresponding change (from > to >=) needs to be made on (or near) line 1544 to ensure that stats.nblocks counts the block used to store 60-char regular symlinks... though it appears that this only affects stats, and not the validity of the generated filesystem.

     
  • correcting/improving above note:
    the value of EXT2_N_BLOCKS is the array size of i_block and equals 15.
    sizeof(i_block) resolves to 60 as i_block array is based upon __u32 data tye.

    i am now basically confirming the problem.
    please also see http://sourceforge.net/tracker/?func=detail&aid=3371606&group_id=2406&atid=202406

    Ted Tso claimed symlink format to be like this (refined in my own words):
    when an inode is flagged as a symlink entry
    then the i_block array will hold a string if the space is sufficient.
    a string consists of the string terminating '\0' character (non-printable)
    and 1-59 printable characters.
    for larger strings the string data is stored elsewhere.
    i_size is set to the same as str/n/len() function family would return, the length of the string in chars without trailing zero.

    i had to add:
    in practical cases the following member i_generation has a value of 0
    resulting in the bug probably might ever hit in normal operation.
    but for picky tools its a violation.
    e2fsck typically offers deletion of the violating symlink which is a correct offer
    but indeed that is dangerous for the data the user wants to stay on the target file system.

     
  • Finn Thain
    Finn Thain
    2013-10-30

    Fixed in CVS.