blob: 444f987e4fcb7ff1bf1a311ff9d6137a0720209c [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
281
282/* Records the current end of the data segment so we can make sense of
283 calls to brk(). Initial value set by hdm_init_memory_audit(). */
284Addr VGM_(curr_dataseg_end);
285
286
sewardj2e93c502002-04-12 11:12:52 +0000287
sewardjde4a1d02002-03-22 01:27:54 +0000288/* The Main Entertainment ... */
289
sewardj2e93c502002-04-12 11:12:52 +0000290void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +0000291{
sewardj2e93c502002-04-12 11:12:52 +0000292 Bool sane_before_call = True;
293 Bool sane_after_call = True;
294 ThreadState* tst = VG_(get_thread_state)( tid );
295 UInt syscallno = tst->m_eax;
296 UInt arg1 = tst->m_ebx;
297 UInt arg2 = tst->m_ecx;
298 UInt arg3 = tst->m_edx;
299 UInt arg4 = tst->m_esi;
300 UInt arg5 = tst->m_edi;
sewardjde4a1d02002-03-22 01:27:54 +0000301
302 /* Do not make this unsigned! */
303 Int res;
304
sewardjde4a1d02002-03-22 01:27:54 +0000305 VGP_PUSHCC(VgpSyscall);
306
307 /* Since buggy syscall wrappers sometimes break this, we may as well
308 check ourselves. */
309 if (! VG_(first_and_last_secondaries_look_plausible))
310 sane_before_call = False;
311
312 /* the syscall no is in %eax. For syscalls with <= 5 args,
313 args 1 .. 5 to the syscall are in %ebx %ecx %edx %esi %edi.
314 For calls with > 5 args, %ebx points to a lump of memory
315 containing the args.
316
317 The result is returned in %eax. If this value >= 0, the call
318 succeeded, and this is the return value. If < 0, it failed, and
319 the negation of this value is errno. To be more specific,
320 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
321 (kernel 2.4.9 sources, include/asm-i386/errno.h)
322 then it indicates an error. Otherwise it doesn't.
323
324 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
325 (inclusive?) indicate error returns. Not sure where the -4095
326 comes from.
327 */
328
329 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000330 VG_(printf)("SYSCALL[%d,%d](%3d): ",
331 VG_(getpid)(), tid, syscallno);
sewardjde4a1d02002-03-22 01:27:54 +0000332
333 switch (syscallno) {
334
335 case __NR_sigaltstack:
336 VG_(unimplemented)
337 ("client signals on alternative stack (SA_ONSTACK)");
338 break;
339
340 case __NR_clone:
341 VG_(unimplemented)
sewardj827d95b2002-04-16 02:09:31 +0000342 ("clone(): not supported by Valgrind.\n "
343 "We do now support programs linked against\n "
344 "libpthread.so, though. Re-run with -v and ensure that\n "
345 "you are picking up Valgrind's implementation of libpthread.so.");
sewardjde4a1d02002-03-22 01:27:54 +0000346 break;
347
348# if defined(__NR_modify_ldt)
349 case __NR_modify_ldt:
350 VG_(unimplemented)
351 ("modify_ldt(): I (JRS) haven't investigated this yet; sorry.");
352 break;
353# endif
354
sewardj73f1f072002-03-29 14:22:46 +0000355 /* !!!!!!!!!! New, untested syscalls !!!!!!!!!!!!!!!!!!!!! */
356
sewardj6e435c02002-04-24 02:24:44 +0000357# if defined(__NR_madvise)
358 case __NR_madvise: /* syscall 219 */
359 /* int madvise(void *start, size_t length, int advice ); */
360 if (VG_(clo_trace_syscalls))
361 VG_(printf)("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
362 KERNEL_DO_SYSCALL(tid,res);
363 break;
364# endif
365
sewardj6af4b5d2002-04-16 04:40:49 +0000366# if defined(__NR_mremap)
367 /* Is this really right? Perhaps it should copy the permissions
368 from the old area into the new. Unclear from the Linux man
369 pages what this really does. Also, the flags don't look like
370 they mean the same as the standard mmap flags, so that's
371 probably wrong too. */
372 case __NR_mremap: /* syscall 163 */
373 /* void* mremap(void * old_address, size_t old_size,
374 size_t new_size, unsigned long flags); */
375 if (VG_(clo_trace_syscalls))
376 VG_(printf)("mremap ( %p, %d, %d, 0x%x )\n",
377 arg1, arg2, arg3, arg4);
378 must_be_writable ( tst, "mremap(old_address)", arg1, arg2 );
379 KERNEL_DO_SYSCALL(tid,res);
380 if (!VG_(is_kerror)(res)) {
381 /* Copied from munmap() wrapper. */
382 Addr start = arg1;
383 Addr length = arg2;
384 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
385 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
386 make_noaccess( start, length );
387 VG_(symtab_notify_munmap) ( start, length );
388 approximate_mmap_permissions( (Addr)res, arg3, arg4 );
389 }
390 break;
391# endif
392
sewardj73f1f072002-03-29 14:22:46 +0000393 case __NR_nice: /* syscall 34 */
394 /* int nice(int inc); */
395 if (VG_(clo_trace_syscalls))
396 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000397 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000398 break;
399
sewardjde4a1d02002-03-22 01:27:54 +0000400 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
401
sewardjd7f07662002-03-24 10:49:46 +0000402# if defined(__NR_setresgid32)
403 case __NR_setresgid32: /* syscall 210 */
404 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
405 if (VG_(clo_trace_syscalls))
406 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000407 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000408 break;
409# endif
410
sewardjde4a1d02002-03-22 01:27:54 +0000411# if defined(__NR_setfsuid32)
412 case __NR_setfsuid32: /* syscall 215 */
413 /* int setfsuid(uid_t fsuid); */
414 if (VG_(clo_trace_syscalls))
415 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000416 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000417 break;
418# endif
419
420# if defined(__NR__sysctl)
421 case __NR__sysctl:
422 /* int _sysctl(struct __sysctl_args *args); */
423 if (VG_(clo_trace_syscalls))
424 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000425 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000426 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000427 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000428 if (!VG_(is_kerror)(res))
429 make_readable ( arg1, sizeof(struct __sysctl_args) );
430 break;
431# endif
432
433# if defined(__NR_sched_getscheduler)
434 case __NR_sched_getscheduler:
435 /* int sched_getscheduler(pid_t pid); */
436 if (VG_(clo_trace_syscalls))
437 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000438 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000439 break;
440# endif
441
442# if defined(__NR_sched_setscheduler)
443 case __NR_sched_setscheduler:
444 /* int sched_setscheduler(pid_t pid, int policy,
445 const struct sched_param *p); */
446 if (VG_(clo_trace_syscalls))
447 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
448 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000449 must_be_readable( tst,
450 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000451 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000452 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000453 break;
454# endif
455
456# if defined(__NR_mlockall)
457 case __NR_mlockall:
458 /* int mlockall(int flags); */
459 if (VG_(clo_trace_syscalls))
460 VG_(printf)("mlockall ( %x )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000461 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000462 break;
463# endif
464
465# if defined(__NR_munlockall)
466 case __NR_munlockall:
467 /* int munlockall(void); */
468 if (VG_(clo_trace_syscalls))
469 VG_(printf)("munlockall ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000470 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000471 break;
472# endif
473
474#if defined(__NR_sched_get_priority_max)
475 case __NR_sched_get_priority_max:
476 /* int sched_get_priority_max(int policy); */
477 if (VG_(clo_trace_syscalls))
478 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000479 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000480 break;
481# endif
482
sewardj9dfb4a72002-04-27 01:56:30 +0000483#if defined(__NR_sched_get_priority_min)
484 case __NR_sched_get_priority_min: /* syscall 160 */
485 /* int sched_get_priority_min(int policy); */
486 if (VG_(clo_trace_syscalls))
487 VG_(printf)("sched_get_priority_min ( %d )\n", arg1);
488 KERNEL_DO_SYSCALL(tid,res);
489 break;
490# endif
491
492#if defined(__NR_setpriority)
493 case __NR_setpriority: /* syscall 97 */
494 /* int setpriority(int which, int who, int prio); */
495 if (VG_(clo_trace_syscalls))
496 VG_(printf)("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
497 KERNEL_DO_SYSCALL(tid,res);
498 break;
499# endif
500
sewardjde4a1d02002-03-22 01:27:54 +0000501# if defined(__NR_setfsgid)
502 case __NR_setfsgid: /* syscall 139 */
503 /* int setfsgid(gid_t gid); */
504 if (VG_(clo_trace_syscalls))
505 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000506 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000507 break;
508# endif
509
510# if defined(__NR_setregid)
511 case __NR_setregid: /* syscall 71 */
512 /* int setregid(gid_t rgid, gid_t egid); */
513 if (VG_(clo_trace_syscalls))
514 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +0000515 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000516 break;
517# endif
518
519# if defined(__NR_setresuid)
520 case __NR_setresuid: /* syscall 164 */
521 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
522 if (VG_(clo_trace_syscalls))
523 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000524 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000525 break;
526# endif
527
528# if defined(__NR_setfsuid)
529 case __NR_setfsuid: /* syscall 138 */
530 /* int setfsuid(uid_t uid); */
531 if (VG_(clo_trace_syscalls))
532 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000533 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000534 break;
535# endif
536
537 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
538
539# if defined(__NR_sendfile)
540 case __NR_sendfile: /* syscall 187 */
541 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
542 size_t count) */
543 if (VG_(clo_trace_syscalls))
544 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000545 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000546 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000547 if (!VG_(is_kerror)(res)) {
548 make_readable( arg3, sizeof( off_t ) );
549 }
550 break;
551# endif
552
553 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
554
555# if defined(__NR_pwrite)
556 case __NR_pwrite: /* syscall 181 */
557 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
558 off_t offset); */
559 if (VG_(clo_trace_syscalls))
560 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000561 must_be_readable( tst, "pwrite(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000562 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000563 break;
564# endif
565
566 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
567
568 case __NR_sync: /* syscall 36 */
569 /* int sync(); */
570 if (VG_(clo_trace_syscalls))
571 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000572 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000573 break;
574
575 case __NR_fstatfs: /* syscall 100 */
576 /* int fstatfs(int fd, struct statfs *buf); */
577 if (VG_(clo_trace_syscalls))
578 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000579 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000580 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000581 if (!VG_(is_kerror)(res))
582 make_readable( arg2, sizeof(struct statfs) );
583 break;
584
585 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
586
587 case __NR_pause: /* syscall 29 */
588 /* int pause(void); */
589 if (VG_(clo_trace_syscalls))
590 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000591 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000592 break;
593
594 case __NR_getsid: /* syscall 147 */
595 /* pid_t getsid(pid_t pid); */
596 if (VG_(clo_trace_syscalls))
597 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000598 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000599 break;
600
601# if defined(__NR_pread)
602 case __NR_pread: /* syscall 180 */
603 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
604 if (VG_(clo_trace_syscalls))
605 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000606 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000607 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000608 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000609 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
610 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000611 arg1, arg2, arg3, arg4, res);
612 if (!VG_(is_kerror)(res) && res > 0) {
613 make_readable( arg2, res );
614 }
615 break;
616# endif
617
618 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
619
620 case __NR_mknod: /* syscall 14 */
621 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
622 if (VG_(clo_trace_syscalls))
623 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000624 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000625 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000626 break;
627
628 case __NR_flock: /* syscall 143 */
629 /* int flock(int fd, int operation); */
630 if (VG_(clo_trace_syscalls))
631 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000632 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000633 break;
634
635# if defined(__NR_rt_sigsuspend)
636 /* Viewed with great suspicion by me, but, hey, let's do it
637 anyway ... */
638 case __NR_rt_sigsuspend: /* syscall 179 */
639 /* int sigsuspend(const sigset_t *mask); */
640 if (VG_(clo_trace_syscalls))
641 VG_(printf)("sigsuspend ( %p )\n", arg1 );
642 if (arg1 != (Addr)NULL) {
643 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000644 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000645 sizeof(vki_ksigset_t) );
646 }
sewardj2e93c502002-04-12 11:12:52 +0000647 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000648 break;
649# endif
650
651 case __NR_init_module: /* syscall 128 */
652 /* int init_module(const char *name, struct module *image); */
653 if (VG_(clo_trace_syscalls))
654 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000655 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
656 must_be_readable( tst, "init_module(image)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000657 sizeof(struct module) );
sewardj2e93c502002-04-12 11:12:52 +0000658 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000659 break;
660
661 case __NR_ioperm: /* syscall 101 */
662 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
663 if (VG_(clo_trace_syscalls))
664 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000665 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000666 break;
667
668 case __NR_capget: /* syscall 184 */
669 /* int capget(cap_user_header_t header, cap_user_data_t data); */
670 if (VG_(clo_trace_syscalls))
671 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000672 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000673 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000674 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000675 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000676 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000677 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
678 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
679 break;
680
681 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
682
683 case __NR_execve:
684 /* int execve (const char *filename,
685 char *const argv [],
686 char *const envp[]); */
687 if (VG_(clo_trace_syscalls))
688 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
689 arg1, arg1, arg2, arg3);
690 /* Make any binding for LD_PRELOAD disappear, so that child
691 processes don't get traced into. */
692 if (!VG_(clo_trace_children)) {
693 Int i;
694 Char** envp = (Char**)arg3;
695 for (i = 0; envp[i] != NULL; i++) {
696 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) {
697 VG_(mash_LD_PRELOAD_string)(&envp[i][11]);
698 }
699 }
700 }
sewardj2e93c502002-04-12 11:12:52 +0000701 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000702 /* Should we still be alive here? Don't think so. */
703 /* Actually, above comment is wrong. execve can fail, just
704 like any other syscall -- typically the file to exec does
705 not exist. Hence: */
706 vg_assert(VG_(is_kerror)(res));
707 break;
708
709 case __NR_exit: /* syscall 1 */
710 /* void _exit(int status); */
711 if (VG_(clo_trace_syscalls))
712 VG_(printf)("exit ( %d )\n", arg1);
713 VG_(message)(Vg_UserMsg,
714 "Warning: client exiting by calling exit(%d). Bye!",
715 arg1);
716
sewardj2e93c502002-04-12 11:12:52 +0000717 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000718 /* Definitely should not be alive here :) */
719 break;
720
721 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
722
723 case __NR_access: /* syscall 33 */
724 /* int access(const char *pathname, int mode); */
725 if (VG_(clo_trace_syscalls))
726 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000727 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000728 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000729 break;
730
731 case __NR_alarm: /* syscall 27 */
732 /* unsigned int alarm(unsigned int seconds); */
733 if (VG_(clo_trace_syscalls))
734 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000735 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000736 break;
737
738 case __NR_brk: /* syscall 45 */
739 /* Haven't a clue if this is really right. */
740 /* int brk(void *end_data_segment); */
741 if (VG_(clo_trace_syscalls))
742 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000743 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000744 if (VG_(clo_trace_syscalls))
745 VG_(printf)("0x%x\n", res);
746
747 if (!VG_(is_kerror)(res)) {
748 if (arg1 == 0) {
749 /* Just asking where the current end is. (???) */
750 VGM_(curr_dataseg_end) = res;
751 } else
752 if (arg1 < VGM_(curr_dataseg_end)) {
753 /* shrinking the data segment. */
754 make_noaccess( (Addr)arg1,
755 VGM_(curr_dataseg_end)-arg1 );
756 VGM_(curr_dataseg_end) = arg1;
757 } else
758 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
759 /* asked for more memory, and got it */
760 /*
761 VG_(printf)("BRK: new area %x .. %x\n",
762 VGM_(curr_dataseg_end, arg1-1 );
763 */
764 make_writable ( (Addr)VGM_(curr_dataseg_end),
765 arg1-VGM_(curr_dataseg_end) );
766 VGM_(curr_dataseg_end) = arg1;
767 }
768 }
769 break;
770
771 case __NR_chdir: /* syscall 12 */
772 /* int chdir(const char *path); */
773 if (VG_(clo_trace_syscalls))
774 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +0000775 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000776 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000777 break;
778
779 case __NR_chmod: /* syscall 15 */
780 /* int chmod(const char *path, mode_t mode); */
781 if (VG_(clo_trace_syscalls))
782 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000783 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000784 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000785 break;
786
787# if defined(__NR_chown32)
788 case __NR_chown32: /* syscall 212 */
789# endif
790# if defined(__NR_lchown32)
791 case __NR_lchown32: /* syscall 198 */
792# endif
793 case __NR_chown: /* syscall 16 */
794 /* int chown(const char *path, uid_t owner, gid_t group); */
795 if (VG_(clo_trace_syscalls))
796 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000797 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000798 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000799 break;
800
801 case __NR_close: /* syscall 6 */
802 /* int close(int fd); */
803 if (VG_(clo_trace_syscalls))
804 VG_(printf)("close ( %d )\n",arg1);
805 /* Detect and negate attempts by the client to close Valgrind's
806 logfile fd ... */
807 if (arg1 == VG_(clo_logfile_fd)) {
808 VG_(message)(Vg_UserMsg,
809 "Warning: client attempted to close "
810 "Valgrind's logfile fd (%d).",
811 VG_(clo_logfile_fd));
812 VG_(message)(Vg_UserMsg,
813 " Use --logfile-fd=<number> to select an "
814 "alternative logfile fd." );
815 } else {
sewardj2e93c502002-04-12 11:12:52 +0000816 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000817 }
818 break;
819
820 case __NR_dup: /* syscall 41 */
821 /* int dup(int oldfd); */
822 if (VG_(clo_trace_syscalls))
823 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000824 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000825 if (VG_(clo_trace_syscalls))
826 VG_(printf)("%d\n", res);
827 break;
828
829 case __NR_dup2: /* syscall 63 */
830 /* int dup2(int oldfd, int newfd); */
831 if (VG_(clo_trace_syscalls))
832 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000833 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000834 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000835 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
836 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000837 arg1, arg2, res);
838 break;
839
840 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +0000841 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +0000842 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000843 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
844 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000845 break;
846
847 case __NR_fchdir: /* syscall 133 */
848 /* int fchdir(int fd); */
849 if (VG_(clo_trace_syscalls))
850 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000851 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000852 break;
853
sewardj2f0de322002-03-24 10:17:25 +0000854# if defined(__NR_fchown32)
855 case __NR_fchown32: /* syscall 207 */
856# endif
857 case __NR_fchown: /* syscall 95 */
858 /* int fchown(int filedes, uid_t owner, gid_t group); */
859 if (VG_(clo_trace_syscalls))
860 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +0000861 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +0000862 break;
863
sewardjde4a1d02002-03-22 01:27:54 +0000864 case __NR_fchmod: /* syscall 94 */
865 /* int fchmod(int fildes, mode_t mode); */
866 if (VG_(clo_trace_syscalls))
867 VG_(printf)("fchmod ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000868 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000869 break;
sewardj2f0de322002-03-24 10:17:25 +0000870
sewardjde4a1d02002-03-22 01:27:54 +0000871# if defined(__NR_fcntl64)
872 case __NR_fcntl64: /* syscall 221 */
873 /* I don't know what the prototype for this is supposed to be. */
874 /* ??? int fcntl(int fd, int cmd); */
875 if (VG_(clo_trace_syscalls))
876 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000877 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000878 break;
879# endif
880
881 case __NR_fstat: /* syscall 108 */
882 /* int fstat(int filedes, struct stat *buf); */
883 if (VG_(clo_trace_syscalls))
884 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000885 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +0000886 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000887 if (!VG_(is_kerror)(res))
888 make_readable( arg2, sizeof(struct stat) );
889 break;
890
891 case __NR_vfork: /* syscall 190 */
892 /* pid_t vfork(void); */
893 if (VG_(clo_trace_syscalls))
894 VG_(printf)("vfork ( ) ... becomes ... ");
895 /* KLUDGE: we prefer to do a fork rather than vfork.
896 vfork gives a SIGSEGV, and the stated semantics looks
897 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +0000898 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +0000899 /* fall through ... */
900 case __NR_fork: /* syscall 2 */
901 /* pid_t fork(void); */
902 if (VG_(clo_trace_syscalls))
903 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000904 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000905 break;
906
907 case __NR_fsync: /* syscall 118 */
908 /* int fsync(int fd); */
909 if (VG_(clo_trace_syscalls))
910 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000911 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000912 break;
913
914 case __NR_ftruncate: /* syscall 93 */
915 /* int ftruncate(int fd, size_t length); */
916 if (VG_(clo_trace_syscalls))
917 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000918 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000919 break;
920
sewardj2f0de322002-03-24 10:17:25 +0000921# if defined(__NR_ftruncate64)
922 case __NR_ftruncate64: /* syscall 194 */
923 /* int ftruncate64(int fd, off64_t length); */
924 if (VG_(clo_trace_syscalls))
925 VG_(printf)("ftruncate64 ( %d, %lld )\n",
926 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +0000927 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000928 break;
929# endif
930
931 case __NR_getdents: /* syscall 141 */
932 /* int getdents(unsigned int fd, struct dirent *dirp,
933 unsigned int count); */
934 if (VG_(clo_trace_syscalls))
935 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000936 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000937 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000938 if (!VG_(is_kerror)(res) && res > 0)
939 make_readable( arg2, res );
940 break;
941
942# if defined(__NR_getdents64)
943 case __NR_getdents64: /* syscall 220 */
944 /* int getdents(unsigned int fd, struct dirent64 *dirp,
945 unsigned int count); */
946 if (VG_(clo_trace_syscalls))
947 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000948 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000949 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000950 if (!VG_(is_kerror)(res) && res > 0)
951 make_readable( arg2, res );
952 break;
953# endif
954
955# if defined(__NR_getgroups32)
956 case __NR_getgroups32: /* syscall 205 */
957# endif
958 case __NR_getgroups: /* syscall 80 */
959 /* int getgroups(int size, gid_t list[]); */
960 if (VG_(clo_trace_syscalls))
961 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
962 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +0000963 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000964 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +0000965 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000966 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
967 make_readable ( arg2, res * sizeof(gid_t) );
968 break;
969
970 case __NR_getcwd: /* syscall 183 */
971 /* char *getcwd(char *buf, size_t size); */
972 if (VG_(clo_trace_syscalls))
973 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000974 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000975 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000976 if (!VG_(is_kerror)(res) && res != (Addr)NULL)
977 make_readable ( arg1, arg2 );
978 /* Not really right -- really we should have the asciiz
979 string starting at arg1 readable, or up to arg2 bytes,
980 whichever finishes first. */
981 break;
982
983 case __NR_geteuid: /* syscall 49 */
984 /* uid_t geteuid(void); */
985 if (VG_(clo_trace_syscalls))
986 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000987 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000988 break;
989
990# if defined(__NR_geteuid32)
991 case __NR_geteuid32: /* syscall 201 */
992 /* ?? uid_t geteuid32(void); */
993 if (VG_(clo_trace_syscalls))
994 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000995 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000996 break;
997# endif
998
999 case __NR_getegid: /* syscall 50 */
1000 /* gid_t getegid(void); */
1001 if (VG_(clo_trace_syscalls))
1002 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001003 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001004 break;
1005
1006# if defined(__NR_getegid32)
1007 case __NR_getegid32: /* syscall 202 */
1008 /* gid_t getegid32(void); */
1009 if (VG_(clo_trace_syscalls))
1010 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001011 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001012 break;
1013# endif
1014
1015 case __NR_getgid: /* syscall 47 */
1016 /* gid_t getgid(void); */
1017 if (VG_(clo_trace_syscalls))
1018 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001019 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001020 break;
1021
1022# if defined(__NR_getgid32)
1023 case __NR_getgid32: /* syscall 200 */
1024 /* gid_t getgid32(void); */
1025 if (VG_(clo_trace_syscalls))
1026 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001027 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001028 break;
1029# endif
1030
1031 case __NR_getpid: /* syscall 20 */
1032 /* pid_t getpid(void); */
1033 if (VG_(clo_trace_syscalls))
1034 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001035 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001036 break;
1037
1038 case __NR_getpgid: /* syscall 132 */
1039 /* pid_t getpgid(pid_t pid); */
1040 if (VG_(clo_trace_syscalls))
1041 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001042 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001043 break;
1044
1045 case __NR_getpgrp: /* syscall 65 */
1046 /* pid_t getpprp(void); */
1047 if (VG_(clo_trace_syscalls))
1048 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001049 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001050 break;
1051
1052 case __NR_getppid: /* syscall 64 */
1053 /* pid_t getppid(void); */
1054 if (VG_(clo_trace_syscalls))
1055 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001056 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001057 break;
1058
1059 case __NR_getresgid: /* syscall 171 */
1060 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1061 if (VG_(clo_trace_syscalls))
1062 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001063 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1064 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1065 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001066 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001067 if (!VG_(is_kerror)(res) && res == 0) {
1068 make_readable ( arg1, sizeof(gid_t) );
1069 make_readable ( arg2, sizeof(gid_t) );
1070 make_readable ( arg3, sizeof(gid_t) );
1071 }
1072 break;
1073
1074# if defined(__NR_getresgid32)
1075 case __NR_getresgid32: /* syscall 211 */
1076 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1077 if (VG_(clo_trace_syscalls))
1078 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001079 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1080 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1081 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001082 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001083 if (!VG_(is_kerror)(res) && res == 0) {
1084 make_readable ( arg1, sizeof(gid_t) );
1085 make_readable ( arg2, sizeof(gid_t) );
1086 make_readable ( arg3, sizeof(gid_t) );
1087 }
1088 break;
1089# endif
1090
1091 case __NR_getresuid: /* syscall 165 */
1092 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1093 if (VG_(clo_trace_syscalls))
1094 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001095 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1096 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1097 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001098 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001099 if (!VG_(is_kerror)(res) && res == 0) {
1100 make_readable ( arg1, sizeof(uid_t) );
1101 make_readable ( arg2, sizeof(uid_t) );
1102 make_readable ( arg3, sizeof(uid_t) );
1103 }
1104 break;
1105
1106# if defined(__NR_getresuid32)
1107 case __NR_getresuid32: /* syscall 209 */
1108 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1109 if (VG_(clo_trace_syscalls))
1110 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001111 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1112 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1113 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001114 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001115 if (!VG_(is_kerror)(res) && res == 0) {
1116 make_readable ( arg1, sizeof(uid_t) );
1117 make_readable ( arg2, sizeof(uid_t) );
1118 make_readable ( arg3, sizeof(uid_t) );
1119 }
1120 break;
1121# endif
1122
1123# if defined(__NR_ugetrlimit)
1124 case __NR_ugetrlimit: /* syscall 191 */
1125# endif
1126 case __NR_getrlimit: /* syscall 76 */
1127 /* int getrlimit (int resource, struct rlimit *rlim); */
1128 if (VG_(clo_trace_syscalls))
1129 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001130 must_be_writable( tst, "getrlimit(rlim)", arg2,
1131 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001132 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001133 if (!VG_(is_kerror)(res) && res == 0)
1134 make_readable( arg2, sizeof(struct rlimit) );
1135 break;
1136
1137 case __NR_getrusage: /* syscall 77 */
1138 /* int getrusage (int who, struct rusage *usage); */
1139 if (VG_(clo_trace_syscalls))
1140 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001141 must_be_writable( tst, "getrusage(usage)", arg2,
1142 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001143 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001144 if (!VG_(is_kerror)(res) && res == 0)
1145 make_readable(arg2, sizeof(struct rusage) );
1146 break;
1147
1148 case __NR_gettimeofday: /* syscall 78 */
1149 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1150 if (VG_(clo_trace_syscalls))
1151 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001152 must_be_writable( tst, "gettimeofday(tv)", arg1,
1153 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001154 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001155 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001156 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001157 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001158 if (!VG_(is_kerror)(res) && res == 0) {
1159 make_readable( arg1, sizeof(struct timeval) );
1160 if (arg2 != 0)
1161 make_readable( arg2, sizeof(struct timezone) );
1162 }
1163 break;
1164
1165 case __NR_getuid: /* syscall 24 */
1166 /* uid_t getuid(void); */
1167 if (VG_(clo_trace_syscalls))
1168 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001169 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001170 break;
1171
1172# if defined(__NR_getuid32)
1173 case __NR_getuid32: /* syscall 199 */
1174 /* ???uid_t getuid32(void); */
1175 if (VG_(clo_trace_syscalls))
1176 VG_(printf)("getuid32 ( )\n");
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_ipc: /* syscall 117 */
1182 /* int ipc ( unsigned int call, int first, int second,
1183 int third, void *ptr, long fifth); */
1184 {
sewardj2e93c502002-04-12 11:12:52 +00001185 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001186
1187 if (VG_(clo_trace_syscalls))
1188 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1189 arg1,arg2,arg3,arg4,arg5,arg6);
1190 switch (arg1 /* call */) {
1191 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001192 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001193 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001194 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001195 break;
sewardj5b9e3502002-03-29 04:35:08 +00001196 case 2: /* IPCOP_semget */
1197 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001198 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001199 break;
1200 case 11: /* IPCOP_msgsnd */
1201 {
1202 struct msgbuf *msgp = (struct msgbuf *)arg5;
1203 Int msgsz = arg3;
1204
sewardj8c824512002-04-14 04:16:48 +00001205 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001206 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001207 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001208 (UInt)msgp->mtext, msgsz );
1209
sewardj2e93c502002-04-12 11:12:52 +00001210 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001211 break;
1212 }
1213 case 12: /* IPCOP_msgrcv */
1214 {
sewardj59c255c2002-04-27 02:06:15 +00001215 struct msgbuf *msgp;
sewardj5b9e3502002-03-29 04:35:08 +00001216 Int msgsz = arg3;
sewardj59c255c2002-04-27 02:06:15 +00001217
1218 msgp = (struct msgbuf *)safe_dereference(
1219 (Addr) (&((struct ipc_kludge *)arg5)->msgp), 0 );
sewardj5b9e3502002-03-29 04:35:08 +00001220
sewardj59c255c2002-04-27 02:06:15 +00001221 must_be_writable ( tst, "msgrcv(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001222 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj59c255c2002-04-27 02:06:15 +00001223 must_be_writable ( tst, "msgrcv(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001224 (UInt)msgp->mtext, msgsz );
1225
sewardj2e93c502002-04-12 11:12:52 +00001226 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001227
1228 if ( !VG_(is_kerror)(res) && res > 0 ) {
1229 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1230 make_readable ( (UInt)msgp->mtext, res );
1231 }
1232 break;
1233 }
1234 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001235 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001236 break;
1237 case 14: /* IPCOP_msgctl */
1238 {
1239 switch (arg3 /* cmd */) {
1240 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001241 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001242 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001243 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001244 if ( !VG_(is_kerror)(res) && res > 0 ) {
1245 make_readable ( arg5, sizeof(struct msqid_ds) );
1246 }
1247 break;
1248 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001249 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001250 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001251 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001252 break;
sewardjc9add3b2002-04-16 01:58:19 +00001253# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001254 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001255 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001256 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001257 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001258 if ( !VG_(is_kerror)(res) && res > 0 ) {
1259 make_readable ( arg5, sizeof(struct msqid64_ds) );
1260 }
1261 break;
sewardjc9add3b2002-04-16 01:58:19 +00001262# endif
1263# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001264 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001265 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001266 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001267 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001268 break;
sewardjc9add3b2002-04-16 01:58:19 +00001269# endif
sewardj5b9e3502002-03-29 04:35:08 +00001270 default:
sewardj2e93c502002-04-12 11:12:52 +00001271 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001272 break;
1273 }
1274 break;
1275 }
sewardjde4a1d02002-03-22 01:27:54 +00001276 case 21: /* IPCOP_shmat */
1277 {
1278 Int shmid = arg2;
1279 Int shmflag = arg3;
1280 UInt addr;
1281
sewardj2e93c502002-04-12 11:12:52 +00001282 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001283
1284 if ( VG_(is_kerror) ( res ) )
1285 break;
1286
1287 /* force readability. before the syscall it is
1288 * indeed uninitialized, as can be seen in
1289 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1290 make_readable ( arg4, sizeof( ULong ) );
1291
1292 addr = safe_dereference ( arg4, 0 );
1293 if ( addr > 0 ) {
1294 UInt segmentSize = get_shm_size ( shmid );
1295 if ( segmentSize > 0 ) {
1296 if ( shmflag & SHM_RDONLY )
1297 make_readable ( addr, segmentSize );
1298 else
1299 make_readwritable ( addr, segmentSize );
1300 }
1301 }
1302 break;
1303 }
1304 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001305 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001306 /* ### FIXME: this should call make_noaccess on the
1307 * area passed to shmdt. But there's no way to
1308 * figure out the size of the shared memory segment
1309 * just from the address... Maybe we want to keep a
1310 * copy of the exiting mappings inside valgrind? */
1311 break;
1312 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001313 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001314 break;
1315 case 24: /* IPCOP_shmctl */
1316 {
1317 if ( arg3 > 0 ) {
sewardj8c824512002-04-14 04:16:48 +00001318 must_be_readable ( tst, "shmctl(buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001319 sizeof( struct shmid_ds ) );
1320
1321 if ( arg2 == SHM_STAT )
sewardj8c824512002-04-14 04:16:48 +00001322 must_be_writable( tst, "shmctl(IPC_STAT,buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001323 sizeof( struct shmid_ds ) );
1324 }
1325
sewardj2e93c502002-04-12 11:12:52 +00001326 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001327 break;
1328 }
1329 default:
1330 VG_(message)(Vg_DebugMsg,
1331 "FATAL: unhandled syscall(ipc) %d",
1332 arg1 );
1333 VG_(panic)("... bye!\n");
1334 break; /*NOTREACHED*/
1335 }
1336 }
1337 break;
1338
1339 case __NR_ioctl: /* syscall 54 */
1340 /* int ioctl(int d, int request, ...)
1341 [The "third" argument is traditionally char *argp,
1342 and will be so named for this discussion.]
1343 */
1344 /*
1345 VG_(message)(
1346 Vg_DebugMsg,
1347 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1348 arg2,arg1,arg3);
1349 */
1350 if (VG_(clo_trace_syscalls))
1351 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1352 switch (arg2 /* request */) {
1353 case TCSETS:
1354 case TCSETSW:
1355 case TCSETSF:
sewardj8c824512002-04-14 04:16:48 +00001356 must_be_readable( tst, "ioctl(TCSETSW)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001357 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001358 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001359 break;
1360 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001361 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001362 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001363 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001364 if (!VG_(is_kerror)(res) && res == 0)
1365 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1366 break;
sewardj2f0de322002-03-24 10:17:25 +00001367 case TCSETA:
sewardj8c824512002-04-14 04:16:48 +00001368 must_be_readable( tst, "ioctl(TCSETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001369 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001370 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001371 break;
1372 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001373 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001374 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001375 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001376 if (!VG_(is_kerror)(res) && res == 0)
1377 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1378 break;
sewardjde4a1d02002-03-22 01:27:54 +00001379 case TCSBRK:
1380 case TCSBRKP:
1381 case TCFLSH:
1382 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001383 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001384 break;
1385 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001386 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001387 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001388 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001389 if (!VG_(is_kerror)(res) && res == 0)
1390 make_readable ( arg3, sizeof(struct winsize) );
1391 break;
1392 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001393 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001394 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001395 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001396 break;
sewardj19fe3d02002-03-29 04:39:00 +00001397 case TIOCGPGRP:
1398 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001399 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001400 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001401 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001402 if (!VG_(is_kerror)(res) && res == 0)
1403 make_readable ( arg3, sizeof(pid_t) );
sewardjde4a1d02002-03-22 01:27:54 +00001404 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001405 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001406 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001407 if (!VG_(is_kerror)(res) && res == 0)
1408 make_readable ( arg3, sizeof(int));
1409 break;
sewardj73f1f072002-03-29 14:22:46 +00001410 case TIOCSCTTY:
1411 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001412 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001413 break;
sewardjde4a1d02002-03-22 01:27:54 +00001414 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001415 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001416 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001417 break;
1418 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001419 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001420 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001421 break;
1422 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001423 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001424 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001425 break;
1426 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001427 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001428 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001429 if (!VG_(is_kerror)(res) && res == 0)
1430 make_readable( arg3, sizeof(int) );
1431 break;
1432
1433 /* If you get compilation problems here, change the #if
1434 1 to #if 0 and get rid of <scsi/sg.h> in
1435 vg_unsafe.h. */
1436# if 1
1437 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001438 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1439 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001440 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001441 break;
1442# if defined(SG_IO)
1443 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001444 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001445 sizeof(struct sg_io_hdr) );
sewardj2e93c502002-04-12 11:12:52 +00001446 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001447 if (!VG_(is_kerror)(res) && res == 0)
1448 make_readable (arg3, sizeof(struct sg_io_hdr));
1449 break;
1450# endif /* SG_IO */
1451 case SG_GET_SCSI_ID:
1452 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001453 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001454 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001455 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001456 if (!VG_(is_kerror)(res) && res == 0)
1457 make_readable (arg3, sizeof(struct sg_scsi_id));
1458 break;
1459 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001460 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001461 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001462 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001463 break;
1464 case SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001465 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1466 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001467 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001468 break;
1469 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001470 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001471 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001472 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001473 if (!VG_(is_kerror)(res) && res == 0)
1474 make_readable (arg3, sizeof(int));
1475 break;
1476 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001477 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1478 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001479 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001480 if (!VG_(is_kerror)(res) && res == 0)
1481 make_readable (arg3, sizeof(int));
1482 break;
1483 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001484 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001485 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001486 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001487 break;
1488# endif
1489
1490 case IIOCGETCPS:
1491 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1492 * when KERNEL was. I never saw a larger value than 64 though */
1493# ifndef ISDN_MAX_CHANNELS
1494# define ISDN_MAX_CHANNELS 64
1495# endif
sewardj8c824512002-04-14 04:16:48 +00001496 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001497 ISDN_MAX_CHANNELS
1498 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001499 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001500 if (!VG_(is_kerror)(res) && res == 0)
1501 make_readable ( arg3, ISDN_MAX_CHANNELS
1502 * 2 * sizeof(unsigned long) );
1503 break;
1504 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001505 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001506 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1507 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001508 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001509 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001510 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001511 if (!VG_(is_kerror)(res) && res == 0)
1512 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1513 break;
1514
1515 /* These all use struct ifreq AFAIK */
1516 case SIOCGIFINDEX:
1517 case SIOCGIFFLAGS: /* get flags */
1518 case SIOCGIFHWADDR: /* Get hardware address */
1519 case SIOCGIFMTU: /* get MTU size */
1520 case SIOCGIFADDR: /* get PA address */
1521 case SIOCGIFNETMASK: /* get network PA mask */
1522 case SIOCGIFMETRIC: /* get metric */
1523 case SIOCGIFMAP: /* Get device parameters */
1524 case SIOCGIFTXQLEN: /* Get the tx queue length */
1525 case SIOCGIFDSTADDR: /* get remote PA address */
1526 case SIOCGIFBRDADDR: /* get broadcast PA address */
1527 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001528 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001529 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001530 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001531 if (!VG_(is_kerror)(res) && res == 0)
1532 make_readable (arg3, sizeof(struct ifreq));
1533 break;
1534 case SIOCGIFCONF: /* get iface list */
1535 /* WAS:
1536 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1537 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001538 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001539 if (!VG_(is_kerror)(res) && res == 0)
1540 make_readable (arg3, sizeof(struct ifconf));
1541 */
sewardj8c824512002-04-14 04:16:48 +00001542 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001543 sizeof(struct ifconf));
1544 if ( arg3 ) {
1545 // TODO len must be readable and writable
1546 // buf pointer only needs to be readable
1547 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001548 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001549 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1550 }
sewardj2e93c502002-04-12 11:12:52 +00001551 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001552 if (!VG_(is_kerror)(res) && res == 0 && arg3 ) {
1553 struct ifconf *ifc = (struct ifconf *) arg3;
1554 make_readable ( (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1555 }
1556 break;
1557 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001558 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001559 sizeof(struct timeval));
sewardj2e93c502002-04-12 11:12:52 +00001560 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001561 if (!VG_(is_kerror)(res) && res == 0)
1562 make_readable (arg3, sizeof(struct timeval));
1563 break;
1564 case SIOCGRARP: /* get RARP table entry */
1565 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001566 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001567 sizeof(struct arpreq));
sewardj2e93c502002-04-12 11:12:52 +00001568 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001569 if (!VG_(is_kerror)(res) && res == 0)
1570 make_readable (arg3, sizeof(struct arpreq));
1571 break;
1572
1573 case SIOCSIFFLAGS: /* set flags */
1574 case SIOCSIFMAP: /* Set device parameters */
1575 case SIOCSIFTXQLEN: /* Set the tx queue length */
1576 case SIOCSIFDSTADDR: /* set remote PA address */
1577 case SIOCSIFBRDADDR: /* set broadcast PA address */
1578 case SIOCSIFNETMASK: /* set network PA mask */
1579 case SIOCSIFMETRIC: /* set metric */
1580 case SIOCSIFADDR: /* set PA address */
1581 case SIOCSIFMTU: /* set MTU size */
1582 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001583 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001584 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001585 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001586 break;
1587 /* Routing table calls. */
1588 case SIOCADDRT: /* add routing table entry */
1589 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001590 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001591 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001592 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001593 break;
1594
1595 /* RARP cache control calls. */
1596 case SIOCDRARP: /* delete RARP table entry */
1597 case SIOCSRARP: /* set RARP table entry */
1598 /* ARP cache control calls. */
1599 case SIOCSARP: /* set ARP table entry */
1600 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001601 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001602 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001603 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001604 break;
1605
1606 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001607 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001608 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001609 break;
1610
1611 /* linux/soundcard interface (OSS) */
1612 case SNDCTL_SEQ_GETOUTCOUNT:
1613 case SNDCTL_SEQ_GETINCOUNT:
1614 case SNDCTL_SEQ_PERCMODE:
1615 case SNDCTL_SEQ_TESTMIDI:
1616 case SNDCTL_SEQ_RESETSAMPLES:
1617 case SNDCTL_SEQ_NRSYNTHS:
1618 case SNDCTL_SEQ_NRMIDIS:
1619 case SNDCTL_SEQ_GETTIME:
1620 case SNDCTL_DSP_GETFMTS:
1621 case SNDCTL_DSP_GETTRIGGER:
1622 case SNDCTL_DSP_GETODELAY:
1623# if defined(SNDCTL_DSP_GETSPDIF)
1624 case SNDCTL_DSP_GETSPDIF:
1625# endif
1626 case SNDCTL_DSP_GETCAPS:
1627 case SOUND_PCM_READ_RATE:
1628 case SOUND_PCM_READ_CHANNELS:
1629 case SOUND_PCM_READ_BITS:
1630 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1631 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001632 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1633 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001634 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001635 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001636 if (!VG_(is_kerror)(res) && res == 0)
1637 make_readable (arg3, sizeof(int));
1638 break;
1639 case SNDCTL_SEQ_CTRLRATE:
1640 case SNDCTL_DSP_SPEED:
1641 case SNDCTL_DSP_STEREO:
1642 case SNDCTL_DSP_GETBLKSIZE:
1643 case SNDCTL_DSP_CHANNELS:
1644 case SOUND_PCM_WRITE_FILTER:
1645 case SNDCTL_DSP_SUBDIVIDE:
1646 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001647# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001648 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001649# endif
1650# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001651 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001652# endif
sewardjde4a1d02002-03-22 01:27:54 +00001653 case SNDCTL_TMR_TIMEBASE:
1654 case SNDCTL_TMR_TEMPO:
1655 case SNDCTL_TMR_SOURCE:
1656 case SNDCTL_MIDI_PRETIME:
1657 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001658 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1659 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001660 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001661 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1662 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001663 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001664 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001665 break;
1666 case SNDCTL_DSP_GETOSPACE:
1667 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001668 must_be_writable(tst,
1669 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001670 "(SIOR, audio_buf_info))", arg3,
1671 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001672 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001673 if (!VG_(is_kerror)(res) && res == 0)
1674 make_readable (arg3, sizeof(audio_buf_info));
1675 break;
1676 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001677 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001678 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001679 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001680 break;
1681
1682 /* We don't have any specific information on it, so
1683 try to do something reasonable based on direction and
1684 size bits. The encoding scheme is described in
1685 /usr/include/asm/ioctl.h. */
1686 default: {
1687 UInt dir = _IOC_DIR(arg2);
1688 UInt size = _IOC_SIZE(arg2);
1689 if (/* size == 0 || */ dir == _IOC_NONE) {
1690 VG_(message)(Vg_UserMsg,
1691 "Warning: noted but unhandled ioctl 0x%x"
1692 " with no size/direction hints",
1693 arg2);
1694 VG_(message)(Vg_UserMsg,
1695 " This could cause spurious value errors"
1696 " to appear.");
1697 VG_(message)(Vg_UserMsg,
1698 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
1699 " writing a proper wrapper." );
1700 } else {
1701 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001702 must_be_readable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001703 if ((dir & _IOC_WRITE) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001704 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001705 }
sewardj2e93c502002-04-12 11:12:52 +00001706 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001707 if (size > 0 && (dir & _IOC_WRITE)
1708 && !VG_(is_kerror)(res) && res == 0)
1709 make_readable (arg3, size);
1710 break;
1711 }
1712 }
1713 break;
1714
1715 case __NR_kill: /* syscall 37 */
1716 /* int kill(pid_t pid, int sig); */
1717 if (VG_(clo_trace_syscalls))
1718 VG_(printf)("kill ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001719 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001720 break;
1721
1722 case __NR_link: /* syscall 9 */
1723 /* int link(const char *oldpath, const char *newpath); */
1724 if (VG_(clo_trace_syscalls))
1725 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00001726 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
1727 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00001728 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001729 break;
1730
1731 case __NR_lseek: /* syscall 19 */
1732 /* off_t lseek(int fildes, off_t offset, int whence); */
1733 if (VG_(clo_trace_syscalls))
1734 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001735 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001736 break;
1737
1738 case __NR__llseek: /* syscall 140 */
1739 /* int _llseek(unsigned int fd, unsigned long offset_high,
1740 unsigned long offset_low,
1741 loff_t * result, unsigned int whence); */
1742 if (VG_(clo_trace_syscalls))
1743 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
1744 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00001745 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00001746 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001747 if (!VG_(is_kerror)(res) && res == 0)
1748 make_readable( arg4, sizeof(loff_t) );
1749 break;
1750
1751 case __NR_lstat: /* syscall 107 */
1752 /* int lstat(const char *file_name, struct stat *buf); */
1753 if (VG_(clo_trace_syscalls))
1754 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001755 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
1756 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001757 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001758 if (!VG_(is_kerror)(res) && res == 0) {
1759 make_readable( arg2, sizeof(struct stat) );
1760 }
1761 break;
1762
1763# if defined(__NR_lstat64)
1764 case __NR_lstat64: /* syscall 196 */
1765 /* int lstat64(const char *file_name, struct stat64 *buf); */
1766 if (VG_(clo_trace_syscalls))
1767 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001768 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
1769 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00001770 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001771 if (!VG_(is_kerror)(res) && res == 0) {
1772 make_readable( arg2, sizeof(struct stat64) );
1773 }
1774 break;
1775# endif
1776
1777 case __NR_mkdir: /* syscall 39 */
1778 /* int mkdir(const char *pathname, mode_t mode); */
1779 if (VG_(clo_trace_syscalls))
1780 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001781 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001782 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001783 break;
1784
1785# if defined(__NR_mmap2)
1786 case __NR_mmap2: /* syscall 192 */
1787 /* My impression is that this is exactly like __NR_mmap
1788 except that all 6 args are passed in regs, rather than in
1789 a memory-block. */
1790 /* void* mmap(void *start, size_t length, int prot,
1791 int flags, int fd, off_t offset);
1792 */
1793 {
sewardj2e93c502002-04-12 11:12:52 +00001794 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001795 if (VG_(clo_trace_syscalls))
1796 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
1797 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00001798 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001799 /* !!! shouldn't we also be doing the symtab loading stuff as
1800 in __NR_mmap ? */
1801 if (!VG_(is_kerror)(res))
1802 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1803 }
1804 break;
1805# endif
1806
1807 case __NR_mmap: /* syscall 90 */
1808 /* void* mmap(void *start, size_t length, int prot,
1809 int flags, int fd, off_t offset);
1810 */
1811 {
1812 Bool arg_block_readable
1813 = VG_(clo_instrument)
1814 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
1815 : True;
sewardj8c824512002-04-14 04:16:48 +00001816 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00001817 if (arg_block_readable) {
1818 UInt* arg_block = (UInt*)arg1;
1819 UInt arg6;
1820 arg1 = arg_block[0];
1821 arg2 = arg_block[1];
1822 arg3 = arg_block[2];
1823 arg4 = arg_block[3];
1824 arg5 = arg_block[4];
1825 arg6 = arg_block[5];
1826 if (VG_(clo_trace_syscalls))
1827 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
1828 arg1, arg2, arg3, arg4, arg5, arg6 );
1829 }
sewardj2e93c502002-04-12 11:12:52 +00001830 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001831 if (arg_block_readable && !VG_(is_kerror)(res))
1832 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1833 if (arg_block_readable && !VG_(is_kerror)(res)
1834 && (arg3 & PROT_EXEC)) {
1835 /* The client mmap'ed a segment with executable
1836 permissions. Tell the symbol-table loader, so that it
1837 has an opportunity to pick up more symbols if this mmap
1838 was caused by the client loading a new .so via
1839 dlopen(). This is important for debugging KDE. */
1840 VG_(read_symbols)();
1841 }
1842 }
1843
1844 break;
1845
1846 case __NR_mprotect: /* syscall 125 */
1847 /* int mprotect(const void *addr, size_t len, int prot); */
1848 /* should addr .. addr+len-1 be checked before the call? */
1849 if (VG_(clo_trace_syscalls))
1850 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001851 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001852 if (!VG_(is_kerror)(res))
1853 approximate_mmap_permissions ( arg1, arg2, arg3 );
1854 break;
1855
1856 case __NR_munmap: /* syscall 91 */
1857 /* int munmap(void *start, size_t length); */
1858 /* should start .. start+length-1 be checked before the call? */
1859 if (VG_(clo_trace_syscalls))
1860 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001861 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001862 if (!VG_(is_kerror)(res)) {
1863 /* Mash around start and length so that the area passed to
1864 make_noaccess() exactly covers an integral number of
1865 pages. If we don't do that, our idea of addressible
1866 memory diverges from that of the kernel's, which causes
1867 the leak detector to crash. */
1868 Addr start = arg1;
1869 Addr length = arg2;
1870 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
1871 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
1872 /*
1873 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
1874 arg1, arg2, start, length, (arg1!=start || arg2!=length)
1875 ? "CHANGE" : "");
1876 */
1877 make_noaccess( start, length );
1878 /* Tell our symbol table machinery about this, so that if
1879 this happens to be a .so being unloaded, the relevant
1880 symbols are removed too. */
1881 VG_(symtab_notify_munmap) ( start, length );
1882 }
1883 break;
1884
1885 case __NR_nanosleep: /* syscall 162 */
1886 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
1887 if (VG_(clo_trace_syscalls))
1888 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001889 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00001890 sizeof(struct timespec) );
1891 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00001892 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001893 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00001894 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001895 /* Somewhat bogus ... is only written by the kernel if
1896 res == -1 && errno == EINTR. */
1897 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
1898 make_readable ( arg2, sizeof(struct timespec) );
1899 break;
1900
1901 case __NR__newselect: /* syscall 142 */
1902 /* int select(int n,
1903 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1904 struct timeval *timeout);
1905 */
1906 if (VG_(clo_trace_syscalls))
1907 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
1908 arg1,arg2,arg3,arg4,arg5);
1909 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001910 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001911 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
1912 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00001913 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00001914 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
1915 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00001916 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001917 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
1918 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00001919 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00001920 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00001921 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001922 break;
1923
1924 case __NR_open: /* syscall 5 */
1925 /* int open(const char *pathname, int flags); */
1926 if (VG_(clo_trace_syscalls))
1927 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001928 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001929 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001930 if (VG_(clo_trace_syscalls))
1931 VG_(printf)("%d\n",res);
1932 break;
1933
1934 case __NR_pipe: /* syscall 42 */
1935 /* int pipe(int filedes[2]); */
1936 if (VG_(clo_trace_syscalls))
1937 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001938 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001939 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001940 if (!VG_(is_kerror)(res))
1941 make_readable ( arg1, 2*sizeof(int) );
1942 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00001943 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
1944 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001945 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
1946 break;
1947
1948 case __NR_poll: /* syscall 168 */
1949 /* struct pollfd {
1950 int fd; -- file descriptor
1951 short events; -- requested events
1952 short revents; -- returned events
1953 };
1954 int poll(struct pollfd *ufds, unsigned int nfds,
1955 int timeout)
1956 */
1957 if (VG_(clo_trace_syscalls))
1958 VG_(printf)("poll ( %d, %d, %d )\n",arg1,arg2,arg3);
1959 /* In fact some parts of this struct should be readable too.
1960 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00001961 must_be_writable( tst, "poll(ufds)",
1962 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00001963 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001964 if (!VG_(is_kerror)(res) && res > 0) {
1965 Int i;
1966 struct pollfd * arr = (struct pollfd *)arg1;
1967 for (i = 0; i < arg2; i++)
1968 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
1969 }
1970 break;
1971
sewardjde4a1d02002-03-22 01:27:54 +00001972 case __NR_readlink: /* syscall 85 */
1973 /* int readlink(const char *path, char *buf, size_t bufsiz); */
1974 if (VG_(clo_trace_syscalls))
1975 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001976 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
1977 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001978 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001979 if (!VG_(is_kerror)(res) && res > 0) {
1980 make_readable ( arg2, res );
1981 }
1982 break;
1983
1984 case __NR_readv: { /* syscall 145 */
1985 /* int readv(int fd, const struct iovec * vector, size_t count); */
1986 UInt i;
1987 struct iovec * vec;
1988 if (VG_(clo_trace_syscalls))
1989 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001990 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00001991 arg2, arg3 * sizeof(struct iovec) );
1992 /* ToDo: don't do any of the following if the vector is invalid */
1993 vec = (struct iovec *)arg2;
1994 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00001995 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00001996 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00001997 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001998 if (!VG_(is_kerror)(res) && res > 0) {
1999 /* res holds the number of bytes read. */
2000 for (i = 0; i < arg3; i++) {
2001 Int nReadThisBuf = vec[i].iov_len;
2002 if (nReadThisBuf > res) nReadThisBuf = res;
2003 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
2004 res -= nReadThisBuf;
2005 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
2006 }
2007 }
2008 break;
2009 }
2010
2011 case __NR_rename: /* syscall 38 */
2012 /* int rename(const char *oldpath, const char *newpath); */
2013 if (VG_(clo_trace_syscalls))
2014 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00002015 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
2016 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002017 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002018 break;
2019
2020 case __NR_rmdir: /* syscall 40 */
2021 /* int rmdir(const char *pathname); */
2022 if (VG_(clo_trace_syscalls))
2023 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002024 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002025 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002026 break;
2027
2028 case __NR_sched_setparam:
2029 case __NR_sched_getparam:
2030 case __NR_sched_yield:
sewardjde4a1d02002-03-22 01:27:54 +00002031 if (VG_(clo_instrument)) {
2032 VG_(message)(Vg_UserMsg,
2033 "Warning: noted but unhandled __NR_sched_* syscall (%d).",
2034 syscallno);
2035 VG_(message)(Vg_UserMsg,
2036 " This could cause spurious value errors"
2037 " to appear.");
2038 }
sewardj2e93c502002-04-12 11:12:52 +00002039 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002040 break;
2041
2042 case __NR_select: /* syscall 82 */
2043 /* struct sel_arg_struct {
2044 unsigned long n;
2045 fd_set *inp, *outp, *exp;
2046 struct timeval *tvp;
2047 };
2048 int old_select(struct sel_arg_struct *arg);
2049 */
2050 {
2051 Bool arg_block_readable
2052 = VG_(clo_instrument)
2053 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
2054 : True;
sewardj8c824512002-04-14 04:16:48 +00002055 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002056 if (arg_block_readable) {
2057 UInt* arg_struct = (UInt*)arg1;
2058 arg1 = arg_struct[0];
2059 arg2 = arg_struct[1];
2060 arg3 = arg_struct[2];
2061 arg4 = arg_struct[3];
2062 arg5 = arg_struct[4];
2063
2064 if (VG_(clo_trace_syscalls))
2065 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2066 arg1,arg2,arg3,arg4,arg5);
2067 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002068 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002069 arg1/8 /* __FD_SETSIZE/8 */ );
2070 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002071 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002072 arg1/8 /* __FD_SETSIZE/8 */ );
2073 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002074 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002075 arg1/8 /* __FD_SETSIZE/8 */ );
2076 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002077 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002078 sizeof(struct timeval) );
2079 }
2080 }
sewardj2e93c502002-04-12 11:12:52 +00002081 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002082 break;
2083
2084 case __NR_setitimer: /* syscall 104 */
2085 /* setitimer(int which, const struct itimerval *value,
2086 struct itimerval *ovalue); */
2087 if (VG_(clo_trace_syscalls))
2088 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002089 must_be_readable(tst, "setitimer(value)",
sewardjde4a1d02002-03-22 01:27:54 +00002090 arg2, sizeof(struct itimerval) );
2091 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002092 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002093 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002094 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002095 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2096 make_readable(arg3, sizeof(struct itimerval));
2097 }
2098 break;
2099
2100# if defined(__NR_setfsgid32)
2101 case __NR_setfsgid32: /* syscall 216 */
2102 /* int setfsgid(uid_t fsgid); */
2103 if (VG_(clo_trace_syscalls))
2104 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002105 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002106 break;
2107# endif
2108
2109# if defined(__NR_setgid32)
2110 case __NR_setgid32: /* syscall 214 */
2111# endif
2112 case __NR_setgid: /* syscall 46 */
2113 /* int setgid(gid_t gid); */
2114 if (VG_(clo_trace_syscalls))
2115 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002116 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002117 break;
2118
2119 case __NR_setsid: /* syscall 66 */
2120 /* pid_t setsid(void); */
2121 if (VG_(clo_trace_syscalls))
2122 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002123 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002124 break;
2125
2126# if defined(__NR_setgroups32)
2127 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002128# endif
2129 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002130 /* int setgroups(size_t size, const gid_t *list); */
2131 if (VG_(clo_trace_syscalls))
2132 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2133 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002134 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002135 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002136 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002137 break;
sewardjde4a1d02002-03-22 01:27:54 +00002138
2139 case __NR_setpgid: /* syscall 57 */
2140 /* int setpgid(pid_t pid, pid_t pgid); */
2141 if (VG_(clo_trace_syscalls))
2142 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002143 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002144 break;
2145
2146# if defined(__NR_setregid32)
2147 case __NR_setregid32: /* syscall 204 */
2148 /* int setregid(gid_t rgid, gid_t egid); */
2149 if (VG_(clo_trace_syscalls))
2150 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002151 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002152 break;
2153# endif
2154
2155# if defined(__NR_setresuid32)
2156 case __NR_setresuid32: /* syscall 208 */
2157 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2158 if (VG_(clo_trace_syscalls))
2159 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002160 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002161 break;
2162# endif
2163
2164# if defined(__NR_setreuid32)
2165 case __NR_setreuid32: /* syscall 203 */
2166# endif
2167 case __NR_setreuid: /* syscall 70 */
2168 /* int setreuid(uid_t ruid, uid_t euid); */
2169 if (VG_(clo_trace_syscalls))
2170 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002171 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002172 break;
2173
2174 case __NR_setrlimit: /* syscall 75 */
2175 /* int setrlimit (int resource, const struct rlimit *rlim); */
2176 if (VG_(clo_trace_syscalls))
2177 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002178 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002179 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002180 break;
2181
2182# if defined(__NR_setuid32)
2183 case __NR_setuid32: /* syscall 213 */
2184# endif
2185 case __NR_setuid: /* syscall 23 */
2186 /* int setuid(uid_t uid); */
2187 if (VG_(clo_trace_syscalls))
2188 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002189 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002190 break;
2191
2192 case __NR_socketcall: /* syscall 102 */
2193 /* int socketcall(int call, unsigned long *args); */
2194 if (VG_(clo_trace_syscalls))
2195 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2196 switch (arg1 /* request */) {
2197
2198 case SYS_SOCKETPAIR:
2199 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002200 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002201 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002202 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002203 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002204 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002205 if (!VG_(is_kerror)(res))
2206 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2207 break;
2208
2209 case SYS_SOCKET:
2210 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002211 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002212 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002213 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002214 break;
2215
2216 case SYS_BIND:
2217 /* int bind(int sockfd, struct sockaddr *my_addr,
2218 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002219 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002220 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002221 must_be_readable( tst, "socketcall.bind(my_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002222 ((UInt*)arg2)[1], ((UInt*)arg2)[2] );
sewardj2e93c502002-04-12 11:12:52 +00002223 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002224 break;
2225
2226 case SYS_LISTEN:
2227 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002228 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002229 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002230 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002231 break;
2232
2233 case SYS_ACCEPT: {
2234 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2235 Addr addr;
2236 Addr p_addrlen;
2237 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002238 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002239 arg2, 3*sizeof(Addr) );
2240 addr = ((UInt*)arg2)[1];
2241 p_addrlen = ((UInt*)arg2)[2];
2242 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002243 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002244 p_addrlen, sizeof(int) );
2245 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002246 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002247 addr, addrlen_in );
2248 }
sewardj2e93c502002-04-12 11:12:52 +00002249 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002250 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2251 addrlen_out = safe_dereference( p_addrlen, 0 );
2252 if (addrlen_out > 0)
2253 make_readable( addr, addrlen_out );
2254 }
2255 break;
2256 }
2257
2258 case SYS_SENDTO:
2259 /* int sendto(int s, const void *msg, int len,
2260 unsigned int flags,
2261 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002262 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002263 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002264 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002265 ((UInt*)arg2)[1], /* msg */
2266 ((UInt*)arg2)[2] /* len */ );
sewardj8c824512002-04-14 04:16:48 +00002267 must_be_readable( tst, "socketcall.sendto(to)",
sewardjde4a1d02002-03-22 01:27:54 +00002268 ((UInt*)arg2)[4], /* to */
2269 ((UInt*)arg2)[5] /* tolen */ );
sewardj2e93c502002-04-12 11:12:52 +00002270 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002271 break;
2272
2273 case SYS_SEND:
2274 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002275 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002276 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002277 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002278 ((UInt*)arg2)[1], /* msg */
2279 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002280 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002281 break;
2282
2283 case SYS_RECVFROM:
2284 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2285 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002286 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002287 arg2, 6*sizeof(Addr) );
2288 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002289 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002290 ((UInt*)arg2)[5] /* fromlen */,
2291 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002292 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002293 ((UInt*)arg2)[4], /*from*/
2294 safe_dereference( (Addr)
2295 ((UInt*)arg2)[5], 0 ) );
2296 }
sewardj8c824512002-04-14 04:16:48 +00002297 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002298 ((UInt*)arg2)[1], /* buf */
2299 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002300 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002301 if (!VG_(is_kerror)(res) && res >= 0) {
2302 make_readable( ((UInt*)arg2)[1], /* buf */
2303 ((UInt*)arg2)[2] /* len */ );
2304 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2305 make_readable(
2306 ((UInt*)arg2)[4], /*from*/
2307 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2308 }
2309 }
2310 /* phew! */
2311 break;
2312
2313 case SYS_RECV:
2314 /* int recv(int s, void *buf, int len, unsigned int flags); */
2315 /* man 2 recv says:
2316 The recv call is normally used only on a connected socket
2317 (see connect(2)) and is identical to recvfrom with a NULL
2318 from parameter.
2319 */
sewardj8c824512002-04-14 04:16:48 +00002320 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002321 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002322 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002323 ((UInt*)arg2)[1], /* buf */
2324 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002325 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002326 if (!VG_(is_kerror)(res) && res >= 0
2327 && ((UInt*)arg2)[1] != (UInt)NULL) {
2328 make_readable( ((UInt*)arg2)[1], /* buf */
2329 ((UInt*)arg2)[2] /* len */ );
2330 }
2331 break;
2332
2333 case SYS_CONNECT: {
2334 struct sockaddr *sa;
2335 /* int connect(int sockfd,
2336 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002337 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002338 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002339 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002340 ((UInt*)arg2)[1], /* serv_addr */
2341 sizeof (sa_family_t));
2342 sa = (struct sockaddr *) (((UInt*)arg2)[1]);
2343 if (sa->sa_family == AF_UNIX)
sewardj8c824512002-04-14 04:16:48 +00002344 must_be_readable_asciiz( tst,
sewardjde4a1d02002-03-22 01:27:54 +00002345 "socketcall.connect(serv_addr.sun_path)",
2346 (UInt) ((struct sockaddr_un *) sa)->sun_path);
2347 /* XXX There probably should be more cases here since not
2348 all of the struct sockaddr_XXX must be initialized. But
2349 wait until something pops up. */
2350 else
sewardj8c824512002-04-14 04:16:48 +00002351 must_be_readable( tst, "socketcall.connect(serv_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002352 ((UInt*)arg2)[1], /* serv_addr */
2353 ((UInt*)arg2)[2] /* addrlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002354 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002355 break;
2356 }
2357
2358 case SYS_SETSOCKOPT:
2359 /* int setsockopt(int s, int level, int optname,
2360 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002361 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002362 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002363 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002364 ((UInt*)arg2)[3], /* optval */
2365 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002366 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002367 break;
2368
2369 case SYS_GETSOCKOPT:
2370 /* int setsockopt(int s, int level, int optname,
2371 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002372 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002373 arg2, 5*sizeof(Addr) );
2374 {
2375 Addr optval_p = ((UInt*)arg2)[3];
2376 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002377 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002378 UInt optlen_after;
2379 UInt optlen = safe_dereference ( optlen_p, 0 );
2380 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002381 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002382 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002383 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002384 optlen_after = safe_dereference ( optlen_p, 0 );
2385 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2386 make_readable( optval_p, optlen_after );
2387 }
2388 break;
2389
2390 case SYS_GETSOCKNAME:
2391 /* int getsockname(int s, struct sockaddr* name,
2392 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002393 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002394 arg2, 3*sizeof(Addr) );
2395 {
2396 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2397 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002398 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002399 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002400 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002401 if (!VG_(is_kerror)(res)) {
2402 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2403 if (namelen > 0
2404 && ((UInt*)arg2)[1] != (UInt)NULL)
2405 make_readable( ((UInt*)arg2)[1], namelen );
2406 }
2407 }
2408 break;
2409
2410 case SYS_GETPEERNAME:
2411 /* int getpeername(int s, struct sockaddr* name,
2412 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002413 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002414 arg2, 3*sizeof(Addr) );
2415 {
2416 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2417 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002418 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002419 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002420 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002421 if (!VG_(is_kerror)(res)) {
2422 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2423 if (namelen > 0
2424 && ((UInt*)arg2)[1] != (UInt)NULL)
2425 make_readable( ((UInt*)arg2)[1], namelen );
2426 }
2427 }
2428 break;
2429
2430 case SYS_SHUTDOWN:
2431 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002432 must_be_readable( tst, "socketcall.shutdown(args)",
2433 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002434 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002435 break;
2436
2437 case SYS_SENDMSG:
2438 {
2439 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2440
2441 /* this causes warnings, and I don't get why. glibc bug?
2442 * (after all it's glibc providing the arguments array)
2443 must_be_readable( "socketcall.sendmsg(args)",
2444 arg2, 3*sizeof(Addr) );
2445 */
2446
2447 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002448 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002449
sewardj2e93c502002-04-12 11:12:52 +00002450 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002451 break;
2452 }
2453
2454 case SYS_RECVMSG:
2455 {
2456 /* int recvmsg(int s, struct msghdr *msg, int flags); */
2457
2458 /* this causes warnings, and I don't get why. glibc bug?
2459 * (after all it's glibc providing the arguments array)
2460 must_be_readable( "socketcall.recvmsg(args)",
2461 arg2, 3*sizeof(Addr) );
2462 */
2463
2464 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002465 msghdr_foreachfield ( tst, msg, must_be_writable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002466
sewardj2e93c502002-04-12 11:12:52 +00002467 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002468
2469 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002470 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002471
2472 break;
2473 }
2474
2475 default:
2476 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2477 VG_(panic)("... bye!\n");
2478 break; /*NOTREACHED*/
2479 }
2480 break;
2481
2482 case __NR_stat: /* syscall 106 */
2483 /* int stat(const char *file_name, struct stat *buf); */
2484 if (VG_(clo_trace_syscalls))
2485 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002486 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2487 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002488 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002489 if (!VG_(is_kerror)(res))
2490 make_readable( arg2, sizeof(struct stat) );
2491 break;
2492
2493 case __NR_statfs: /* syscall 99 */
2494 /* int statfs(const char *path, struct statfs *buf); */
2495 if (VG_(clo_trace_syscalls))
2496 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002497 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2498 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002499 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002500 if (!VG_(is_kerror)(res))
2501 make_readable( arg2, sizeof(struct statfs) );
2502 break;
2503
2504 case __NR_symlink: /* syscall 83 */
2505 /* int symlink(const char *oldpath, const char *newpath); */
2506 if (VG_(clo_trace_syscalls))
2507 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002508 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2509 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002510 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002511 break;
2512
2513# if defined(__NR_stat64)
2514 case __NR_stat64: /* syscall 195 */
2515 /* int stat64(const char *file_name, struct stat64 *buf); */
2516 if (VG_(clo_trace_syscalls))
2517 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002518 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2519 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002520 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002521 if (!VG_(is_kerror)(res))
2522 make_readable( arg2, sizeof(struct stat64) );
2523 break;
2524# endif
2525
2526# if defined(__NR_fstat64)
2527 case __NR_fstat64: /* syscall 197 */
2528 /* int fstat64(int filedes, struct stat64 *buf); */
2529 if (VG_(clo_trace_syscalls))
2530 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002531 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002532 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002533 if (!VG_(is_kerror)(res))
2534 make_readable( arg2, sizeof(struct stat64) );
2535 break;
2536# endif
2537
2538 case __NR_sysinfo: /* syscall 116 */
2539 /* int sysinfo(struct sysinfo *info); */
2540 if (VG_(clo_trace_syscalls))
2541 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002542 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002543 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002544 if (!VG_(is_kerror)(res))
2545 make_readable( arg1, sizeof(struct sysinfo) );
2546 break;
2547
2548 case __NR_time: /* syscall 13 */
2549 /* time_t time(time_t *t); */
2550 if (VG_(clo_trace_syscalls))
2551 VG_(printf)("time ( %p )\n",arg1);
2552 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002553 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002554 }
sewardj2e93c502002-04-12 11:12:52 +00002555 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002556 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2557 make_readable( arg1, sizeof(time_t) );
2558 }
2559 break;
2560
2561 case __NR_times: /* syscall 43 */
2562 /* clock_t times(struct tms *buf); */
2563 if (VG_(clo_trace_syscalls))
2564 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002565 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002566 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002567 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2568 make_readable( arg1, sizeof(struct tms) );
2569 }
2570 break;
2571
2572 case __NR_truncate: /* syscall 92 */
2573 /* int truncate(const char *path, size_t length); */
2574 if (VG_(clo_trace_syscalls))
2575 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002576 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002577 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002578 break;
2579
2580 case __NR_umask: /* syscall 60 */
2581 /* mode_t umask(mode_t mask); */
2582 if (VG_(clo_trace_syscalls))
2583 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002584 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002585 break;
2586
2587 case __NR_unlink: /* syscall 10 */
2588 /* int unlink(const char *pathname) */
2589 if (VG_(clo_trace_syscalls))
2590 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002591 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002592 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002593 break;
2594
2595 case __NR_uname: /* syscall 122 */
2596 /* int uname(struct utsname *buf); */
2597 if (VG_(clo_trace_syscalls))
2598 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002599 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002600 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002601 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2602 make_readable( arg1, sizeof(struct utsname) );
2603 }
2604 break;
2605
2606 case __NR_utime: /* syscall 30 */
2607 /* int utime(const char *filename, struct utimbuf *buf); */
2608 if (VG_(clo_trace_syscalls))
2609 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002610 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00002611 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002612 must_be_readable( tst, "utime(buf)", arg2,
2613 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00002614 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002615 break;
2616
2617 case __NR_wait4: /* syscall 114 */
2618 /* pid_t wait4(pid_t pid, int *status, int options,
2619 struct rusage *rusage) */
2620 if (VG_(clo_trace_syscalls))
2621 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
2622 arg1,arg2,arg3,arg4);
2623 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002624 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00002625 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002626 must_be_writable( tst, "wait4(rusage)", arg4,
2627 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00002628 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002629 if (!VG_(is_kerror)(res)) {
2630 if (arg2 != (Addr)NULL)
2631 make_readable( arg2, sizeof(int) );
2632 if (arg4 != (Addr)NULL)
2633 make_readable( arg4, sizeof(struct rusage) );
2634 }
2635 break;
2636
sewardjde4a1d02002-03-22 01:27:54 +00002637 case __NR_writev: { /* syscall 146 */
2638 /* int writev(int fd, const struct iovec * vector, size_t count); */
2639 UInt i;
2640 struct iovec * vec;
2641 if (VG_(clo_trace_syscalls))
2642 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002643 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002644 arg2, arg3 * sizeof(struct iovec) );
2645 /* ToDo: don't do any of the following if the vector is invalid */
2646 vec = (struct iovec *)arg2;
2647 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002648 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002649 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002650 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002651 break;
2652 }
2653
2654 /*-------------------------- SIGNALS --------------------------*/
2655
2656 /* Normally set to 1, so that Valgrind's signal-simulation machinery
2657 is engaged. Sometimes useful to disable (set to 0), for
2658 debugging purposes, to make clients more deterministic. */
2659# define SIGNAL_SIMULATION 1
2660
2661 case __NR_rt_sigaction:
2662 case __NR_sigaction:
2663 /* int sigaction(int signum, struct k_sigaction *act,
2664 struct k_sigaction *oldact); */
2665 if (VG_(clo_trace_syscalls))
2666 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
2667 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002668 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00002669 arg2, sizeof(vki_ksigaction));
2670 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002671 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00002672 arg3, sizeof(vki_ksigaction));
2673 /* We do this one ourselves! */
2674# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00002675 VG_(do__NR_sigaction)(tid);
2676 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00002677# else
2678 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00002679 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002680# endif
2681 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2682 make_readable( arg3, sizeof(vki_ksigaction));
2683 break;
2684
2685 case __NR_rt_sigprocmask:
2686 case __NR_sigprocmask:
2687 /* int sigprocmask(int how, k_sigset_t *set,
2688 k_sigset_t *oldset); */
2689 if (VG_(clo_trace_syscalls))
2690 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
2691 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002692 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00002693 arg2, sizeof(vki_ksigset_t));
2694 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002695 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00002696 arg3, sizeof(vki_ksigset_t));
sewardj2e93c502002-04-12 11:12:52 +00002697 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002698 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2699 make_readable( arg3, sizeof(vki_ksigset_t));
2700# if SIGNAL_SIMULATION
2701 /* For the reason why both the kernel and Valgrind process
2702 sigprocmask, see the detailed comment at
2703 vg_do__NR_sigprocmask(). */
2704 VG_(do__NR_sigprocmask) ( arg1 /*how*/, (vki_ksigset_t*) arg2 );
2705# endif
2706 break;
2707
2708 default:
2709 VG_(message)
2710 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
2711 VG_(message)
2712 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
2713 VG_(message)
2714 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
2715 VG_(unimplemented)("no wrapper for the above system call");
2716 vg_assert(3+3 == 7);
2717 break; /*NOTREACHED*/
2718 }
2719
sewardjde4a1d02002-03-22 01:27:54 +00002720 /* { void zzzmemscan(void); zzzmemscan(); } */
2721
sewardjde4a1d02002-03-22 01:27:54 +00002722 if (! VG_(first_and_last_secondaries_look_plausible))
2723 sane_before_call = False;
2724
2725 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00002726 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00002727 VG_(message)(Vg_DebugMsg,
2728 "probable sanity check failure for syscall number %d\n",
2729 syscallno );
2730 VG_(panic)("aborting due to the above ... bye!");
2731 }
2732
2733 VGP_POPCC;
2734}
2735
2736
sewardj2e93c502002-04-12 11:12:52 +00002737
2738/* Perform pre- and post- actions for a blocking syscall, but do not
2739 do the syscall itself. If res is NULL, the pre-syscall actions are
2740 to be performed. If res is non-NULL, the post-syscall actions are
2741 to be performed, and *res is assumed to hold the result of the
2742 syscall. This slightly strange scheme makes it impossible to
2743 mistakenly use the value of *res in the pre-syscall actions.
2744
2745 This doesn't actually do the syscall itself, it is important to
2746 observe.
2747
2748 Because %eax is used both for the syscall number before the call
2749 and the result value afterwards, we can't reliably use it to get
2750 the syscall number. So the caller has to pass it explicitly.
2751*/
sewardj8c824512002-04-14 04:16:48 +00002752void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00002753 Int syscallno,
2754 Int* /*IN*/ res )
2755{
2756 Bool sane_before_post = True;
2757 Bool sane_after_post = True;
2758 ThreadState* tst = VG_(get_thread_state)( tid );
2759 UInt arg1 = tst->m_ebx;
2760 UInt arg2 = tst->m_ecx;
2761 UInt arg3 = tst->m_edx;
2762 /*
2763 UInt arg4 = tst->m_esi;
2764 UInt arg5 = tst->m_edi;
2765 */
2766 VGP_PUSHCC(VgpSyscall);
2767
2768 if (res != NULL
2769 && ! VG_(first_and_last_secondaries_look_plausible))
2770 sane_before_post = False;
2771
2772 switch (syscallno) {
2773
2774 case __NR_read: /* syscall 3 */
2775 /* size_t read(int fd, void *buf, size_t count); */
2776 if (res == NULL) {
2777 /* PRE */
2778 if (VG_(clo_trace_syscalls))
2779 VG_(printf)(
2780 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
2781 VG_(getpid)(), tid,
2782 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002783 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002784 } else {
2785 /* POST */
2786 if (VG_(clo_trace_syscalls))
2787 VG_(printf)(
2788 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
2789 VG_(getpid)(), tid,
2790 arg1, arg2, arg3, *res);
2791 if (!VG_(is_kerror)(*res) && *res > 0) {
2792 make_readable( arg2, *res );
2793 }
2794 }
2795 break;
2796
2797 case __NR_write: /* syscall 4 */
2798 /* size_t write(int fd, const void *buf, size_t count); */
2799 if (res == NULL) {
2800 /* PRE */
2801 if (VG_(clo_trace_syscalls))
2802 VG_(printf)(
2803 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
2804 VG_(getpid)(), tid,
2805 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002806 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002807 } else {
2808 /* POST */
2809 if (VG_(clo_trace_syscalls))
2810 VG_(printf)(
2811 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
2812 VG_(getpid)(), tid,
2813 arg1, arg2, arg3, *res);
2814 }
2815 break;
2816
2817 default:
2818 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
2819 syscallno);
2820 VG_(panic)("check_known_blocking_syscall");
2821 /*NOTREACHED*/
2822 break;
2823 }
2824
2825 if (res != NULL) { /* only check after syscall */
2826 if (! VG_(first_and_last_secondaries_look_plausible))
2827 sane_after_post = False;
2828
2829 if (sane_before_post && (!sane_after_post)) {
2830 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
2831 VG_(message)(Vg_DebugMsg,
2832 "probable sanity check failure for syscall number %d\n",
2833 syscallno );
2834 VG_(panic)("aborting due to the above ... bye!");
2835 }
2836 }
2837
2838 VGP_POPCC;
2839}
2840
2841
sewardjde4a1d02002-03-22 01:27:54 +00002842/*--------------------------------------------------------------------*/
2843/*--- end vg_syscall_mem.c ---*/
2844/*--------------------------------------------------------------------*/