3 ms·
IMO the article's conclusion is backwards. There's nothing wrong with symlinks when files are opened with openat(), since in principal the program (or controlli
by jmillikin 4y ago
IMO the article's conclusion is backwards. There's nothing wrong with symlinks when files are opened with openat(), since in principal the program (or controlling program) should always be in control of the filesystem layout. It's open() that causes problems, and complex interactions with symlinks in attacker-controlled directories are just one of them.
The POSIX file API was designed before the concept of capability passing (arguably, before the concept of computer security in general). A modern replacement would look more like Fuchsia, where child processes are provided file access scoped to their parent process's authority. This same scoping can also be used within a process, for example to implement a server that can "self-chroot".
> So, more functions following the pattern of openat() had to be created
> [...]
> Some are still missing, like getxattrat() and setxattrat().
The functions to get/set xattrs on a file descriptor (rather than a path) are fgetxattr() and fsetxattr(). They're not usable for the specific case of a file descriptor opened with O_PATH, but that restriction is both documented and reasonable -- O_PATH doesn't allow operations that inspect the state of the file itself, such as reading/writing.
A better example might have been listxattr() vs flistxattr(), because the former works on a file without read permissions, but the latter fails on a descriptor opened with O_PATH.
listxattr("xattr-chmod000.txt", NULL, 0) = 14
listxattr("xattr-chmod000.txt", "user.testattr\0", 14) = 14
getxattr("xattr-chmod000.txt", "user.testattr", NULL, 0) = -1 EACCES (Permission denied)
vs
openat(AT_FDCWD, "xattr-chmod000.txt", O_RDONLY|O_PATH) = 3
flistxattr(3, NULL, 0) = -1 EBADF (Bad file descriptor)
- jerf 4y ago"There's nothing wrong with symlinks when files are opened with openat(), since in principal the program (or controlling program) should always be in control of the filesystem layout. It's open() that causes problems, and complex interactions with symlinks in attacker-controlled directories are just one of them." One of my minor annoyances with new languages is the continued persistence of open-based file APIs, with openat APIs shoved off to the side if they are even implemented at all. If you start from scratch with an openat-based API, it's not even that hard; you basically get a file object, just one with some different attributes and methods (or appropriate local ideas), most of which you don't care about, and it's not that hard to work with if you start with that from day one. It can be quite hard to backport something deeply based on string-based path manipulation into the *at-based APIs, though. I haven't deeply studied it but you ought to be able to simulate an openat-based API on a conventional filesystem that doesn't support it. It may not immunize you to security issues, but at least the code ought to be as portable as any other code that starts getting detailed about its interactions with filesystems, which is already "kinda, not very, some elbow grease required"... it's not like the bar is sky high because all that stuff already works perfectly across all platforms and filesystems anyhow.