Hi,

solene@ reported on ports an error with unveil(2) on creating
subdirectories on previously not existent directory, for a port she
tried to unveiled.

        https://marc.info/?l=openbsd-ports&m=155992715132013&w=2

so I tried to reproduced it with simple C program.

        $ cat test.c
        #include <sys/stat.h>

        #include <err.h>
        #include <errno.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>

        int
        main(int argc, char *argv[])
        {
                struct stat sb;
                int error;

                /* check if "test" already exists */
                error = stat("test", &sb);
                if (error == 0)
                        errx(EXIT_FAILURE, "test already exists, please remove 
it for test");
                else if ((error == -1) && (errno != ENOENT))
                        err(EXIT_FAILURE, "stat: test");

                /* unveil the name in current directory */
                if (unveil("test", "rwc") == -1)
                        err(EXIT_FAILURE, "unveil: test");

                /* create a directory with that name */
                if (mkdir("test", 0700) == -1)
                        err(EXIT_FAILURE, "mkdir: test");

                /* create a subdirectory in it */
                if (mkdir("test/foo", 0700) == -1)
                        err(EXIT_FAILURE, "mkdir: test/foo");

                return EXIT_SUCCESS;
        }

        $ cc -Wall test.c && ./a.out
        a.out: mkdir: test/foo: No such file or directory


As the "test" vnode doesn't exists in "." at unveil(2) time, it will
record a "non-directory path" name attached to "." vnode (as documented
in man page).

Later, when mkdir(2) will try to use it, namei() will use
unveil_check_compoment() during path traversal, and the function which
only look at "directory path" (using unveil_lookup()), and will not
found it.

The problem is "test" vnode isn't unveiled as a directory, but is
unveiled as a name in "." directory.

Please note the problem exists for any use of "test" as a directory: all
traversal using it will return ENOENT.


Now I am unsure what to do with that.

We could just add a new CAVEATS in unveil(2) as we already have for
another directory subtility:

        a directory that is removed and recreated after a call to
        unveil() will appear to not exist.

Or we could try to duplicate the logical from unveil_check_final() to
unveil_check_compoment(), but I fear of corner-cases it could introduce.

Thanks.
-- 
Sebastien Marie

Reply via email to