[PATCH] Fix readdir_r with long file names
Florian Weimer
fweimer@redhat.com
Thu Jun 6 20:32:00 GMT 2013
On 06/06/2013 09:53 PM, KOSAKI Motohiro wrote:
> +#ifdef NAME_MAX
> + if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
> + {
> + /* The record is very long. It could still fit into the
> + caller-supplied buffer if we can skip padding at the
> + end. */
> + size_t namelen = strlen(dp->d_name);
> + if (namelen <= NAME_MAX)
> + reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
> + else
> + {
> + /* The name is too long. Ignore this file. */
> + dirp->errcode = ENAMETOOLONG;
> + dp->d_ino = 0;
> + continue;
> + }
> + }
> +#endif
>
> Hmm...
> Linux man pages say:
>
>> Since POSIX.1 does not specify the size of the d_name field, and other
>> nonstandard fields may precede that field within the dirent structure, portable
>> applications that use readdir_r() should allocate the buffer whose address is
>> passed in entry as follows:
>>
>> name_max = pathconf(dirpath, _PC_NAME_MAX);
>> if (name_max == -1) /* Limit not defined, or error */
>> name_max = 255; /* Take a guess */
>> len = offsetof(struct dirent, d_name) + name_max + 1;
>> entryp = malloc(len);
>> (POSIX.1 requires that d_name is the last field in a struct dirent.)
>
> So, only broken applications may hit this? If so, do you really think such
> broken application checks return code correctly?
There's precedent for my approach in realpath, where we don't use
pathconf(path, _PC_PATH_MAX), either, but cap the path length at PATH_MAX.
> If a fuse filesystem which allow >256 file names is legal, this patch breaks
> right applications. In the other hands, if it is illegal, I'd suggest
> to fix such broken filesystems instead.
Hmm. We could fix the file systems and patch all affected applications
to use the approach from the manual page, with s/pathconf/fpathconf/ to
avoid the race, and a hard failure on failure ("take a guess" is a very
bad idea here).
For some reason, I discarded that approach. Probably I didn't know
about the f_namemax member of fstatvfs at the time (and I didn't look at
the fpathconf implementation). f_namemax is wrong for the file systems
in question, but that could be fixed.
We'd still have to patch readdir_r to pass through long file names.
The best approach would be a readdir4 function which takes an explicit
size argument. A bit unsual would be a newdirent function which returns
a suitably sized dirent object, based on a DIR *.
--
Florian Weimer / Red Hat Product Security Team
More information about the Libc-alpha
mailing list