1 /*
2  * Check decoding of utimensat syscall.
3  *
4  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2015-2018 The strace developers.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "tests.h"
32 #include <fcntl.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <unistd.h>
38 #include <asm/unistd.h>
39 
40 #if defined __NR_utimensat && defined UTIME_NOW && defined UTIME_OMIT
41 
42 #if SIZEOF_KERNEL_LONG_T == 4
43 #  define big_tv_sec "-559038737"
44 #  define huge_tv_sec "-559038737"
45 # else
46 #  define big_tv_sec "3735928559"
47 #  define huge_tv_sec "-3819351491602432273"
48 # endif
49 
50 # if XLAT_RAW
51 #  define str_at_fdcwd			"-100"
52 #  define str_at_symlink_nofollow	"0x100"
53 #  define str_at_removedir		"0x200"
54 #  define str_flags1			"0x600"
55 #  define str_flags2			"0xffffffff"
56 #  define str_utime_now_omit \
57 	"[{tv_sec=" big_tv_sec ", tv_nsec=1073741823}, " \
58 	"{tv_sec=" huge_tv_sec ", tv_nsec=1073741822}]"
59 # elif XLAT_VERBOSE
60 #  define str_at_fdcwd			"-100 /* AT_FDCWD */"
61 #  define str_at_symlink_nofollow	"0x100 /* AT_SYMLINK_NOFOLLOW */"
62 #  define str_at_removedir		"0x200 /* AT_REMOVEDIR */"
63 #  define str_flags1 \
64 	"0x600 /* AT_REMOVEDIR|AT_SYMLINK_FOLLOW */"
65 #  define str_flags2 \
66 	"0xffffffff /* AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW" \
67 	"|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|0xffffe0ff */"
68 #  define str_utime_now_omit \
69 	"[{tv_sec=" big_tv_sec ", tv_nsec=1073741823} /* UTIME_NOW */, " \
70 	"{tv_sec=" huge_tv_sec ", tv_nsec=1073741822} /* UTIME_OMIT */]"
71 # else
72 #  define str_at_fdcwd			"AT_FDCWD"
73 #  define str_at_symlink_nofollow	"AT_SYMLINK_NOFOLLOW"
74 #  define str_at_removedir		"AT_REMOVEDIR"
75 #  define str_flags1			"AT_REMOVEDIR|AT_SYMLINK_FOLLOW"
76 #  define str_flags2 \
77 	"AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW" \
78 	"|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|0xffffe0ff"
79 #  define str_utime_now_omit		"[UTIME_NOW, UTIME_OMIT]"
80 # endif
81 
82 static void
print_ts(const struct timespec * ts)83 print_ts(const struct timespec *ts)
84 {
85 	printf("{tv_sec=%lld, tv_nsec=%llu}", (long long) ts->tv_sec,
86 		zero_extend_signed_to_ull(ts->tv_nsec));
87 	print_time_t_nsec(ts->tv_sec,
88 			  zero_extend_signed_to_ull(ts->tv_nsec), 1);
89 }
90 
91 static const char *errstr;
92 
93 static long
k_utimensat(const kernel_ulong_t dirfd,const kernel_ulong_t pathname,const kernel_ulong_t times,const kernel_ulong_t flags)94 k_utimensat(const kernel_ulong_t dirfd,
95 	    const kernel_ulong_t pathname,
96 	    const kernel_ulong_t times,
97 	    const kernel_ulong_t flags)
98 {
99 	long rc = syscall(__NR_utimensat, dirfd, pathname, times, flags);
100 	errstr = sprintrc(rc);
101 	return rc;
102 }
103 
104 int
main(void)105 main(void)
106 {
107 	static const kernel_ulong_t bogus_fd =
108 		(kernel_ulong_t) 0xbadc0deddeadbeef;
109 	static const kernel_ulong_t kfdcwd =
110 		(kernel_ulong_t) 0xdefaced00000000 | -100U;
111 	static const char proto_fname[] = "utimensat\nfilename";
112 	static const char qname[] = "\"utimensat\\nfilename\"";
113 
114 	char *const fname = tail_memdup(proto_fname, sizeof(proto_fname));
115 	const kernel_ulong_t kfname = (uintptr_t) fname;
116 	struct timespec *const ts = tail_alloc(sizeof(*ts) * 2);
117 
118 	(void) close(0);
119 
120 	/* dirfd */
121 	k_utimensat(0, kfname, 0, 0);
122 	printf("utimensat(0, %s, NULL, 0) = %s\n", qname, errstr);
123 
124 	k_utimensat(bogus_fd, kfname, 0, 0);
125 	printf("utimensat(%d, %s, NULL, 0) = %s\n",
126 	       (int) bogus_fd, qname, errstr);
127 
128 	k_utimensat(-100U, kfname, 0, 0);
129 	printf("utimensat(" str_at_fdcwd ", %s, NULL, 0) = %s\n", qname, errstr);
130 
131 	k_utimensat(kfdcwd, kfname, 0, 0);
132 	printf("utimensat(" str_at_fdcwd ", %s, NULL, 0) = %s\n", qname, errstr);
133 
134 	/* pathname */
135 	k_utimensat(kfdcwd, 0, 0, 0);
136 	printf("utimensat(" str_at_fdcwd ", NULL, NULL, 0) = %s\n", errstr);
137 
138 	k_utimensat(kfdcwd, kfname + sizeof(proto_fname) - 1, 0, 0);
139 	printf("utimensat(" str_at_fdcwd ", \"\", NULL, 0) = %s\n", errstr);
140 
141 	fname[sizeof(proto_fname) - 1] = '+';
142 	k_utimensat(kfdcwd, kfname, 0, 0);
143 	fname[sizeof(proto_fname) - 1] = '\0';
144 	printf("utimensat(" str_at_fdcwd ", %p, NULL, 0) = %s\n", fname, errstr);
145 
146 	if (F8ILL_KULONG_SUPPORTED) {
147 		k_utimensat(kfdcwd, f8ill_ptr_to_kulong(fname), 0, 0);
148 		printf("utimensat(" str_at_fdcwd ", %#jx, NULL, 0) = %s\n",
149 		       (uintmax_t) f8ill_ptr_to_kulong(fname), errstr);
150 	}
151 
152 	/* times */
153 	k_utimensat(kfdcwd, kfname, (uintptr_t) (ts + 1), 0);
154 	printf("utimensat(" str_at_fdcwd ", %s, %p, 0) = %s\n",
155 	       qname, ts + 1, errstr);
156 
157 	k_utimensat(kfdcwd, kfname, (uintptr_t) (ts + 2), 0);
158 	printf("utimensat(" str_at_fdcwd ", %s, %p, 0)"
159 	       " = %s\n", qname, ts + 2, errstr);
160 
161 	ts[0].tv_sec = 1492358706;
162 	ts[0].tv_nsec = 123456789;
163 	ts[1].tv_sec = 1492357068;
164 	ts[1].tv_nsec = 234567890;
165 
166 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
167 	printf("utimensat(" str_at_fdcwd ", %s, [", qname);
168 	print_ts(&ts[0]);
169 	printf(", ");
170 	print_ts(&ts[1]);
171 	printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
172 
173 	ts[0].tv_sec = -1;
174 	ts[0].tv_nsec = 2000000000;
175 	ts[1].tv_sec = (time_t) -0x100000001LL;
176 	ts[1].tv_nsec = 2345678900U;
177 
178 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
179 	printf("utimensat(" str_at_fdcwd ", %s, [", qname);
180 	print_ts(&ts[0]);
181 	printf(", ");
182 	print_ts(&ts[1]);
183 	printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
184 
185 	ts[0].tv_sec = 0;
186 	ts[0].tv_nsec = 0;
187 	ts[1].tv_sec = (time_t) 0xcafef00ddeadbeefLL;
188 	ts[1].tv_nsec = 0;
189 
190 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
191 	printf("utimensat(" str_at_fdcwd ", %s, [", qname);
192 	print_ts(&ts[0]);
193 	printf(", ");
194 	print_ts(&ts[1]);
195 	printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
196 
197 	ts[0].tv_sec = 0xdeadbeefU;
198 	ts[0].tv_nsec = 0xfacefeedU;
199 	ts[1].tv_sec = (time_t) 0xcafef00ddeadbeefLL;
200 	ts[1].tv_nsec = (long) 0xbadc0dedfacefeedLL;
201 
202 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
203 	printf("utimensat(" str_at_fdcwd ", %s, [", qname);
204 	print_ts(&ts[0]);
205 	printf(", ");
206 	print_ts(&ts[1]);
207 	printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
208 
209 	ts[0].tv_nsec = UTIME_NOW;
210 	ts[1].tv_nsec = UTIME_OMIT;
211 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
212 	printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
213 	       ", " str_at_symlink_nofollow ") = %s\n", qname, errstr);
214 
215 	if (F8ILL_KULONG_SUPPORTED) {
216 		k_utimensat(kfdcwd, kfname, f8ill_ptr_to_kulong(ts), 0);
217 		printf("utimensat(" str_at_fdcwd ", %s, %#jx, 0) = %s\n",
218 		       qname, (uintmax_t) f8ill_ptr_to_kulong(ts), errstr);
219 	}
220 
221 	/* flags */
222 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts,
223 		    (kernel_ulong_t) 0xdefaced00000200);
224 	printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
225 	       ", " str_at_removedir ") = %s\n",
226 	       qname, errstr);
227 
228 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts,
229 		    (kernel_ulong_t) 0xdefaced00000600);
230 	printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
231 	       ", " str_flags1 ") = %s\n",
232 	       qname, errstr);
233 
234 	k_utimensat(kfdcwd, kfname, (uintptr_t) ts, (kernel_ulong_t) -1ULL);
235 	printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
236 	       ", " str_flags2 ") = %s\n",
237 	       qname, errstr);
238 
239 	puts("+++ exited with 0 +++");
240 	return 0;
241 }
242 
243 #else
244 
245 SKIP_MAIN_UNDEFINED("__NR_utimensat && UTIME_NOW && UTIME_OMIT")
246 
247 #endif
248