1 /*
2 * Copyright (c) 2016 Katerina Koukiou <k.koukiou@gmail.com>
3 * Copyright (c) 2016-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "tests.h"
10 #include "scno.h"
11
12 #ifdef __NR_openat
13
14 # include <asm/fcntl.h>
15 # include <stdio.h>
16 # include <unistd.h>
17
18 # include "secontext.h"
19
20 # ifdef O_TMPFILE
21 /* The kernel & C libraries often inline O_DIRECTORY. */
22 # define STRACE_O_TMPFILE (O_TMPFILE & ~O_DIRECTORY)
23 # else
24 # define STRACE_O_TMPFILE 0
25 # endif
26
27 static const char sample[] = "openat.sample";
28
29 static void
30 test_mode_flag(unsigned int mode_val, const char *mode_str,
31 unsigned int flag_val, const char *flag_str,
32 const char *my_secontext)
33 {
34 long rc = syscall(__NR_openat, -1, sample, mode_val | flag_val, 0);
35 printf("%s%s(-1, \"%s\", %s%s%s%s) = %s\n",
36 my_secontext, "openat",
37 sample, mode_str,
38 flag_val ? "|" : "", flag_str,
39 flag_val & (O_CREAT | STRACE_O_TMPFILE) ? ", 000" : "",
40 sprintrc(rc));
41 }
42
43 int
44 main(void)
45 {
46 /*
47 * Make sure the current workdir of the tracee
48 * is different from the current workdir of the tracer.
49 */
50 create_and_enter_subdir("openat_subdir");
51
52 char *my_secontext = SECONTEXT_PID_MY();
53 struct {
54 unsigned int val;
55 const char *str;
56 } modes[] = {
57 { ARG_STR(O_RDONLY) },
58 { ARG_STR(O_WRONLY) },
59 { ARG_STR(O_RDWR) },
60 { ARG_STR(O_ACCMODE) }
61 }, flags[] = {
62 { ARG_STR(O_APPEND) },
63 { ARG_STR(O_DIRECT) },
64 { ARG_STR(O_DIRECTORY) },
65 { ARG_STR(O_EXCL) },
66 { ARG_STR(O_LARGEFILE) },
67 { ARG_STR(O_NOATIME) },
68 { ARG_STR(O_NOCTTY) },
69 { ARG_STR(O_NOFOLLOW) },
70 { ARG_STR(O_NONBLOCK) },
71 { ARG_STR(O_SYNC) },
72 { ARG_STR(O_TRUNC) },
73 { ARG_STR(O_CREAT) },
74 # ifdef O_CLOEXEC
75 { ARG_STR(O_CLOEXEC) },
76 # endif
77 # ifdef O_DSYNC
78 { ARG_STR(O_DSYNC) },
79 # endif
80 # ifdef __O_SYNC
81 { ARG_STR(__O_SYNC) },
82 # endif
83 # ifdef O_PATH
84 { ARG_STR(O_PATH) },
85 # endif
86 # ifdef O_TMPFILE
87 { ARG_STR(O_TMPFILE) },
88 # endif
89 # ifdef __O_TMPFILE
90 { ARG_STR(__O_TMPFILE) },
91 # endif
92 { ARG_STR(0x80000000) },
93 { 0, "" }
94 };
95
96 for (unsigned int m = 0; m < ARRAY_SIZE(modes); ++m)
97 for (unsigned int f = 0; f < ARRAY_SIZE(flags); ++f)
98 test_mode_flag(modes[m].val, modes[m].str,
99 flags[f].val, flags[f].str,
100 my_secontext);
101
102 /*
103 * Tests with AT_FDCWD.
104 */
105
106 (void) unlink(sample);
107 long fd = syscall(__NR_openat, -100, sample, O_RDONLY|O_CREAT, 0400);
108
109 char *sample_secontext = SECONTEXT_FILE(sample);
110
111 /*
112 * File context in openat() is not displayed because file doesn't exist
113 * yet, but is displayed in return value since the file got created.
114 */
115 printf("%s%s(AT_FDCWD, \"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n",
116 my_secontext, "openat",
117 sample,
118 sprintrc(fd), sample_secontext);
119
120 close(fd);
121
122 fd = syscall(__NR_openat, -100, sample, O_RDONLY);
123 printf("%s%s(AT_FDCWD, \"%s\"%s, O_RDONLY) = %s%s\n",
124 my_secontext, "openat",
125 sample, sample_secontext,
126 sprintrc(fd), sample_secontext);
127 if (fd != -1) {
128 close(fd);
129 if (unlink(sample))
130 perror_msg_and_fail("unlink");
131 }
132
133 /*
134 * Tests with dirfd.
135 */
136
137 int cwd_fd = get_dir_fd(".");
138 char *cwd_secontext = SECONTEXT_FILE(".");
139
140 fd = syscall(__NR_openat, cwd_fd, sample, O_RDONLY|O_CREAT, 0400);
141 if (fd == -1)
142 perror_msg_and_fail("openat");
143 close(fd);
144
145 /*
146 * File context in openat() is not displayed because file doesn't exist
147 * yet, but is displayed in return value since the file got created.
148 */
149 printf("%s%s(%d%s, \"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n",
150 my_secontext, "openat",
151 cwd_fd, cwd_secontext,
152 sample,
153 sprintrc(fd), sample_secontext);
154
155 fd = syscall(__NR_openat, cwd_fd, sample, O_RDONLY);
156 printf("%s%s(%d%s, \"%s\"%s, O_RDONLY) = %s%s\n",
157 my_secontext, "openat",
158 cwd_fd, cwd_secontext,
159 sample, sample_secontext,
160 sprintrc(fd), sample_secontext);
161 if (fd != -1) {
162 close(fd);
163 if (unlink(sample))
164 perror_msg_and_fail("unlink");
165 }
166
167 leave_and_remove_subdir();
168
169 puts("+++ exited with 0 +++");
170 return 0;
171 }
172
173 #else
174
175 SKIP_MAIN_UNDEFINED("__NR_openat")
176
177 #endif