blob: 6e91d33278da32ba215e64efea757a524fe375c2 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Update the byte permission maps following a system call. ---*/
4/*--- vg_syscall_mem.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_include.h"
33
34/* vg_unsafe.h should NOT be included into any file except this
35 one. */
36#include "vg_unsafe.h"
37
38
39/* All system calls are channelled through vg_wrap_syscall. It does
40 three things:
41
42 * optionally, checks the permissions for the args to the call
43
44 * perform the syscall, usually by passing it along to the kernel
45 unmodified. However, because we simulate signals ourselves,
46 signal-related syscalls are routed to vg_signal.c, and are not
47 delivered to the kernel.
48
49 * Update the permission maps following the syscall.
50
51 A magical piece of assembly code, vg_do_syscall(), in vg_syscall.S
52 does the tricky bit of passing a syscall to the kernel, whilst
53 having the simulator retain control.
54*/
55
56static void make_noaccess ( Addr a, UInt len )
57{
58 if (VG_(clo_instrument))
59 VGM_(make_noaccess) ( a, len );
60}
61
62static void make_writable ( Addr a, UInt len )
63{
64 if (VG_(clo_instrument))
65 VGM_(make_writable) ( a, len );
66}
67
68static void make_readable ( Addr a, UInt len )
69{
70 if (VG_(clo_instrument))
71 VGM_(make_readable) ( a, len );
72}
73
74static void make_readwritable ( Addr a, UInt len )
75{
76 if (VG_(clo_instrument))
77 VGM_(make_readwritable) ( a, len );
78}
79
80static
sewardj8c824512002-04-14 04:16:48 +000081void must_be_writable ( ThreadState* tst,
82 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000083{
84 Bool ok;
85 Addr bad_addr;
86 /* VG_(message)(Vg_DebugMsg,"must be writable: %x .. %x",
87 base,base+size-1); */
88 if (!VG_(clo_instrument))
89 return;
90 ok = VGM_(check_writable) ( base, size, &bad_addr );
91 if (!ok)
sewardj8c824512002-04-14 04:16:48 +000092 VG_(record_param_err) ( tst, bad_addr, True, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +000093}
94
95static
sewardj8c824512002-04-14 04:16:48 +000096void must_be_readable ( ThreadState* tst,
97 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000098{
99 Bool ok;
100 Addr bad_addr;
101 /* VG_(message)(Vg_DebugMsg,"must be readable: %x .. %x",
102 base,base+size-1); */
103 if (!VG_(clo_instrument))
104 return;
105 ok = VGM_(check_readable) ( base, size, &bad_addr );
106 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000107 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000108}
109
110static
sewardj8c824512002-04-14 04:16:48 +0000111void must_be_readable_asciiz ( ThreadState* tst,
112 Char* syscall_name, UInt str )
sewardjde4a1d02002-03-22 01:27:54 +0000113{
114 Bool ok = True;
115 Addr bad_addr;
116 /* VG_(message)(Vg_DebugMsg,"must be readable asciiz: 0x%x",str); */
117 if (!VG_(clo_instrument))
118 return;
119 ok = VGM_(check_readable_asciiz) ( (Addr)str, &bad_addr );
120 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000121 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000122}
123
124
125/* Set memory permissions, based on PROT_* values for mmap/mprotect,
126 into the permissions our scheme understands. Dunno if this is
127 really correct. */
128
129static void approximate_mmap_permissions ( Addr a, UInt len, UInt prot )
130{
131 /* PROT_READ and PROT_WRITE --> readable
132 PROT_READ only --> readable
133 PROT_WRITE only --> writable
134 NEITHER --> noaccess
135 */
136 if (prot & PROT_READ)
137 make_readable(a,len);
138 else
139 if (prot & PROT_WRITE)
140 make_writable(a,len);
141 else
142 make_noaccess(a,len);
143}
144
145
146/* Dereference a pointer, but only after checking that it's
147 safe to do so. If not, return the default.
148*/
149static
150UInt safe_dereference ( Addr aa, UInt defawlt )
151{
152 if (!VG_(clo_instrument))
153 return * (UInt*)aa;
154 if (VGM_(check_readable)(aa,4,NULL))
155 return * (UInt*)aa;
156 else
157 return defawlt;
158}
159
160
161/* Is this a Linux kernel error return value? */
162/* From:
163 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
164 linux/i386/sysdep.h?
165 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
166
167 QUOTE:
168
169 Linux uses a negative return value to indicate syscall errors,
170 unlike most Unices, which use the condition codes' carry flag.
171
172 Since version 2.1 the return value of a system call might be
173 negative even if the call succeeded. E.g., the `lseek' system call
174 might return a large offset. Therefore we must not anymore test
175 for < 0, but test for a real error by making sure the value in %eax
176 is a real error number. Linus said he will make sure the no syscall
177 returns a value in -1 .. -4095 as a valid result so we can savely
178 test with -4095.
179
180 END QUOTE
181*/
182Bool VG_(is_kerror) ( Int res )
183{
184 if (res >= -4095 && res <= -1)
185 return True;
186 else
187 return False;
188}
189
190static
191UInt get_shm_size ( Int shmid )
192{
193 struct shmid_ds buf;
194 long __res;
195 __asm__ volatile ( "int $0x80"
196 : "=a" (__res)
197 : "0" (__NR_ipc),
198 "b" ((long)(24) /*IPCOP_shmctl*/),
199 "c" ((long)(shmid)),
200 "d" ((long)(IPC_STAT)),
201 "S" ((long)(0)),
202 "D" ((long)(&buf)) );
203 if ( VG_(is_kerror) ( __res ) )
204 return 0;
205
206 return buf.shm_segsz;
207}
208
209static
sewardj8c824512002-04-14 04:16:48 +0000210Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000211{
212 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
213 Char *result = VG_(malloc) ( aid, len );
214 VG_(strcpy) ( result, s1 );
215 VG_(strcat) ( result, s2 );
216 return result;
217}
218
219static
sewardj8c824512002-04-14 04:16:48 +0000220void must_be_readable_sendmsg ( ThreadState* tst,
221 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000222{
223 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000224 must_be_readable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000225 VG_(free) ( VG_AR_TRANSIENT, outmsg );
226}
227
228static
sewardj8c824512002-04-14 04:16:48 +0000229void must_be_writable_recvmsg ( ThreadState* tst,
230 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000231{
232 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000233 must_be_writable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000234 VG_(free) ( VG_AR_TRANSIENT, outmsg );
235}
236
237static
sewardj8c824512002-04-14 04:16:48 +0000238void make_readable_recvmsg ( ThreadState* tst,
239 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000240{
241 make_readable( base, size );
242}
243
244static
sewardj8c824512002-04-14 04:16:48 +0000245void msghdr_foreachfield (
246 ThreadState* tst,
247 struct msghdr *msg,
248 void (*foreach_func)( ThreadState*, Char *, UInt, UInt )
249 )
sewardjde4a1d02002-03-22 01:27:54 +0000250{
251 if ( !msg )
252 return;
253
sewardj8c824512002-04-14 04:16:48 +0000254 foreach_func ( tst, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000255
256 if ( msg->msg_name )
sewardj8c824512002-04-14 04:16:48 +0000257 foreach_func ( tst,
258 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000259 (Addr)msg->msg_name, msg->msg_namelen );
260
261 if ( msg->msg_iov ) {
262 struct iovec *iov = msg->msg_iov;
263 UInt i;
264
sewardj8c824512002-04-14 04:16:48 +0000265 foreach_func ( tst,
266 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000267 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
268
269 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
sewardj8c824512002-04-14 04:16:48 +0000270 foreach_func ( tst,
271 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000272 (Addr)iov->iov_base, iov->iov_len );
273 }
274
275 if ( msg->msg_control )
sewardj8c824512002-04-14 04:16:48 +0000276 foreach_func ( tst,
277 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000278 (Addr)msg->msg_control, msg->msg_controllen );
279}
280
sewardjc483e8f2002-05-03 21:01:35 +0000281static
282void must_be_readable_sockaddr ( ThreadState* tst,
283 Char *description,
284 struct sockaddr *sa, UInt salen )
285{
286 Char *outmsg = VG_(malloc) ( VG_AR_TRANSIENT, strlen( description ) + 30 );
287
288 VG_(sprintf) ( outmsg, description, ".sa_family" );
289 must_be_readable( tst, outmsg, (UInt) &sa->sa_family, sizeof (sa_family_t));
290
291 switch (sa->sa_family) {
292
293 case AF_UNIX:
294 VG_(sprintf) ( outmsg, description, ".sun_path" );
295 must_be_readable_asciiz( tst, outmsg,
296 (UInt) ((struct sockaddr_un *) sa)->sun_path);
297 break;
298
299 case AF_INET:
300 VG_(sprintf) ( outmsg, description, ".sin_port" );
301 must_be_readable( tst, outmsg,
302 (UInt) &((struct sockaddr_in *) sa)->sin_port,
sewardj32102152002-05-04 10:28:17 +0000303 sizeof (((struct sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000304 VG_(sprintf) ( outmsg, description, ".sin_addr" );
305 must_be_readable( tst, outmsg,
306 (UInt) &((struct sockaddr_in *) sa)->sin_addr,
307 sizeof (struct in_addr));
308 break;
309
310 case AF_INET6:
311 VG_(sprintf) ( outmsg, description, ".sin6_port" );
312 must_be_readable( tst, outmsg,
313 (UInt) &((struct sockaddr_in6 *) sa)->sin6_port,
sewardj32102152002-05-04 10:28:17 +0000314 sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000315 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
316 must_be_readable( tst, outmsg,
317 (UInt) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
318 sizeof (uint32_t));
319 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
320 must_be_readable( tst, outmsg,
321 (UInt) &((struct sockaddr_in6 *) sa)->sin6_addr,
322 sizeof (struct in6_addr));
sewardj32102152002-05-04 10:28:17 +0000323# ifndef GLIBC_2_1
sewardjc483e8f2002-05-03 21:01:35 +0000324 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
325 must_be_readable( tst, outmsg,
326 (UInt) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
327 sizeof (uint32_t));
sewardj32102152002-05-04 10:28:17 +0000328# endif
sewardjc483e8f2002-05-03 21:01:35 +0000329 break;
330
331 default:
332 VG_(sprintf) ( outmsg, description, "" );
333 must_be_readable( tst, outmsg, (UInt) sa, salen );
334 break;
335 }
336
337 VG_(free) ( VG_AR_TRANSIENT, outmsg );
338}
339
sewardjde4a1d02002-03-22 01:27:54 +0000340
341/* Records the current end of the data segment so we can make sense of
342 calls to brk(). Initial value set by hdm_init_memory_audit(). */
343Addr VGM_(curr_dataseg_end);
344
345
sewardj2e93c502002-04-12 11:12:52 +0000346
sewardjde4a1d02002-03-22 01:27:54 +0000347/* The Main Entertainment ... */
348
sewardj2e93c502002-04-12 11:12:52 +0000349void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +0000350{
sewardj018f7622002-05-15 21:13:39 +0000351 ThreadState* tst;
352 Bool sane_before_call, sane_after_call;
353 UInt syscallno, arg1, arg2, arg3, arg4, arg5;
sewardjde4a1d02002-03-22 01:27:54 +0000354 /* Do not make this unsigned! */
355 Int res;
356
sewardjde4a1d02002-03-22 01:27:54 +0000357 VGP_PUSHCC(VgpSyscall);
358
sewardj018f7622002-05-15 21:13:39 +0000359 vg_assert(VG_(is_valid_tid)(tid));
360 sane_before_call = True;
361 sane_after_call = True;
362 tst = & VG_(threads)[tid];
363 syscallno = tst->m_eax;
364 arg1 = tst->m_ebx;
365 arg2 = tst->m_ecx;
366 arg3 = tst->m_edx;
367 arg4 = tst->m_esi;
368 arg5 = tst->m_edi;
369
sewardjde4a1d02002-03-22 01:27:54 +0000370 /* Since buggy syscall wrappers sometimes break this, we may as well
371 check ourselves. */
sewardj126a41f2002-05-07 23:45:03 +0000372 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardjde4a1d02002-03-22 01:27:54 +0000373 sane_before_call = False;
374
375 /* the syscall no is in %eax. For syscalls with <= 5 args,
376 args 1 .. 5 to the syscall are in %ebx %ecx %edx %esi %edi.
377 For calls with > 5 args, %ebx points to a lump of memory
378 containing the args.
379
380 The result is returned in %eax. If this value >= 0, the call
381 succeeded, and this is the return value. If < 0, it failed, and
382 the negation of this value is errno. To be more specific,
383 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
384 (kernel 2.4.9 sources, include/asm-i386/errno.h)
385 then it indicates an error. Otherwise it doesn't.
386
387 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
388 (inclusive?) indicate error returns. Not sure where the -4095
389 comes from.
390 */
391
392 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000393 VG_(printf)("SYSCALL[%d,%d](%3d): ",
394 VG_(getpid)(), tid, syscallno);
sewardjde4a1d02002-03-22 01:27:54 +0000395
396 switch (syscallno) {
397
sewardj7e87e382002-05-03 19:09:05 +0000398 case __NR_exit:
399 VG_(panic)("syscall exit() not caught by the scheduler?!");
400 break;
401
sewardjde4a1d02002-03-22 01:27:54 +0000402 case __NR_clone:
403 VG_(unimplemented)
sewardj827d95b2002-04-16 02:09:31 +0000404 ("clone(): not supported by Valgrind.\n "
405 "We do now support programs linked against\n "
406 "libpthread.so, though. Re-run with -v and ensure that\n "
407 "you are picking up Valgrind's implementation of libpthread.so.");
sewardjde4a1d02002-03-22 01:27:54 +0000408 break;
409
410# if defined(__NR_modify_ldt)
411 case __NR_modify_ldt:
sewardjcfc39b22002-05-08 01:58:18 +0000412 VG_(nvidia_moan)();
sewardjde4a1d02002-03-22 01:27:54 +0000413 VG_(unimplemented)
sewardjcfc39b22002-05-08 01:58:18 +0000414 ("modify_ldt(): I (JRS) haven't investigated this yet; sorry.");
sewardjde4a1d02002-03-22 01:27:54 +0000415 break;
416# endif
417
sewardj73f1f072002-03-29 14:22:46 +0000418 /* !!!!!!!!!! New, untested syscalls !!!!!!!!!!!!!!!!!!!!! */
sewardje5328262002-07-13 12:58:08 +0000419
420# if defined(__NR_quotactl)
421 case __NR_quotactl: /* syscall 131 */
422 /* int quotactl(int cmd, char *special, int uid, caddr_t addr); */
423 if (VG_(clo_trace_syscalls))
424 VG_(printf)("quotactl (0x%x, %p, 0x%x, 0x%x )\n",
425 arg1,arg2,arg3, arg4);
426 must_be_readable_asciiz( tst, "quotactl(special)", arg2 );
427 KERNEL_DO_SYSCALL(tid,res);
428 break;
429# endif
sewardj73f1f072002-03-29 14:22:46 +0000430
sewardjbe23ae72002-06-20 07:21:48 +0000431# if defined(__NR_truncate64)
432 case __NR_truncate64: /* syscall 193 */
433 /* int truncate64(const char *path, off64_t length); */
434 if (VG_(clo_trace_syscalls))
435 VG_(printf)("truncate64 ( %p, %lld )\n",
436 arg1, ((ULong)arg2) | (((ULong) arg3) << 32));
437 must_be_readable_asciiz( tst, "truncate64(path)", arg1 );
438 KERNEL_DO_SYSCALL(tid,res);
439 break;
440# endif
441
sewardj6ea29382002-06-18 09:11:33 +0000442# if defined(__NR_fdatasync)
443 case __NR_fdatasync: /* syscall 148 */
444 /* int fdatasync(int fd); */
445 if (VG_(clo_trace_syscalls))
446 VG_(printf)("fdatasync ( %d )\n", arg1);
447 KERNEL_DO_SYSCALL(tid,res);
448 break;
449# endif
450
sewardj67f1d582002-05-24 02:11:32 +0000451# if defined(__NR_msync) /* syscall 144 */
452 case __NR_msync:
453 /* int msync(const void *start, size_t length, int flags); */
sewardj6ea29382002-06-18 09:11:33 +0000454 if (VG_(clo_trace_syscalls))
455 VG_(printf)("msync ( %p, %d, %d )\n", arg1,arg2,arg3);
456 must_be_readable( tst, "msync(start)", arg1, arg2 );
457 KERNEL_DO_SYSCALL(tid,res);
458 break;
sewardj67f1d582002-05-24 02:11:32 +0000459# endif
460
sewardj0ff15782002-05-18 13:24:24 +0000461# if defined(__NR_getpmsg) /* syscall 188 */
462 case __NR_getpmsg:
463 {
464 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
465 /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
466 int *bandp, int *flagsp); */
467 struct strbuf {
468 int maxlen; /* no. of bytes in buffer */
469 int len; /* no. of bytes returned */
470 caddr_t buf; /* pointer to data */
471 };
472 struct strbuf *ctrl;
473 struct strbuf *data;
474 if (VG_(clo_trace_syscalls))
475 VG_(printf)("getpmsg ( %d, %p, %p, %p, %p )\n",
476 arg1,arg2,arg3,arg4,arg5);
477 ctrl = (struct strbuf *)arg2;
478 data = (struct strbuf *)arg3;
479 if (ctrl && ctrl->maxlen > 0)
480 must_be_writable(tst, "getpmsg(ctrl)",
481 (UInt)ctrl->buf, ctrl->maxlen);
482 if (data && data->maxlen > 0)
483 must_be_writable(tst, "getpmsg(data)",
484 (UInt)data->buf, data->maxlen);
485 if (arg4)
486 must_be_writable(tst, "getpmsg(bandp)",
487 (UInt)arg4, sizeof(int));
488 if (arg5)
489 must_be_writable(tst, "getpmsg(flagsp)",
490 (UInt)arg5, sizeof(int));
491 KERNEL_DO_SYSCALL(tid,res);
492 if (!VG_(is_kerror)(res) && res == 0 && ctrl && ctrl->len > 0) {
493 make_readable( (UInt)ctrl->buf, ctrl->len);
494 }
495 if (!VG_(is_kerror)(res) && res == 0 && data && data->len > 0) {
496 make_readable( (UInt)data->buf, data->len);
497 }
498 }
499 break;
500# endif
501
502
503# if defined(__NR_putpmsg) /* syscall 189 */
504 case __NR_putpmsg:
505 {
506 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
507 /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
508 int band, int flags); */
509 struct strbuf {
510 int maxlen; /* no. of bytes in buffer */
511 int len; /* no. of bytes returned */
512 caddr_t buf; /* pointer to data */
513 };
514 struct strbuf *ctrl;
515 struct strbuf *data;
516 if (VG_(clo_trace_syscalls))
517 VG_(printf)("putpmsg ( %d, %p, %p, %d, %d )\n",
518 arg1,arg2,arg3,arg4,arg5);
519 ctrl = (struct strbuf *)arg2;
520 data = (struct strbuf *)arg3;
521 if (ctrl && ctrl->len > 0)
522 must_be_readable(tst, "putpmsg(ctrl)",
523 (UInt)ctrl->buf, ctrl->len);
524 if (data && data->len > 0)
525 must_be_readable(tst, "putpmsg(data)",
526 (UInt)data->buf, data->len);
527 KERNEL_DO_SYSCALL(tid,res);
528 }
529 break;
530# endif
531
sewardj9e631f72002-05-18 11:01:06 +0000532 case __NR_getitimer: /* syscall 105 */
533 /* int getitimer(int which, struct itimerval *value); */
534 if (VG_(clo_trace_syscalls))
535 VG_(printf)("getitimer ( %d, %p )\n", arg1, arg2);
536 must_be_writable( tst, "getitimer(timer)", arg2,
537 sizeof(struct itimerval) );
538 KERNEL_DO_SYSCALL(tid,res);
539 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL) {
540 make_readable(arg2, sizeof(struct itimerval));
541 }
542 break;
543
sewardjd354bb32002-05-10 22:58:14 +0000544# if defined(__NR_syslog)
545 case __NR_syslog: /* syscall 103 */
546 /* int syslog(int type, char *bufp, int len); */
547 if (VG_(clo_trace_syscalls))
548 VG_(printf)("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
549 switch(arg1) {
550 case 2: case 3: case 4:
551 must_be_writable( tst, "syslog(buf)", arg2, arg3);
552 break;
553 default:
554 break;
555 }
556 KERNEL_DO_SYSCALL(tid, res);
557 if (!VG_(is_kerror)(res)) {
558 switch (arg1) {
559 case 2: case 3: case 4:
560 make_readable( arg2, arg3 );
561 break;
562 default:
563 break;
564 }
565 }
566 break;
567# endif
568
sewardjf4afb002002-05-10 21:01:34 +0000569 case __NR_personality: /* syscall 136 */
sewardjd354bb32002-05-10 22:58:14 +0000570 /* int personality(unsigned long persona); */
sewardjf4afb002002-05-10 21:01:34 +0000571 if (VG_(clo_trace_syscalls))
572 VG_(printf)("personality ( %d )\n", arg1);
573 KERNEL_DO_SYSCALL(tid,res);
574 break;
575
sewardjfb617112002-05-03 21:07:55 +0000576 case __NR_chroot: /* syscall 61 */
577 /* int chroot(const char *path); */
578 if (VG_(clo_trace_syscalls))
579 VG_(printf)("chroot ( %p )\n", arg1);
580 must_be_readable_asciiz( tst, "chroot(path)", arg1 );
581 KERNEL_DO_SYSCALL(tid,res);
582 break;
583
sewardj6e435c02002-04-24 02:24:44 +0000584# if defined(__NR_madvise)
585 case __NR_madvise: /* syscall 219 */
586 /* int madvise(void *start, size_t length, int advice ); */
587 if (VG_(clo_trace_syscalls))
588 VG_(printf)("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
589 KERNEL_DO_SYSCALL(tid,res);
590 break;
591# endif
592
sewardj6af4b5d2002-04-16 04:40:49 +0000593# if defined(__NR_mremap)
594 /* Is this really right? Perhaps it should copy the permissions
595 from the old area into the new. Unclear from the Linux man
596 pages what this really does. Also, the flags don't look like
597 they mean the same as the standard mmap flags, so that's
598 probably wrong too. */
599 case __NR_mremap: /* syscall 163 */
600 /* void* mremap(void * old_address, size_t old_size,
601 size_t new_size, unsigned long flags); */
602 if (VG_(clo_trace_syscalls))
603 VG_(printf)("mremap ( %p, %d, %d, 0x%x )\n",
604 arg1, arg2, arg3, arg4);
605 must_be_writable ( tst, "mremap(old_address)", arg1, arg2 );
606 KERNEL_DO_SYSCALL(tid,res);
607 if (!VG_(is_kerror)(res)) {
608 /* Copied from munmap() wrapper. */
sewardj18d75132002-05-16 11:06:21 +0000609 Bool munmap_exe;
sewardj6af4b5d2002-04-16 04:40:49 +0000610 Addr start = arg1;
611 Addr length = arg2;
612 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
613 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
614 make_noaccess( start, length );
sewardj18d75132002-05-16 11:06:21 +0000615 munmap_exe = VG_(symtab_notify_munmap) ( start, length );
616 if (munmap_exe)
617 VG_(invalidate_translations) ( start, length );
sewardj6af4b5d2002-04-16 04:40:49 +0000618 approximate_mmap_permissions( (Addr)res, arg3, arg4 );
619 }
620 break;
621# endif
622
sewardj73f1f072002-03-29 14:22:46 +0000623 case __NR_nice: /* syscall 34 */
624 /* int nice(int inc); */
625 if (VG_(clo_trace_syscalls))
626 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000627 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000628 break;
629
sewardjde4a1d02002-03-22 01:27:54 +0000630 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
631
sewardjd7f07662002-03-24 10:49:46 +0000632# if defined(__NR_setresgid32)
633 case __NR_setresgid32: /* syscall 210 */
634 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
635 if (VG_(clo_trace_syscalls))
636 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000637 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000638 break;
639# endif
640
sewardjde4a1d02002-03-22 01:27:54 +0000641# if defined(__NR_setfsuid32)
642 case __NR_setfsuid32: /* syscall 215 */
643 /* int setfsuid(uid_t fsuid); */
644 if (VG_(clo_trace_syscalls))
645 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000646 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000647 break;
648# endif
649
650# if defined(__NR__sysctl)
651 case __NR__sysctl:
652 /* int _sysctl(struct __sysctl_args *args); */
653 if (VG_(clo_trace_syscalls))
654 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000655 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000656 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000657 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000658 if (!VG_(is_kerror)(res))
659 make_readable ( arg1, sizeof(struct __sysctl_args) );
660 break;
661# endif
662
663# if defined(__NR_sched_getscheduler)
664 case __NR_sched_getscheduler:
665 /* int sched_getscheduler(pid_t pid); */
666 if (VG_(clo_trace_syscalls))
667 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000668 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000669 break;
670# endif
671
672# if defined(__NR_sched_setscheduler)
673 case __NR_sched_setscheduler:
674 /* int sched_setscheduler(pid_t pid, int policy,
675 const struct sched_param *p); */
676 if (VG_(clo_trace_syscalls))
677 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
678 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000679 must_be_readable( tst,
680 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000681 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000682 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000683 break;
684# endif
685
sewardj9d8bcc52002-06-02 00:10:41 +0000686# if defined(__NR_mlock)
687 case __NR_mlock:
688 /* int mlock(const void * addr, size_t len) */
689 if (VG_(clo_trace_syscalls))
690 VG_(printf)("mlock ( %p, %d )\n", arg1, arg2);
691 KERNEL_DO_SYSCALL(tid,res);
692 break;
693# endif
694
sewardjde4a1d02002-03-22 01:27:54 +0000695# if defined(__NR_mlockall)
696 case __NR_mlockall:
697 /* int mlockall(int flags); */
698 if (VG_(clo_trace_syscalls))
699 VG_(printf)("mlockall ( %x )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000700 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000701 break;
702# endif
703
704# if defined(__NR_munlockall)
705 case __NR_munlockall:
706 /* int munlockall(void); */
707 if (VG_(clo_trace_syscalls))
708 VG_(printf)("munlockall ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000709 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000710 break;
711# endif
712
713#if defined(__NR_sched_get_priority_max)
714 case __NR_sched_get_priority_max:
715 /* int sched_get_priority_max(int policy); */
716 if (VG_(clo_trace_syscalls))
717 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000718 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000719 break;
720# endif
721
sewardj9dfb4a72002-04-27 01:56:30 +0000722#if defined(__NR_sched_get_priority_min)
723 case __NR_sched_get_priority_min: /* syscall 160 */
724 /* int sched_get_priority_min(int policy); */
725 if (VG_(clo_trace_syscalls))
726 VG_(printf)("sched_get_priority_min ( %d )\n", arg1);
727 KERNEL_DO_SYSCALL(tid,res);
728 break;
729# endif
730
731#if defined(__NR_setpriority)
732 case __NR_setpriority: /* syscall 97 */
733 /* int setpriority(int which, int who, int prio); */
734 if (VG_(clo_trace_syscalls))
735 VG_(printf)("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
736 KERNEL_DO_SYSCALL(tid,res);
737 break;
738# endif
739
sewardjde5ac182002-04-27 02:13:24 +0000740#if defined(__NR_getpriority)
741 case __NR_getpriority: /* syscall 96 */
742 /* int getpriority(int which, int who); */
743 if (VG_(clo_trace_syscalls))
744 VG_(printf)("getpriority ( %d, %d )\n", arg1, arg2);
745 KERNEL_DO_SYSCALL(tid,res);
746 break;
747# endif
748
sewardjde4a1d02002-03-22 01:27:54 +0000749# if defined(__NR_setfsgid)
750 case __NR_setfsgid: /* syscall 139 */
751 /* int setfsgid(gid_t gid); */
752 if (VG_(clo_trace_syscalls))
753 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000754 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000755 break;
756# endif
757
758# if defined(__NR_setregid)
759 case __NR_setregid: /* syscall 71 */
760 /* int setregid(gid_t rgid, gid_t egid); */
761 if (VG_(clo_trace_syscalls))
762 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +0000763 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000764 break;
765# endif
766
767# if defined(__NR_setresuid)
768 case __NR_setresuid: /* syscall 164 */
769 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
770 if (VG_(clo_trace_syscalls))
771 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000772 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000773 break;
774# endif
775
776# if defined(__NR_setfsuid)
777 case __NR_setfsuid: /* syscall 138 */
778 /* int setfsuid(uid_t uid); */
779 if (VG_(clo_trace_syscalls))
780 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000781 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000782 break;
783# endif
784
785 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
786
787# if defined(__NR_sendfile)
788 case __NR_sendfile: /* syscall 187 */
789 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
790 size_t count) */
791 if (VG_(clo_trace_syscalls))
792 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardje5328262002-07-13 12:58:08 +0000793 if (arg3 != (UInt)NULL)
794 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000795 KERNEL_DO_SYSCALL(tid,res);
sewardje5328262002-07-13 12:58:08 +0000796 if (!VG_(is_kerror)(res) && arg3 != (UInt)NULL) {
sewardjde4a1d02002-03-22 01:27:54 +0000797 make_readable( arg3, sizeof( off_t ) );
798 }
799 break;
800# endif
801
802 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
803
804# if defined(__NR_pwrite)
805 case __NR_pwrite: /* syscall 181 */
806 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
807 off_t offset); */
808 if (VG_(clo_trace_syscalls))
809 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000810 must_be_readable( tst, "pwrite(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000811 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000812 break;
813# endif
814
815 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
816
817 case __NR_sync: /* syscall 36 */
818 /* int sync(); */
819 if (VG_(clo_trace_syscalls))
820 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000821 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000822 break;
823
824 case __NR_fstatfs: /* syscall 100 */
825 /* int fstatfs(int fd, struct statfs *buf); */
826 if (VG_(clo_trace_syscalls))
827 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000828 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000829 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000830 if (!VG_(is_kerror)(res))
831 make_readable( arg2, sizeof(struct statfs) );
832 break;
833
834 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
835
836 case __NR_pause: /* syscall 29 */
837 /* int pause(void); */
838 if (VG_(clo_trace_syscalls))
839 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000840 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000841 break;
842
843 case __NR_getsid: /* syscall 147 */
844 /* pid_t getsid(pid_t pid); */
845 if (VG_(clo_trace_syscalls))
846 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000847 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000848 break;
849
850# if defined(__NR_pread)
851 case __NR_pread: /* syscall 180 */
852 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
853 if (VG_(clo_trace_syscalls))
854 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000855 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000856 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000857 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000858 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
859 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000860 arg1, arg2, arg3, arg4, res);
861 if (!VG_(is_kerror)(res) && res > 0) {
862 make_readable( arg2, res );
863 }
864 break;
865# endif
866
867 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
868
869 case __NR_mknod: /* syscall 14 */
870 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
871 if (VG_(clo_trace_syscalls))
872 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000873 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000874 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000875 break;
876
877 case __NR_flock: /* syscall 143 */
878 /* int flock(int fd, int operation); */
879 if (VG_(clo_trace_syscalls))
880 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000881 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000882 break;
883
884# if defined(__NR_rt_sigsuspend)
885 /* Viewed with great suspicion by me, but, hey, let's do it
886 anyway ... */
887 case __NR_rt_sigsuspend: /* syscall 179 */
888 /* int sigsuspend(const sigset_t *mask); */
889 if (VG_(clo_trace_syscalls))
890 VG_(printf)("sigsuspend ( %p )\n", arg1 );
891 if (arg1 != (Addr)NULL) {
892 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000893 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000894 sizeof(vki_ksigset_t) );
895 }
sewardj2e93c502002-04-12 11:12:52 +0000896 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000897 break;
898# endif
899
900 case __NR_init_module: /* syscall 128 */
901 /* int init_module(const char *name, struct module *image); */
902 if (VG_(clo_trace_syscalls))
903 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000904 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
905 must_be_readable( tst, "init_module(image)", arg2,
sewardja83005f2002-06-13 16:07:51 +0000906 VKI_SIZEOF_STRUCT_MODULE );
sewardj2e93c502002-04-12 11:12:52 +0000907 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000908 break;
909
910 case __NR_ioperm: /* syscall 101 */
911 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
912 if (VG_(clo_trace_syscalls))
913 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000914 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000915 break;
916
917 case __NR_capget: /* syscall 184 */
918 /* int capget(cap_user_header_t header, cap_user_data_t data); */
919 if (VG_(clo_trace_syscalls))
920 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000921 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000922 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000923 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000924 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000925 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000926 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
927 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
928 break;
929
930 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
931
932 case __NR_execve:
933 /* int execve (const char *filename,
934 char *const argv [],
935 char *const envp[]); */
936 if (VG_(clo_trace_syscalls))
937 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
938 arg1, arg1, arg2, arg3);
sewardjccef2e62002-05-29 19:26:32 +0000939 /* Resistance is futile. Nuke all other threads. POSIX
940 mandates this. */
941 VG_(nuke_all_threads_except)( tid );
sewardjde4a1d02002-03-22 01:27:54 +0000942 /* Make any binding for LD_PRELOAD disappear, so that child
943 processes don't get traced into. */
944 if (!VG_(clo_trace_children)) {
945 Int i;
946 Char** envp = (Char**)arg3;
sewardj3e1eb1f2002-05-18 13:14:17 +0000947 Char* ld_preload_str = NULL;
948 Char* ld_library_path_str = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000949 for (i = 0; envp[i] != NULL; i++) {
sewardj3e1eb1f2002-05-18 13:14:17 +0000950 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
951 ld_preload_str = &envp[i][11];
952 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
953 ld_library_path_str = &envp[i][16];
sewardjde4a1d02002-03-22 01:27:54 +0000954 }
sewardj3e1eb1f2002-05-18 13:14:17 +0000955 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
956 ld_preload_str, ld_library_path_str );
sewardjde4a1d02002-03-22 01:27:54 +0000957 }
sewardj2e93c502002-04-12 11:12:52 +0000958 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000959 /* Should we still be alive here? Don't think so. */
960 /* Actually, above comment is wrong. execve can fail, just
961 like any other syscall -- typically the file to exec does
962 not exist. Hence: */
963 vg_assert(VG_(is_kerror)(res));
964 break;
965
sewardjde4a1d02002-03-22 01:27:54 +0000966 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
967
968 case __NR_access: /* syscall 33 */
969 /* int access(const char *pathname, int mode); */
970 if (VG_(clo_trace_syscalls))
971 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000972 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000973 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000974 break;
975
976 case __NR_alarm: /* syscall 27 */
977 /* unsigned int alarm(unsigned int seconds); */
978 if (VG_(clo_trace_syscalls))
979 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000980 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000981 break;
982
983 case __NR_brk: /* syscall 45 */
984 /* Haven't a clue if this is really right. */
985 /* int brk(void *end_data_segment); */
986 if (VG_(clo_trace_syscalls))
987 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000988 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000989 if (VG_(clo_trace_syscalls))
990 VG_(printf)("0x%x\n", res);
991
992 if (!VG_(is_kerror)(res)) {
993 if (arg1 == 0) {
994 /* Just asking where the current end is. (???) */
995 VGM_(curr_dataseg_end) = res;
996 } else
997 if (arg1 < VGM_(curr_dataseg_end)) {
998 /* shrinking the data segment. */
999 make_noaccess( (Addr)arg1,
1000 VGM_(curr_dataseg_end)-arg1 );
1001 VGM_(curr_dataseg_end) = arg1;
1002 } else
1003 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
1004 /* asked for more memory, and got it */
1005 /*
1006 VG_(printf)("BRK: new area %x .. %x\n",
1007 VGM_(curr_dataseg_end, arg1-1 );
1008 */
1009 make_writable ( (Addr)VGM_(curr_dataseg_end),
1010 arg1-VGM_(curr_dataseg_end) );
1011 VGM_(curr_dataseg_end) = arg1;
1012 }
1013 }
1014 break;
1015
1016 case __NR_chdir: /* syscall 12 */
1017 /* int chdir(const char *path); */
1018 if (VG_(clo_trace_syscalls))
1019 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001020 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001021 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001022 break;
1023
1024 case __NR_chmod: /* syscall 15 */
1025 /* int chmod(const char *path, mode_t mode); */
1026 if (VG_(clo_trace_syscalls))
1027 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001028 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001029 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001030 break;
1031
1032# if defined(__NR_chown32)
1033 case __NR_chown32: /* syscall 212 */
1034# endif
1035# if defined(__NR_lchown32)
1036 case __NR_lchown32: /* syscall 198 */
1037# endif
1038 case __NR_chown: /* syscall 16 */
1039 /* int chown(const char *path, uid_t owner, gid_t group); */
1040 if (VG_(clo_trace_syscalls))
1041 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001042 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001043 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001044 break;
1045
1046 case __NR_close: /* syscall 6 */
1047 /* int close(int fd); */
1048 if (VG_(clo_trace_syscalls))
1049 VG_(printf)("close ( %d )\n",arg1);
1050 /* Detect and negate attempts by the client to close Valgrind's
1051 logfile fd ... */
1052 if (arg1 == VG_(clo_logfile_fd)) {
1053 VG_(message)(Vg_UserMsg,
1054 "Warning: client attempted to close "
1055 "Valgrind's logfile fd (%d).",
1056 VG_(clo_logfile_fd));
1057 VG_(message)(Vg_UserMsg,
1058 " Use --logfile-fd=<number> to select an "
1059 "alternative logfile fd." );
1060 } else {
sewardj2e93c502002-04-12 11:12:52 +00001061 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001062 }
1063 break;
1064
1065 case __NR_dup: /* syscall 41 */
1066 /* int dup(int oldfd); */
1067 if (VG_(clo_trace_syscalls))
1068 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001069 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001070 if (VG_(clo_trace_syscalls))
1071 VG_(printf)("%d\n", res);
1072 break;
1073
1074 case __NR_dup2: /* syscall 63 */
1075 /* int dup2(int oldfd, int newfd); */
1076 if (VG_(clo_trace_syscalls))
1077 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001078 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001079 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +00001080 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
1081 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001082 arg1, arg2, res);
1083 break;
1084
1085 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +00001086 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +00001087 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +00001088 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
1089 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001090 break;
1091
1092 case __NR_fchdir: /* syscall 133 */
1093 /* int fchdir(int fd); */
1094 if (VG_(clo_trace_syscalls))
1095 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001096 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001097 break;
1098
sewardj2f0de322002-03-24 10:17:25 +00001099# if defined(__NR_fchown32)
1100 case __NR_fchown32: /* syscall 207 */
1101# endif
1102 case __NR_fchown: /* syscall 95 */
1103 /* int fchown(int filedes, uid_t owner, gid_t group); */
1104 if (VG_(clo_trace_syscalls))
1105 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001106 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001107 break;
1108
sewardjde4a1d02002-03-22 01:27:54 +00001109 case __NR_fchmod: /* syscall 94 */
1110 /* int fchmod(int fildes, mode_t mode); */
1111 if (VG_(clo_trace_syscalls))
1112 VG_(printf)("fchmod ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001113 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001114 break;
sewardj2f0de322002-03-24 10:17:25 +00001115
sewardjde4a1d02002-03-22 01:27:54 +00001116# if defined(__NR_fcntl64)
1117 case __NR_fcntl64: /* syscall 221 */
1118 /* I don't know what the prototype for this is supposed to be. */
1119 /* ??? int fcntl(int fd, int cmd); */
1120 if (VG_(clo_trace_syscalls))
1121 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001122 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001123 break;
1124# endif
1125
1126 case __NR_fstat: /* syscall 108 */
1127 /* int fstat(int filedes, struct stat *buf); */
1128 if (VG_(clo_trace_syscalls))
1129 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001130 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001131 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001132 if (!VG_(is_kerror)(res))
1133 make_readable( arg2, sizeof(struct stat) );
1134 break;
1135
1136 case __NR_vfork: /* syscall 190 */
1137 /* pid_t vfork(void); */
1138 if (VG_(clo_trace_syscalls))
1139 VG_(printf)("vfork ( ) ... becomes ... ");
1140 /* KLUDGE: we prefer to do a fork rather than vfork.
1141 vfork gives a SIGSEGV, and the stated semantics looks
1142 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +00001143 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +00001144 /* fall through ... */
1145 case __NR_fork: /* syscall 2 */
1146 /* pid_t fork(void); */
1147 if (VG_(clo_trace_syscalls))
1148 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001149 KERNEL_DO_SYSCALL(tid,res);
sewardjccef2e62002-05-29 19:26:32 +00001150 if (res == 0) {
1151 /* I am the child. Nuke all other threads which I might
1152 have inherited from my parent. POSIX mandates this. */
1153 VG_(nuke_all_threads_except)( tid );
1154 }
sewardjde4a1d02002-03-22 01:27:54 +00001155 break;
1156
1157 case __NR_fsync: /* syscall 118 */
1158 /* int fsync(int fd); */
1159 if (VG_(clo_trace_syscalls))
1160 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001161 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001162 break;
1163
1164 case __NR_ftruncate: /* syscall 93 */
1165 /* int ftruncate(int fd, size_t length); */
1166 if (VG_(clo_trace_syscalls))
1167 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001168 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001169 break;
1170
sewardj2f0de322002-03-24 10:17:25 +00001171# if defined(__NR_ftruncate64)
1172 case __NR_ftruncate64: /* syscall 194 */
1173 /* int ftruncate64(int fd, off64_t length); */
1174 if (VG_(clo_trace_syscalls))
1175 VG_(printf)("ftruncate64 ( %d, %lld )\n",
1176 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +00001177 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001178 break;
1179# endif
1180
1181 case __NR_getdents: /* syscall 141 */
1182 /* int getdents(unsigned int fd, struct dirent *dirp,
1183 unsigned int count); */
1184 if (VG_(clo_trace_syscalls))
1185 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001186 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001187 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001188 if (!VG_(is_kerror)(res) && res > 0)
1189 make_readable( arg2, res );
1190 break;
1191
1192# if defined(__NR_getdents64)
1193 case __NR_getdents64: /* syscall 220 */
1194 /* int getdents(unsigned int fd, struct dirent64 *dirp,
1195 unsigned int count); */
1196 if (VG_(clo_trace_syscalls))
1197 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001198 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001199 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001200 if (!VG_(is_kerror)(res) && res > 0)
1201 make_readable( arg2, res );
1202 break;
1203# endif
1204
1205# if defined(__NR_getgroups32)
1206 case __NR_getgroups32: /* syscall 205 */
1207# endif
1208 case __NR_getgroups: /* syscall 80 */
1209 /* int getgroups(int size, gid_t list[]); */
1210 if (VG_(clo_trace_syscalls))
1211 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
1212 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00001213 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001214 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001215 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001216 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
1217 make_readable ( arg2, res * sizeof(gid_t) );
1218 break;
1219
1220 case __NR_getcwd: /* syscall 183 */
1221 /* char *getcwd(char *buf, size_t size); */
1222 if (VG_(clo_trace_syscalls))
1223 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001224 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +00001225 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001226 if (!VG_(is_kerror)(res) && res != (Addr)NULL)
1227 make_readable ( arg1, arg2 );
1228 /* Not really right -- really we should have the asciiz
1229 string starting at arg1 readable, or up to arg2 bytes,
1230 whichever finishes first. */
1231 break;
1232
1233 case __NR_geteuid: /* syscall 49 */
1234 /* uid_t geteuid(void); */
1235 if (VG_(clo_trace_syscalls))
1236 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001237 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001238 break;
1239
1240# if defined(__NR_geteuid32)
1241 case __NR_geteuid32: /* syscall 201 */
1242 /* ?? uid_t geteuid32(void); */
1243 if (VG_(clo_trace_syscalls))
1244 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001245 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001246 break;
1247# endif
1248
1249 case __NR_getegid: /* syscall 50 */
1250 /* gid_t getegid(void); */
1251 if (VG_(clo_trace_syscalls))
1252 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001253 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001254 break;
1255
1256# if defined(__NR_getegid32)
1257 case __NR_getegid32: /* syscall 202 */
1258 /* gid_t getegid32(void); */
1259 if (VG_(clo_trace_syscalls))
1260 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001261 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001262 break;
1263# endif
1264
1265 case __NR_getgid: /* syscall 47 */
1266 /* gid_t getgid(void); */
1267 if (VG_(clo_trace_syscalls))
1268 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001269 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001270 break;
1271
1272# if defined(__NR_getgid32)
1273 case __NR_getgid32: /* syscall 200 */
1274 /* gid_t getgid32(void); */
1275 if (VG_(clo_trace_syscalls))
1276 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001277 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001278 break;
1279# endif
1280
1281 case __NR_getpid: /* syscall 20 */
1282 /* pid_t getpid(void); */
1283 if (VG_(clo_trace_syscalls))
1284 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001285 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001286 break;
1287
1288 case __NR_getpgid: /* syscall 132 */
1289 /* pid_t getpgid(pid_t pid); */
1290 if (VG_(clo_trace_syscalls))
1291 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001292 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001293 break;
1294
1295 case __NR_getpgrp: /* syscall 65 */
1296 /* pid_t getpprp(void); */
1297 if (VG_(clo_trace_syscalls))
1298 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001299 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001300 break;
1301
1302 case __NR_getppid: /* syscall 64 */
1303 /* pid_t getppid(void); */
1304 if (VG_(clo_trace_syscalls))
1305 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001306 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001307 break;
1308
1309 case __NR_getresgid: /* syscall 171 */
1310 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1311 if (VG_(clo_trace_syscalls))
1312 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001313 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1314 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1315 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001316 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001317 if (!VG_(is_kerror)(res) && res == 0) {
1318 make_readable ( arg1, sizeof(gid_t) );
1319 make_readable ( arg2, sizeof(gid_t) );
1320 make_readable ( arg3, sizeof(gid_t) );
1321 }
1322 break;
1323
1324# if defined(__NR_getresgid32)
1325 case __NR_getresgid32: /* syscall 211 */
1326 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1327 if (VG_(clo_trace_syscalls))
1328 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001329 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1330 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1331 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001332 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001333 if (!VG_(is_kerror)(res) && res == 0) {
1334 make_readable ( arg1, sizeof(gid_t) );
1335 make_readable ( arg2, sizeof(gid_t) );
1336 make_readable ( arg3, sizeof(gid_t) );
1337 }
1338 break;
1339# endif
1340
1341 case __NR_getresuid: /* syscall 165 */
1342 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1343 if (VG_(clo_trace_syscalls))
1344 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001345 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1346 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1347 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001348 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001349 if (!VG_(is_kerror)(res) && res == 0) {
1350 make_readable ( arg1, sizeof(uid_t) );
1351 make_readable ( arg2, sizeof(uid_t) );
1352 make_readable ( arg3, sizeof(uid_t) );
1353 }
1354 break;
1355
1356# if defined(__NR_getresuid32)
1357 case __NR_getresuid32: /* syscall 209 */
1358 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1359 if (VG_(clo_trace_syscalls))
1360 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001361 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1362 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1363 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001364 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001365 if (!VG_(is_kerror)(res) && res == 0) {
1366 make_readable ( arg1, sizeof(uid_t) );
1367 make_readable ( arg2, sizeof(uid_t) );
1368 make_readable ( arg3, sizeof(uid_t) );
1369 }
1370 break;
1371# endif
1372
1373# if defined(__NR_ugetrlimit)
1374 case __NR_ugetrlimit: /* syscall 191 */
1375# endif
1376 case __NR_getrlimit: /* syscall 76 */
1377 /* int getrlimit (int resource, struct rlimit *rlim); */
1378 if (VG_(clo_trace_syscalls))
1379 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001380 must_be_writable( tst, "getrlimit(rlim)", arg2,
1381 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001382 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001383 if (!VG_(is_kerror)(res) && res == 0)
1384 make_readable( arg2, sizeof(struct rlimit) );
1385 break;
1386
1387 case __NR_getrusage: /* syscall 77 */
1388 /* int getrusage (int who, struct rusage *usage); */
1389 if (VG_(clo_trace_syscalls))
1390 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001391 must_be_writable( tst, "getrusage(usage)", arg2,
1392 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001393 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001394 if (!VG_(is_kerror)(res) && res == 0)
1395 make_readable(arg2, sizeof(struct rusage) );
1396 break;
1397
1398 case __NR_gettimeofday: /* syscall 78 */
1399 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1400 if (VG_(clo_trace_syscalls))
1401 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001402 must_be_writable( tst, "gettimeofday(tv)", arg1,
1403 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001404 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001405 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001406 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001407 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001408 if (!VG_(is_kerror)(res) && res == 0) {
1409 make_readable( arg1, sizeof(struct timeval) );
1410 if (arg2 != 0)
1411 make_readable( arg2, sizeof(struct timezone) );
1412 }
1413 break;
1414
1415 case __NR_getuid: /* syscall 24 */
1416 /* uid_t getuid(void); */
1417 if (VG_(clo_trace_syscalls))
1418 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001419 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001420 break;
1421
1422# if defined(__NR_getuid32)
1423 case __NR_getuid32: /* syscall 199 */
1424 /* ???uid_t getuid32(void); */
1425 if (VG_(clo_trace_syscalls))
1426 VG_(printf)("getuid32 ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001427 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001428 break;
1429# endif
1430
1431 case __NR_ipc: /* syscall 117 */
1432 /* int ipc ( unsigned int call, int first, int second,
1433 int third, void *ptr, long fifth); */
1434 {
sewardj2e93c502002-04-12 11:12:52 +00001435 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001436
1437 if (VG_(clo_trace_syscalls))
1438 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1439 arg1,arg2,arg3,arg4,arg5,arg6);
1440 switch (arg1 /* call */) {
1441 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001442 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001443 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001444 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001445 break;
sewardj5b9e3502002-03-29 04:35:08 +00001446 case 2: /* IPCOP_semget */
1447 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001448 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001449 break;
1450 case 11: /* IPCOP_msgsnd */
1451 {
1452 struct msgbuf *msgp = (struct msgbuf *)arg5;
1453 Int msgsz = arg3;
1454
sewardj8c824512002-04-14 04:16:48 +00001455 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001456 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001457 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001458 (UInt)msgp->mtext, msgsz );
1459
sewardj2e93c502002-04-12 11:12:52 +00001460 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001461 break;
1462 }
1463 case 12: /* IPCOP_msgrcv */
1464 {
sewardj59c255c2002-04-27 02:06:15 +00001465 struct msgbuf *msgp;
sewardj5b9e3502002-03-29 04:35:08 +00001466 Int msgsz = arg3;
sewardj59c255c2002-04-27 02:06:15 +00001467
1468 msgp = (struct msgbuf *)safe_dereference(
1469 (Addr) (&((struct ipc_kludge *)arg5)->msgp), 0 );
sewardj5b9e3502002-03-29 04:35:08 +00001470
sewardj59c255c2002-04-27 02:06:15 +00001471 must_be_writable ( tst, "msgrcv(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001472 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj59c255c2002-04-27 02:06:15 +00001473 must_be_writable ( tst, "msgrcv(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001474 (UInt)msgp->mtext, msgsz );
1475
sewardj2e93c502002-04-12 11:12:52 +00001476 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001477
1478 if ( !VG_(is_kerror)(res) && res > 0 ) {
1479 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1480 make_readable ( (UInt)msgp->mtext, res );
1481 }
1482 break;
1483 }
1484 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001485 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001486 break;
1487 case 14: /* IPCOP_msgctl */
1488 {
1489 switch (arg3 /* cmd */) {
1490 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001491 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001492 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001493 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001494 if ( !VG_(is_kerror)(res) && res > 0 ) {
1495 make_readable ( arg5, sizeof(struct msqid_ds) );
1496 }
1497 break;
1498 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001499 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001500 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001501 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001502 break;
sewardjc9add3b2002-04-16 01:58:19 +00001503# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001504 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001505 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001506 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001507 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001508 if ( !VG_(is_kerror)(res) && res > 0 ) {
1509 make_readable ( arg5, sizeof(struct msqid64_ds) );
1510 }
1511 break;
sewardjc9add3b2002-04-16 01:58:19 +00001512# endif
1513# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001514 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001515 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001516 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001517 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001518 break;
sewardjc9add3b2002-04-16 01:58:19 +00001519# endif
sewardj5b9e3502002-03-29 04:35:08 +00001520 default:
sewardj2e93c502002-04-12 11:12:52 +00001521 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001522 break;
1523 }
1524 break;
1525 }
sewardjde4a1d02002-03-22 01:27:54 +00001526 case 21: /* IPCOP_shmat */
1527 {
1528 Int shmid = arg2;
1529 Int shmflag = arg3;
1530 UInt addr;
1531
sewardj2e93c502002-04-12 11:12:52 +00001532 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001533
1534 if ( VG_(is_kerror) ( res ) )
1535 break;
1536
1537 /* force readability. before the syscall it is
1538 * indeed uninitialized, as can be seen in
1539 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1540 make_readable ( arg4, sizeof( ULong ) );
1541
1542 addr = safe_dereference ( arg4, 0 );
1543 if ( addr > 0 ) {
1544 UInt segmentSize = get_shm_size ( shmid );
1545 if ( segmentSize > 0 ) {
1546 if ( shmflag & SHM_RDONLY )
1547 make_readable ( addr, segmentSize );
1548 else
1549 make_readwritable ( addr, segmentSize );
1550 }
1551 }
1552 break;
1553 }
1554 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001555 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001556 /* ### FIXME: this should call make_noaccess on the
1557 * area passed to shmdt. But there's no way to
1558 * figure out the size of the shared memory segment
1559 * just from the address... Maybe we want to keep a
1560 * copy of the exiting mappings inside valgrind? */
1561 break;
1562 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001563 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001564 break;
1565 case 24: /* IPCOP_shmctl */
sewardj2390bb52002-05-09 17:45:06 +00001566 /* Subject: shmctl: The True Story
1567 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
1568 From: Reuben Thomas <rrt@mupsych.org>
1569 To: Julian Seward <jseward@acm.org>
1570
1571 1. As you suggested, the syscall subop is in arg1.
1572
1573 2. There are a couple more twists, so the arg order
1574 is actually:
1575
1576 arg1 syscall subop
1577 arg2 file desc
1578 arg3 shm operation code (can have IPC_64 set)
1579 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
1580 is defined?
1581 arg5 pointer to buffer
1582
1583 3. With this in mind, I've amended the case as below:
1584 */
1585 {
1586 UInt cmd = arg3;
1587 Bool out_arg = False;
1588 if ( arg5 ) {
1589# if defined(IPC_64)
1590 cmd = cmd & (~IPC_64);
1591# endif
sewardj2a8cda12002-05-10 22:51:26 +00001592 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
sewardj2390bb52002-05-09 17:45:06 +00001593 if ( out_arg )
1594 must_be_writable( tst,
1595 "shmctl(SHM_STAT or IPC_STAT,buf)",
1596 arg5, sizeof(struct shmid_ds) );
1597 else
1598 must_be_readable( tst,
1599 "shmctl(SHM_XXXX,buf)",
1600 arg5, sizeof(struct shmid_ds) );
1601 }
1602 KERNEL_DO_SYSCALL(tid,res);
1603 if ( arg5 && !VG_(is_kerror)(res) && res == 0 && out_arg )
1604 make_readable( arg5, sizeof(struct shmid_ds) );
sewardjde4a1d02002-03-22 01:27:54 +00001605 }
sewardj84b380a2002-05-08 01:31:15 +00001606 break;
sewardjde4a1d02002-03-22 01:27:54 +00001607 default:
1608 VG_(message)(Vg_DebugMsg,
1609 "FATAL: unhandled syscall(ipc) %d",
1610 arg1 );
1611 VG_(panic)("... bye!\n");
1612 break; /*NOTREACHED*/
1613 }
1614 }
1615 break;
1616
1617 case __NR_ioctl: /* syscall 54 */
1618 /* int ioctl(int d, int request, ...)
1619 [The "third" argument is traditionally char *argp,
1620 and will be so named for this discussion.]
1621 */
1622 /*
1623 VG_(message)(
1624 Vg_DebugMsg,
1625 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1626 arg2,arg1,arg3);
1627 */
1628 if (VG_(clo_trace_syscalls))
1629 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1630 switch (arg2 /* request */) {
1631 case TCSETS:
1632 case TCSETSW:
1633 case TCSETSF:
sewardj730e4d32002-05-09 18:40:45 +00001634 must_be_readable( tst, "ioctl(TCSET{S,SW,SF})", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001635 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001636 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001637 break;
1638 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001639 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001640 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001641 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001642 if (!VG_(is_kerror)(res) && res == 0)
1643 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1644 break;
sewardj2f0de322002-03-24 10:17:25 +00001645 case TCSETA:
sewardj730e4d32002-05-09 18:40:45 +00001646 case TCSETAW:
1647 case TCSETAF:
1648 must_be_readable( tst, "ioctl(TCSET{A,AW,AF})", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001649 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001650 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001651 break;
1652 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001653 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001654 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001655 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001656 if (!VG_(is_kerror)(res) && res == 0)
1657 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1658 break;
sewardjde4a1d02002-03-22 01:27:54 +00001659 case TCSBRK:
sewardj835021e2002-05-22 12:03:54 +00001660 case TCXONC:
sewardjde4a1d02002-03-22 01:27:54 +00001661 case TCSBRKP:
1662 case TCFLSH:
1663 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001664 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001665 break;
1666 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001667 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001668 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001669 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001670 if (!VG_(is_kerror)(res) && res == 0)
1671 make_readable ( arg3, sizeof(struct winsize) );
1672 break;
1673 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001674 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001675 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001676 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001677 break;
sewardj19fe3d02002-03-29 04:39:00 +00001678 case TIOCGPGRP:
1679 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001680 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001681 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001682 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001683 if (!VG_(is_kerror)(res) && res == 0)
1684 make_readable ( arg3, sizeof(pid_t) );
sewardja4da9372002-05-21 00:44:02 +00001685 break;
1686 case TIOCSPGRP:
1687 /* Set a process group ID? */
1688 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
1689 sizeof(pid_t) );
1690 KERNEL_DO_SYSCALL(tid,res);
1691 if (!VG_(is_kerror)(res) && res == 0)
1692 make_readable ( arg3, sizeof(pid_t) );
1693 break;
sewardjde4a1d02002-03-22 01:27:54 +00001694 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001695 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001696 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001697 if (!VG_(is_kerror)(res) && res == 0)
1698 make_readable ( arg3, sizeof(int));
1699 break;
sewardj73f1f072002-03-29 14:22:46 +00001700 case TIOCSCTTY:
1701 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001702 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001703 break;
sewardjde4a1d02002-03-22 01:27:54 +00001704 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001705 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001706 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001707 break;
1708 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001709 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001710 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001711 break;
1712 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001713 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001714 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001715 break;
1716 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001717 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001718 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001719 if (!VG_(is_kerror)(res) && res == 0)
1720 make_readable( arg3, sizeof(int) );
1721 break;
1722
1723 /* If you get compilation problems here, change the #if
1724 1 to #if 0 and get rid of <scsi/sg.h> in
1725 vg_unsafe.h. */
1726# if 1
1727 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001728 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1729 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001730 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001731 break;
1732# if defined(SG_IO)
1733 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001734 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001735 sizeof(struct sg_io_hdr) );
sewardj2e93c502002-04-12 11:12:52 +00001736 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001737 if (!VG_(is_kerror)(res) && res == 0)
1738 make_readable (arg3, sizeof(struct sg_io_hdr));
1739 break;
1740# endif /* SG_IO */
1741 case SG_GET_SCSI_ID:
1742 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001743 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001744 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001745 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001746 if (!VG_(is_kerror)(res) && res == 0)
1747 make_readable (arg3, sizeof(struct sg_scsi_id));
1748 break;
1749 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001750 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001751 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001752 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001753 break;
1754 case SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001755 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1756 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001757 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001758 break;
1759 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001760 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001761 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001762 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001763 if (!VG_(is_kerror)(res) && res == 0)
1764 make_readable (arg3, sizeof(int));
1765 break;
1766 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001767 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1768 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001769 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001770 if (!VG_(is_kerror)(res) && res == 0)
1771 make_readable (arg3, sizeof(int));
1772 break;
1773 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001774 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001775 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001776 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001777 break;
1778# endif
1779
1780 case IIOCGETCPS:
1781 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1782 * when KERNEL was. I never saw a larger value than 64 though */
1783# ifndef ISDN_MAX_CHANNELS
1784# define ISDN_MAX_CHANNELS 64
1785# endif
sewardj8c824512002-04-14 04:16:48 +00001786 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001787 ISDN_MAX_CHANNELS
1788 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001789 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001790 if (!VG_(is_kerror)(res) && res == 0)
1791 make_readable ( arg3, ISDN_MAX_CHANNELS
1792 * 2 * sizeof(unsigned long) );
1793 break;
1794 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001795 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001796 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1797 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001798 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001799 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001800 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001801 if (!VG_(is_kerror)(res) && res == 0)
1802 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1803 break;
1804
1805 /* These all use struct ifreq AFAIK */
1806 case SIOCGIFINDEX:
1807 case SIOCGIFFLAGS: /* get flags */
1808 case SIOCGIFHWADDR: /* Get hardware address */
1809 case SIOCGIFMTU: /* get MTU size */
1810 case SIOCGIFADDR: /* get PA address */
1811 case SIOCGIFNETMASK: /* get network PA mask */
1812 case SIOCGIFMETRIC: /* get metric */
1813 case SIOCGIFMAP: /* Get device parameters */
1814 case SIOCGIFTXQLEN: /* Get the tx queue length */
1815 case SIOCGIFDSTADDR: /* get remote PA address */
1816 case SIOCGIFBRDADDR: /* get broadcast PA address */
1817 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001818 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001819 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001820 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001821 if (!VG_(is_kerror)(res) && res == 0)
1822 make_readable (arg3, sizeof(struct ifreq));
1823 break;
1824 case SIOCGIFCONF: /* get iface list */
1825 /* WAS:
1826 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1827 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001828 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001829 if (!VG_(is_kerror)(res) && res == 0)
1830 make_readable (arg3, sizeof(struct ifconf));
1831 */
sewardj8c824512002-04-14 04:16:48 +00001832 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001833 sizeof(struct ifconf));
1834 if ( arg3 ) {
1835 // TODO len must be readable and writable
1836 // buf pointer only needs to be readable
1837 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001838 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001839 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1840 }
sewardj2e93c502002-04-12 11:12:52 +00001841 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001842 if (!VG_(is_kerror)(res) && res == 0 && arg3 ) {
1843 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj402c9362002-05-24 11:57:36 +00001844 if (ifc->ifc_buf != NULL)
1845 make_readable ( (Addr)(ifc->ifc_buf),
1846 (UInt)(ifc->ifc_len) );
sewardjde4a1d02002-03-22 01:27:54 +00001847 }
1848 break;
1849 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001850 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001851 sizeof(struct timeval));
sewardj2e93c502002-04-12 11:12:52 +00001852 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001853 if (!VG_(is_kerror)(res) && res == 0)
1854 make_readable (arg3, sizeof(struct timeval));
1855 break;
1856 case SIOCGRARP: /* get RARP table entry */
1857 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001858 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001859 sizeof(struct arpreq));
sewardj2e93c502002-04-12 11:12:52 +00001860 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001861 if (!VG_(is_kerror)(res) && res == 0)
1862 make_readable (arg3, sizeof(struct arpreq));
1863 break;
1864
1865 case SIOCSIFFLAGS: /* set flags */
1866 case SIOCSIFMAP: /* Set device parameters */
1867 case SIOCSIFTXQLEN: /* Set the tx queue length */
1868 case SIOCSIFDSTADDR: /* set remote PA address */
1869 case SIOCSIFBRDADDR: /* set broadcast PA address */
1870 case SIOCSIFNETMASK: /* set network PA mask */
1871 case SIOCSIFMETRIC: /* set metric */
1872 case SIOCSIFADDR: /* set PA address */
1873 case SIOCSIFMTU: /* set MTU size */
1874 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001875 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001876 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001877 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001878 break;
1879 /* Routing table calls. */
1880 case SIOCADDRT: /* add routing table entry */
1881 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001882 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001883 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001884 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001885 break;
1886
1887 /* RARP cache control calls. */
1888 case SIOCDRARP: /* delete RARP table entry */
1889 case SIOCSRARP: /* set RARP table entry */
1890 /* ARP cache control calls. */
1891 case SIOCSARP: /* set ARP table entry */
1892 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001893 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001894 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001895 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001896 break;
1897
1898 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001899 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001900 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001901 break;
1902
1903 /* linux/soundcard interface (OSS) */
1904 case SNDCTL_SEQ_GETOUTCOUNT:
1905 case SNDCTL_SEQ_GETINCOUNT:
1906 case SNDCTL_SEQ_PERCMODE:
1907 case SNDCTL_SEQ_TESTMIDI:
1908 case SNDCTL_SEQ_RESETSAMPLES:
1909 case SNDCTL_SEQ_NRSYNTHS:
1910 case SNDCTL_SEQ_NRMIDIS:
1911 case SNDCTL_SEQ_GETTIME:
1912 case SNDCTL_DSP_GETFMTS:
1913 case SNDCTL_DSP_GETTRIGGER:
1914 case SNDCTL_DSP_GETODELAY:
1915# if defined(SNDCTL_DSP_GETSPDIF)
1916 case SNDCTL_DSP_GETSPDIF:
1917# endif
1918 case SNDCTL_DSP_GETCAPS:
1919 case SOUND_PCM_READ_RATE:
1920 case SOUND_PCM_READ_CHANNELS:
1921 case SOUND_PCM_READ_BITS:
1922 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1923 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001924 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1925 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001926 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001927 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001928 if (!VG_(is_kerror)(res) && res == 0)
1929 make_readable (arg3, sizeof(int));
1930 break;
1931 case SNDCTL_SEQ_CTRLRATE:
1932 case SNDCTL_DSP_SPEED:
1933 case SNDCTL_DSP_STEREO:
1934 case SNDCTL_DSP_GETBLKSIZE:
1935 case SNDCTL_DSP_CHANNELS:
1936 case SOUND_PCM_WRITE_FILTER:
1937 case SNDCTL_DSP_SUBDIVIDE:
1938 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001939# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001940 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001941# endif
1942# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001943 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001944# endif
sewardjde4a1d02002-03-22 01:27:54 +00001945 case SNDCTL_TMR_TIMEBASE:
1946 case SNDCTL_TMR_TEMPO:
1947 case SNDCTL_TMR_SOURCE:
1948 case SNDCTL_MIDI_PRETIME:
1949 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001950 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1951 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001952 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001953 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1954 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001955 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001956 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001957 break;
1958 case SNDCTL_DSP_GETOSPACE:
1959 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001960 must_be_writable(tst,
1961 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001962 "(SIOR, audio_buf_info))", arg3,
1963 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001964 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001965 if (!VG_(is_kerror)(res) && res == 0)
1966 make_readable (arg3, sizeof(audio_buf_info));
1967 break;
1968 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001969 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001970 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001971 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001972 break;
sewardj0aa4c252002-04-27 02:20:14 +00001973
1974 /* Real Time Clock (/dev/rtc) ioctls */
sewardjfbe18b92002-05-10 00:46:59 +00001975# ifndef GLIBC_2_1
sewardj0aa4c252002-04-27 02:20:14 +00001976 case RTC_UIE_ON:
1977 case RTC_UIE_OFF:
1978 case RTC_AIE_ON:
1979 case RTC_AIE_OFF:
1980 case RTC_PIE_ON:
1981 case RTC_PIE_OFF:
1982 case RTC_IRQP_SET:
1983 KERNEL_DO_SYSCALL(tid,res);
1984 break;
1985 case RTC_RD_TIME:
1986 case RTC_ALM_READ:
1987 must_be_writable(tst, "ioctl(RTC_RD_TIME/ALM_READ)", arg3,
1988 sizeof(struct rtc_time));
1989 KERNEL_DO_SYSCALL(tid,res);
1990 if (!VG_(is_kerror) && res == 0)
1991 make_readable(arg3, sizeof(struct rtc_time));
1992 break;
1993 case RTC_ALM_SET:
1994 must_be_readable(tst, "ioctl(RTC_ALM_SET)", arg3,
1995 sizeof(struct rtc_time));
1996 KERNEL_DO_SYSCALL(tid,res);
1997 break;
1998 case RTC_IRQP_READ:
1999 must_be_writable(tst, "ioctl(RTC_IRQP_READ)", arg3,
2000 sizeof(unsigned long));
2001 KERNEL_DO_SYSCALL(tid,res);
2002 if(!VG_(is_kerror) && res == 0)
2003 make_readable(arg3, sizeof(unsigned long));
2004 break;
sewardjfbe18b92002-05-10 00:46:59 +00002005# endif /* GLIBC_2_1 */
sewardjeea0f2e2002-04-27 02:28:19 +00002006
sewardje097ec22002-06-01 23:53:10 +00002007# ifdef BLKGETSIZE
2008 case BLKGETSIZE:
2009 must_be_writable(tst, "ioctl(BLKGETSIZE)", arg3,
2010 sizeof(unsigned long));
2011 KERNEL_DO_SYSCALL(tid,res);
2012 if (!VG_(is_kerror)(res) && res == 0)
2013 make_readable (arg3, sizeof(unsigned long));
2014 break;
2015# endif /* BLKGETSIZE */
2016
sewardjeea0f2e2002-04-27 02:28:19 +00002017 /* CD ROM stuff (??) */
2018 case CDROMSUBCHNL:
2019 must_be_readable(tst, "ioctl(CDROMSUBCHNL (cdsc_format, char))",
2020 (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format),
2021 sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
2022 must_be_writable(tst, "ioctl(CDROMSUBCHNL)", arg3,
2023 sizeof(struct cdrom_subchnl));
2024 KERNEL_DO_SYSCALL(tid,res);
2025 if (!VG_(is_kerror)(res) && res == 0)
2026 make_readable (arg3, sizeof(struct cdrom_subchnl));
2027 break;
2028 case CDROMREADTOCHDR:
2029 must_be_writable(tst, "ioctl(CDROMREADTOCHDR)", arg3,
2030 sizeof(struct cdrom_tochdr));
2031 KERNEL_DO_SYSCALL(tid,res);
2032 if (!VG_(is_kerror)(res) && res == 0)
2033 make_readable (arg3, sizeof(struct cdrom_tochdr));
2034 break;
2035 case CDROMREADTOCENTRY:
2036 must_be_readable(tst, "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
2037 (int) &(((struct cdrom_tocentry *) arg3)->cdte_format),
2038 sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
2039 must_be_readable(tst, "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
2040 (int) &(((struct cdrom_tocentry *) arg3)->cdte_track),
2041 sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
2042 must_be_writable(tst, "ioctl(CDROMREADTOCENTRY)", arg3,
2043 sizeof(struct cdrom_tocentry));
2044 KERNEL_DO_SYSCALL(tid,res);
2045 if (!VG_(is_kerror)(res) && res == 0)
2046 make_readable (arg3, sizeof(struct cdrom_tochdr));
2047 break;
2048 case CDROMPLAYMSF:
2049 must_be_readable(tst, "ioctl(CDROMPLAYMSF)", arg3,
2050 sizeof(struct cdrom_msf));
2051 KERNEL_DO_SYSCALL(tid,res);
2052 break;
sewardjde4a1d02002-03-22 01:27:54 +00002053 /* We don't have any specific information on it, so
2054 try to do something reasonable based on direction and
2055 size bits. The encoding scheme is described in
sewardja4da9372002-05-21 00:44:02 +00002056 /usr/include/asm/ioctl.h.
2057
2058 According to Simon Hausmann, _IOC_READ means the kernel
2059 writes a value to the ioctl value passed from the user
2060 space and the other way around with _IOC_WRITE. */
sewardjde4a1d02002-03-22 01:27:54 +00002061 default: {
2062 UInt dir = _IOC_DIR(arg2);
2063 UInt size = _IOC_SIZE(arg2);
2064 if (/* size == 0 || */ dir == _IOC_NONE) {
2065 VG_(message)(Vg_UserMsg,
2066 "Warning: noted but unhandled ioctl 0x%x"
2067 " with no size/direction hints",
2068 arg2);
2069 VG_(message)(Vg_UserMsg,
2070 " This could cause spurious value errors"
2071 " to appear.");
2072 VG_(message)(Vg_UserMsg,
2073 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
2074 " writing a proper wrapper." );
2075 } else {
sewardjde4a1d02002-03-22 01:27:54 +00002076 if ((dir & _IOC_WRITE) && size > 0)
sewardja4da9372002-05-21 00:44:02 +00002077 must_be_readable(tst, "ioctl(generic)", arg3, size);
2078 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00002079 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00002080 }
sewardj2e93c502002-04-12 11:12:52 +00002081 KERNEL_DO_SYSCALL(tid,res);
sewardja4da9372002-05-21 00:44:02 +00002082 if (size > 0 && (dir & _IOC_READ)
sewardja9fad522002-06-03 13:05:48 +00002083 && !VG_(is_kerror)(res) && res == 0
2084 && arg3 != (Addr)NULL)
sewardjde4a1d02002-03-22 01:27:54 +00002085 make_readable (arg3, size);
2086 break;
2087 }
2088 }
2089 break;
2090
2091 case __NR_kill: /* syscall 37 */
2092 /* int kill(pid_t pid, int sig); */
2093 if (VG_(clo_trace_syscalls))
2094 VG_(printf)("kill ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00002095 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002096 break;
2097
2098 case __NR_link: /* syscall 9 */
2099 /* int link(const char *oldpath, const char *newpath); */
2100 if (VG_(clo_trace_syscalls))
2101 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00002102 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
2103 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00002104 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002105 break;
2106
2107 case __NR_lseek: /* syscall 19 */
2108 /* off_t lseek(int fildes, off_t offset, int whence); */
2109 if (VG_(clo_trace_syscalls))
2110 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00002111 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002112 break;
2113
2114 case __NR__llseek: /* syscall 140 */
2115 /* int _llseek(unsigned int fd, unsigned long offset_high,
2116 unsigned long offset_low,
2117 loff_t * result, unsigned int whence); */
2118 if (VG_(clo_trace_syscalls))
2119 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
2120 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00002121 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00002122 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002123 if (!VG_(is_kerror)(res) && res == 0)
2124 make_readable( arg4, sizeof(loff_t) );
2125 break;
2126
2127 case __NR_lstat: /* syscall 107 */
2128 /* int lstat(const char *file_name, struct stat *buf); */
2129 if (VG_(clo_trace_syscalls))
2130 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002131 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
2132 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002133 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002134 if (!VG_(is_kerror)(res) && res == 0) {
2135 make_readable( arg2, sizeof(struct stat) );
2136 }
2137 break;
2138
2139# if defined(__NR_lstat64)
2140 case __NR_lstat64: /* syscall 196 */
2141 /* int lstat64(const char *file_name, struct stat64 *buf); */
2142 if (VG_(clo_trace_syscalls))
2143 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002144 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
2145 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002146 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002147 if (!VG_(is_kerror)(res) && res == 0) {
2148 make_readable( arg2, sizeof(struct stat64) );
2149 }
2150 break;
2151# endif
2152
2153 case __NR_mkdir: /* syscall 39 */
2154 /* int mkdir(const char *pathname, mode_t mode); */
2155 if (VG_(clo_trace_syscalls))
2156 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002157 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002158 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002159 break;
2160
2161# if defined(__NR_mmap2)
2162 case __NR_mmap2: /* syscall 192 */
2163 /* My impression is that this is exactly like __NR_mmap
2164 except that all 6 args are passed in regs, rather than in
2165 a memory-block. */
2166 /* void* mmap(void *start, size_t length, int prot,
2167 int flags, int fd, off_t offset);
2168 */
2169 {
sewardj2e93c502002-04-12 11:12:52 +00002170 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00002171 if (VG_(clo_trace_syscalls))
2172 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
2173 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00002174 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002175 if (!VG_(is_kerror)(res))
2176 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
sewardj32515c22002-06-03 23:22:23 +00002177 if (!VG_(is_kerror)(res)
2178 && (arg3 & PROT_EXEC)) {
2179 /* The client mmap'ed a segment with executable
2180 permissions. Tell the symbol-table loader, so that it
2181 has an opportunity to pick up more symbols if this mmap
2182 was caused by the client loading a new .so via
2183 dlopen(). This is important for debugging KDE. */
2184 VG_(read_symbols)();
2185 }
sewardjde4a1d02002-03-22 01:27:54 +00002186 }
2187 break;
2188# endif
2189
2190 case __NR_mmap: /* syscall 90 */
2191 /* void* mmap(void *start, size_t length, int prot,
2192 int flags, int fd, off_t offset);
2193 */
2194 {
2195 Bool arg_block_readable
2196 = VG_(clo_instrument)
2197 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
2198 : True;
sewardj8c824512002-04-14 04:16:48 +00002199 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002200 if (arg_block_readable) {
2201 UInt* arg_block = (UInt*)arg1;
2202 UInt arg6;
2203 arg1 = arg_block[0];
2204 arg2 = arg_block[1];
2205 arg3 = arg_block[2];
2206 arg4 = arg_block[3];
2207 arg5 = arg_block[4];
2208 arg6 = arg_block[5];
2209 if (VG_(clo_trace_syscalls))
2210 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
2211 arg1, arg2, arg3, arg4, arg5, arg6 );
2212 }
sewardj2e93c502002-04-12 11:12:52 +00002213 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002214 if (arg_block_readable && !VG_(is_kerror)(res))
2215 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
2216 if (arg_block_readable && !VG_(is_kerror)(res)
2217 && (arg3 & PROT_EXEC)) {
2218 /* The client mmap'ed a segment with executable
2219 permissions. Tell the symbol-table loader, so that it
2220 has an opportunity to pick up more symbols if this mmap
2221 was caused by the client loading a new .so via
2222 dlopen(). This is important for debugging KDE. */
2223 VG_(read_symbols)();
2224 }
2225 }
2226
2227 break;
2228
2229 case __NR_mprotect: /* syscall 125 */
2230 /* int mprotect(const void *addr, size_t len, int prot); */
2231 /* should addr .. addr+len-1 be checked before the call? */
2232 if (VG_(clo_trace_syscalls))
2233 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00002234 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002235 if (!VG_(is_kerror)(res))
2236 approximate_mmap_permissions ( arg1, arg2, arg3 );
2237 break;
2238
2239 case __NR_munmap: /* syscall 91 */
2240 /* int munmap(void *start, size_t length); */
2241 /* should start .. start+length-1 be checked before the call? */
2242 if (VG_(clo_trace_syscalls))
2243 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00002244 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002245 if (!VG_(is_kerror)(res)) {
2246 /* Mash around start and length so that the area passed to
2247 make_noaccess() exactly covers an integral number of
2248 pages. If we don't do that, our idea of addressible
2249 memory diverges from that of the kernel's, which causes
2250 the leak detector to crash. */
sewardj18d75132002-05-16 11:06:21 +00002251 Bool munmap_exe;
sewardjde4a1d02002-03-22 01:27:54 +00002252 Addr start = arg1;
2253 Addr length = arg2;
2254 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
2255 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
2256 /*
2257 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
2258 arg1, arg2, start, length, (arg1!=start || arg2!=length)
2259 ? "CHANGE" : "");
2260 */
2261 make_noaccess( start, length );
2262 /* Tell our symbol table machinery about this, so that if
2263 this happens to be a .so being unloaded, the relevant
2264 symbols are removed too. */
sewardj18d75132002-05-16 11:06:21 +00002265 munmap_exe = VG_(symtab_notify_munmap) ( start, length );
2266 if (munmap_exe)
2267 VG_(invalidate_translations) ( start, length );
sewardjde4a1d02002-03-22 01:27:54 +00002268 }
2269 break;
2270
2271 case __NR_nanosleep: /* syscall 162 */
2272 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
2273 if (VG_(clo_trace_syscalls))
2274 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002275 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00002276 sizeof(struct timespec) );
2277 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002278 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002279 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00002280 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002281 /* Somewhat bogus ... is only written by the kernel if
2282 res == -1 && errno == EINTR. */
2283 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
2284 make_readable ( arg2, sizeof(struct timespec) );
2285 break;
2286
2287 case __NR__newselect: /* syscall 142 */
2288 /* int select(int n,
2289 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
2290 struct timeval *timeout);
2291 */
2292 if (VG_(clo_trace_syscalls))
2293 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
2294 arg1,arg2,arg3,arg4,arg5);
2295 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00002296 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00002297 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
2298 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00002299 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00002300 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
2301 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00002302 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00002303 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
2304 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00002305 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002306 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00002307 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002308 break;
2309
2310 case __NR_open: /* syscall 5 */
2311 /* int open(const char *pathname, int flags); */
2312 if (VG_(clo_trace_syscalls))
2313 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002314 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002315 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002316 if (VG_(clo_trace_syscalls))
2317 VG_(printf)("%d\n",res);
2318 break;
2319
2320 case __NR_pipe: /* syscall 42 */
2321 /* int pipe(int filedes[2]); */
2322 if (VG_(clo_trace_syscalls))
2323 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002324 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002325 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002326 if (!VG_(is_kerror)(res))
2327 make_readable ( arg1, 2*sizeof(int) );
2328 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00002329 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
2330 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00002331 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
2332 break;
2333
2334 case __NR_poll: /* syscall 168 */
2335 /* struct pollfd {
2336 int fd; -- file descriptor
2337 short events; -- requested events
2338 short revents; -- returned events
2339 };
2340 int poll(struct pollfd *ufds, unsigned int nfds,
2341 int timeout)
2342 */
2343 if (VG_(clo_trace_syscalls))
sewardja4da9372002-05-21 00:44:02 +00002344 VG_(printf)("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
sewardjde4a1d02002-03-22 01:27:54 +00002345 /* In fact some parts of this struct should be readable too.
2346 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00002347 must_be_writable( tst, "poll(ufds)",
2348 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00002349 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002350 if (!VG_(is_kerror)(res) && res > 0) {
2351 Int i;
2352 struct pollfd * arr = (struct pollfd *)arg1;
2353 for (i = 0; i < arg2; i++)
2354 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
2355 }
2356 break;
2357
sewardjde4a1d02002-03-22 01:27:54 +00002358 case __NR_readlink: /* syscall 85 */
2359 /* int readlink(const char *path, char *buf, size_t bufsiz); */
2360 if (VG_(clo_trace_syscalls))
2361 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002362 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
2363 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002364 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002365 if (!VG_(is_kerror)(res) && res > 0) {
2366 make_readable ( arg2, res );
2367 }
2368 break;
2369
2370 case __NR_readv: { /* syscall 145 */
2371 /* int readv(int fd, const struct iovec * vector, size_t count); */
2372 UInt i;
2373 struct iovec * vec;
2374 if (VG_(clo_trace_syscalls))
2375 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002376 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002377 arg2, arg3 * sizeof(struct iovec) );
2378 /* ToDo: don't do any of the following if the vector is invalid */
2379 vec = (struct iovec *)arg2;
2380 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002381 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002382 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002383 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002384 if (!VG_(is_kerror)(res) && res > 0) {
2385 /* res holds the number of bytes read. */
2386 for (i = 0; i < arg3; i++) {
2387 Int nReadThisBuf = vec[i].iov_len;
2388 if (nReadThisBuf > res) nReadThisBuf = res;
2389 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
2390 res -= nReadThisBuf;
2391 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
2392 }
2393 }
2394 break;
2395 }
2396
2397 case __NR_rename: /* syscall 38 */
2398 /* int rename(const char *oldpath, const char *newpath); */
2399 if (VG_(clo_trace_syscalls))
2400 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00002401 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
2402 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002403 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002404 break;
2405
2406 case __NR_rmdir: /* syscall 40 */
2407 /* int rmdir(const char *pathname); */
2408 if (VG_(clo_trace_syscalls))
2409 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002410 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002411 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002412 break;
2413
sewardja4d4e482002-05-03 21:18:11 +00002414 case __NR_sched_setparam: /* syscall 154 */
2415 /* int sched_setparam(pid_t pid, const struct sched_param *p); */
sewardj705d3cb2002-05-23 13:13:12 +00002416 if (VG_(clo_trace_syscalls))
sewardja4d4e482002-05-03 21:18:11 +00002417 VG_(printf)("sched_setparam ( %d, %p )\n", arg1, arg2 );
2418 must_be_readable( tst, "sched_setparam(ptr)",
2419 arg2, sizeof(struct sched_param) );
2420 KERNEL_DO_SYSCALL(tid,res);
2421 if (!VG_(is_kerror)(res))
2422 make_readable( arg2, sizeof(struct sched_param) );
2423 break;
2424
2425 case __NR_sched_getparam: /* syscall 155 */
2426 /* int sched_getparam(pid_t pid, struct sched_param *p); */
sewardj705d3cb2002-05-23 13:13:12 +00002427 if (VG_(clo_trace_syscalls))
sewardja4d4e482002-05-03 21:18:11 +00002428 VG_(printf)("sched_getparam ( %d, %p )\n", arg1, arg2 );
2429 must_be_writable( tst, "sched_getparam(ptr)",
2430 arg2, sizeof(struct sched_param) );
2431 KERNEL_DO_SYSCALL(tid,res);
2432 if (!VG_(is_kerror)(res))
2433 make_readable( arg2, sizeof(struct sched_param) );
2434 break;
2435
2436 case __NR_sched_yield: /* syscall 158 */
2437 /* int sched_yield(void); */
sewardj705d3cb2002-05-23 13:13:12 +00002438 if (VG_(clo_trace_syscalls))
sewardja4d4e482002-05-03 21:18:11 +00002439 VG_(printf)("sched_yield ()\n" );
sewardj2e93c502002-04-12 11:12:52 +00002440 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002441 break;
2442
2443 case __NR_select: /* syscall 82 */
2444 /* struct sel_arg_struct {
2445 unsigned long n;
2446 fd_set *inp, *outp, *exp;
2447 struct timeval *tvp;
2448 };
2449 int old_select(struct sel_arg_struct *arg);
2450 */
2451 {
2452 Bool arg_block_readable
2453 = VG_(clo_instrument)
2454 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
2455 : True;
sewardj8c824512002-04-14 04:16:48 +00002456 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002457 if (arg_block_readable) {
2458 UInt* arg_struct = (UInt*)arg1;
2459 arg1 = arg_struct[0];
2460 arg2 = arg_struct[1];
2461 arg3 = arg_struct[2];
2462 arg4 = arg_struct[3];
2463 arg5 = arg_struct[4];
2464
2465 if (VG_(clo_trace_syscalls))
2466 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2467 arg1,arg2,arg3,arg4,arg5);
2468 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002469 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002470 arg1/8 /* __FD_SETSIZE/8 */ );
2471 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002472 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002473 arg1/8 /* __FD_SETSIZE/8 */ );
2474 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002475 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002476 arg1/8 /* __FD_SETSIZE/8 */ );
2477 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002478 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002479 sizeof(struct timeval) );
2480 }
2481 }
sewardj2e93c502002-04-12 11:12:52 +00002482 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002483 break;
2484
2485 case __NR_setitimer: /* syscall 104 */
2486 /* setitimer(int which, const struct itimerval *value,
2487 struct itimerval *ovalue); */
2488 if (VG_(clo_trace_syscalls))
2489 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj55314d42002-05-23 17:14:54 +00002490 if (arg2 != (Addr)NULL)
2491 must_be_readable(tst, "setitimer(value)",
2492 arg2, sizeof(struct itimerval) );
sewardjde4a1d02002-03-22 01:27:54 +00002493 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002494 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002495 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002496 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002497 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2498 make_readable(arg3, sizeof(struct itimerval));
2499 }
2500 break;
2501
2502# if defined(__NR_setfsgid32)
2503 case __NR_setfsgid32: /* syscall 216 */
2504 /* int setfsgid(uid_t fsgid); */
2505 if (VG_(clo_trace_syscalls))
2506 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002507 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002508 break;
2509# endif
2510
2511# if defined(__NR_setgid32)
2512 case __NR_setgid32: /* syscall 214 */
2513# endif
2514 case __NR_setgid: /* syscall 46 */
2515 /* int setgid(gid_t gid); */
2516 if (VG_(clo_trace_syscalls))
2517 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002518 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002519 break;
2520
2521 case __NR_setsid: /* syscall 66 */
2522 /* pid_t setsid(void); */
2523 if (VG_(clo_trace_syscalls))
2524 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002525 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002526 break;
2527
2528# if defined(__NR_setgroups32)
2529 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002530# endif
2531 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002532 /* int setgroups(size_t size, const gid_t *list); */
2533 if (VG_(clo_trace_syscalls))
2534 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2535 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002536 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002537 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002538 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002539 break;
sewardjde4a1d02002-03-22 01:27:54 +00002540
2541 case __NR_setpgid: /* syscall 57 */
2542 /* int setpgid(pid_t pid, pid_t pgid); */
2543 if (VG_(clo_trace_syscalls))
2544 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002545 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002546 break;
2547
2548# if defined(__NR_setregid32)
2549 case __NR_setregid32: /* syscall 204 */
2550 /* int setregid(gid_t rgid, gid_t egid); */
2551 if (VG_(clo_trace_syscalls))
2552 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002553 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002554 break;
2555# endif
2556
2557# if defined(__NR_setresuid32)
2558 case __NR_setresuid32: /* syscall 208 */
2559 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2560 if (VG_(clo_trace_syscalls))
2561 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002562 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002563 break;
2564# endif
2565
2566# if defined(__NR_setreuid32)
2567 case __NR_setreuid32: /* syscall 203 */
2568# endif
2569 case __NR_setreuid: /* syscall 70 */
2570 /* int setreuid(uid_t ruid, uid_t euid); */
2571 if (VG_(clo_trace_syscalls))
2572 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002573 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002574 break;
2575
2576 case __NR_setrlimit: /* syscall 75 */
2577 /* int setrlimit (int resource, const struct rlimit *rlim); */
2578 if (VG_(clo_trace_syscalls))
2579 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002580 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002581 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002582 break;
2583
2584# if defined(__NR_setuid32)
2585 case __NR_setuid32: /* syscall 213 */
2586# endif
2587 case __NR_setuid: /* syscall 23 */
2588 /* int setuid(uid_t uid); */
2589 if (VG_(clo_trace_syscalls))
2590 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002591 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002592 break;
2593
2594 case __NR_socketcall: /* syscall 102 */
2595 /* int socketcall(int call, unsigned long *args); */
2596 if (VG_(clo_trace_syscalls))
2597 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2598 switch (arg1 /* request */) {
2599
2600 case SYS_SOCKETPAIR:
2601 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002602 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002603 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002604 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002605 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002606 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002607 if (!VG_(is_kerror)(res))
2608 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2609 break;
2610
2611 case SYS_SOCKET:
2612 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002613 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002614 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002615 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002616 break;
2617
2618 case SYS_BIND:
2619 /* int bind(int sockfd, struct sockaddr *my_addr,
2620 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002621 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002622 arg2, 3*sizeof(Addr) );
sewardjc483e8f2002-05-03 21:01:35 +00002623 must_be_readable_sockaddr( tst, "socketcall.bind(my_addr.%s)",
2624 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
sewardj2e93c502002-04-12 11:12:52 +00002625 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002626 break;
sewardjc483e8f2002-05-03 21:01:35 +00002627
sewardjde4a1d02002-03-22 01:27:54 +00002628 case SYS_LISTEN:
2629 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002630 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002631 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002632 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002633 break;
2634
2635 case SYS_ACCEPT: {
2636 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2637 Addr addr;
2638 Addr p_addrlen;
2639 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002640 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002641 arg2, 3*sizeof(Addr) );
2642 addr = ((UInt*)arg2)[1];
2643 p_addrlen = ((UInt*)arg2)[2];
2644 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002645 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002646 p_addrlen, sizeof(int) );
2647 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002648 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002649 addr, addrlen_in );
2650 }
sewardj2e93c502002-04-12 11:12:52 +00002651 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002652 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2653 addrlen_out = safe_dereference( p_addrlen, 0 );
2654 if (addrlen_out > 0)
2655 make_readable( addr, addrlen_out );
2656 }
2657 break;
2658 }
2659
2660 case SYS_SENDTO:
2661 /* int sendto(int s, const void *msg, int len,
2662 unsigned int flags,
2663 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002664 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002665 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002666 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002667 ((UInt*)arg2)[1], /* msg */
2668 ((UInt*)arg2)[2] /* len */ );
sewardjc483e8f2002-05-03 21:01:35 +00002669 must_be_readable_sockaddr( tst, "socketcall.sendto(to.%s)",
2670 (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
sewardj2e93c502002-04-12 11:12:52 +00002671 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002672 break;
2673
2674 case SYS_SEND:
2675 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002676 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002677 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002678 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002679 ((UInt*)arg2)[1], /* msg */
2680 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002681 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002682 break;
2683
2684 case SYS_RECVFROM:
2685 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2686 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002687 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002688 arg2, 6*sizeof(Addr) );
2689 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002690 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002691 ((UInt*)arg2)[5] /* fromlen */,
2692 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002693 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002694 ((UInt*)arg2)[4], /*from*/
2695 safe_dereference( (Addr)
2696 ((UInt*)arg2)[5], 0 ) );
2697 }
sewardj8c824512002-04-14 04:16:48 +00002698 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002699 ((UInt*)arg2)[1], /* buf */
2700 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002701 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002702 if (!VG_(is_kerror)(res) && res >= 0) {
2703 make_readable( ((UInt*)arg2)[1], /* buf */
2704 ((UInt*)arg2)[2] /* len */ );
2705 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2706 make_readable(
2707 ((UInt*)arg2)[4], /*from*/
2708 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2709 }
2710 }
2711 /* phew! */
2712 break;
2713
2714 case SYS_RECV:
2715 /* int recv(int s, void *buf, int len, unsigned int flags); */
2716 /* man 2 recv says:
2717 The recv call is normally used only on a connected socket
2718 (see connect(2)) and is identical to recvfrom with a NULL
2719 from parameter.
2720 */
sewardj8c824512002-04-14 04:16:48 +00002721 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002722 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002723 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002724 ((UInt*)arg2)[1], /* buf */
2725 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002726 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002727 if (!VG_(is_kerror)(res) && res >= 0
2728 && ((UInt*)arg2)[1] != (UInt)NULL) {
2729 make_readable( ((UInt*)arg2)[1], /* buf */
2730 ((UInt*)arg2)[2] /* len */ );
2731 }
2732 break;
2733
sewardjc483e8f2002-05-03 21:01:35 +00002734 case SYS_CONNECT:
sewardjde4a1d02002-03-22 01:27:54 +00002735 /* int connect(int sockfd,
2736 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002737 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002738 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002739 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002740 ((UInt*)arg2)[1], /* serv_addr */
2741 sizeof (sa_family_t));
sewardjc483e8f2002-05-03 21:01:35 +00002742 must_be_readable_sockaddr( tst,
2743 "socketcall.connect(serv_addr.%s)",
2744 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
sewardj2e93c502002-04-12 11:12:52 +00002745 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002746 break;
sewardjde4a1d02002-03-22 01:27:54 +00002747
2748 case SYS_SETSOCKOPT:
2749 /* int setsockopt(int s, int level, int optname,
2750 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002751 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002752 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002753 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002754 ((UInt*)arg2)[3], /* optval */
2755 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002756 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002757 break;
2758
2759 case SYS_GETSOCKOPT:
2760 /* int setsockopt(int s, int level, int optname,
2761 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002762 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002763 arg2, 5*sizeof(Addr) );
2764 {
2765 Addr optval_p = ((UInt*)arg2)[3];
2766 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002767 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002768 UInt optlen_after;
2769 UInt optlen = safe_dereference ( optlen_p, 0 );
2770 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002771 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002772 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002773 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002774 optlen_after = safe_dereference ( optlen_p, 0 );
2775 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2776 make_readable( optval_p, optlen_after );
2777 }
2778 break;
2779
2780 case SYS_GETSOCKNAME:
2781 /* int getsockname(int s, struct sockaddr* name,
2782 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002783 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002784 arg2, 3*sizeof(Addr) );
2785 {
2786 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2787 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002788 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002789 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002790 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002791 if (!VG_(is_kerror)(res)) {
2792 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2793 if (namelen > 0
2794 && ((UInt*)arg2)[1] != (UInt)NULL)
2795 make_readable( ((UInt*)arg2)[1], namelen );
2796 }
2797 }
2798 break;
2799
2800 case SYS_GETPEERNAME:
2801 /* int getpeername(int s, struct sockaddr* name,
2802 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002803 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002804 arg2, 3*sizeof(Addr) );
2805 {
2806 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2807 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002808 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002809 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002810 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002811 if (!VG_(is_kerror)(res)) {
2812 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2813 if (namelen > 0
2814 && ((UInt*)arg2)[1] != (UInt)NULL)
2815 make_readable( ((UInt*)arg2)[1], namelen );
2816 }
2817 }
2818 break;
2819
2820 case SYS_SHUTDOWN:
2821 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002822 must_be_readable( tst, "socketcall.shutdown(args)",
2823 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002824 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002825 break;
2826
2827 case SYS_SENDMSG:
2828 {
2829 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2830
2831 /* this causes warnings, and I don't get why. glibc bug?
2832 * (after all it's glibc providing the arguments array)
2833 must_be_readable( "socketcall.sendmsg(args)",
2834 arg2, 3*sizeof(Addr) );
2835 */
2836
2837 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002838 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002839
sewardj2e93c502002-04-12 11:12:52 +00002840 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002841 break;
2842 }
2843
2844 case SYS_RECVMSG:
2845 {
2846 /* int recvmsg(int s, struct msghdr *msg, int flags); */
2847
2848 /* this causes warnings, and I don't get why. glibc bug?
2849 * (after all it's glibc providing the arguments array)
2850 must_be_readable( "socketcall.recvmsg(args)",
2851 arg2, 3*sizeof(Addr) );
2852 */
2853
2854 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002855 msghdr_foreachfield ( tst, msg, must_be_writable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002856
sewardj2e93c502002-04-12 11:12:52 +00002857 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002858
2859 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002860 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002861
2862 break;
2863 }
2864
2865 default:
2866 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2867 VG_(panic)("... bye!\n");
2868 break; /*NOTREACHED*/
2869 }
2870 break;
2871
2872 case __NR_stat: /* syscall 106 */
2873 /* int stat(const char *file_name, struct stat *buf); */
2874 if (VG_(clo_trace_syscalls))
2875 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002876 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2877 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002878 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002879 if (!VG_(is_kerror)(res))
2880 make_readable( arg2, sizeof(struct stat) );
2881 break;
2882
2883 case __NR_statfs: /* syscall 99 */
2884 /* int statfs(const char *path, struct statfs *buf); */
2885 if (VG_(clo_trace_syscalls))
2886 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002887 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2888 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002889 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002890 if (!VG_(is_kerror)(res))
2891 make_readable( arg2, sizeof(struct statfs) );
2892 break;
2893
2894 case __NR_symlink: /* syscall 83 */
2895 /* int symlink(const char *oldpath, const char *newpath); */
2896 if (VG_(clo_trace_syscalls))
2897 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002898 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2899 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002900 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002901 break;
2902
2903# if defined(__NR_stat64)
2904 case __NR_stat64: /* syscall 195 */
2905 /* int stat64(const char *file_name, struct stat64 *buf); */
2906 if (VG_(clo_trace_syscalls))
2907 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002908 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2909 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002910 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002911 if (!VG_(is_kerror)(res))
2912 make_readable( arg2, sizeof(struct stat64) );
2913 break;
2914# endif
2915
2916# if defined(__NR_fstat64)
2917 case __NR_fstat64: /* syscall 197 */
2918 /* int fstat64(int filedes, struct stat64 *buf); */
2919 if (VG_(clo_trace_syscalls))
2920 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002921 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002922 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002923 if (!VG_(is_kerror)(res))
2924 make_readable( arg2, sizeof(struct stat64) );
2925 break;
2926# endif
2927
2928 case __NR_sysinfo: /* syscall 116 */
2929 /* int sysinfo(struct sysinfo *info); */
2930 if (VG_(clo_trace_syscalls))
2931 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002932 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002933 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002934 if (!VG_(is_kerror)(res))
2935 make_readable( arg1, sizeof(struct sysinfo) );
2936 break;
2937
2938 case __NR_time: /* syscall 13 */
2939 /* time_t time(time_t *t); */
2940 if (VG_(clo_trace_syscalls))
2941 VG_(printf)("time ( %p )\n",arg1);
2942 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002943 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002944 }
sewardj2e93c502002-04-12 11:12:52 +00002945 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002946 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2947 make_readable( arg1, sizeof(time_t) );
2948 }
2949 break;
2950
2951 case __NR_times: /* syscall 43 */
2952 /* clock_t times(struct tms *buf); */
2953 if (VG_(clo_trace_syscalls))
2954 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002955 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002956 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002957 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2958 make_readable( arg1, sizeof(struct tms) );
2959 }
2960 break;
2961
2962 case __NR_truncate: /* syscall 92 */
2963 /* int truncate(const char *path, size_t length); */
2964 if (VG_(clo_trace_syscalls))
2965 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002966 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002967 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002968 break;
2969
2970 case __NR_umask: /* syscall 60 */
2971 /* mode_t umask(mode_t mask); */
2972 if (VG_(clo_trace_syscalls))
2973 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002974 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002975 break;
2976
2977 case __NR_unlink: /* syscall 10 */
2978 /* int unlink(const char *pathname) */
2979 if (VG_(clo_trace_syscalls))
2980 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002981 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002982 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002983 break;
2984
2985 case __NR_uname: /* syscall 122 */
2986 /* int uname(struct utsname *buf); */
2987 if (VG_(clo_trace_syscalls))
2988 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002989 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002990 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002991 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2992 make_readable( arg1, sizeof(struct utsname) );
2993 }
2994 break;
2995
2996 case __NR_utime: /* syscall 30 */
2997 /* int utime(const char *filename, struct utimbuf *buf); */
2998 if (VG_(clo_trace_syscalls))
2999 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00003000 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00003001 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003002 must_be_readable( tst, "utime(buf)", arg2,
3003 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00003004 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00003005 break;
3006
3007 case __NR_wait4: /* syscall 114 */
3008 /* pid_t wait4(pid_t pid, int *status, int options,
3009 struct rusage *rusage) */
3010 if (VG_(clo_trace_syscalls))
3011 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
3012 arg1,arg2,arg3,arg4);
3013 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00003014 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00003015 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00003016 must_be_writable( tst, "wait4(rusage)", arg4,
3017 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00003018 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00003019 if (!VG_(is_kerror)(res)) {
3020 if (arg2 != (Addr)NULL)
3021 make_readable( arg2, sizeof(int) );
3022 if (arg4 != (Addr)NULL)
3023 make_readable( arg4, sizeof(struct rusage) );
3024 }
3025 break;
3026
sewardjde4a1d02002-03-22 01:27:54 +00003027 case __NR_writev: { /* syscall 146 */
3028 /* int writev(int fd, const struct iovec * vector, size_t count); */
3029 UInt i;
3030 struct iovec * vec;
3031 if (VG_(clo_trace_syscalls))
3032 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00003033 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00003034 arg2, arg3 * sizeof(struct iovec) );
3035 /* ToDo: don't do any of the following if the vector is invalid */
3036 vec = (struct iovec *)arg2;
3037 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00003038 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00003039 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00003040 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00003041 break;
3042 }
3043
3044 /*-------------------------- SIGNALS --------------------------*/
3045
3046 /* Normally set to 1, so that Valgrind's signal-simulation machinery
3047 is engaged. Sometimes useful to disable (set to 0), for
3048 debugging purposes, to make clients more deterministic. */
3049# define SIGNAL_SIMULATION 1
3050
sewardj2342c972002-05-22 23:34:20 +00003051 case __NR_sigaltstack: /* syscall 186 */
3052 /* int sigaltstack(const stack_t *ss, stack_t *oss); */
3053 if (VG_(clo_trace_syscalls))
3054 VG_(printf)("sigaltstack ( %p, %p )\n",arg1,arg2);
3055 if (arg1 != (UInt)NULL) {
3056 must_be_readable( tst, "sigaltstack(ss)",
3057 arg1, sizeof(vki_kstack_t) );
3058 }
3059 if (arg2 != (UInt)NULL) {
3060 must_be_writable( tst, "sigaltstack(ss)",
3061 arg1, sizeof(vki_kstack_t) );
3062 }
3063# if SIGNAL_SIMULATION
3064 VG_(do__NR_sigaltstack) (tid);
3065 res = tst->m_eax;
3066# else
3067 KERNEL_DO_SYSCALL(tid,res);
3068# endif
3069 if (!VG_(is_kerror)(res) && res == 0 && arg2 != (UInt)NULL)
3070 make_readable( arg2, sizeof(vki_kstack_t));
3071 break;
3072
sewardjde4a1d02002-03-22 01:27:54 +00003073 case __NR_rt_sigaction:
3074 case __NR_sigaction:
3075 /* int sigaction(int signum, struct k_sigaction *act,
3076 struct k_sigaction *oldact); */
3077 if (VG_(clo_trace_syscalls))
3078 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
3079 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003080 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00003081 arg2, sizeof(vki_ksigaction));
3082 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003083 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00003084 arg3, sizeof(vki_ksigaction));
3085 /* We do this one ourselves! */
3086# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00003087 VG_(do__NR_sigaction)(tid);
3088 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00003089# else
3090 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00003091 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00003092# endif
3093 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
3094 make_readable( arg3, sizeof(vki_ksigaction));
3095 break;
3096
3097 case __NR_rt_sigprocmask:
3098 case __NR_sigprocmask:
3099 /* int sigprocmask(int how, k_sigset_t *set,
3100 k_sigset_t *oldset); */
3101 if (VG_(clo_trace_syscalls))
3102 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
3103 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003104 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00003105 arg2, sizeof(vki_ksigset_t));
3106 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003107 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00003108 arg3, sizeof(vki_ksigset_t));
sewardj018f7622002-05-15 21:13:39 +00003109# if SIGNAL_SIMULATION
3110 VG_(do__NR_sigprocmask) ( tid,
3111 arg1 /*how*/,
3112 (vki_ksigset_t*) arg2,
3113 (vki_ksigset_t*) arg3 );
3114 res = tst->m_eax;
3115# else
sewardj2e93c502002-04-12 11:12:52 +00003116 KERNEL_DO_SYSCALL(tid,res);
sewardj018f7622002-05-15 21:13:39 +00003117# endif
sewardjde4a1d02002-03-22 01:27:54 +00003118 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
3119 make_readable( arg3, sizeof(vki_ksigset_t));
sewardjde4a1d02002-03-22 01:27:54 +00003120 break;
3121
sewardjefbfcdf2002-06-19 17:35:45 +00003122 case __NR_sigpending: /* syscall 73 */
3123# if defined(__NR_rt_sigpending)
3124 case __NR_rt_sigpending: /* syscall 176 */
3125# endif
3126 /* int sigpending( sigset_t *set ) ; */
3127 if (VG_(clo_trace_syscalls))
3128 VG_(printf)( "sigpending ( %p )\n", arg1 );
3129 must_be_writable( tst, "sigpending(set)",
3130 arg1, sizeof(vki_ksigset_t));
3131# if SIGNAL_SIMULATION
3132 VG_(do_sigpending)( tid, (vki_ksigset_t*)arg1 );
3133 res = 0;
3134 SET_EAX(tid, res);
3135# else
3136 KERNEL_DO_SYSCALL(tid, res);
3137# endif
3138 if ( !VG_( is_kerror )( res ) && res == 0 )
3139 make_readable( arg1, sizeof( vki_ksigset_t ) ) ;
3140 break ;
3141
sewardjde4a1d02002-03-22 01:27:54 +00003142 default:
3143 VG_(message)
3144 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
3145 VG_(message)
3146 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
3147 VG_(message)
3148 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
3149 VG_(unimplemented)("no wrapper for the above system call");
3150 vg_assert(3+3 == 7);
3151 break; /*NOTREACHED*/
3152 }
3153
sewardjde4a1d02002-03-22 01:27:54 +00003154 /* { void zzzmemscan(void); zzzmemscan(); } */
3155
sewardj126a41f2002-05-07 23:45:03 +00003156 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardjde4a1d02002-03-22 01:27:54 +00003157 sane_before_call = False;
3158
3159 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00003160 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00003161 VG_(message)(Vg_DebugMsg,
3162 "probable sanity check failure for syscall number %d\n",
3163 syscallno );
3164 VG_(panic)("aborting due to the above ... bye!");
3165 }
3166
3167 VGP_POPCC;
3168}
3169
3170
sewardj2e93c502002-04-12 11:12:52 +00003171
3172/* Perform pre- and post- actions for a blocking syscall, but do not
3173 do the syscall itself. If res is NULL, the pre-syscall actions are
3174 to be performed. If res is non-NULL, the post-syscall actions are
3175 to be performed, and *res is assumed to hold the result of the
3176 syscall. This slightly strange scheme makes it impossible to
3177 mistakenly use the value of *res in the pre-syscall actions.
3178
3179 This doesn't actually do the syscall itself, it is important to
3180 observe.
3181
3182 Because %eax is used both for the syscall number before the call
3183 and the result value afterwards, we can't reliably use it to get
3184 the syscall number. So the caller has to pass it explicitly.
3185*/
sewardj8c824512002-04-14 04:16:48 +00003186void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00003187 Int syscallno,
3188 Int* /*IN*/ res )
3189{
sewardj018f7622002-05-15 21:13:39 +00003190 ThreadState* tst;
3191 Bool sane_before_post, sane_after_post;
3192 UInt arg1, arg2, arg3;
3193
sewardj2e93c502002-04-12 11:12:52 +00003194 VGP_PUSHCC(VgpSyscall);
3195
sewardj018f7622002-05-15 21:13:39 +00003196 vg_assert(VG_(is_valid_tid)(tid));
3197 sane_before_post = True;
3198 sane_after_post = True;
3199 tst = & VG_(threads)[tid];
3200 arg1 = tst->m_ebx;
3201 arg2 = tst->m_ecx;
3202 arg3 = tst->m_edx;
3203 /*
3204 arg4 = tst->m_esi;
3205 arg5 = tst->m_edi;
3206 */
3207
sewardj2e93c502002-04-12 11:12:52 +00003208 if (res != NULL
sewardj126a41f2002-05-07 23:45:03 +00003209 && ! VG_(first_and_last_secondaries_look_plausible)())
sewardj2e93c502002-04-12 11:12:52 +00003210 sane_before_post = False;
3211
3212 switch (syscallno) {
3213
3214 case __NR_read: /* syscall 3 */
3215 /* size_t read(int fd, void *buf, size_t count); */
3216 if (res == NULL) {
3217 /* PRE */
3218 if (VG_(clo_trace_syscalls))
3219 VG_(printf)(
3220 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
3221 VG_(getpid)(), tid,
3222 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00003223 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00003224 } else {
3225 /* POST */
3226 if (VG_(clo_trace_syscalls))
3227 VG_(printf)(
3228 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
3229 VG_(getpid)(), tid,
3230 arg1, arg2, arg3, *res);
3231 if (!VG_(is_kerror)(*res) && *res > 0) {
3232 make_readable( arg2, *res );
3233 }
3234 }
3235 break;
3236
3237 case __NR_write: /* syscall 4 */
3238 /* size_t write(int fd, const void *buf, size_t count); */
3239 if (res == NULL) {
3240 /* PRE */
3241 if (VG_(clo_trace_syscalls))
3242 VG_(printf)(
3243 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
3244 VG_(getpid)(), tid,
3245 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00003246 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00003247 } else {
3248 /* POST */
3249 if (VG_(clo_trace_syscalls))
3250 VG_(printf)(
3251 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
3252 VG_(getpid)(), tid,
3253 arg1, arg2, arg3, *res);
3254 }
3255 break;
3256
3257 default:
3258 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
3259 syscallno);
3260 VG_(panic)("check_known_blocking_syscall");
3261 /*NOTREACHED*/
3262 break;
3263 }
3264
3265 if (res != NULL) { /* only check after syscall */
sewardj126a41f2002-05-07 23:45:03 +00003266 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardj2e93c502002-04-12 11:12:52 +00003267 sane_after_post = False;
3268
3269 if (sane_before_post && (!sane_after_post)) {
3270 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
3271 VG_(message)(Vg_DebugMsg,
3272 "probable sanity check failure for syscall number %d\n",
3273 syscallno );
3274 VG_(panic)("aborting due to the above ... bye!");
3275 }
3276 }
3277
3278 VGP_POPCC;
3279}
3280
3281
sewardjde4a1d02002-03-22 01:27:54 +00003282/*--------------------------------------------------------------------*/
3283/*--- end vg_syscall_mem.c ---*/
3284/*--------------------------------------------------------------------*/