1 /*
2 * Check decoding of openat2 syscall.
3 *
4 * Copyright (c) 2020-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 <errno.h>
14 #include <stdint.h>
15 #include <inttypes.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <linux/fcntl.h>
20
21 #ifndef VERBOSE
22 # define VERBOSE 0
23 #endif
24 #ifndef FD0_PATH
25 # define FD0_PATH ""
26 #else
27 # define YFLAG
28 #endif
29 #ifndef SKIP_IF_PROC_IS_UNAVAILABLE
30 # define SKIP_IF_PROC_IS_UNAVAILABLE
31 #endif
32
33 #ifdef YFLAG
34 # define AT_FDCWD_FMT "<%s>"
35 # define AT_FDCWD_ARG(arg) arg,
36 #else
37 # define AT_FDCWD_FMT
38 # define AT_FDCWD_ARG(arg)
39 #endif
40
41 static const char sample[] = "openat2.sample";
42
43 int
44 main(void)
45 {
46 SKIP_IF_PROC_IS_UNAVAILABLE;
47
48 #ifdef YFLAG
49 char *cwd = get_fd_path(get_dir_fd("."));
50 #endif
51 long rc;
52 const char *rcstr;
53 struct open_how *how = tail_alloc(sizeof(*how));
54 struct open_how *how_big = tail_alloc(sizeof(*how_big) + 8);
55
56 rc = syscall(__NR_openat2, 0, NULL, NULL,
57 (kernel_ulong_t) 0xdeadc0debadc0dedULL);
58 printf("openat2(0" FD0_PATH ", NULL, NULL, %llu) = %s\n",
59 (unsigned long long) (kernel_ulong_t) 0xdeadc0debadc0dedULL,
60 sprintrc(rc));
61
62 rc = syscall(__NR_openat2, -100, "", how + 1, sizeof(*how));
63 printf("openat2(%s" AT_FDCWD_FMT ", \"\", %p, %zu) = %s\n",
64 XLAT_KNOWN(-100, "AT_FDCWD"),
65 AT_FDCWD_ARG(cwd)
66 how + 1, sizeof(*how),
67 sprintrc(rc));
68
69 rc = syscall(__NR_openat2, -1, sample, how, 11);
70 printf("openat2(-1, \"%s\", %p, 11) = %s\n", sample, how, sprintrc(rc));
71
72 static struct strval64 flags[] = {
73 { ARG_STR(O_RDONLY|O_EXCL) },
74 { ARG_STR(O_WRONLY|O_CREAT) },
75 { ARG_STR(O_RDWR|O_LARGEFILE) },
76 { ARG_STR(O_ACCMODE|O_TMPFILE) },
77 { ARG_ULL_STR(O_RDONLY|0xdeadface80000000) },
78 };
79 static uint64_t modes[] = { 0, 0777, 0xbadc0dedfacebeefULL };
80 static struct strval64 resolve[] = {
81 { 0, NULL },
82 { ARG_STR(RESOLVE_NO_XDEV) },
83 { ARG_ULL_STR(RESOLVE_NO_XDEV|RESOLVE_IN_ROOT|RESOLVE_CACHED|0xfeedfacedcaffec0) },
84 { 0xdec0dedbeeffffc0, NULL },
85 };
86 const size_t iters = MAX(MAX(ARRAY_SIZE(flags), ARRAY_SIZE(modes)),
87 ARRAY_SIZE(resolve));
88
89
90 for (size_t i = 0; i < iters * 4; i++) {
91 how->flags = flags[i % ARRAY_SIZE(flags)].val;
92 how->mode = modes[i % ARRAY_SIZE(modes)];
93 how->resolve = resolve[i % ARRAY_SIZE(resolve)].val;
94
95 fill_memory(how_big + 1, 8);
96 memcpy(how_big, how, sizeof(*how));
97
98 for (size_t j = 0; j < 4; j++) {
99 rc = syscall(__NR_openat2, -1, sample,
100 j > 1 ? how_big : how,
101 j ? sizeof(*how) + 8 : sizeof(*how));
102 rcstr = sprintrc(rc);
103 printf("openat2(-1, \"%s\", {flags=%s",
104 sample,
105 sprintxlat(flags[i % ARRAY_SIZE(flags)].str,
106 flags[i % ARRAY_SIZE(flags)].val,
107 NULL));
108
109 if (how->mode || (i % ARRAY_SIZE(flags) == 1)
110 || (i % ARRAY_SIZE(flags) == 3)) {
111 printf(", mode=%#03" PRIo64,
112 modes[i % ARRAY_SIZE(modes)]);
113 }
114
115 printf(", resolve=%s",
116 sprintxlat(resolve[i % ARRAY_SIZE(resolve)].str,
117 resolve[i % ARRAY_SIZE(resolve)].val,
118 resolve[i % ARRAY_SIZE(resolve)].val
119 ? "RESOLVE_???" : NULL));
120 if (j == 1)
121 printf(", ???");
122 if (j == 2) {
123 printf(", /* bytes %zu..%zu */ \"\\x80\\x81"
124 "\\x82\\x83\\x84\\x85\\x86\\x87\"",
125 sizeof(*how), sizeof(*how) + 7);
126 }
127 printf("}, %zu) = %s\n",
128 j ? sizeof(*how) + 8 : sizeof(*how), rcstr);
129
130 if (j == 2)
131 memset(how_big + 1, 0, 8);
132 }
133 }
134
135 how->flags = O_RDONLY | O_NOCTTY;
136 how->mode = 0;
137 how->resolve = 0;
138 rc = syscall(__NR_openat2, -100, "/dev/full", how, sizeof(*how));
139 printf("openat2(%s" AT_FDCWD_FMT ", \"/dev/full\""
140 ", {flags=%s, resolve=0}, %zu) = %s%s\n",
141 XLAT_KNOWN(-100, "AT_FDCWD"),
142 AT_FDCWD_ARG(cwd)
143 XLAT_STR(O_RDONLY|O_NOCTTY),
144 sizeof(*how), sprintrc(rc), rc >= 0 ? FD0_PATH : "");
145
146 puts("+++ exited with 0 +++");
147 return 0;
148 }