I'm a little surprised this got a CVE number to be honest; allowing users to edit files via some privileged mechanism when they may control some portion of the filesystem under consideration is always going to be dangerous.
sudo cannot actually prevent this -- for example, the patch for this issue http://www.sudo.ws/repos/sudo/rev/9636fd256325 (look for the sudo_edit.c hunk) just uses O_NOFOLLOW to try to mitigate this issue:
+#ifdef O_NOFOLLOW
+static int
+sudo_edit_open(const char *path, int oflags, mode_t mode, int sflags)
+{
+ if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW))
+ oflags |= O_NOFOLLOW;
+ return open(path, oflags, mode);
+}
+#else
But O_NOFOLLOW only functions on the final component of a pathname, so you can still edit e.g. /etc/shadow if you create a symlink "ln -s /etc etc".
I'm pretty sure the sudo patch is more or less worthless; here's a far simpler program to test with:
(Sorry for the pipes, launchpad collapsed all the spacing, making it illegible.)
$ make o_nofollow
cc o_nofollow.c -o o_nofollow
$ mkdir tests
$ cd tests
$ ln -s /etc etc
$ ln -s /etc/passwd passwd
$ ln -s /etc/shadow shadow
$ ../o_nofollow /etc/passwd /etc/shadow ./etc/passwd ./etc/shadow ./passwd ./shadow
open /etc/shadow failed: Permission denied
open ./etc/shadow failed: Permission denied
open ./passwd failed: Too many levels of symbolic links
open ./shadow failed: Too many levels of symbolic links
$
Note that opening ./etc/passwd succeeded here because ./etc is a symlink to /etc and O_NOFOLLOW does not prevent this.
The #else portion of the code may be fine, I haven't studied it extensively, so there may be some way to salvage the patch. But I suspect it's never going to be perfect.
I'm a little surprised this got a CVE number to be honest; allowing users to edit files via some privileged mechanism when they may control some portion of the filesystem under consideration is always going to be dangerous.
sudo cannot actually prevent this -- for example, the patch for this issue http:// www.sudo. ws/repos/ sudo/rev/ 9636fd256325 (look for the sudo_edit.c hunk) just uses O_NOFOLLOW to try to mitigate this issue:
+#ifdef O_NOFOLLOW open(const char *path, int oflags, mode_t mode, int sflags) FOLLOW) )
+static int
+sudo_edit_
+{
+ if (!ISSET(sflags, CD_SUDOEDIT_
+ oflags |= O_NOFOLLOW;
+ return open(path, oflags, mode);
+}
+#else
But O_NOFOLLOW only functions on the final component of a pathname, so you can still edit e.g. /etc/shadow if you create a symlink "ln -s /etc etc".
I'm pretty sure the sudo patch is more or less worthless; here's a far simpler program to test with:
| #include <sys/types.h>
| #include <sys/stat.h>
| #include <fcntl.h>
| #include <stdio.h>
|
| int main(int argc, char* argv[]) {
| int fd;
| int err = 0;
| int i;
|
| for (i=0; i<argc; i++) {
| fd = open(argv[i], O_RDONLY | O_NOFOLLOW);
| if (fd < 0) {
| fprintf(stderr, "open %s failed: %m\n", argv[i]);
| err++;
| } else {
| close(fd);
| }
| }
|
| return err;
| }
(Sorry for the pipes, launchpad collapsed all the spacing, making it illegible.)
$ make o_nofollow
cc o_nofollow.c -o o_nofollow
$ mkdir tests
$ cd tests
$ ln -s /etc etc
$ ln -s /etc/passwd passwd
$ ln -s /etc/shadow shadow
$ ../o_nofollow /etc/passwd /etc/shadow ./etc/passwd ./etc/shadow ./passwd ./shadow
open /etc/shadow failed: Permission denied
open ./etc/shadow failed: Permission denied
open ./passwd failed: Too many levels of symbolic links
open ./shadow failed: Too many levels of symbolic links
$
Note that opening ./etc/passwd succeeded here because ./etc is a symlink to /etc and O_NOFOLLOW does not prevent this.
The #else portion of the code may be fine, I haven't studied it extensively, so there may be some way to salvage the patch. But I suspect it's never going to be perfect.
Thanks