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