1 /*
2 * Check decoding and dumping of read and write syscalls.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@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
dump_str(const char * str,const unsigned int len)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
print_hex(const char * str,const unsigned int len)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
k_read(unsigned int fd,void * buf,size_t count)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
k_write(unsigned int fd,const void * buf,size_t count)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
test_dump(const unsigned int len)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
main(void)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