cposixchrootrealpath

Determine if path is inside directory


In my application, I am trying to check if a path is inside of a specific directory. E.g., I want the files in the path /x/y/z not to be accessible by parts of my application. I cannot use traditional file permissions, as other parts of the application should be able to access these files.

Several Internet resources suggest the use of realpath to first canonicalize paths, i.e., resolving all symlinks and instances of .. (e.g. 1, 2). However, it seems not to be possible to perform path resolution followed by an open without an race condition (TOCTOU).

char *resolved = realpath("/my/potentially/dangerous/path.txt", NULL);
// someone changes any part of the path to a symlink to something else   <--- race condition
if (check_path(resolved)) {
    //                                                                   <--- race condition
    int fd = open(resolved, O_RDONLY);
}

Am I overlooking something or does POSIX (and Linux) not provide any way to do something like this without a race condition?


Solution

  • What about 'openat2' (Linux only)?

    And once you have a file descriptor, see man open

    Description:

    A file descriptor is a reference to an open file description; this reference is unaffected if pathname is subsequently removed or modified to refer to a different file.