1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1991, 1992 Paul Kranenburg <[email protected]>
3*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1993 Branko Lankester <[email protected]>
4*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <[email protected]>
5*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1996-1999 Wichert Akkerman <[email protected]>
6*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1999-2018 The strace developers.
7*cf84ac9aSAndroid Build Coastguard Worker * All rights reserved.
8*cf84ac9aSAndroid Build Coastguard Worker *
9*cf84ac9aSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
10*cf84ac9aSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
11*cf84ac9aSAndroid Build Coastguard Worker * are met:
12*cf84ac9aSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
13*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
14*cf84ac9aSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
15*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
16*cf84ac9aSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
17*cf84ac9aSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
18*cf84ac9aSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
19*cf84ac9aSAndroid Build Coastguard Worker *
20*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21*cf84ac9aSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22*cf84ac9aSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23*cf84ac9aSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24*cf84ac9aSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25*cf84ac9aSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*cf84ac9aSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*cf84ac9aSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*cf84ac9aSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*cf84ac9aSAndroid Build Coastguard Worker */
31*cf84ac9aSAndroid Build Coastguard Worker
32*cf84ac9aSAndroid Build Coastguard Worker #include "defs.h"
33*cf84ac9aSAndroid Build Coastguard Worker #include "xstring.h"
34*cf84ac9aSAndroid Build Coastguard Worker
SYS_FUNC(close)35*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(close)
36*cf84ac9aSAndroid Build Coastguard Worker {
37*cf84ac9aSAndroid Build Coastguard Worker printfd(tcp, tcp->u_arg[0]);
38*cf84ac9aSAndroid Build Coastguard Worker
39*cf84ac9aSAndroid Build Coastguard Worker return RVAL_DECODED;
40*cf84ac9aSAndroid Build Coastguard Worker }
41*cf84ac9aSAndroid Build Coastguard Worker
SYS_FUNC(dup)42*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(dup)
43*cf84ac9aSAndroid Build Coastguard Worker {
44*cf84ac9aSAndroid Build Coastguard Worker printfd(tcp, tcp->u_arg[0]);
45*cf84ac9aSAndroid Build Coastguard Worker
46*cf84ac9aSAndroid Build Coastguard Worker return RVAL_DECODED | RVAL_FD;
47*cf84ac9aSAndroid Build Coastguard Worker }
48*cf84ac9aSAndroid Build Coastguard Worker
49*cf84ac9aSAndroid Build Coastguard Worker static int
do_dup2(struct tcb * tcp,int flags_arg)50*cf84ac9aSAndroid Build Coastguard Worker do_dup2(struct tcb *tcp, int flags_arg)
51*cf84ac9aSAndroid Build Coastguard Worker {
52*cf84ac9aSAndroid Build Coastguard Worker printfd(tcp, tcp->u_arg[0]);
53*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
54*cf84ac9aSAndroid Build Coastguard Worker printfd(tcp, tcp->u_arg[1]);
55*cf84ac9aSAndroid Build Coastguard Worker if (flags_arg >= 0) {
56*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
57*cf84ac9aSAndroid Build Coastguard Worker printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
58*cf84ac9aSAndroid Build Coastguard Worker }
59*cf84ac9aSAndroid Build Coastguard Worker
60*cf84ac9aSAndroid Build Coastguard Worker return RVAL_DECODED | RVAL_FD;
61*cf84ac9aSAndroid Build Coastguard Worker }
62*cf84ac9aSAndroid Build Coastguard Worker
SYS_FUNC(dup2)63*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(dup2)
64*cf84ac9aSAndroid Build Coastguard Worker {
65*cf84ac9aSAndroid Build Coastguard Worker return do_dup2(tcp, -1);
66*cf84ac9aSAndroid Build Coastguard Worker }
67*cf84ac9aSAndroid Build Coastguard Worker
SYS_FUNC(dup3)68*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(dup3)
69*cf84ac9aSAndroid Build Coastguard Worker {
70*cf84ac9aSAndroid Build Coastguard Worker return do_dup2(tcp, 2);
71*cf84ac9aSAndroid Build Coastguard Worker }
72*cf84ac9aSAndroid Build Coastguard Worker
73*cf84ac9aSAndroid Build Coastguard Worker static int
decode_select(struct tcb * const tcp,const kernel_ulong_t * const args,void (* const print_tv_ts)(struct tcb *,kernel_ulong_t),const char * (* const sprint_tv_ts)(struct tcb *,kernel_ulong_t))74*cf84ac9aSAndroid Build Coastguard Worker decode_select(struct tcb *const tcp, const kernel_ulong_t *const args,
75*cf84ac9aSAndroid Build Coastguard Worker void (*const print_tv_ts) (struct tcb *, kernel_ulong_t),
76*cf84ac9aSAndroid Build Coastguard Worker const char * (*const sprint_tv_ts) (struct tcb *, kernel_ulong_t))
77*cf84ac9aSAndroid Build Coastguard Worker {
78*cf84ac9aSAndroid Build Coastguard Worker int i, j;
79*cf84ac9aSAndroid Build Coastguard Worker int nfds, fdsize;
80*cf84ac9aSAndroid Build Coastguard Worker fd_set *fds = NULL;
81*cf84ac9aSAndroid Build Coastguard Worker const char *sep;
82*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t addr;
83*cf84ac9aSAndroid Build Coastguard Worker
84*cf84ac9aSAndroid Build Coastguard Worker /* Kernel truncates args[0] to int, we do the same. */
85*cf84ac9aSAndroid Build Coastguard Worker nfds = (int) args[0];
86*cf84ac9aSAndroid Build Coastguard Worker
87*cf84ac9aSAndroid Build Coastguard Worker /* Kernel rejects negative nfds, so we don't parse it either. */
88*cf84ac9aSAndroid Build Coastguard Worker if (nfds < 0)
89*cf84ac9aSAndroid Build Coastguard Worker nfds = 0;
90*cf84ac9aSAndroid Build Coastguard Worker
91*cf84ac9aSAndroid Build Coastguard Worker /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
92*cf84ac9aSAndroid Build Coastguard Worker if (nfds > 1024*1024)
93*cf84ac9aSAndroid Build Coastguard Worker nfds = 1024*1024;
94*cf84ac9aSAndroid Build Coastguard Worker
95*cf84ac9aSAndroid Build Coastguard Worker /*
96*cf84ac9aSAndroid Build Coastguard Worker * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
97*cf84ac9aSAndroid Build Coastguard Worker * Instead of args[0], use nfds for fd count, fdsize for array lengths.
98*cf84ac9aSAndroid Build Coastguard Worker */
99*cf84ac9aSAndroid Build Coastguard Worker fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
100*cf84ac9aSAndroid Build Coastguard Worker
101*cf84ac9aSAndroid Build Coastguard Worker if (entering(tcp)) {
102*cf84ac9aSAndroid Build Coastguard Worker tprintf("%d", (int) args[0]);
103*cf84ac9aSAndroid Build Coastguard Worker
104*cf84ac9aSAndroid Build Coastguard Worker if (verbose(tcp) && fdsize > 0)
105*cf84ac9aSAndroid Build Coastguard Worker fds = malloc(fdsize);
106*cf84ac9aSAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
107*cf84ac9aSAndroid Build Coastguard Worker addr = args[i+1];
108*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
109*cf84ac9aSAndroid Build Coastguard Worker if (!fds) {
110*cf84ac9aSAndroid Build Coastguard Worker printaddr(addr);
111*cf84ac9aSAndroid Build Coastguard Worker continue;
112*cf84ac9aSAndroid Build Coastguard Worker }
113*cf84ac9aSAndroid Build Coastguard Worker if (umoven_or_printaddr(tcp, addr, fdsize, fds))
114*cf84ac9aSAndroid Build Coastguard Worker continue;
115*cf84ac9aSAndroid Build Coastguard Worker tprints("[");
116*cf84ac9aSAndroid Build Coastguard Worker for (j = 0, sep = "";; j++) {
117*cf84ac9aSAndroid Build Coastguard Worker j = next_set_bit(fds, j, nfds);
118*cf84ac9aSAndroid Build Coastguard Worker if (j < 0)
119*cf84ac9aSAndroid Build Coastguard Worker break;
120*cf84ac9aSAndroid Build Coastguard Worker tprints(sep);
121*cf84ac9aSAndroid Build Coastguard Worker printfd(tcp, j);
122*cf84ac9aSAndroid Build Coastguard Worker sep = " ";
123*cf84ac9aSAndroid Build Coastguard Worker }
124*cf84ac9aSAndroid Build Coastguard Worker tprints("]");
125*cf84ac9aSAndroid Build Coastguard Worker }
126*cf84ac9aSAndroid Build Coastguard Worker free(fds);
127*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
128*cf84ac9aSAndroid Build Coastguard Worker print_tv_ts(tcp, args[4]);
129*cf84ac9aSAndroid Build Coastguard Worker } else {
130*cf84ac9aSAndroid Build Coastguard Worker static char outstr[1024];
131*cf84ac9aSAndroid Build Coastguard Worker char *outptr;
132*cf84ac9aSAndroid Build Coastguard Worker #define end_outstr (outstr + sizeof(outstr))
133*cf84ac9aSAndroid Build Coastguard Worker int ready_fds;
134*cf84ac9aSAndroid Build Coastguard Worker
135*cf84ac9aSAndroid Build Coastguard Worker if (syserror(tcp))
136*cf84ac9aSAndroid Build Coastguard Worker return 0;
137*cf84ac9aSAndroid Build Coastguard Worker
138*cf84ac9aSAndroid Build Coastguard Worker ready_fds = tcp->u_rval;
139*cf84ac9aSAndroid Build Coastguard Worker if (ready_fds == 0) {
140*cf84ac9aSAndroid Build Coastguard Worker tcp->auxstr = "Timeout";
141*cf84ac9aSAndroid Build Coastguard Worker return RVAL_STR;
142*cf84ac9aSAndroid Build Coastguard Worker }
143*cf84ac9aSAndroid Build Coastguard Worker
144*cf84ac9aSAndroid Build Coastguard Worker fds = malloc(fdsize);
145*cf84ac9aSAndroid Build Coastguard Worker
146*cf84ac9aSAndroid Build Coastguard Worker outptr = outstr;
147*cf84ac9aSAndroid Build Coastguard Worker sep = "";
148*cf84ac9aSAndroid Build Coastguard Worker for (i = 0; i < 3 && ready_fds > 0; i++) {
149*cf84ac9aSAndroid Build Coastguard Worker int first = 1;
150*cf84ac9aSAndroid Build Coastguard Worker
151*cf84ac9aSAndroid Build Coastguard Worker addr = args[i+1];
152*cf84ac9aSAndroid Build Coastguard Worker if (!addr || !fds || umoven(tcp, addr, fdsize, fds) < 0)
153*cf84ac9aSAndroid Build Coastguard Worker continue;
154*cf84ac9aSAndroid Build Coastguard Worker for (j = 0;; j++) {
155*cf84ac9aSAndroid Build Coastguard Worker j = next_set_bit(fds, j, nfds);
156*cf84ac9aSAndroid Build Coastguard Worker if (j < 0)
157*cf84ac9aSAndroid Build Coastguard Worker break;
158*cf84ac9aSAndroid Build Coastguard Worker /* +2 chars needed at the end: ']',NUL */
159*cf84ac9aSAndroid Build Coastguard Worker if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
160*cf84ac9aSAndroid Build Coastguard Worker if (first) {
161*cf84ac9aSAndroid Build Coastguard Worker outptr = xappendstr(outstr,
162*cf84ac9aSAndroid Build Coastguard Worker outptr,
163*cf84ac9aSAndroid Build Coastguard Worker "%s%s [%u",
164*cf84ac9aSAndroid Build Coastguard Worker sep,
165*cf84ac9aSAndroid Build Coastguard Worker i == 0 ? "in" : i == 1 ? "out" : "except",
166*cf84ac9aSAndroid Build Coastguard Worker j
167*cf84ac9aSAndroid Build Coastguard Worker );
168*cf84ac9aSAndroid Build Coastguard Worker first = 0;
169*cf84ac9aSAndroid Build Coastguard Worker sep = ", ";
170*cf84ac9aSAndroid Build Coastguard Worker } else {
171*cf84ac9aSAndroid Build Coastguard Worker outptr = xappendstr(outstr,
172*cf84ac9aSAndroid Build Coastguard Worker outptr,
173*cf84ac9aSAndroid Build Coastguard Worker " %u", j);
174*cf84ac9aSAndroid Build Coastguard Worker }
175*cf84ac9aSAndroid Build Coastguard Worker }
176*cf84ac9aSAndroid Build Coastguard Worker if (--ready_fds == 0)
177*cf84ac9aSAndroid Build Coastguard Worker break;
178*cf84ac9aSAndroid Build Coastguard Worker }
179*cf84ac9aSAndroid Build Coastguard Worker if (outptr != outstr)
180*cf84ac9aSAndroid Build Coastguard Worker *outptr++ = ']';
181*cf84ac9aSAndroid Build Coastguard Worker }
182*cf84ac9aSAndroid Build Coastguard Worker free(fds);
183*cf84ac9aSAndroid Build Coastguard Worker /* This contains no useful information on SunOS. */
184*cf84ac9aSAndroid Build Coastguard Worker if (args[4]) {
185*cf84ac9aSAndroid Build Coastguard Worker const char *str = sprint_tv_ts(tcp, args[4]);
186*cf84ac9aSAndroid Build Coastguard Worker if (outptr + sizeof("left ") + strlen(sep) + strlen(str) < end_outstr) {
187*cf84ac9aSAndroid Build Coastguard Worker outptr = xappendstr(outstr, outptr,
188*cf84ac9aSAndroid Build Coastguard Worker "%sleft %s", sep, str);
189*cf84ac9aSAndroid Build Coastguard Worker }
190*cf84ac9aSAndroid Build Coastguard Worker }
191*cf84ac9aSAndroid Build Coastguard Worker *outptr = '\0';
192*cf84ac9aSAndroid Build Coastguard Worker tcp->auxstr = outstr;
193*cf84ac9aSAndroid Build Coastguard Worker return RVAL_STR;
194*cf84ac9aSAndroid Build Coastguard Worker #undef end_outstr
195*cf84ac9aSAndroid Build Coastguard Worker }
196*cf84ac9aSAndroid Build Coastguard Worker return 0;
197*cf84ac9aSAndroid Build Coastguard Worker }
198*cf84ac9aSAndroid Build Coastguard Worker
199*cf84ac9aSAndroid Build Coastguard Worker #if HAVE_ARCH_OLD_SELECT
SYS_FUNC(oldselect)200*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(oldselect)
201*cf84ac9aSAndroid Build Coastguard Worker {
202*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t *args =
203*cf84ac9aSAndroid Build Coastguard Worker fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 5);
204*cf84ac9aSAndroid Build Coastguard Worker
205*cf84ac9aSAndroid Build Coastguard Worker if (args) {
206*cf84ac9aSAndroid Build Coastguard Worker return decode_select(tcp, args, print_timeval, sprint_timeval);
207*cf84ac9aSAndroid Build Coastguard Worker } else {
208*cf84ac9aSAndroid Build Coastguard Worker if (entering(tcp))
209*cf84ac9aSAndroid Build Coastguard Worker printaddr(tcp->u_arg[0]);
210*cf84ac9aSAndroid Build Coastguard Worker return RVAL_DECODED;
211*cf84ac9aSAndroid Build Coastguard Worker }
212*cf84ac9aSAndroid Build Coastguard Worker }
213*cf84ac9aSAndroid Build Coastguard Worker #endif /* HAVE_ARCH_OLD_SELECT */
214*cf84ac9aSAndroid Build Coastguard Worker
215*cf84ac9aSAndroid Build Coastguard Worker #ifdef ALPHA
SYS_FUNC(osf_select)216*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(osf_select)
217*cf84ac9aSAndroid Build Coastguard Worker {
218*cf84ac9aSAndroid Build Coastguard Worker return decode_select(tcp, tcp->u_arg, print_timeval32, sprint_timeval32);
219*cf84ac9aSAndroid Build Coastguard Worker }
220*cf84ac9aSAndroid Build Coastguard Worker #endif
221*cf84ac9aSAndroid Build Coastguard Worker
SYS_FUNC(select)222*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(select)
223*cf84ac9aSAndroid Build Coastguard Worker {
224*cf84ac9aSAndroid Build Coastguard Worker return decode_select(tcp, tcp->u_arg, print_timeval, sprint_timeval);
225*cf84ac9aSAndroid Build Coastguard Worker }
226*cf84ac9aSAndroid Build Coastguard Worker
227*cf84ac9aSAndroid Build Coastguard Worker static int
umove_kulong_array_or_printaddr(struct tcb * const tcp,const kernel_ulong_t addr,kernel_ulong_t * const ptr,const size_t n)228*cf84ac9aSAndroid Build Coastguard Worker umove_kulong_array_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr,
229*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t *const ptr, const size_t n)
230*cf84ac9aSAndroid Build Coastguard Worker {
231*cf84ac9aSAndroid Build Coastguard Worker #ifndef current_klongsize
232*cf84ac9aSAndroid Build Coastguard Worker if (current_klongsize < sizeof(*ptr)) {
233*cf84ac9aSAndroid Build Coastguard Worker uint32_t ptr32[n];
234*cf84ac9aSAndroid Build Coastguard Worker int r = umove_or_printaddr(tcp, addr, &ptr32);
235*cf84ac9aSAndroid Build Coastguard Worker if (!r) {
236*cf84ac9aSAndroid Build Coastguard Worker size_t i;
237*cf84ac9aSAndroid Build Coastguard Worker
238*cf84ac9aSAndroid Build Coastguard Worker for (i = 0; i < n; ++i)
239*cf84ac9aSAndroid Build Coastguard Worker ptr[i] = ptr32[i];
240*cf84ac9aSAndroid Build Coastguard Worker }
241*cf84ac9aSAndroid Build Coastguard Worker return r;
242*cf84ac9aSAndroid Build Coastguard Worker }
243*cf84ac9aSAndroid Build Coastguard Worker #endif /* !current_klongsize */
244*cf84ac9aSAndroid Build Coastguard Worker return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr);
245*cf84ac9aSAndroid Build Coastguard Worker }
246*cf84ac9aSAndroid Build Coastguard Worker
SYS_FUNC(pselect6)247*cf84ac9aSAndroid Build Coastguard Worker SYS_FUNC(pselect6)
248*cf84ac9aSAndroid Build Coastguard Worker {
249*cf84ac9aSAndroid Build Coastguard Worker int rc = decode_select(tcp, tcp->u_arg, print_timespec, sprint_timespec);
250*cf84ac9aSAndroid Build Coastguard Worker if (entering(tcp)) {
251*cf84ac9aSAndroid Build Coastguard Worker kernel_ulong_t data[2];
252*cf84ac9aSAndroid Build Coastguard Worker
253*cf84ac9aSAndroid Build Coastguard Worker tprints(", ");
254*cf84ac9aSAndroid Build Coastguard Worker if (!umove_kulong_array_or_printaddr(tcp, tcp->u_arg[5],
255*cf84ac9aSAndroid Build Coastguard Worker data, ARRAY_SIZE(data))) {
256*cf84ac9aSAndroid Build Coastguard Worker tprints("{");
257*cf84ac9aSAndroid Build Coastguard Worker /* NB: kernel requires data[1] == NSIG_BYTES */
258*cf84ac9aSAndroid Build Coastguard Worker print_sigset_addr_len(tcp, data[0], data[1]);
259*cf84ac9aSAndroid Build Coastguard Worker tprintf(", %" PRI_klu "}", data[1]);
260*cf84ac9aSAndroid Build Coastguard Worker }
261*cf84ac9aSAndroid Build Coastguard Worker }
262*cf84ac9aSAndroid Build Coastguard Worker
263*cf84ac9aSAndroid Build Coastguard Worker return rc;
264*cf84ac9aSAndroid Build Coastguard Worker }
265