1 /* 2 * Check decoding of pread64 and pwrite64 syscalls. 3 * 4 * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * Copyright (c) 2016-2017 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 33 #include <fcntl.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 38 static void 39 dump_str(const char *str, const unsigned int len) 40 { 41 static const char dots[16] = "................"; 42 unsigned int i; 43 44 for (i = 0; i < len; i += 16) { 45 unsigned int n = len - i > 16 ? 16 : len - i; 46 const char *dump = hexdump_memdup(str + i, n); 47 48 tprintf(" | %05x %-49s %-16.*s |\n", 49 i, dump, n, dots); 50 51 free((void *) dump); 52 } 53 } 54 55 static void 56 print_hex(const char *str, const unsigned int len) 57 { 58 const unsigned char *ustr = (const unsigned char *) str; 59 unsigned int i; 60 61 for (i = 0; i < len; ++i) { 62 unsigned int c = ustr[i]; 63 64 switch (c) { 65 case '\t': 66 tprintf("\\t"); break; 67 case '\n': 68 tprintf("\\n"); break; 69 case '\v': 70 tprintf("\\v"); break; 71 case '\f': 72 tprintf("\\f"); break; 73 case '\r': 74 tprintf("\\r"); break; 75 default: 76 tprintf("\\%o", ustr[i]); 77 } 78 } 79 } 80 81 static void 82 test_dump(const unsigned int len) 83 { 84 static char *buf; 85 86 if (buf) { 87 size_t ps1 = get_page_size() - 1; 88 buf = (void *) (((size_t) buf + ps1) & ~ps1) - len; 89 } else { 90 buf = tail_alloc(len); 91 } 92 93 const off_t offset = 0xdefaceddeadbeefLL + len; 94 long rc = pread(0, buf, len, offset); 95 if (rc != (int) len) 96 perror_msg_and_fail("pread64: expected %d, returned %ld", 97 len, rc); 98 99 tprintf("%s(%d, \"", "pread64", 0); 100 print_hex(buf, len); 101 tprintf("\", %d, %lld) = %ld\n", len, (long long) offset, rc); 102 dump_str(buf, len); 103 104 unsigned int i; 105 for (i = 0; i < len; ++i) 106 buf[i] = i; 107 108 rc = pwrite(1, buf, len, offset); 109 if (rc != (int) len) 110 perror_msg_and_fail("pwrite64: expected %d, returned %ld", 111 len, rc); 112 113 tprintf("%s(%d, \"", "pwrite64", 1); 114 print_hex(buf, len); 115 tprintf("\", %d, %lld) = %ld\n", len, (long long) offset, rc); 116 dump_str(buf, len); 117 118 if (!len) 119 buf = 0; 120 } 121 122 int 123 main(void) 124 { 125 tprintf("%s", ""); 126 127 skip_if_unavailable("/proc/self/fd/"); 128 129 static const char tmp[] = "pread64-pwrite64-tmpfile"; 130 if (open(tmp, O_CREAT|O_RDONLY|O_TRUNC, 0600) != 0) 131 perror_msg_and_fail("creat: %s", tmp); 132 if (open(tmp, O_WRONLY) != 1) 133 perror_msg_and_fail("open: %s", tmp); 134 135 char *nil = tail_alloc(1); 136 *nil = '\0'; 137 138 static const char w_c[] = "0123456789abcde"; 139 const unsigned int w_len = LENGTH_OF(w_c); 140 const char *w_d = hexdump_strdup(w_c); 141 const void *w = tail_memdup(w_c, w_len); 142 143 static const char r0_c[] = "01234567"; 144 const char *r0_d = hexdump_strdup(r0_c); 145 const unsigned int r0_len = (w_len + 1) / 2; 146 void *r0 = tail_alloc(r0_len); 147 148 static const char r1_c[] = "89abcde"; 149 const char *r1_d = hexdump_strdup(r1_c); 150 const unsigned int r1_len = w_len - r0_len; 151 void *r1 = tail_alloc(w_len); 152 153 void *efault = r1 - get_page_size(); 154 155 long rc; 156 157 rc = pwrite(1, w, 0, 0); 158 if (rc) 159 perror_msg_and_fail("pwrite64: expected 0, returned %ld", rc); 160 tprintf("pwrite64(1, \"\", 0, 0) = 0\n"); 161 162 rc = pwrite(1, efault, 1, 0); 163 if (rc != -1) 164 perror_msg_and_fail("pwrite64: expected -1 EFAULT" 165 ", returned %ld", rc); 166 tprintf("pwrite64(1, %p, 1, 0) = -1 EFAULT (%m)\n", efault); 167 168 rc = pwrite(1, nil, 1, -3); 169 if (rc != -1) 170 perror_msg_and_fail("pwrite64: expected -1, returned %ld", rc); 171 tprintf("pwrite64(1, \"\\0\", 1, -3) = -1 EINVAL (%m)\n"); 172 173 rc = pwrite(1, w, w_len, 0); 174 if (rc != (int) w_len) 175 perror_msg_and_fail("pwrite64: expected %u, returned %ld", 176 w_len, rc); 177 tprintf("pwrite64(1, \"%s\", %u, 0) = %ld\n" 178 " | 00000 %-49s %-16s |\n", 179 w_c, w_len, rc, w_d, w_c); 180 close(1); 181 182 rc = pread(0, r0, 0, 0); 183 if (rc) 184 perror_msg_and_fail("pread64: expected 0, returned %ld", rc); 185 tprintf("pread64(0, \"\", 0, 0) = 0\n"); 186 187 rc = pread(0, efault, 1, 0); 188 if (rc != -1) 189 perror_msg_and_fail("pread64: expected -1, returned %ld", rc); 190 tprintf("pread64(0, %p, 1, 0) = -1 EFAULT (%m)\n", efault); 191 192 rc = pread(0, efault, 2, -7); 193 if (rc != -1) 194 perror_msg_and_fail("pread64: expected -1, returned %ld", rc); 195 tprintf("pread64(0, %p, 2, -7) = -1 EINVAL (%m)\n", efault); 196 197 rc = pread(0, r0, r0_len, 0); 198 if (rc != (int) r0_len) 199 perror_msg_and_fail("pread64: expected %u, returned %ld", 200 r0_len, rc); 201 tprintf("pread64(0, \"%s\", %u, 0) = %ld\n" 202 " | 00000 %-49s %-16s |\n", 203 r0_c, r0_len, rc, r0_d, r0_c); 204 205 rc = pread(0, r1, w_len, r0_len); 206 if (rc != (int) r1_len) 207 perror_msg_and_fail("pread64: expected %u, returned %ld", 208 r1_len, rc); 209 tprintf("pread64(0, \"%s\", %u, %u) = %ld\n" 210 " | 00000 %-49s %-16s |\n", 211 r1_c, w_len, r0_len, rc, r1_d, r1_c); 212 close(0); 213 214 if (open("/dev/zero", O_RDONLY)) 215 perror_msg_and_fail("open"); 216 217 if (open("/dev/null", O_WRONLY) != 1) 218 perror_msg_and_fail("open"); 219 220 unsigned int i; 221 for (i = 0; i <= 32; ++i) 222 test_dump(i); 223 224 tprintf("+++ exited with 0 +++\n"); 225 return 0; 226 } 227