Filelight crashes if readdir returns very long file name
ClosedPublic

Authored by i.Dark_Templar on Oct 22 2017, 8:04 AM.

Details

Summary

While it's usually stated that 'struct dirent' has member 'char d_name[PATH_MAX + 1]', it is possible to obtain results when this field contains a string longer than PATH_MAX + 1. Stringbuilder in that case would copy only PATH_MAX + 1 first bytes, and wouldn't add zero terminator to this copied string, which would eventually lead to crash.

How to reproduce:

  1. use ntfs filesystem (for example, via ntfs-3g)

Ntfs filesystem uses maximum number of characters for restricting file name length, not bytes, and character may be longer than 1 byte.

  1. create a file with name out of > 255 bytes, but less than 255 characters. Use non-ascii characters for that and UTF-8 locale.

It's too long filename for a Linux filesystem, but actually a valid name for ntfs filesystem.
In my case, I hit a file with name of 166 characters and 264 bytes (not including zero terminator).

  1. run filelight on filesystem containing that file and see it crash.

What should happen:
Filelight should run fine, and if struct dirent::d_name is longer that PATH_MAX, it should work fine with it.

Diff Detail

Repository
R352 Filelight
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
i.Dark_Templar created this revision.Oct 22 2017, 8:04 AM
Restricted Application added a subscriber: kde-utils-devel. · View Herald TranscriptOct 22 2017, 8:04 AM
sandsmark accepted this revision.Oct 22 2017, 9:52 AM
sandsmark added a subscriber: sandsmark.

so it's really ntfs-3g that is broken, I guess? but we should never crash anyways, so thanks.

This revision is now accepted and ready to land.Oct 22 2017, 9:52 AM

I'm not sure what part exactly is broken. It's just an incompatibility between linux (posix maybe?) file length limits and windows (ntfs) limits. I'm using default gentoo libc (sys-libs/glibc-, "GNU lib C library"). I've ran filelight under valgrind and didn't notice any warnings that glibc writes anything to wrong memory address. I've looked it up, and it looks like glibc allocates buffer large enough to hold more than NAME_MAX path (on my system it allocates 32768 bytes for whole DIRP, struct dirent and additional internal stuff). And it has a special structure field d_reclen to indicate the actual length of returned record. In my case d_reclen holds value 288 (for a filename 264 bytes long). It's not fully standard compatible, but I guess it helps to work around such system design incompatibilities and usually goes unnoticed by users.

This revision was automatically updated to reflect the committed changes.