/* * Check corner cases of AT_FDCWD path decoding. * * Copyright (c) 2021 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include "scno.h" #include #include #include #include #include #include #include /* * This test is designed to cover cases where AT_FDCWD path decoding * cannot happen because paths length exceed PATH_MAX. * It should be executed with -y or a similar option. */ int main(void) { /* * Make sure the current workdir of the tracee * is different from the current workdir of the tracer. */ create_and_enter_subdir("pathmax_subdir"); char *topdir = get_fd_path(get_dir_fd(".")); /* * AT_FDCWD path decoding */ char name[NAME_MAX + 1]; memset(name, 'x', sizeof(name) - 1); name[sizeof(name) - 1] = '\0'; unsigned int count = 0; for (size_t len = strlen(topdir); len <= PATH_MAX; len += sizeof(name), ++count) { if (mkdir(name, 0700)) perror_msg_and_fail("mkdir, count=%u", count); if (chdir(name)) perror_msg_and_fail("chdir, count=%u", count); } /* AT_FDCWD is not be printed since path cannot be resolved. */ int fd = syscall(__NR_openat, AT_FDCWD, "sample", O_RDONLY); printf("openat(AT_FDCWD, \"sample\", O_RDONLY) = %s\n", sprintrc(fd)); /* Go back one dir and verify it's printed. */ --count; if (chdir("..")) perror_msg_and_fail("chdir"); if (rmdir(name)) perror_msg_and_fail("rmdir"); char *cwd = get_fd_path(get_dir_fd(".")); fd = syscall(__NR_openat, AT_FDCWD, "sample", O_RDONLY); printf("openat(AT_FDCWD<%s>, \"sample\", O_RDONLY) = %s\n", cwd, sprintrc(fd)); /* Create a dir for which exact PATH_MAX size is returned. */ char dir[NAME_MAX + 1]; memset(dir, 'x', sizeof(dir) - 1); dir[PATH_MAX - (strlen(cwd) + 1)] = '\0'; if (mkdir(dir, 0700)) perror_msg_and_fail("mkdir"); if (chdir(dir)) perror_msg_and_fail("chdir"); /* AT_FDCWD is not printed since path cannot be resolved fully. */ fd = syscall(__NR_openat, AT_FDCWD, "sample", O_RDONLY); printf("openat(AT_FDCWD, \"sample\", O_RDONLY) = %s\n", sprintrc(fd)); if (chdir("..")) perror_msg_and_fail("chdir"); if (rmdir(dir)) perror_msg_and_fail("rmdir"); for (; count > 0; --count) { if (chdir("..")) perror_msg_and_fail("chdir, count=%u", count); if (rmdir(name)) perror_msg_and_fail("rmdir, count=%u", count); } leave_and_remove_subdir(); puts("+++ exited with 0 +++"); return 0; }