^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Permission to use, copy, modify, and distribute this software for any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * purpose with or without fee is hereby granted, provided that the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * copyright notice and this permission notice appear in all copies.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) // Test /proc/*/fd lookup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #undef NDEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <dirent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "proc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* lstat(2) has more "coverage" in case non-symlink pops up somehow. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void test_lookup_pass(const char *pathname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) memset(&st, 0, sizeof(struct stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) rv = lstat(pathname, &st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) assert(rv == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) assert(S_ISLNK(st.st_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static void test_lookup_fail(const char *pathname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) rv = lstat(pathname, &st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) assert(rv == -1 && errno == ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void test_lookup(unsigned int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char buf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) snprintf(buf, sizeof(buf), "/proc/self/fd/%u", fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) test_lookup_pass(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* leading junk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) for (c = 1; c <= 255; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (c == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) snprintf(buf, sizeof(buf), "/proc/self/fd/%c%u", c, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) test_lookup_fail(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* trailing junk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) for (c = 1; c <= 255; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (c == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) snprintf(buf, sizeof(buf), "/proc/self/fd/%u%c", fd, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) test_lookup_fail(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (i = INT_MIN; i < INT_MIN + 1024; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) snprintf(buf, sizeof(buf), "/proc/self/fd/%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) test_lookup_fail(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) for (i = -1024; i < 0; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) snprintf(buf, sizeof(buf), "/proc/self/fd/%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) test_lookup_fail(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) for (u = INT_MAX - 1024; u <= (unsigned int)INT_MAX + 1024; u++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) snprintf(buf, sizeof(buf), "/proc/self/fd/%u", u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) test_lookup_fail(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) for (u = UINT_MAX - 1024; u != 0; u++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) snprintf(buf, sizeof(buf), "/proc/self/fd/%u", u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) test_lookup_fail(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int main(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct dirent *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int fd, target_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (unshare(CLONE_FILES) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Wipe fdtable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) DIR *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) d = opendir("/proc/self/fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) de = xreaddir(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) assert(de->d_type == DT_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) assert(streq(de->d_name, "."));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) de = xreaddir(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) assert(de->d_type == DT_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) assert(streq(de->d_name, ".."));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) de = xreaddir(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (de) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned long long fd_ull;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) assert(de->d_type == DT_LNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fd_ull = xstrtoull(de->d_name, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) assert(*end == '\0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) assert(fd_ull == (unsigned int)fd_ull);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) fd = fd_ull;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (fd == dirfd(d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) closedir(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) } while (de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Now fdtable is clean. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) fd = open("/", O_PATH|O_DIRECTORY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) assert(fd == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) test_lookup(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* Clean again! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) fd = open("/", O_PATH|O_DIRECTORY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) assert(fd == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* Default RLIMIT_NOFILE-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) target_fd = 1023;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) while (target_fd > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (dup2(fd, target_fd) == target_fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) target_fd /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) assert(target_fd > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) test_lookup(target_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) close(target_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }