1 /*
2 * Check corner cases of AT_FDCWD path decoding.
3 *
4 * Copyright (c) 2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11 #include "scno.h"
12
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20
21 /*
22 * This test is designed to cover cases where AT_FDCWD path decoding
23 * cannot happen because paths length exceed PATH_MAX.
24 * It should be executed with -y or a similar option.
25 */
26
27 int main(void)
28 {
29 /*
30 * Make sure the current workdir of the tracee
31 * is different from the current workdir of the tracer.
32 */
33 create_and_enter_subdir("pathmax_subdir");
34
35 char *topdir = get_fd_path(get_dir_fd("."));
36
37 /*
38 * AT_FDCWD path decoding
39 */
40 char name[NAME_MAX + 1];
41 memset(name, 'x', sizeof(name) - 1);
42 name[sizeof(name) - 1] = '\0';
43
44 unsigned int count = 0;
45 for (size_t len = strlen(topdir);
46 len <= PATH_MAX;
47 len += sizeof(name), ++count) {
48 if (mkdir(name, 0700))
49 perror_msg_and_fail("mkdir, count=%u", count);
50 if (chdir(name))
51 perror_msg_and_fail("chdir, count=%u", count);
52 }
53
54 /* AT_FDCWD is not be printed since path cannot be resolved. */
55
56 int fd = syscall(__NR_openat, AT_FDCWD, "sample", O_RDONLY);
57 printf("openat(AT_FDCWD, \"sample\", O_RDONLY) = %s\n",
58 sprintrc(fd));
59
60 /* Go back one dir and verify it's printed. */
61
62 --count;
63 if (chdir(".."))
64 perror_msg_and_fail("chdir");
65 if (rmdir(name))
66 perror_msg_and_fail("rmdir");
67
68 char *cwd = get_fd_path(get_dir_fd("."));
69
70 fd = syscall(__NR_openat, AT_FDCWD, "sample", O_RDONLY);
71 printf("openat(AT_FDCWD<%s>, \"sample\", O_RDONLY) = %s\n",
72 cwd, sprintrc(fd));
73
74 /* Create a dir for which exact PATH_MAX size is returned. */
75
76 char dir[NAME_MAX + 1];
77 memset(dir, 'x', sizeof(dir) - 1);
78 dir[PATH_MAX - (strlen(cwd) + 1)] = '\0';
79 if (mkdir(dir, 0700))
80 perror_msg_and_fail("mkdir");
81 if (chdir(dir))
82 perror_msg_and_fail("chdir");
83
84 /* AT_FDCWD is not printed since path cannot be resolved fully. */
85
86 fd = syscall(__NR_openat, AT_FDCWD, "sample", O_RDONLY);
87 printf("openat(AT_FDCWD, \"sample\", O_RDONLY) = %s\n",
88 sprintrc(fd));
89
90 if (chdir(".."))
91 perror_msg_and_fail("chdir");
92 if (rmdir(dir))
93 perror_msg_and_fail("rmdir");
94
95 for (; count > 0; --count) {
96 if (chdir(".."))
97 perror_msg_and_fail("chdir, count=%u", count);
98 if (rmdir(name))
99 perror_msg_and_fail("rmdir, count=%u", count);
100 }
101
102 leave_and_remove_subdir();
103
104 puts("+++ exited with 0 +++");
105 return 0;
106 }