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