FsObjReal
Implemented in: plash/src/filesysobj-real.c
FsObjReal is an implementation of the FsObj interface in terms of kernel-level directories, files and symlinks. It provides a way to access the "real" filesystem that is implemented by the Linux kernel. FsObjReal is an adaptor converting the POSIX filesystem interface to the FsObj interface; FsOp provides the reverse conversion.
Ideally, FsObjReal directories, files and symlinks represent inodes on the underlying filesystem.
FsObjReal is the only object that needs to be located outside the Plash sandbox. In practice, for efficiency, other objects are located outside the sandbox too, in the same ServerProcess.
Implementation
The FsObj interface is not supposed to follow symlinks on its invoker's behalf, and so FsObjReal must be careful to use system calls in such a way that the kernel does not follow any symlinks on its behalf.
FsObjReal directories
An FsObjReal directory is implemented using a kernel-level directory file descriptor.
The dir_traverse() method does the following:
- fchdir() to the directory.
- lstat() the "leaf" entry in the directory
- If the directory entry is a subdirectory: open() the entry with O_DIRECTORY and O_NOFOLLOW, create a directory object using the resulting file descriptor and return that object
Note: Currently, dir_traverse() and other FsObjReal methods do not restore the previous cwd.
Limitations
The dir_link() and dir_rename() methods are only implemented for the same-directory case. It is not possible to rename or hard link files between different directories. This is a limitation of the fchdir()-based implementation.
Alternative implementations
There are three ways we can implement symlink-race-free directory traversal:
Use fchdir() (current implementation)
- Use /proc/self/fd/N on directory file descriptors
Note: I was not aware that /proc/self/fd/N could be treated as a directory when I first implemented FsObjReal
- Use the new *at() calls introduced in glibc 2.4
- On recent 2.6 Linux kernels, many of these library calls are implemented as system calls
- On older 2.6 Linux kernels, these library calls fall back to using /proc/self/fd/N
- glibc 2.4 does not work with Linux 2.4 and earlier
Planned changes
Story7: Change FsObjReal to use *at() calls and/or /proc
