blob: a23390010be2d4b911d223a547e429c0498db941 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * 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.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000029 */
30
31#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000033SYS_FUNC(close)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000034{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +000035 printfd(tcp, tcp->u_arg[0]);
36
37 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000038}
39
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000040SYS_FUNC(dup)
Zubin Mithra64aa1b12014-06-04 08:30:41 +053041{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +000042 printfd(tcp, tcp->u_arg[0]);
43
44 return RVAL_DECODED | RVAL_FD;
Zubin Mithra64aa1b12014-06-04 08:30:41 +053045}
46
Dmitry V. Levin4371b102008-11-10 22:53:02 +000047static int
48do_dup2(struct tcb *tcp, int flags_arg)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049{
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +000050 printfd(tcp, tcp->u_arg[0]);
51 tprints(", ");
52 printfd(tcp, tcp->u_arg[1]);
53 if (flags_arg >= 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +020054 tprints(", ");
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +000055 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000056 }
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +000057
58 return RVAL_DECODED | RVAL_FD;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000059}
60
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000061SYS_FUNC(dup2)
Dmitry V. Levin4371b102008-11-10 22:53:02 +000062{
63 return do_dup2(tcp, -1);
64}
65
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000066SYS_FUNC(dup3)
Dmitry V. Levin4371b102008-11-10 22:53:02 +000067{
68 return do_dup2(tcp, 2);
69}
Dmitry V. Levin4371b102008-11-10 22:53:02 +000070
Denys Vlasenko84703742012-02-25 02:38:52 +010071#if defined(ALPHA)
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000072SYS_FUNC(getdtablesize)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073{
74 return 0;
75}
Denys Vlasenko84703742012-02-25 02:38:52 +010076#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077
Dmitry V. Levinc2982b52013-11-05 23:00:22 +000078static int
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +000079decode_select(struct tcb *tcp, long *args,
80 void (*print_tv_ts) (struct tcb *, const long),
81 const char * (*sprint_tv_ts) (struct tcb *, const long))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082{
Denys Vlasenkoad5155a2011-09-01 18:18:04 +020083 int i, j;
Denys Vlasenko1f65c3c2013-11-05 16:20:16 +010084 int nfds, fdsize;
Dmitry V. Levin6522f132014-09-09 22:42:12 +000085 fd_set *fds = NULL;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +000086 const char *sep;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087 long arg;
88
Dmitry V. Levinf3696b32013-11-05 22:46:43 +000089 /* Kernel truncates arg[0] to int, we do the same. */
90 nfds = (int) args[0];
91
92 /* Kernel rejects negative nfds, so we don't parse it either. */
Dmitry V. Levin6522f132014-09-09 22:42:12 +000093 if (nfds < 0)
Dmitry V. Levinf3696b32013-11-05 22:46:43 +000094 nfds = 0;
Dmitry V. Levin6522f132014-09-09 22:42:12 +000095
Denys Vlasenko79a79ea2011-09-01 16:35:44 +020096 /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
Dmitry V. Levinf3696b32013-11-05 22:46:43 +000097 if (nfds > 1024*1024)
98 nfds = 1024*1024;
99
100 /*
101 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
Dr. David Alan Gilbert025f1082013-11-05 11:54:51 +0100102 * Instead of args[0], use nfds for fd count, fdsize for array lengths.
103 */
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100104 fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
Denys Vlasenko79a79ea2011-09-01 16:35:44 +0200105
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106 if (entering(tcp)) {
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000107 tprintf("%d", (int) args[0]);
108
Dmitry V. Levin3e9d71f2015-05-25 20:41:02 +0000109 if (verbose(tcp) && fdsize > 0)
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000110 fds = malloc(fdsize);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111 for (i = 0; i < 3; i++) {
112 arg = args[i+1];
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000113 tprints(", ");
Dmitry V. Levin2fc5d802015-01-28 01:26:04 +0000114 if (!fds) {
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000115 printaddr(arg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116 continue;
117 }
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000118 if (umoven_or_printaddr(tcp, arg, fdsize, fds))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119 continue;
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000120 tprints("[");
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100121 for (j = 0, sep = "";; j++) {
122 j = next_set_bit(fds, j, nfds);
123 if (j < 0)
124 break;
125 tprints(sep);
126 printfd(tcp, j);
127 sep = " ";
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200129 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130 }
Roland McGrathe85aaa42005-02-06 01:55:12 +0000131 free(fds);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200132 tprints(", ");
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +0000133 print_tv_ts(tcp, args[4]);
Dmitry V. Levindf0c18c2015-07-20 16:59:50 +0000134 } else {
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200135 static char outstr[1024];
136 char *outptr;
137#define end_outstr (outstr + sizeof(outstr))
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000138 int ready_fds;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139
140 if (syserror(tcp))
141 return 0;
142
Dr. David Alan Gilbert025f1082013-11-05 11:54:51 +0100143 ready_fds = tcp->u_rval;
144 if (ready_fds == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145 tcp->auxstr = "Timeout";
146 return RVAL_STR;
147 }
Roland McGrathe85aaa42005-02-06 01:55:12 +0000148
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000149 fds = malloc(fdsize);
Roland McGrathe85aaa42005-02-06 01:55:12 +0000150
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200151 outptr = outstr;
152 sep = "";
Dmitry V. Levinf3696b32013-11-05 22:46:43 +0000153 for (i = 0; i < 3 && ready_fds > 0; i++) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154 int first = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156 arg = args[i+1];
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000157 if (!arg || !fds || umoven(tcp, arg, fdsize, fds) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158 continue;
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100159 for (j = 0;; j++) {
160 j = next_set_bit(fds, j, nfds);
161 if (j < 0)
162 break;
163 /* +2 chars needed at the end: ']',NUL */
164 if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
165 if (first) {
166 outptr += sprintf(outptr, "%s%s [%u",
167 sep,
168 i == 0 ? "in" : i == 1 ? "out" : "except",
169 j
170 );
171 first = 0;
172 sep = ", ";
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000173 }
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100174 else {
175 outptr += sprintf(outptr, " %u", j);
176 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000177 }
Denys Vlasenkob338f2d2013-11-09 20:40:31 +0100178 if (--ready_fds == 0)
179 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180 }
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200181 if (outptr != outstr)
182 *outptr++ = ']';
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183 }
Roland McGrathe85aaa42005-02-06 01:55:12 +0000184 free(fds);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185 /* This contains no useful information on SunOS. */
186 if (args[4]) {
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +0000187 const char *str = sprint_tv_ts(tcp, args[4]);
188 if (outptr + sizeof("left ") + strlen(sep) + strlen(str) < end_outstr) {
189 outptr += sprintf(outptr, "%sleft %s", sep, str);
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200190 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000191 }
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200192 *outptr = '\0';
Denys Vlasenko11617252011-09-01 11:27:37 +0200193 tcp->auxstr = outstr;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194 return RVAL_STR;
Denys Vlasenko2fb4db32011-08-31 12:26:03 +0200195#undef end_outstr
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000196 }
197 return 0;
198}
199
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000200SYS_FUNC(oldselect)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201{
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300202 long long_args[5];
203#undef oldselect_args
204#if SIZEOF_LONG == 4
205# define oldselect_args long_args
206#else
207 unsigned int oldselect_args[5];
208 unsigned int i;
209#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300211 if (umove(tcp, tcp->u_arg[0], &oldselect_args) < 0) {
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000212 printaddr(tcp->u_arg[0]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213 return 0;
214 }
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300215#ifndef oldselect_args
216 for (i = 0; i < 5; i++) {
217 long_args[i] = oldselect_args[i];
218 }
219#endif
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +0000220 return decode_select(tcp, long_args, print_timeval, sprint_timeval);
Elvira Khabirovac44df3e2015-07-29 21:38:54 +0300221#undef oldselect_args
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000222}
223
Wichert Akkermanf5eeabb1999-11-18 17:09:47 +0000224#ifdef ALPHA
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000225SYS_FUNC(osf_select)
Wichert Akkermanf5eeabb1999-11-18 17:09:47 +0000226{
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +0000227 return decode_select(tcp, tcp->u_arg, print_timeval32, sprint_timeval32);
Wichert Akkermanf5eeabb1999-11-18 17:09:47 +0000228}
229#endif
230
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000231SYS_FUNC(select)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232{
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +0000233 return decode_select(tcp, tcp->u_arg, print_timeval, sprint_timeval);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234}
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000235
Dmitry V. Levin4408e852015-11-27 04:37:46 +0000236#include "kernel_types.h"
237
238static int
239umove_kulong_array_or_printaddr(struct tcb *tcp, const long addr,
240 kernel_ulong_t *ptr, size_t n)
241{
242#if defined X86_64 || defined X32
243 if (current_personality == 1) {
244#else
245 if (current_wordsize < sizeof(*ptr)) {
246#endif
247 uint32_t ptr32[n];
248 int r = umove_or_printaddr(tcp, addr, &ptr32);
249 if (!r) {
250 size_t i;
251
252 for (i = 0; i < n; ++i)
253 ptr[i] = (kernel_ulong_t) ptr32[i];
254 }
255 return r;
256 }
257 return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr);
258}
259
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000260SYS_FUNC(pselect6)
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000261{
Dmitry V. Levin4cb5ccc2015-09-18 18:02:50 +0000262 int rc = decode_select(tcp, tcp->u_arg, print_timespec, sprint_timespec);
Roland McGrathfe10aa72007-11-01 21:52:20 +0000263 if (entering(tcp)) {
Dmitry V. Levin4408e852015-11-27 04:37:46 +0000264 kernel_ulong_t data[2];
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000265
266 tprints(", ");
Dmitry V. Levin4408e852015-11-27 04:37:46 +0000267 if (!umove_kulong_array_or_printaddr(tcp, tcp->u_arg[5],
268 data, ARRAY_SIZE(data))) {
Dmitry V. Levine6019fd2015-07-20 16:44:51 +0000269 tprints("{");
Dmitry V. Levinb172a942015-09-15 02:17:32 +0000270 /* NB: kernel requires data[1] == NSIG / 8 */
Dmitry V. Levin4408e852015-11-27 04:37:46 +0000271 print_sigset_addr_len(tcp, (unsigned long) data[0],
272 (unsigned long) data[1]);
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000273 tprintf(", %llu}", (unsigned long long) data[1]);
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000274 }
275 }
Dmitry V. Levin4408e852015-11-27 04:37:46 +0000276
Dmitry V. Levin95ebf5a2006-10-13 20:25:12 +0000277 return rc;
278}