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