1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include <errno.h>
16#include <fcntl.h>
17#include <signal.h>
18#include <string.h>
19#include <sys/wait.h>
20#include <sigchain.h>
21#include "fortify_test.h"
22#include "functionalext.h"
23#include "test.h"
24
25#define FILE_MODE_ALL (0777)
26
27#ifdef open64
28#undef open64
29#endif
30
31#ifdef openat64
32#undef openat64
33#endif
34
35/**
36 * @tc.name     : open_0010
37 * @tc.desc     : test open normal condition
38 * @tc.level    : Level 0
39 */
40static void open_0010(void)
41{
42    int fd = open("/proc/version", O_RDWR | O_CREAT, FILE_MODE_ALL);
43    TEST(fd != -1);
44    close(fd);
45
46    return;
47}
48
49/**
50 * @tc.name     : open_0020
51 * @tc.desc     : test open O_CREAT without mode
52 * @tc.level    : Level 2
53 */
54static void open_0020(void)
55{
56    struct sigaction sigabrt = {
57        .sa_handler = SignalHandler,
58    };
59    sigaction(SIGABRT, &sigabrt, NULL);
60
61    int flags = O_CREAT;
62    int status;
63    int pid = fork();
64    switch (pid) {
65        case -1:
66            t_error("fork failed: %s\n", strerror(errno));
67            break;
68        case 0:
69            open("/proc/version", flags);
70            exit(0);
71        default:
72            waitpid(pid, &status, WUNTRACED);
73            TEST(WIFEXITED(status) == 0);
74            TEST(WIFSTOPPED(status) == 1);
75            TEST(WSTOPSIG(status) == SIGSTOP);
76            kill(pid, SIGCONT);
77            break;
78    }
79
80    return;
81}
82
83/**
84 * @tc.name     : open_0030
85 * @tc.desc     : test open O_TMPFILE without mode
86 * @tc.level    : Level 2
87 */
88static void open_0030(void)
89{
90    struct sigaction sigabrt = {
91        .sa_handler = SignalHandler,
92    };
93    sigaction(SIGABRT, &sigabrt, NULL);
94
95    int flags = O_TMPFILE;
96    int status;
97    int pid = fork();
98    switch (pid) {
99        case -1:
100            t_error("fork failed: %s\n", strerror(errno));
101            break;
102        case 0:
103            open("/proc/version", flags);
104            exit(0);
105        default:
106            waitpid(pid, &status, WUNTRACED);
107            TEST(WIFEXITED(status) == 0);
108            TEST(WIFSTOPPED(status) == 1);
109            TEST(WSTOPSIG(status) == SIGSTOP);
110            kill(pid, SIGCONT);
111            break;
112    }
113
114    return;
115}
116
117/**
118 * @tc.name     : open_0040
119 * @tc.desc     : test open only O_RDWR
120 * @tc.level    : Level 1
121 */
122static void open_0040(void)
123{
124    int fd = open("/proc/version", O_RDWR);
125    EXPECT_NE(open_0040, fd, -1);
126    close(fd);
127
128    return;
129}
130
131/**
132 * @tc.name     : openat_0010
133 * @tc.desc     : test openat normal condition
134 * @tc.level    : Level 0
135 */
136static void openat_0010(void)
137{
138    int fd = openat(AT_FDCWD, "/proc/version", O_RDWR | O_CREAT, FILE_MODE_ALL);
139    TEST(fd != -1);
140    close(fd);
141
142    return;
143}
144
145/**
146 * @tc.name     : openat_0020
147 * @tc.desc     : test openat O_CREAT without mode
148 * @tc.level    : Level 2
149 */
150static void openat_0020(void)
151{
152    struct sigaction sigabrt = {
153        .sa_handler = SignalHandler,
154    };
155    sigaction(SIGABRT, &sigabrt, NULL);
156
157    int flags = O_CREAT;
158    int status;
159    int pid = fork();
160    switch (pid) {
161        case -1:
162            t_error("fork failed: %s\n", strerror(errno));
163            break;
164        case 0:
165            openat(AT_FDCWD, "/proc/version", flags);
166            exit(0);
167        default:
168            waitpid(pid, &status, WUNTRACED);
169            TEST(WIFEXITED(status) == 0);
170            TEST(WIFSTOPPED(status) == 1);
171            TEST(WSTOPSIG(status) == SIGSTOP);
172            kill(pid, SIGCONT);
173            break;
174    }
175
176    return;
177}
178
179/**
180 * @tc.name     : openat_0030
181 * @tc.desc     : test openat O_TMPFILE without mode
182 * @tc.level    : Level 2
183 */
184static void openat_0030(void)
185{
186    struct sigaction sigabrt = {
187        .sa_handler = SignalHandler,
188    };
189    sigaction(SIGABRT, &sigabrt, NULL);
190
191    int flags = O_TMPFILE;
192    int status;
193    int pid = fork();
194    switch (pid) {
195        case -1:
196            t_error("fork failed: %s\n", strerror(errno));
197            break;
198        case 0:
199            openat(AT_FDCWD, "/proc/version", flags);
200            exit(0);
201        default:
202            waitpid(pid, &status, WUNTRACED);
203            TEST(WIFEXITED(status) == 0);
204            TEST(WIFSTOPPED(status) == 1);
205            TEST(WSTOPSIG(status) == SIGSTOP);
206            kill(pid, SIGCONT);
207            break;
208    }
209
210    return;
211}
212
213/**
214 * @tc.name     : openat_0040
215 * @tc.desc     : test openat only O_RDWR
216 * @tc.level    : Level 1
217 */
218static void openat_0040(void)
219{
220    int fd = openat(AT_FDCWD, "/proc/version", O_RDWR);
221    EXPECT_NE(openat_0040, fd, -1);
222    close(fd);
223
224    return;
225}
226
227#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
228/**
229 * @tc.name     : open64_0010
230 * @tc.desc     : test open64 normal condition
231 * @tc.level    : Level 0
232 */
233static void open64_0010(void)
234{
235    int fd = open64("/proc/version", O_RDWR | O_CREAT, FILE_MODE_ALL);
236    TEST(fd != -1);
237    close(fd);
238
239    return;
240}
241
242/**
243 * @tc.name     : open64_0020
244 * @tc.desc     : test open64 O_CREAT without mode
245 * @tc.level    : Level 2
246 */
247static void open64_0020(void)
248{
249    struct sigaction sigabrt = {
250        .sa_handler = SignalHandler,
251    };
252    sigaction(SIGABRT, &sigabrt, NULL);
253
254    int flags = O_CREAT;
255    int status;
256    int pid = fork();
257    switch (pid) {
258        case -1:
259            t_error("fork failed: %s\n", strerror(errno));
260            break;
261        case 0:
262            open64("/proc/version", flags);
263            exit(0);
264        default:
265            waitpid(pid, &status, WUNTRACED);
266            TEST(WIFEXITED(status) == 0);
267            TEST(WIFSTOPPED(status) == 1);
268            TEST(WSTOPSIG(status) == SIGSTOP);
269            kill(pid, SIGCONT);
270            break;
271    }
272
273    return;
274}
275
276/**
277 * @tc.name     : open64_0030
278 * @tc.desc     : test open64 O_TMPFILE without mode
279 * @tc.level    : Level 2
280 */
281static void open64_0030(void)
282{
283    struct sigaction sigabrt = {
284        .sa_handler = SignalHandler,
285    };
286    sigaction(SIGABRT, &sigabrt, NULL);
287
288    int flags = O_TMPFILE;
289    int status;
290    int pid = fork();
291    switch (pid) {
292        case -1:
293            t_error("fork failed: %s\n", strerror(errno));
294            break;
295        case 0:
296            open64("/proc/version", flags);
297            exit(0);
298        default:
299            waitpid(pid, &status, WUNTRACED);
300            TEST(WIFEXITED(status) == 0);
301            TEST(WIFSTOPPED(status) == 1);
302            TEST(WSTOPSIG(status) == SIGSTOP);
303            kill(pid, SIGCONT);
304            break;
305    }
306
307    return;
308}
309
310/**
311 * @tc.name     : open64_0040
312 * @tc.desc     : test open64 only O_RDWR
313 * @tc.level    : Level 1
314 */
315static void open64_0040(void)
316{
317    int fd = open64("/proc/version", O_RDWR);
318    EXPECT_NE(open64_0040, fd, -1);
319    close(fd);
320
321    return;
322}
323
324/**
325 * @tc.name     : openat64_0010
326 * @tc.desc     : test openat64 normal condition
327 * @tc.level    : Level 0
328 */
329static void openat64_0010(void)
330{
331    int fd = openat64(AT_FDCWD, "/proc/version", O_RDWR | O_CREAT, FILE_MODE_ALL);
332    TEST(fd != -1);
333    close(fd);
334
335    return;
336}
337
338/**
339 * @tc.name     : openat64_0020
340 * @tc.desc     : test openat64 O_CREAT without mode
341 * @tc.level    : Level 2
342 */
343static void openat64_0020(void)
344{
345    struct sigaction sigabrt = {
346        .sa_handler = SignalHandler,
347    };
348    sigaction(SIGABRT, &sigabrt, NULL);
349
350    int flags = O_CREAT;
351    int status;
352    int pid = fork();
353    switch (pid) {
354        case -1:
355            t_error("fork failed: %s\n", strerror(errno));
356            break;
357        case 0:
358            openat64(AT_FDCWD, "/proc/version", flags);
359            exit(0);
360        default:
361            waitpid(pid, &status, WUNTRACED);
362            TEST(WIFEXITED(status) == 0);
363            TEST(WIFSTOPPED(status) == 1);
364            TEST(WSTOPSIG(status) == SIGSTOP);
365            kill(pid, SIGCONT);
366            break;
367    }
368
369    return;
370}
371
372/**
373 * @tc.name     : openat64_0030
374 * @tc.desc     : test openat64 O_TMPFILE without mode
375 * @tc.level    : Level 2
376 */
377static void openat64_0030(void)
378{
379    struct sigaction sigabrt = {
380        .sa_handler = SignalHandler,
381    };
382    sigaction(SIGABRT, &sigabrt, NULL);
383
384    int flags = O_TMPFILE;
385    int status;
386    int pid = fork();
387    switch (pid) {
388        case -1:
389            t_error("fork failed: %s\n", strerror(errno));
390            break;
391        case 0:
392            openat64(AT_FDCWD, "/proc/version", flags);
393            exit(0);
394        default:
395            waitpid(pid, &status, WUNTRACED);
396            TEST(WIFEXITED(status) == 0);
397            TEST(WIFSTOPPED(status) == 1);
398            TEST(WSTOPSIG(status) == SIGSTOP);
399            kill(pid, SIGCONT);
400            break;
401    }
402
403    return;
404}
405
406/**
407 * @tc.name     : openat64_0040
408 * @tc.desc     : test openat64 only O_RDWR
409 * @tc.level    : Level 1
410 */
411static void openat64_0040(void)
412{
413    int fd = openat64(AT_FDCWD, "/proc/version", O_RDWR);
414    EXPECT_NE(openat64_0040, fd, -1);
415    close(fd);
416
417    return;
418}
419#endif
420
421int main(int argc, char *argv[]) {
422    remove_all_special_handler(SIGABRT);
423    open_0010();
424    open_0020();
425    open_0030();
426    open_0040();
427    openat_0010();
428    openat_0020();
429    openat_0030();
430    openat_0040();
431#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
432    open64_0010();
433    open64_0020();
434    open64_0030();
435    open64_0040();
436    openat64_0010();
437    openat64_0020();
438    openat64_0030();
439    openat64_0040();
440#endif
441    return t_status;
442}