1d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/*
2d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Check decoding of process_vm_readv/process_vm_writev syscall.
3d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *
4d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * All rights reserved.
6d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *
7d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Redistribution and use in source and binary forms, with or without
8d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * modification, are permitted provided that the following conditions
9d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * are met:
10d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 1. Redistributions of source code must retain the above copyright
11d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    notice, this list of conditions and the following disclaimer.
12d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright
13d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    notice, this list of conditions and the following disclaimer in the
14d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    documentation and/or other materials provided with the distribution.
15d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 3. The name of the author may not be used to endorse or promote products
16d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *    derived from this software without specific prior written permission.
17d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *
18d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */
29d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
30d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include <inttypes.h>
31d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include <stdio.h>
32d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include <unistd.h>
33d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include <sys/uio.h>
34d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
35d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#if OP_WR
36d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define in_iovec  rmt_iovec
37d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define out_iovec lcl_iovec
38d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define in_iov    rmt_iov
39d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define out_iov   lcl_iov
40d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#else
41d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define in_iovec  lcl_iovec
42d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define out_iovec rmt_iovec
43d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define in_iov    lcl_iov
44d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes# define out_iov   rmt_iov
45d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#endif
46d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
47d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughestypedef void (*iov_print_fn)(const struct iovec *, const void *, long);
48d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
49d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesenum { MAX_SEGM_COUNT = 2, MAX_STR_LEN = 5 };
50d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
51d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct print_iov_arg {
52d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint32_t count;
53d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint32_t valid    :1,
54dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes		 string   :1,
55d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 addr_term:1,
56d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		 check_rc :1;
57d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint32_t str_segms;
58d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint8_t  str_base[MAX_SEGM_COUNT];
59d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint8_t  str_size[MAX_SEGM_COUNT];
60d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes};
61d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
62d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
63d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesprint_iov(const struct iovec *iov, const void *arg_ptr, long rc)
64d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
65d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const struct print_iov_arg *arg = arg_ptr;
66d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint32_t i;
67d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint32_t num_segm = 0;
68d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	uint64_t segm_offs = 0;
69d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
70d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (!arg || !arg->valid) {
71d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (iov)
72d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			printf("%p", iov);
73d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		else
74d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			printf("NULL");
75d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
76d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		return;
77d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
78d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
79d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	printf("[");
80d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
81d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	for (i = 0; i < arg->count; i++) {
82d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (i)
83d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			printf(", ");
84d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
85d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (i >= MAX_STR_LEN) {
86d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			printf("...");
87d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			break;
88d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
89d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
90d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		printf("{iov_base=");
91d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		if (arg->string && (!arg->check_rc || (rc != -1))) {
92d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			uint64_t str_left = iov[i].iov_len;
93d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			uint64_t pr_count = 0;
94d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
95d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			printf("\"");
96d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
97d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			while (str_left--) {
98d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				static const char oct_str[] = "01234567";
99d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				uint8_t c = arg->str_base[num_segm] + segm_offs;
100d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
101d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				if ((num_segm >= arg->str_segms) ||
102d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				    (num_segm >= MAX_SEGM_COUNT))
103d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					error_msg_and_fail("print_iov: segment "
104d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes							   "count overrun");
105d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
106d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				if (pr_count++ < MAX_STR_LEN)
107d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					printf("\\%.1s%.1s%d",
108d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					       (c >> 6) ?
109d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					       oct_str + (c >> 6) : "",
110d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					       (c >> 3) ?
111d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					       oct_str + ((c >> 3) & 7) : "",
112d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					       c & 7);
113d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
114d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				segm_offs++;
115d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
116d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				if (segm_offs >= arg->str_size[num_segm]) {
117d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					num_segm++;
118d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes					segm_offs = 0;
119d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				}
120d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			}
121d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
122d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			printf("\"");
123d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
124d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			if (pr_count > MAX_STR_LEN)
125d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				printf("...");
126d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		} else {
127d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			if (iov[i].iov_base)
128d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				printf("%p", iov[i].iov_base);
129d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			else
130d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes				printf("NULL");
131d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		}
132d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
133d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		printf(", iov_len=%zu}", iov[i].iov_len);
134d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	}
135d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
136d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (arg->addr_term)
137d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		printf(", %p", iov + arg->count);
138d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
139d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	printf("]");
140d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
141d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
142d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void
143d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesdo_call(kernel_ulong_t pid,
144d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	kernel_ulong_t local_iov, const char *local_arg,
145d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	kernel_ulong_t liovcnt,
146d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	kernel_ulong_t remote_iov, const char *remote_arg,
147d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	kernel_ulong_t riovcnt,
148d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	kernel_ulong_t flags, iov_print_fn pr_iov)
149d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
150d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	long rc;
151d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	const char *errstr;
152d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
153d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	rc = syscall(OP_NR, pid, local_iov, liovcnt, remote_iov, riovcnt,
154d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		flags);
155d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	errstr = sprintrc(rc);
156d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
157d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	printf("%s(%d, ", OP_STR, (int) pid);
158d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
159d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (pr_iov)
160d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		pr_iov((const struct iovec *) (uintptr_t) local_iov, local_arg,
161d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes			rc);
162d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	else
163d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		printf("%s", local_arg);
164d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
165d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	printf(", %lu, ", (unsigned long) liovcnt);
166d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
167d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	if (pr_iov)
168d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		pr_iov((const struct iovec *) (uintptr_t) remote_iov,
169d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		       remote_arg, rc);
170d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	else
171d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		printf("%s", remote_arg);
172d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
173d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	printf(", %lu, %lu) = %s\n", (unsigned long) riovcnt,
174d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(unsigned long) flags, errstr);
175d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
176d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
177d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheskernel_ulong_t
178d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesptr_cast(void *ptr)
179d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
180d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return (kernel_ulong_t) (uintptr_t) ptr;
181d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
182d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
183d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesint
184d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesmain(void)
185d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{
186d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	enum {
187d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_11 = 2,
188d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_12 = 3,
189d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_13 = 4,
190d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_1 = SIZE_11 + SIZE_12 + SIZE_13,
191d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_21 = 5,
192d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_22 = 6,
193d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_23 = 7,
194d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SIZE_2 = SIZE_21 + SIZE_22 + SIZE_23,
195d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
196d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
197d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	enum {
198d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SEGM1_BASE = 0x80,
199d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		SEGM2_BASE = 0xA0,
200d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
201d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
202d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	static const kernel_ulong_t bogus_pid =
203d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(kernel_ulong_t) 0xbadfaceddeadca57ULL;
204d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	static const kernel_ulong_t bogus_iovcnt1 =
205d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(kernel_ulong_t) 0xdec0ded1defaced2ULL;
206d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	static const kernel_ulong_t bogus_iovcnt2 =
207d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(kernel_ulong_t) 0xdec0ded3defaced4ULL;
208d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	static const kernel_ulong_t bogus_flags =
209d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(kernel_ulong_t) 0xdeadc0deda7adeadULL;
210d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
211d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	pid_t my_pid = getpid();
212d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *data1_out = tail_alloc(SIZE_1);
213d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *data2_out = tail_alloc(SIZE_2);
214d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *data1_in  = tail_alloc(SIZE_2);
215d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	char *data2_in  = tail_alloc(SIZE_1);
216d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
217d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct iovec bogus_iovec[] = {
218d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_out + SIZE_1, (size_t) 0xdeadfaceca57beefULL },
219d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_in  + SIZE_2, (size_t) 0xbadc0dedda7adeadULL },
220d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_out + SIZE_2, (size_t) 0xf157facedec0ded1ULL },
221d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_in  + SIZE_1, (size_t) 0xdefaced2bea7be57ULL },
222d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
223d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
224d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct iovec out_iovec[] = {
225d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_out,  SIZE_11 },
226d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_out + SIZE_11,  SIZE_12 },
227d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_out + SIZE_11 + SIZE_12,  SIZE_13 },
228d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_out,  SIZE_21 },
229d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_out + SIZE_21,  SIZE_22 },
230d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_out + SIZE_21 + SIZE_22,  SIZE_23 },
231d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
232d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct iovec in_iovec[] = {
233d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_in,  SIZE_23 },
234d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_in + SIZE_23,  SIZE_22 },
235d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data1_in + SIZE_23 + SIZE_22,  SIZE_21 },
236d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_in,  SIZE_13 },
237d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_in + SIZE_13,  SIZE_12 },
238d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		{ data2_in + SIZE_13 + SIZE_12,  SIZE_11 },
239d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	};
240d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
241d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct iovec *bogus_iov = tail_memdup(bogus_iovec, sizeof(bogus_iovec));
242d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct iovec *lcl_iov   = tail_memdup(lcl_iovec,   sizeof(lcl_iovec));
243d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct iovec *rmt_iov   = tail_memdup(rmt_iovec,   sizeof(rmt_iovec));
244d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
245d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct print_iov_arg bogus_arg   = { ARRAY_SIZE(bogus_iovec), 1 };
246d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct print_iov_arg lcl_arg     = { ARRAY_SIZE(lcl_iovec), 1, 1, 0, 0,
247d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		2, {SEGM1_BASE, SEGM2_BASE}, {SIZE_1, SIZE_2} };
248d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	struct print_iov_arg rmt_arg     = { ARRAY_SIZE(rmt_iovec), 1 };
249d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
250dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes	struct print_iov_arg bogus_arg_cut = {
251dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes		ARRAY_SIZE(bogus_iovec) - 2, 1, 0, 1
252dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes	};
253dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes	struct print_iov_arg lcl_arg_cut = {
254dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes		ARRAY_SIZE(lcl_iovec) - 2, 1, 1, 1, 0, 2,
255dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes		{ SEGM1_BASE + SIZE_11 + SIZE_12, SEGM2_BASE },
256dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes		{SIZE_13, SIZE_2}
257dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes	};
258dc75b01004a0588c1eb3bc26d7248a6e473b2cddElliott Hughes	struct print_iov_arg rmt_arg_cut = { ARRAY_SIZE(rmt_iovec) - 2, 1 };
259d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
260d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
261d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	fill_memory_ex(data1_out, SIZE_1, SEGM1_BASE, SIZE_1);
262d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	fill_memory_ex(data2_out, SIZE_2, SEGM2_BASE, SIZE_2);
263d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
264d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
265d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(bogus_pid, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL),
266d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		bogus_iovcnt1, (kernel_ulong_t) (uintptr_t) ARG_STR(NULL),
267d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		bogus_iovcnt2, bogus_flags, NULL);
268d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
269d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)),
270d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		"[]", 0, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), "[]",
271d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		0, 0, NULL);
272d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(my_pid, ptr_cast(bogus_iov + ARRAY_SIZE(bogus_iovec)), NULL,
273d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		bogus_iovcnt1, ptr_cast(in_iov + ARRAY_SIZE(in_iovec)), NULL,
274d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		bogus_iovcnt2, 0, print_iov);
275d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
276d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(my_pid, ptr_cast(bogus_iov), (char *) &bogus_arg,
277d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		ARRAY_SIZE(bogus_iovec), ptr_cast(rmt_iov + 2),
278d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec) - 2, 0, print_iov);
279d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
280d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#if !OP_WR
281d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	lcl_arg.check_rc = 1;
282d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	lcl_arg_cut.check_rc = 1;
283d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#endif
284d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
285d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut,
286d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		ARRAY_SIZE(lcl_iovec) - 1, ptr_cast(bogus_iov + 2),
287d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(char *) &bogus_arg_cut, ARRAY_SIZE(bogus_iovec) - 1, 0,
288d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		print_iov);
289d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
290d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	lcl_arg_cut.addr_term = 0;
291d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
292d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	rmt_arg_cut.addr_term = 1;
293d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	rmt_arg_cut.count = 5;
294d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
295d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(my_pid, ptr_cast(lcl_iov + 2), (char *) &lcl_arg_cut,
296d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		ARRAY_SIZE(lcl_iovec) - 2, ptr_cast(rmt_iov + 1),
297d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		(char *) &rmt_arg_cut, ARRAY_SIZE(rmt_iovec), 0, print_iov);
298d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
299d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	/* Correct call */
300d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	do_call(my_pid, ptr_cast(lcl_iov), (char *) &lcl_arg,
301d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		ARRAY_SIZE(lcl_iovec), ptr_cast(rmt_iov), (char *) &rmt_arg,
302d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes		ARRAY_SIZE(rmt_iovec), 0, print_iov);
303d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
304d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	puts("+++ exited with 0 +++");
305d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes
306d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes	return 0;
307d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}
308