1 /* 2 * Check decoding of utimensat syscall. 3 * 4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv (at) 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 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 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 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