[Bug 202892] open with O_CREAT | O_DIRECTORY when path references a symlink

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Fri Sep 4 14:09:25 UTC 2015


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=202892

            Bug ID: 202892
           Summary: open with O_CREAT | O_DIRECTORY when path references a
                    symlink
           Product: Base System
           Version: 11.0-CURRENT
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: freebsd at tom-ridge.com

The following test code (thanks R Watson) tries to call open with O_CREAT |
O_DIRECTORY, on a path that references a broken symlink. The symlink is
removed, a file is created, and the call to open returns with an error ENOTDIR.

There are similar strange behaviours. For example, O_CREAT | O_DIRECTORY |
O_EXCL on a symlink to a directory will result in the symlink being removed, a
file being created, and the call returning with an error. POSIX says "If O_EXCL
and O_CREAT are set, and path names a symbolic link, open() shall fail and set
errno to [EEXIST], regardless of the contents of the symbolic link. " (
http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html ) but I'm
not sure whether FreeBSD aims for compliance here. Even if FreeBSD doesn't aim
for compliance, this behaviour possibly breaks a possible POSIX invariant:
calls which return with errors do not alter the underlying file system state
(here, we get an error, but a symlink is removed and a new file is created).


#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
        int fd;

        /* Setup. */
        if (unlink("broken") <= 0 && errno != ENOENT)
                err(-1, "unlink(broken)");
        if (unlink("target") <= 0 && errno != ENOENT)
                err(-1, "unlink(target)");
        if (symlink("target", "broken") < 0)
                err(-1, "symlink(target, broken)");

        /* Test. */
        fd = open("broken", O_CREAT | O_DIRECTORY, 0600);
        if (fd >= 0)
                errx(-1, "open(broken, O_CREAT | O_DIRECTORY) - no error");
        else
                printf("Error on open() was %s\n", strerror(errno));


}

Thanks

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list