> I suspect that it is possible, and maybe even feasible, to work around > this violation of fundamental assumptions in some limited cases. > However, in general, I think it's not possible, or at least not > worth the effort. > > In spite of that, I have thought about changing fts to be usable even > in the unusual event that these inode-less file systems misbehave. > However, ignoring all dev/inode-based tests would raise other issues: > > - there would be no protection against the attacks I already mentioned > But a work-around is possible: rather than hard-coding the failure, > provide a callback, and let the caller determine how to handle it. > However, this is a lame hack: on an affected file system, there would > be no way to distinguish between an attack and a directory inode number > that changed due to a flushed cache. > IMHO, disabling such a safety net is a very bad idea.
The details of the attack are not clear to me, can you please explain? Is test in fts_safe_changedir() for protecting against this? > - directory cycle detection would be unreliable, which applies to > symlink loops as well as hard-link (file system corruption) loops. This one should work, since the file descriptor in the working directory should prevent the inode from going away. Or is there something I'm missing? > - this would be a device(file system)-specific attribute, yet a > directory traversal can span many devices. Do we really want fts > to be calling statfs (like "stat -f --format %T ." does) every time > it transitions from one file system type to another (new one)? > Then, it'd turn work-arounds on and off depending. No, I think if it can't be solved in a universally correct way, it's probably not worth trying to solve. > All of the above sounds like it'd be invasive, yet provide little benefit: > mere half-measures to work around low-probability events affecting > only unreliable-by-definition, non-POSIX file systems. > > Are you still convinced it's worthwhile? I think it's worthwile trying to fix these problems, unless the fix itself causes problems (performance, complexity, etc). > If so, would you please build coreutils-6.3 > > ftp://ftp.gnu.org/gnu/coreutils/coreutils-6.3.tar.gz > ftp://ftp.gnu.org/gnu/coreutils/coreutils-6.3.tar.bz2 > > and run its tests ("make check") from a build directory in your > modified file system? Done that and there are lots of errors, some of those are unrelated. Two that are relevant stand out: chmod: fts_read failed: No such file or directory This might be the same as the 'find' one. The other is: cp: skipping file `f', as it was replaced while being copied Again the same kind: stat64("g", 0xbfdb9a20) = -1 ENOENT (No such file or directory) stat64("f", {st_dev=makedev(0, 14), st_ino=133, st_mode=S_IFREG|0777, st_nlink=1, st_uid=1001, st_gid=1001, st_blksize=4096, st_blocks=27776, st_size=14198719, st_atime=2006/10/04-13:53:13, st_mtime=2006/10/04-13:53:17, st_ctime=2006/10/05-14:58:56}) = 0 stat64("g", 0xbfdb98c0) = -1 ENOENT (No such file or directory) open("f", O_RDONLY|O_LARGEFILE) = 3 fstat64(3, {st_dev=makedev(0, 14), st_ino=134, st_mode=S_IFREG|0777, st_nlink=1, st_uid=1001, st_gid=1001, st_blksize=4096, st_blocks=27776, st_size=14198719, st_atime=2006/10/04-13:53:13, st_mtime=2006/10/04-13:53:17, st_ctime=2006/10/05-14:58:56}) = 0 write(2, "/tmp/coreutils-6.3/src/cp: ", 27) = 27 write(2, "skipping file `f\', as it was rep"..., 56) = 56 write(2, "\n", 1) = 1 close(3) = 0 This not only has the problem of not working reliably on inode-less filesystems, but is also inefficient, doing stat twice on both source and destination. Seems worth fixing, no? Miklos