blob: aebd4e0e632f9f7ecbafd4b4b4db4ff542b123ca [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
sewardj6af4b5d2002-04-16 04:40:49 +0000357# if defined(__NR_mremap)
358 /* Is this really right? Perhaps it should copy the permissions
359 from the old area into the new. Unclear from the Linux man
360 pages what this really does. Also, the flags don't look like
361 they mean the same as the standard mmap flags, so that's
362 probably wrong too. */
363 case __NR_mremap: /* syscall 163 */
364 /* void* mremap(void * old_address, size_t old_size,
365 size_t new_size, unsigned long flags); */
366 if (VG_(clo_trace_syscalls))
367 VG_(printf)("mremap ( %p, %d, %d, 0x%x )\n",
368 arg1, arg2, arg3, arg4);
369 must_be_writable ( tst, "mremap(old_address)", arg1, arg2 );
370 KERNEL_DO_SYSCALL(tid,res);
371 if (!VG_(is_kerror)(res)) {
372 /* Copied from munmap() wrapper. */
373 Addr start = arg1;
374 Addr length = arg2;
375 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
376 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
377 make_noaccess( start, length );
378 VG_(symtab_notify_munmap) ( start, length );
379 approximate_mmap_permissions( (Addr)res, arg3, arg4 );
380 }
381 break;
382# endif
383
sewardj73f1f072002-03-29 14:22:46 +0000384 case __NR_nice: /* syscall 34 */
385 /* int nice(int inc); */
386 if (VG_(clo_trace_syscalls))
387 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000388 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000389 break;
390
sewardjde4a1d02002-03-22 01:27:54 +0000391 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
392
sewardjd7f07662002-03-24 10:49:46 +0000393# if defined(__NR_setresgid32)
394 case __NR_setresgid32: /* syscall 210 */
395 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
396 if (VG_(clo_trace_syscalls))
397 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000398 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000399 break;
400# endif
401
sewardjde4a1d02002-03-22 01:27:54 +0000402# if defined(__NR_setfsuid32)
403 case __NR_setfsuid32: /* syscall 215 */
404 /* int setfsuid(uid_t fsuid); */
405 if (VG_(clo_trace_syscalls))
406 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000407 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000408 break;
409# endif
410
411# if defined(__NR__sysctl)
412 case __NR__sysctl:
413 /* int _sysctl(struct __sysctl_args *args); */
414 if (VG_(clo_trace_syscalls))
415 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000416 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000417 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000418 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000419 if (!VG_(is_kerror)(res))
420 make_readable ( arg1, sizeof(struct __sysctl_args) );
421 break;
422# endif
423
424# if defined(__NR_sched_getscheduler)
425 case __NR_sched_getscheduler:
426 /* int sched_getscheduler(pid_t pid); */
427 if (VG_(clo_trace_syscalls))
428 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000429 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000430 break;
431# endif
432
433# if defined(__NR_sched_setscheduler)
434 case __NR_sched_setscheduler:
435 /* int sched_setscheduler(pid_t pid, int policy,
436 const struct sched_param *p); */
437 if (VG_(clo_trace_syscalls))
438 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
439 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000440 must_be_readable( tst,
441 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000442 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000443 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000444 break;
445# endif
446
447# if defined(__NR_mlockall)
448 case __NR_mlockall:
449 /* int mlockall(int flags); */
450 if (VG_(clo_trace_syscalls))
451 VG_(printf)("mlockall ( %x )\n", arg1);
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_munlockall)
457 case __NR_munlockall:
458 /* int munlockall(void); */
459 if (VG_(clo_trace_syscalls))
460 VG_(printf)("munlockall ( )\n");
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_sched_get_priority_max)
466 case __NR_sched_get_priority_max:
467 /* int sched_get_priority_max(int policy); */
468 if (VG_(clo_trace_syscalls))
469 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
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_setfsgid)
475 case __NR_setfsgid: /* syscall 139 */
476 /* int setfsgid(gid_t gid); */
477 if (VG_(clo_trace_syscalls))
478 VG_(printf)("setfsgid ( %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
483# if defined(__NR_setregid)
484 case __NR_setregid: /* syscall 71 */
485 /* int setregid(gid_t rgid, gid_t egid); */
486 if (VG_(clo_trace_syscalls))
487 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +0000488 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000489 break;
490# endif
491
492# if defined(__NR_setresuid)
493 case __NR_setresuid: /* syscall 164 */
494 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
495 if (VG_(clo_trace_syscalls))
496 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000497 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000498 break;
499# endif
500
501# if defined(__NR_setfsuid)
502 case __NR_setfsuid: /* syscall 138 */
503 /* int setfsuid(uid_t uid); */
504 if (VG_(clo_trace_syscalls))
505 VG_(printf)("setfsuid ( %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 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
511
512# if defined(__NR_sendfile)
513 case __NR_sendfile: /* syscall 187 */
514 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
515 size_t count) */
516 if (VG_(clo_trace_syscalls))
517 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000518 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000519 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000520 if (!VG_(is_kerror)(res)) {
521 make_readable( arg3, sizeof( off_t ) );
522 }
523 break;
524# endif
525
526 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
527
528# if defined(__NR_pwrite)
529 case __NR_pwrite: /* syscall 181 */
530 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
531 off_t offset); */
532 if (VG_(clo_trace_syscalls))
533 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000534 must_be_readable( tst, "pwrite(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000535 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000536 break;
537# endif
538
539 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
540
541 case __NR_sync: /* syscall 36 */
542 /* int sync(); */
543 if (VG_(clo_trace_syscalls))
544 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000545 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000546 break;
547
548 case __NR_fstatfs: /* syscall 100 */
549 /* int fstatfs(int fd, struct statfs *buf); */
550 if (VG_(clo_trace_syscalls))
551 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000552 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000553 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000554 if (!VG_(is_kerror)(res))
555 make_readable( arg2, sizeof(struct statfs) );
556 break;
557
558 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
559
560 case __NR_pause: /* syscall 29 */
561 /* int pause(void); */
562 if (VG_(clo_trace_syscalls))
563 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000564 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000565 break;
566
567 case __NR_getsid: /* syscall 147 */
568 /* pid_t getsid(pid_t pid); */
569 if (VG_(clo_trace_syscalls))
570 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000571 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000572 break;
573
574# if defined(__NR_pread)
575 case __NR_pread: /* syscall 180 */
576 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
577 if (VG_(clo_trace_syscalls))
578 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000579 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000580 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000581 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000582 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
583 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000584 arg1, arg2, arg3, arg4, res);
585 if (!VG_(is_kerror)(res) && res > 0) {
586 make_readable( arg2, res );
587 }
588 break;
589# endif
590
591 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
592
593 case __NR_mknod: /* syscall 14 */
594 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
595 if (VG_(clo_trace_syscalls))
596 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000597 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000598 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000599 break;
600
601 case __NR_flock: /* syscall 143 */
602 /* int flock(int fd, int operation); */
603 if (VG_(clo_trace_syscalls))
604 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000605 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000606 break;
607
608# if defined(__NR_rt_sigsuspend)
609 /* Viewed with great suspicion by me, but, hey, let's do it
610 anyway ... */
611 case __NR_rt_sigsuspend: /* syscall 179 */
612 /* int sigsuspend(const sigset_t *mask); */
613 if (VG_(clo_trace_syscalls))
614 VG_(printf)("sigsuspend ( %p )\n", arg1 );
615 if (arg1 != (Addr)NULL) {
616 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000617 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000618 sizeof(vki_ksigset_t) );
619 }
sewardj2e93c502002-04-12 11:12:52 +0000620 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000621 break;
622# endif
623
624 case __NR_init_module: /* syscall 128 */
625 /* int init_module(const char *name, struct module *image); */
626 if (VG_(clo_trace_syscalls))
627 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000628 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
629 must_be_readable( tst, "init_module(image)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000630 sizeof(struct module) );
sewardj2e93c502002-04-12 11:12:52 +0000631 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000632 break;
633
634 case __NR_ioperm: /* syscall 101 */
635 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
636 if (VG_(clo_trace_syscalls))
637 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000638 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000639 break;
640
641 case __NR_capget: /* syscall 184 */
642 /* int capget(cap_user_header_t header, cap_user_data_t data); */
643 if (VG_(clo_trace_syscalls))
644 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000645 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000646 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000647 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000648 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000649 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000650 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
651 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
652 break;
653
654 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
655
656 case __NR_execve:
657 /* int execve (const char *filename,
658 char *const argv [],
659 char *const envp[]); */
660 if (VG_(clo_trace_syscalls))
661 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
662 arg1, arg1, arg2, arg3);
663 /* Make any binding for LD_PRELOAD disappear, so that child
664 processes don't get traced into. */
665 if (!VG_(clo_trace_children)) {
666 Int i;
667 Char** envp = (Char**)arg3;
668 for (i = 0; envp[i] != NULL; i++) {
669 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) {
670 VG_(mash_LD_PRELOAD_string)(&envp[i][11]);
671 }
672 }
673 }
sewardj2e93c502002-04-12 11:12:52 +0000674 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000675 /* Should we still be alive here? Don't think so. */
676 /* Actually, above comment is wrong. execve can fail, just
677 like any other syscall -- typically the file to exec does
678 not exist. Hence: */
679 vg_assert(VG_(is_kerror)(res));
680 break;
681
682 case __NR_exit: /* syscall 1 */
683 /* void _exit(int status); */
684 if (VG_(clo_trace_syscalls))
685 VG_(printf)("exit ( %d )\n", arg1);
686 VG_(message)(Vg_UserMsg,
687 "Warning: client exiting by calling exit(%d). Bye!",
688 arg1);
689
sewardj2e93c502002-04-12 11:12:52 +0000690 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000691 /* Definitely should not be alive here :) */
692 break;
693
694 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
695
696 case __NR_access: /* syscall 33 */
697 /* int access(const char *pathname, int mode); */
698 if (VG_(clo_trace_syscalls))
699 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000700 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000701 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000702 break;
703
704 case __NR_alarm: /* syscall 27 */
705 /* unsigned int alarm(unsigned int seconds); */
706 if (VG_(clo_trace_syscalls))
707 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000708 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000709 break;
710
711 case __NR_brk: /* syscall 45 */
712 /* Haven't a clue if this is really right. */
713 /* int brk(void *end_data_segment); */
714 if (VG_(clo_trace_syscalls))
715 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000716 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000717 if (VG_(clo_trace_syscalls))
718 VG_(printf)("0x%x\n", res);
719
720 if (!VG_(is_kerror)(res)) {
721 if (arg1 == 0) {
722 /* Just asking where the current end is. (???) */
723 VGM_(curr_dataseg_end) = res;
724 } else
725 if (arg1 < VGM_(curr_dataseg_end)) {
726 /* shrinking the data segment. */
727 make_noaccess( (Addr)arg1,
728 VGM_(curr_dataseg_end)-arg1 );
729 VGM_(curr_dataseg_end) = arg1;
730 } else
731 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
732 /* asked for more memory, and got it */
733 /*
734 VG_(printf)("BRK: new area %x .. %x\n",
735 VGM_(curr_dataseg_end, arg1-1 );
736 */
737 make_writable ( (Addr)VGM_(curr_dataseg_end),
738 arg1-VGM_(curr_dataseg_end) );
739 VGM_(curr_dataseg_end) = arg1;
740 }
741 }
742 break;
743
744 case __NR_chdir: /* syscall 12 */
745 /* int chdir(const char *path); */
746 if (VG_(clo_trace_syscalls))
747 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +0000748 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000749 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000750 break;
751
752 case __NR_chmod: /* syscall 15 */
753 /* int chmod(const char *path, mode_t mode); */
754 if (VG_(clo_trace_syscalls))
755 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000756 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000757 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000758 break;
759
760# if defined(__NR_chown32)
761 case __NR_chown32: /* syscall 212 */
762# endif
763# if defined(__NR_lchown32)
764 case __NR_lchown32: /* syscall 198 */
765# endif
766 case __NR_chown: /* syscall 16 */
767 /* int chown(const char *path, uid_t owner, gid_t group); */
768 if (VG_(clo_trace_syscalls))
769 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000770 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000771 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000772 break;
773
774 case __NR_close: /* syscall 6 */
775 /* int close(int fd); */
776 if (VG_(clo_trace_syscalls))
777 VG_(printf)("close ( %d )\n",arg1);
778 /* Detect and negate attempts by the client to close Valgrind's
779 logfile fd ... */
780 if (arg1 == VG_(clo_logfile_fd)) {
781 VG_(message)(Vg_UserMsg,
782 "Warning: client attempted to close "
783 "Valgrind's logfile fd (%d).",
784 VG_(clo_logfile_fd));
785 VG_(message)(Vg_UserMsg,
786 " Use --logfile-fd=<number> to select an "
787 "alternative logfile fd." );
788 } else {
sewardj2e93c502002-04-12 11:12:52 +0000789 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000790 }
791 break;
792
793 case __NR_dup: /* syscall 41 */
794 /* int dup(int oldfd); */
795 if (VG_(clo_trace_syscalls))
796 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000797 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000798 if (VG_(clo_trace_syscalls))
799 VG_(printf)("%d\n", res);
800 break;
801
802 case __NR_dup2: /* syscall 63 */
803 /* int dup2(int oldfd, int newfd); */
804 if (VG_(clo_trace_syscalls))
805 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000806 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000807 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000808 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
809 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000810 arg1, arg2, res);
811 break;
812
813 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +0000814 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +0000815 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000816 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
817 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000818 break;
819
820 case __NR_fchdir: /* syscall 133 */
821 /* int fchdir(int fd); */
822 if (VG_(clo_trace_syscalls))
823 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000824 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000825 break;
826
sewardj2f0de322002-03-24 10:17:25 +0000827# if defined(__NR_fchown32)
828 case __NR_fchown32: /* syscall 207 */
829# endif
830 case __NR_fchown: /* syscall 95 */
831 /* int fchown(int filedes, uid_t owner, gid_t group); */
832 if (VG_(clo_trace_syscalls))
833 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +0000834 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +0000835 break;
836
sewardjde4a1d02002-03-22 01:27:54 +0000837 case __NR_fchmod: /* syscall 94 */
838 /* int fchmod(int fildes, mode_t mode); */
839 if (VG_(clo_trace_syscalls))
840 VG_(printf)("fchmod ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000841 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000842 break;
sewardj2f0de322002-03-24 10:17:25 +0000843
sewardjde4a1d02002-03-22 01:27:54 +0000844# if defined(__NR_fcntl64)
845 case __NR_fcntl64: /* syscall 221 */
846 /* I don't know what the prototype for this is supposed to be. */
847 /* ??? int fcntl(int fd, int cmd); */
848 if (VG_(clo_trace_syscalls))
849 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000850 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000851 break;
852# endif
853
854 case __NR_fstat: /* syscall 108 */
855 /* int fstat(int filedes, struct stat *buf); */
856 if (VG_(clo_trace_syscalls))
857 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000858 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +0000859 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000860 if (!VG_(is_kerror)(res))
861 make_readable( arg2, sizeof(struct stat) );
862 break;
863
864 case __NR_vfork: /* syscall 190 */
865 /* pid_t vfork(void); */
866 if (VG_(clo_trace_syscalls))
867 VG_(printf)("vfork ( ) ... becomes ... ");
868 /* KLUDGE: we prefer to do a fork rather than vfork.
869 vfork gives a SIGSEGV, and the stated semantics looks
870 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +0000871 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +0000872 /* fall through ... */
873 case __NR_fork: /* syscall 2 */
874 /* pid_t fork(void); */
875 if (VG_(clo_trace_syscalls))
876 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000877 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000878 break;
879
880 case __NR_fsync: /* syscall 118 */
881 /* int fsync(int fd); */
882 if (VG_(clo_trace_syscalls))
883 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000884 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000885 break;
886
887 case __NR_ftruncate: /* syscall 93 */
888 /* int ftruncate(int fd, size_t length); */
889 if (VG_(clo_trace_syscalls))
890 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000891 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000892 break;
893
sewardj2f0de322002-03-24 10:17:25 +0000894# if defined(__NR_ftruncate64)
895 case __NR_ftruncate64: /* syscall 194 */
896 /* int ftruncate64(int fd, off64_t length); */
897 if (VG_(clo_trace_syscalls))
898 VG_(printf)("ftruncate64 ( %d, %lld )\n",
899 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +0000900 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000901 break;
902# endif
903
904 case __NR_getdents: /* syscall 141 */
905 /* int getdents(unsigned int fd, struct dirent *dirp,
906 unsigned int count); */
907 if (VG_(clo_trace_syscalls))
908 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000909 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000910 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000911 if (!VG_(is_kerror)(res) && res > 0)
912 make_readable( arg2, res );
913 break;
914
915# if defined(__NR_getdents64)
916 case __NR_getdents64: /* syscall 220 */
917 /* int getdents(unsigned int fd, struct dirent64 *dirp,
918 unsigned int count); */
919 if (VG_(clo_trace_syscalls))
920 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000921 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000922 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000923 if (!VG_(is_kerror)(res) && res > 0)
924 make_readable( arg2, res );
925 break;
926# endif
927
928# if defined(__NR_getgroups32)
929 case __NR_getgroups32: /* syscall 205 */
930# endif
931 case __NR_getgroups: /* syscall 80 */
932 /* int getgroups(int size, gid_t list[]); */
933 if (VG_(clo_trace_syscalls))
934 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
935 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +0000936 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000937 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +0000938 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000939 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
940 make_readable ( arg2, res * sizeof(gid_t) );
941 break;
942
943 case __NR_getcwd: /* syscall 183 */
944 /* char *getcwd(char *buf, size_t size); */
945 if (VG_(clo_trace_syscalls))
946 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000947 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000948 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000949 if (!VG_(is_kerror)(res) && res != (Addr)NULL)
950 make_readable ( arg1, arg2 );
951 /* Not really right -- really we should have the asciiz
952 string starting at arg1 readable, or up to arg2 bytes,
953 whichever finishes first. */
954 break;
955
956 case __NR_geteuid: /* syscall 49 */
957 /* uid_t geteuid(void); */
958 if (VG_(clo_trace_syscalls))
959 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000960 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000961 break;
962
963# if defined(__NR_geteuid32)
964 case __NR_geteuid32: /* syscall 201 */
965 /* ?? uid_t geteuid32(void); */
966 if (VG_(clo_trace_syscalls))
967 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000968 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000969 break;
970# endif
971
972 case __NR_getegid: /* syscall 50 */
973 /* gid_t getegid(void); */
974 if (VG_(clo_trace_syscalls))
975 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000976 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000977 break;
978
979# if defined(__NR_getegid32)
980 case __NR_getegid32: /* syscall 202 */
981 /* gid_t getegid32(void); */
982 if (VG_(clo_trace_syscalls))
983 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000984 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000985 break;
986# endif
987
988 case __NR_getgid: /* syscall 47 */
989 /* gid_t getgid(void); */
990 if (VG_(clo_trace_syscalls))
991 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000992 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000993 break;
994
995# if defined(__NR_getgid32)
996 case __NR_getgid32: /* syscall 200 */
997 /* gid_t getgid32(void); */
998 if (VG_(clo_trace_syscalls))
999 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001000 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001001 break;
1002# endif
1003
1004 case __NR_getpid: /* syscall 20 */
1005 /* pid_t getpid(void); */
1006 if (VG_(clo_trace_syscalls))
1007 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001008 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001009 break;
1010
1011 case __NR_getpgid: /* syscall 132 */
1012 /* pid_t getpgid(pid_t pid); */
1013 if (VG_(clo_trace_syscalls))
1014 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001015 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001016 break;
1017
1018 case __NR_getpgrp: /* syscall 65 */
1019 /* pid_t getpprp(void); */
1020 if (VG_(clo_trace_syscalls))
1021 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001022 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001023 break;
1024
1025 case __NR_getppid: /* syscall 64 */
1026 /* pid_t getppid(void); */
1027 if (VG_(clo_trace_syscalls))
1028 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001029 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001030 break;
1031
1032 case __NR_getresgid: /* syscall 171 */
1033 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1034 if (VG_(clo_trace_syscalls))
1035 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001036 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1037 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1038 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001039 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001040 if (!VG_(is_kerror)(res) && res == 0) {
1041 make_readable ( arg1, sizeof(gid_t) );
1042 make_readable ( arg2, sizeof(gid_t) );
1043 make_readable ( arg3, sizeof(gid_t) );
1044 }
1045 break;
1046
1047# if defined(__NR_getresgid32)
1048 case __NR_getresgid32: /* syscall 211 */
1049 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1050 if (VG_(clo_trace_syscalls))
1051 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001052 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1053 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1054 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001055 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001056 if (!VG_(is_kerror)(res) && res == 0) {
1057 make_readable ( arg1, sizeof(gid_t) );
1058 make_readable ( arg2, sizeof(gid_t) );
1059 make_readable ( arg3, sizeof(gid_t) );
1060 }
1061 break;
1062# endif
1063
1064 case __NR_getresuid: /* syscall 165 */
1065 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1066 if (VG_(clo_trace_syscalls))
1067 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001068 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1069 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1070 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001071 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001072 if (!VG_(is_kerror)(res) && res == 0) {
1073 make_readable ( arg1, sizeof(uid_t) );
1074 make_readable ( arg2, sizeof(uid_t) );
1075 make_readable ( arg3, sizeof(uid_t) );
1076 }
1077 break;
1078
1079# if defined(__NR_getresuid32)
1080 case __NR_getresuid32: /* syscall 209 */
1081 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1082 if (VG_(clo_trace_syscalls))
1083 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001084 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1085 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1086 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001087 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001088 if (!VG_(is_kerror)(res) && res == 0) {
1089 make_readable ( arg1, sizeof(uid_t) );
1090 make_readable ( arg2, sizeof(uid_t) );
1091 make_readable ( arg3, sizeof(uid_t) );
1092 }
1093 break;
1094# endif
1095
1096# if defined(__NR_ugetrlimit)
1097 case __NR_ugetrlimit: /* syscall 191 */
1098# endif
1099 case __NR_getrlimit: /* syscall 76 */
1100 /* int getrlimit (int resource, struct rlimit *rlim); */
1101 if (VG_(clo_trace_syscalls))
1102 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001103 must_be_writable( tst, "getrlimit(rlim)", arg2,
1104 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001105 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001106 if (!VG_(is_kerror)(res) && res == 0)
1107 make_readable( arg2, sizeof(struct rlimit) );
1108 break;
1109
1110 case __NR_getrusage: /* syscall 77 */
1111 /* int getrusage (int who, struct rusage *usage); */
1112 if (VG_(clo_trace_syscalls))
1113 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001114 must_be_writable( tst, "getrusage(usage)", arg2,
1115 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001116 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001117 if (!VG_(is_kerror)(res) && res == 0)
1118 make_readable(arg2, sizeof(struct rusage) );
1119 break;
1120
1121 case __NR_gettimeofday: /* syscall 78 */
1122 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1123 if (VG_(clo_trace_syscalls))
1124 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001125 must_be_writable( tst, "gettimeofday(tv)", arg1,
1126 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001127 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001128 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001129 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001130 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001131 if (!VG_(is_kerror)(res) && res == 0) {
1132 make_readable( arg1, sizeof(struct timeval) );
1133 if (arg2 != 0)
1134 make_readable( arg2, sizeof(struct timezone) );
1135 }
1136 break;
1137
1138 case __NR_getuid: /* syscall 24 */
1139 /* uid_t getuid(void); */
1140 if (VG_(clo_trace_syscalls))
1141 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001142 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001143 break;
1144
1145# if defined(__NR_getuid32)
1146 case __NR_getuid32: /* syscall 199 */
1147 /* ???uid_t getuid32(void); */
1148 if (VG_(clo_trace_syscalls))
1149 VG_(printf)("getuid32 ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001150 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001151 break;
1152# endif
1153
1154 case __NR_ipc: /* syscall 117 */
1155 /* int ipc ( unsigned int call, int first, int second,
1156 int third, void *ptr, long fifth); */
1157 {
sewardj2e93c502002-04-12 11:12:52 +00001158 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001159
1160 if (VG_(clo_trace_syscalls))
1161 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1162 arg1,arg2,arg3,arg4,arg5,arg6);
1163 switch (arg1 /* call */) {
1164 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001165 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001166 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001167 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001168 break;
sewardj5b9e3502002-03-29 04:35:08 +00001169 case 2: /* IPCOP_semget */
1170 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001171 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001172 break;
1173 case 11: /* IPCOP_msgsnd */
1174 {
1175 struct msgbuf *msgp = (struct msgbuf *)arg5;
1176 Int msgsz = arg3;
1177
sewardj8c824512002-04-14 04:16:48 +00001178 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001179 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001180 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001181 (UInt)msgp->mtext, msgsz );
1182
sewardj2e93c502002-04-12 11:12:52 +00001183 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001184 break;
1185 }
1186 case 12: /* IPCOP_msgrcv */
1187 {
1188 struct msgbuf *msgp = ((struct ipc_kludge *)arg5)->msgp;
1189 Int msgsz = arg3;
1190
sewardj8c824512002-04-14 04:16:48 +00001191 must_be_writable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001192 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001193 must_be_writable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001194 (UInt)msgp->mtext, msgsz );
1195
sewardj2e93c502002-04-12 11:12:52 +00001196 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001197
1198 if ( !VG_(is_kerror)(res) && res > 0 ) {
1199 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1200 make_readable ( (UInt)msgp->mtext, res );
1201 }
1202 break;
1203 }
1204 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001205 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001206 break;
1207 case 14: /* IPCOP_msgctl */
1208 {
1209 switch (arg3 /* cmd */) {
1210 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001211 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001212 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001213 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001214 if ( !VG_(is_kerror)(res) && res > 0 ) {
1215 make_readable ( arg5, sizeof(struct msqid_ds) );
1216 }
1217 break;
1218 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001219 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001220 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001221 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001222 break;
sewardjc9add3b2002-04-16 01:58:19 +00001223# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001224 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001225 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001226 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001227 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001228 if ( !VG_(is_kerror)(res) && res > 0 ) {
1229 make_readable ( arg5, sizeof(struct msqid64_ds) );
1230 }
1231 break;
sewardjc9add3b2002-04-16 01:58:19 +00001232# endif
1233# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001234 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001235 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001236 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001237 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001238 break;
sewardjc9add3b2002-04-16 01:58:19 +00001239# endif
sewardj5b9e3502002-03-29 04:35:08 +00001240 default:
sewardj2e93c502002-04-12 11:12:52 +00001241 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001242 break;
1243 }
1244 break;
1245 }
sewardjde4a1d02002-03-22 01:27:54 +00001246 case 21: /* IPCOP_shmat */
1247 {
1248 Int shmid = arg2;
1249 Int shmflag = arg3;
1250 UInt addr;
1251
sewardj2e93c502002-04-12 11:12:52 +00001252 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001253
1254 if ( VG_(is_kerror) ( res ) )
1255 break;
1256
1257 /* force readability. before the syscall it is
1258 * indeed uninitialized, as can be seen in
1259 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1260 make_readable ( arg4, sizeof( ULong ) );
1261
1262 addr = safe_dereference ( arg4, 0 );
1263 if ( addr > 0 ) {
1264 UInt segmentSize = get_shm_size ( shmid );
1265 if ( segmentSize > 0 ) {
1266 if ( shmflag & SHM_RDONLY )
1267 make_readable ( addr, segmentSize );
1268 else
1269 make_readwritable ( addr, segmentSize );
1270 }
1271 }
1272 break;
1273 }
1274 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001275 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001276 /* ### FIXME: this should call make_noaccess on the
1277 * area passed to shmdt. But there's no way to
1278 * figure out the size of the shared memory segment
1279 * just from the address... Maybe we want to keep a
1280 * copy of the exiting mappings inside valgrind? */
1281 break;
1282 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001283 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001284 break;
1285 case 24: /* IPCOP_shmctl */
1286 {
1287 if ( arg3 > 0 ) {
sewardj8c824512002-04-14 04:16:48 +00001288 must_be_readable ( tst, "shmctl(buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001289 sizeof( struct shmid_ds ) );
1290
1291 if ( arg2 == SHM_STAT )
sewardj8c824512002-04-14 04:16:48 +00001292 must_be_writable( tst, "shmctl(IPC_STAT,buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001293 sizeof( struct shmid_ds ) );
1294 }
1295
sewardj2e93c502002-04-12 11:12:52 +00001296 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001297 break;
1298 }
1299 default:
1300 VG_(message)(Vg_DebugMsg,
1301 "FATAL: unhandled syscall(ipc) %d",
1302 arg1 );
1303 VG_(panic)("... bye!\n");
1304 break; /*NOTREACHED*/
1305 }
1306 }
1307 break;
1308
1309 case __NR_ioctl: /* syscall 54 */
1310 /* int ioctl(int d, int request, ...)
1311 [The "third" argument is traditionally char *argp,
1312 and will be so named for this discussion.]
1313 */
1314 /*
1315 VG_(message)(
1316 Vg_DebugMsg,
1317 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1318 arg2,arg1,arg3);
1319 */
1320 if (VG_(clo_trace_syscalls))
1321 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1322 switch (arg2 /* request */) {
1323 case TCSETS:
1324 case TCSETSW:
1325 case TCSETSF:
sewardj8c824512002-04-14 04:16:48 +00001326 must_be_readable( tst, "ioctl(TCSETSW)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001327 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001328 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001329 break;
1330 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001331 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001332 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001333 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001334 if (!VG_(is_kerror)(res) && res == 0)
1335 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1336 break;
sewardj2f0de322002-03-24 10:17:25 +00001337 case TCSETA:
sewardj8c824512002-04-14 04:16:48 +00001338 must_be_readable( tst, "ioctl(TCSETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001339 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001340 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001341 break;
1342 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001343 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001344 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001345 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001346 if (!VG_(is_kerror)(res) && res == 0)
1347 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1348 break;
sewardjde4a1d02002-03-22 01:27:54 +00001349 case TCSBRK:
1350 case TCSBRKP:
1351 case TCFLSH:
1352 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001353 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001354 break;
1355 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001356 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001357 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001358 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001359 if (!VG_(is_kerror)(res) && res == 0)
1360 make_readable ( arg3, sizeof(struct winsize) );
1361 break;
1362 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001363 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001364 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001365 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001366 break;
sewardj19fe3d02002-03-29 04:39:00 +00001367 case TIOCGPGRP:
1368 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001369 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001370 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001371 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001372 if (!VG_(is_kerror)(res) && res == 0)
1373 make_readable ( arg3, sizeof(pid_t) );
sewardjde4a1d02002-03-22 01:27:54 +00001374 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001375 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001376 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001377 if (!VG_(is_kerror)(res) && res == 0)
1378 make_readable ( arg3, sizeof(int));
1379 break;
sewardj73f1f072002-03-29 14:22:46 +00001380 case TIOCSCTTY:
1381 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001382 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001383 break;
sewardjde4a1d02002-03-22 01:27:54 +00001384 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001385 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001386 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001387 break;
1388 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001389 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001390 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001391 break;
1392 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001393 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001394 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001395 break;
1396 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001397 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001398 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001399 if (!VG_(is_kerror)(res) && res == 0)
1400 make_readable( arg3, sizeof(int) );
1401 break;
1402
1403 /* If you get compilation problems here, change the #if
1404 1 to #if 0 and get rid of <scsi/sg.h> in
1405 vg_unsafe.h. */
1406# if 1
1407 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001408 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1409 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001410 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001411 break;
1412# if defined(SG_IO)
1413 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001414 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001415 sizeof(struct sg_io_hdr) );
sewardj2e93c502002-04-12 11:12:52 +00001416 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001417 if (!VG_(is_kerror)(res) && res == 0)
1418 make_readable (arg3, sizeof(struct sg_io_hdr));
1419 break;
1420# endif /* SG_IO */
1421 case SG_GET_SCSI_ID:
1422 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001423 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001424 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001425 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001426 if (!VG_(is_kerror)(res) && res == 0)
1427 make_readable (arg3, sizeof(struct sg_scsi_id));
1428 break;
1429 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001430 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001431 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001432 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001433 break;
1434 case SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001435 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1436 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001437 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001438 break;
1439 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001440 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001441 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001442 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001443 if (!VG_(is_kerror)(res) && res == 0)
1444 make_readable (arg3, sizeof(int));
1445 break;
1446 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001447 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1448 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001449 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001450 if (!VG_(is_kerror)(res) && res == 0)
1451 make_readable (arg3, sizeof(int));
1452 break;
1453 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001454 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001455 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001456 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001457 break;
1458# endif
1459
1460 case IIOCGETCPS:
1461 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1462 * when KERNEL was. I never saw a larger value than 64 though */
1463# ifndef ISDN_MAX_CHANNELS
1464# define ISDN_MAX_CHANNELS 64
1465# endif
sewardj8c824512002-04-14 04:16:48 +00001466 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001467 ISDN_MAX_CHANNELS
1468 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001469 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001470 if (!VG_(is_kerror)(res) && res == 0)
1471 make_readable ( arg3, ISDN_MAX_CHANNELS
1472 * 2 * sizeof(unsigned long) );
1473 break;
1474 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001475 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001476 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1477 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001478 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001479 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001480 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001481 if (!VG_(is_kerror)(res) && res == 0)
1482 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1483 break;
1484
1485 /* These all use struct ifreq AFAIK */
1486 case SIOCGIFINDEX:
1487 case SIOCGIFFLAGS: /* get flags */
1488 case SIOCGIFHWADDR: /* Get hardware address */
1489 case SIOCGIFMTU: /* get MTU size */
1490 case SIOCGIFADDR: /* get PA address */
1491 case SIOCGIFNETMASK: /* get network PA mask */
1492 case SIOCGIFMETRIC: /* get metric */
1493 case SIOCGIFMAP: /* Get device parameters */
1494 case SIOCGIFTXQLEN: /* Get the tx queue length */
1495 case SIOCGIFDSTADDR: /* get remote PA address */
1496 case SIOCGIFBRDADDR: /* get broadcast PA address */
1497 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001498 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001499 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001500 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001501 if (!VG_(is_kerror)(res) && res == 0)
1502 make_readable (arg3, sizeof(struct ifreq));
1503 break;
1504 case SIOCGIFCONF: /* get iface list */
1505 /* WAS:
1506 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1507 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001508 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001509 if (!VG_(is_kerror)(res) && res == 0)
1510 make_readable (arg3, sizeof(struct ifconf));
1511 */
sewardj8c824512002-04-14 04:16:48 +00001512 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001513 sizeof(struct ifconf));
1514 if ( arg3 ) {
1515 // TODO len must be readable and writable
1516 // buf pointer only needs to be readable
1517 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001518 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001519 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1520 }
sewardj2e93c502002-04-12 11:12:52 +00001521 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001522 if (!VG_(is_kerror)(res) && res == 0 && arg3 ) {
1523 struct ifconf *ifc = (struct ifconf *) arg3;
1524 make_readable ( (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1525 }
1526 break;
1527 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001528 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001529 sizeof(struct timeval));
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 timeval));
1533 break;
1534 case SIOCGRARP: /* get RARP table entry */
1535 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001536 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001537 sizeof(struct arpreq));
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 arpreq));
1541 break;
1542
1543 case SIOCSIFFLAGS: /* set flags */
1544 case SIOCSIFMAP: /* Set device parameters */
1545 case SIOCSIFTXQLEN: /* Set the tx queue length */
1546 case SIOCSIFDSTADDR: /* set remote PA address */
1547 case SIOCSIFBRDADDR: /* set broadcast PA address */
1548 case SIOCSIFNETMASK: /* set network PA mask */
1549 case SIOCSIFMETRIC: /* set metric */
1550 case SIOCSIFADDR: /* set PA address */
1551 case SIOCSIFMTU: /* set MTU size */
1552 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001553 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001554 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001555 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001556 break;
1557 /* Routing table calls. */
1558 case SIOCADDRT: /* add routing table entry */
1559 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001560 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001561 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001562 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001563 break;
1564
1565 /* RARP cache control calls. */
1566 case SIOCDRARP: /* delete RARP table entry */
1567 case SIOCSRARP: /* set RARP table entry */
1568 /* ARP cache control calls. */
1569 case SIOCSARP: /* set ARP table entry */
1570 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001571 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001572 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001573 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001574 break;
1575
1576 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001577 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001578 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001579 break;
1580
1581 /* linux/soundcard interface (OSS) */
1582 case SNDCTL_SEQ_GETOUTCOUNT:
1583 case SNDCTL_SEQ_GETINCOUNT:
1584 case SNDCTL_SEQ_PERCMODE:
1585 case SNDCTL_SEQ_TESTMIDI:
1586 case SNDCTL_SEQ_RESETSAMPLES:
1587 case SNDCTL_SEQ_NRSYNTHS:
1588 case SNDCTL_SEQ_NRMIDIS:
1589 case SNDCTL_SEQ_GETTIME:
1590 case SNDCTL_DSP_GETFMTS:
1591 case SNDCTL_DSP_GETTRIGGER:
1592 case SNDCTL_DSP_GETODELAY:
1593# if defined(SNDCTL_DSP_GETSPDIF)
1594 case SNDCTL_DSP_GETSPDIF:
1595# endif
1596 case SNDCTL_DSP_GETCAPS:
1597 case SOUND_PCM_READ_RATE:
1598 case SOUND_PCM_READ_CHANNELS:
1599 case SOUND_PCM_READ_BITS:
1600 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1601 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001602 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1603 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001604 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001605 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001606 if (!VG_(is_kerror)(res) && res == 0)
1607 make_readable (arg3, sizeof(int));
1608 break;
1609 case SNDCTL_SEQ_CTRLRATE:
1610 case SNDCTL_DSP_SPEED:
1611 case SNDCTL_DSP_STEREO:
1612 case SNDCTL_DSP_GETBLKSIZE:
1613 case SNDCTL_DSP_CHANNELS:
1614 case SOUND_PCM_WRITE_FILTER:
1615 case SNDCTL_DSP_SUBDIVIDE:
1616 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001617# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001618 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001619# endif
1620# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001621 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001622# endif
sewardjde4a1d02002-03-22 01:27:54 +00001623 case SNDCTL_TMR_TIMEBASE:
1624 case SNDCTL_TMR_TEMPO:
1625 case SNDCTL_TMR_SOURCE:
1626 case SNDCTL_MIDI_PRETIME:
1627 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001628 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1629 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001630 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001631 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1632 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001633 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001634 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001635 break;
1636 case SNDCTL_DSP_GETOSPACE:
1637 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001638 must_be_writable(tst,
1639 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001640 "(SIOR, audio_buf_info))", arg3,
1641 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001642 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001643 if (!VG_(is_kerror)(res) && res == 0)
1644 make_readable (arg3, sizeof(audio_buf_info));
1645 break;
1646 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001647 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001648 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001649 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001650 break;
1651
1652 /* We don't have any specific information on it, so
1653 try to do something reasonable based on direction and
1654 size bits. The encoding scheme is described in
1655 /usr/include/asm/ioctl.h. */
1656 default: {
1657 UInt dir = _IOC_DIR(arg2);
1658 UInt size = _IOC_SIZE(arg2);
1659 if (/* size == 0 || */ dir == _IOC_NONE) {
1660 VG_(message)(Vg_UserMsg,
1661 "Warning: noted but unhandled ioctl 0x%x"
1662 " with no size/direction hints",
1663 arg2);
1664 VG_(message)(Vg_UserMsg,
1665 " This could cause spurious value errors"
1666 " to appear.");
1667 VG_(message)(Vg_UserMsg,
1668 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
1669 " writing a proper wrapper." );
1670 } else {
1671 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001672 must_be_readable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001673 if ((dir & _IOC_WRITE) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001674 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001675 }
sewardj2e93c502002-04-12 11:12:52 +00001676 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001677 if (size > 0 && (dir & _IOC_WRITE)
1678 && !VG_(is_kerror)(res) && res == 0)
1679 make_readable (arg3, size);
1680 break;
1681 }
1682 }
1683 break;
1684
1685 case __NR_kill: /* syscall 37 */
1686 /* int kill(pid_t pid, int sig); */
1687 if (VG_(clo_trace_syscalls))
1688 VG_(printf)("kill ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001689 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001690 break;
1691
1692 case __NR_link: /* syscall 9 */
1693 /* int link(const char *oldpath, const char *newpath); */
1694 if (VG_(clo_trace_syscalls))
1695 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00001696 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
1697 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00001698 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001699 break;
1700
1701 case __NR_lseek: /* syscall 19 */
1702 /* off_t lseek(int fildes, off_t offset, int whence); */
1703 if (VG_(clo_trace_syscalls))
1704 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001705 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001706 break;
1707
1708 case __NR__llseek: /* syscall 140 */
1709 /* int _llseek(unsigned int fd, unsigned long offset_high,
1710 unsigned long offset_low,
1711 loff_t * result, unsigned int whence); */
1712 if (VG_(clo_trace_syscalls))
1713 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
1714 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00001715 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00001716 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001717 if (!VG_(is_kerror)(res) && res == 0)
1718 make_readable( arg4, sizeof(loff_t) );
1719 break;
1720
1721 case __NR_lstat: /* syscall 107 */
1722 /* int lstat(const char *file_name, struct stat *buf); */
1723 if (VG_(clo_trace_syscalls))
1724 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001725 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
1726 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001727 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001728 if (!VG_(is_kerror)(res) && res == 0) {
1729 make_readable( arg2, sizeof(struct stat) );
1730 }
1731 break;
1732
1733# if defined(__NR_lstat64)
1734 case __NR_lstat64: /* syscall 196 */
1735 /* int lstat64(const char *file_name, struct stat64 *buf); */
1736 if (VG_(clo_trace_syscalls))
1737 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001738 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
1739 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00001740 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001741 if (!VG_(is_kerror)(res) && res == 0) {
1742 make_readable( arg2, sizeof(struct stat64) );
1743 }
1744 break;
1745# endif
1746
1747 case __NR_mkdir: /* syscall 39 */
1748 /* int mkdir(const char *pathname, mode_t mode); */
1749 if (VG_(clo_trace_syscalls))
1750 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001751 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001752 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001753 break;
1754
1755# if defined(__NR_mmap2)
1756 case __NR_mmap2: /* syscall 192 */
1757 /* My impression is that this is exactly like __NR_mmap
1758 except that all 6 args are passed in regs, rather than in
1759 a memory-block. */
1760 /* void* mmap(void *start, size_t length, int prot,
1761 int flags, int fd, off_t offset);
1762 */
1763 {
sewardj2e93c502002-04-12 11:12:52 +00001764 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001765 if (VG_(clo_trace_syscalls))
1766 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
1767 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00001768 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001769 /* !!! shouldn't we also be doing the symtab loading stuff as
1770 in __NR_mmap ? */
1771 if (!VG_(is_kerror)(res))
1772 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1773 }
1774 break;
1775# endif
1776
1777 case __NR_mmap: /* syscall 90 */
1778 /* void* mmap(void *start, size_t length, int prot,
1779 int flags, int fd, off_t offset);
1780 */
1781 {
1782 Bool arg_block_readable
1783 = VG_(clo_instrument)
1784 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
1785 : True;
sewardj8c824512002-04-14 04:16:48 +00001786 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00001787 if (arg_block_readable) {
1788 UInt* arg_block = (UInt*)arg1;
1789 UInt arg6;
1790 arg1 = arg_block[0];
1791 arg2 = arg_block[1];
1792 arg3 = arg_block[2];
1793 arg4 = arg_block[3];
1794 arg5 = arg_block[4];
1795 arg6 = arg_block[5];
1796 if (VG_(clo_trace_syscalls))
1797 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
1798 arg1, arg2, arg3, arg4, arg5, arg6 );
1799 }
sewardj2e93c502002-04-12 11:12:52 +00001800 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001801 if (arg_block_readable && !VG_(is_kerror)(res))
1802 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1803 if (arg_block_readable && !VG_(is_kerror)(res)
1804 && (arg3 & PROT_EXEC)) {
1805 /* The client mmap'ed a segment with executable
1806 permissions. Tell the symbol-table loader, so that it
1807 has an opportunity to pick up more symbols if this mmap
1808 was caused by the client loading a new .so via
1809 dlopen(). This is important for debugging KDE. */
1810 VG_(read_symbols)();
1811 }
1812 }
1813
1814 break;
1815
1816 case __NR_mprotect: /* syscall 125 */
1817 /* int mprotect(const void *addr, size_t len, int prot); */
1818 /* should addr .. addr+len-1 be checked before the call? */
1819 if (VG_(clo_trace_syscalls))
1820 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001821 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001822 if (!VG_(is_kerror)(res))
1823 approximate_mmap_permissions ( arg1, arg2, arg3 );
1824 break;
1825
1826 case __NR_munmap: /* syscall 91 */
1827 /* int munmap(void *start, size_t length); */
1828 /* should start .. start+length-1 be checked before the call? */
1829 if (VG_(clo_trace_syscalls))
1830 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001831 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001832 if (!VG_(is_kerror)(res)) {
1833 /* Mash around start and length so that the area passed to
1834 make_noaccess() exactly covers an integral number of
1835 pages. If we don't do that, our idea of addressible
1836 memory diverges from that of the kernel's, which causes
1837 the leak detector to crash. */
1838 Addr start = arg1;
1839 Addr length = arg2;
1840 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
1841 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
1842 /*
1843 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
1844 arg1, arg2, start, length, (arg1!=start || arg2!=length)
1845 ? "CHANGE" : "");
1846 */
1847 make_noaccess( start, length );
1848 /* Tell our symbol table machinery about this, so that if
1849 this happens to be a .so being unloaded, the relevant
1850 symbols are removed too. */
1851 VG_(symtab_notify_munmap) ( start, length );
1852 }
1853 break;
1854
1855 case __NR_nanosleep: /* syscall 162 */
1856 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
1857 if (VG_(clo_trace_syscalls))
1858 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001859 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00001860 sizeof(struct timespec) );
1861 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00001862 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001863 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00001864 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001865 /* Somewhat bogus ... is only written by the kernel if
1866 res == -1 && errno == EINTR. */
1867 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
1868 make_readable ( arg2, sizeof(struct timespec) );
1869 break;
1870
1871 case __NR__newselect: /* syscall 142 */
1872 /* int select(int n,
1873 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1874 struct timeval *timeout);
1875 */
1876 if (VG_(clo_trace_syscalls))
1877 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
1878 arg1,arg2,arg3,arg4,arg5);
1879 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001880 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001881 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
1882 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00001883 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00001884 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
1885 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00001886 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001887 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
1888 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00001889 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00001890 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00001891 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001892 break;
1893
1894 case __NR_open: /* syscall 5 */
1895 /* int open(const char *pathname, int flags); */
1896 if (VG_(clo_trace_syscalls))
1897 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001898 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001899 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001900 if (VG_(clo_trace_syscalls))
1901 VG_(printf)("%d\n",res);
1902 break;
1903
1904 case __NR_pipe: /* syscall 42 */
1905 /* int pipe(int filedes[2]); */
1906 if (VG_(clo_trace_syscalls))
1907 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001908 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001909 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001910 if (!VG_(is_kerror)(res))
1911 make_readable ( arg1, 2*sizeof(int) );
1912 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00001913 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
1914 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001915 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
1916 break;
1917
1918 case __NR_poll: /* syscall 168 */
1919 /* struct pollfd {
1920 int fd; -- file descriptor
1921 short events; -- requested events
1922 short revents; -- returned events
1923 };
1924 int poll(struct pollfd *ufds, unsigned int nfds,
1925 int timeout)
1926 */
1927 if (VG_(clo_trace_syscalls))
1928 VG_(printf)("poll ( %d, %d, %d )\n",arg1,arg2,arg3);
1929 /* In fact some parts of this struct should be readable too.
1930 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00001931 must_be_writable( tst, "poll(ufds)",
1932 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00001933 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001934 if (!VG_(is_kerror)(res) && res > 0) {
1935 Int i;
1936 struct pollfd * arr = (struct pollfd *)arg1;
1937 for (i = 0; i < arg2; i++)
1938 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
1939 }
1940 break;
1941
sewardjde4a1d02002-03-22 01:27:54 +00001942 case __NR_readlink: /* syscall 85 */
1943 /* int readlink(const char *path, char *buf, size_t bufsiz); */
1944 if (VG_(clo_trace_syscalls))
1945 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001946 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
1947 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001948 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001949 if (!VG_(is_kerror)(res) && res > 0) {
1950 make_readable ( arg2, res );
1951 }
1952 break;
1953
1954 case __NR_readv: { /* syscall 145 */
1955 /* int readv(int fd, const struct iovec * vector, size_t count); */
1956 UInt i;
1957 struct iovec * vec;
1958 if (VG_(clo_trace_syscalls))
1959 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001960 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00001961 arg2, arg3 * sizeof(struct iovec) );
1962 /* ToDo: don't do any of the following if the vector is invalid */
1963 vec = (struct iovec *)arg2;
1964 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00001965 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00001966 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00001967 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001968 if (!VG_(is_kerror)(res) && res > 0) {
1969 /* res holds the number of bytes read. */
1970 for (i = 0; i < arg3; i++) {
1971 Int nReadThisBuf = vec[i].iov_len;
1972 if (nReadThisBuf > res) nReadThisBuf = res;
1973 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
1974 res -= nReadThisBuf;
1975 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
1976 }
1977 }
1978 break;
1979 }
1980
1981 case __NR_rename: /* syscall 38 */
1982 /* int rename(const char *oldpath, const char *newpath); */
1983 if (VG_(clo_trace_syscalls))
1984 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00001985 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
1986 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00001987 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001988 break;
1989
1990 case __NR_rmdir: /* syscall 40 */
1991 /* int rmdir(const char *pathname); */
1992 if (VG_(clo_trace_syscalls))
1993 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001994 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001995 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001996 break;
1997
1998 case __NR_sched_setparam:
1999 case __NR_sched_getparam:
2000 case __NR_sched_yield:
2001 case __NR_sched_get_priority_min:
2002 if (VG_(clo_instrument)) {
2003 VG_(message)(Vg_UserMsg,
2004 "Warning: noted but unhandled __NR_sched_* syscall (%d).",
2005 syscallno);
2006 VG_(message)(Vg_UserMsg,
2007 " This could cause spurious value errors"
2008 " to appear.");
2009 }
sewardj2e93c502002-04-12 11:12:52 +00002010 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002011 break;
2012
2013 case __NR_select: /* syscall 82 */
2014 /* struct sel_arg_struct {
2015 unsigned long n;
2016 fd_set *inp, *outp, *exp;
2017 struct timeval *tvp;
2018 };
2019 int old_select(struct sel_arg_struct *arg);
2020 */
2021 {
2022 Bool arg_block_readable
2023 = VG_(clo_instrument)
2024 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
2025 : True;
sewardj8c824512002-04-14 04:16:48 +00002026 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002027 if (arg_block_readable) {
2028 UInt* arg_struct = (UInt*)arg1;
2029 arg1 = arg_struct[0];
2030 arg2 = arg_struct[1];
2031 arg3 = arg_struct[2];
2032 arg4 = arg_struct[3];
2033 arg5 = arg_struct[4];
2034
2035 if (VG_(clo_trace_syscalls))
2036 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2037 arg1,arg2,arg3,arg4,arg5);
2038 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002039 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002040 arg1/8 /* __FD_SETSIZE/8 */ );
2041 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002042 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002043 arg1/8 /* __FD_SETSIZE/8 */ );
2044 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002045 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002046 arg1/8 /* __FD_SETSIZE/8 */ );
2047 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002048 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002049 sizeof(struct timeval) );
2050 }
2051 }
sewardj2e93c502002-04-12 11:12:52 +00002052 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002053 break;
2054
2055 case __NR_setitimer: /* syscall 104 */
2056 /* setitimer(int which, const struct itimerval *value,
2057 struct itimerval *ovalue); */
2058 if (VG_(clo_trace_syscalls))
2059 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002060 must_be_readable(tst, "setitimer(value)",
sewardjde4a1d02002-03-22 01:27:54 +00002061 arg2, sizeof(struct itimerval) );
2062 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002063 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002064 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002065 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002066 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2067 make_readable(arg3, sizeof(struct itimerval));
2068 }
2069 break;
2070
2071# if defined(__NR_setfsgid32)
2072 case __NR_setfsgid32: /* syscall 216 */
2073 /* int setfsgid(uid_t fsgid); */
2074 if (VG_(clo_trace_syscalls))
2075 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002076 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002077 break;
2078# endif
2079
2080# if defined(__NR_setgid32)
2081 case __NR_setgid32: /* syscall 214 */
2082# endif
2083 case __NR_setgid: /* syscall 46 */
2084 /* int setgid(gid_t gid); */
2085 if (VG_(clo_trace_syscalls))
2086 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002087 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002088 break;
2089
2090 case __NR_setsid: /* syscall 66 */
2091 /* pid_t setsid(void); */
2092 if (VG_(clo_trace_syscalls))
2093 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002094 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002095 break;
2096
2097# if defined(__NR_setgroups32)
2098 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002099# endif
2100 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002101 /* int setgroups(size_t size, const gid_t *list); */
2102 if (VG_(clo_trace_syscalls))
2103 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2104 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002105 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002106 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002107 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002108 break;
sewardjde4a1d02002-03-22 01:27:54 +00002109
2110 case __NR_setpgid: /* syscall 57 */
2111 /* int setpgid(pid_t pid, pid_t pgid); */
2112 if (VG_(clo_trace_syscalls))
2113 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002114 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002115 break;
2116
2117# if defined(__NR_setregid32)
2118 case __NR_setregid32: /* syscall 204 */
2119 /* int setregid(gid_t rgid, gid_t egid); */
2120 if (VG_(clo_trace_syscalls))
2121 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002122 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002123 break;
2124# endif
2125
2126# if defined(__NR_setresuid32)
2127 case __NR_setresuid32: /* syscall 208 */
2128 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2129 if (VG_(clo_trace_syscalls))
2130 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002131 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002132 break;
2133# endif
2134
2135# if defined(__NR_setreuid32)
2136 case __NR_setreuid32: /* syscall 203 */
2137# endif
2138 case __NR_setreuid: /* syscall 70 */
2139 /* int setreuid(uid_t ruid, uid_t euid); */
2140 if (VG_(clo_trace_syscalls))
2141 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002142 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002143 break;
2144
2145 case __NR_setrlimit: /* syscall 75 */
2146 /* int setrlimit (int resource, const struct rlimit *rlim); */
2147 if (VG_(clo_trace_syscalls))
2148 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002149 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002150 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002151 break;
2152
2153# if defined(__NR_setuid32)
2154 case __NR_setuid32: /* syscall 213 */
2155# endif
2156 case __NR_setuid: /* syscall 23 */
2157 /* int setuid(uid_t uid); */
2158 if (VG_(clo_trace_syscalls))
2159 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002160 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002161 break;
2162
2163 case __NR_socketcall: /* syscall 102 */
2164 /* int socketcall(int call, unsigned long *args); */
2165 if (VG_(clo_trace_syscalls))
2166 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2167 switch (arg1 /* request */) {
2168
2169 case SYS_SOCKETPAIR:
2170 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002171 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002172 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002173 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002174 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002175 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002176 if (!VG_(is_kerror)(res))
2177 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2178 break;
2179
2180 case SYS_SOCKET:
2181 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002182 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002183 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002184 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002185 break;
2186
2187 case SYS_BIND:
2188 /* int bind(int sockfd, struct sockaddr *my_addr,
2189 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002190 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002191 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002192 must_be_readable( tst, "socketcall.bind(my_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002193 ((UInt*)arg2)[1], ((UInt*)arg2)[2] );
sewardj2e93c502002-04-12 11:12:52 +00002194 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002195 break;
2196
2197 case SYS_LISTEN:
2198 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002199 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002200 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002201 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002202 break;
2203
2204 case SYS_ACCEPT: {
2205 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2206 Addr addr;
2207 Addr p_addrlen;
2208 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002209 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002210 arg2, 3*sizeof(Addr) );
2211 addr = ((UInt*)arg2)[1];
2212 p_addrlen = ((UInt*)arg2)[2];
2213 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002214 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002215 p_addrlen, sizeof(int) );
2216 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002217 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002218 addr, addrlen_in );
2219 }
sewardj2e93c502002-04-12 11:12:52 +00002220 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002221 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2222 addrlen_out = safe_dereference( p_addrlen, 0 );
2223 if (addrlen_out > 0)
2224 make_readable( addr, addrlen_out );
2225 }
2226 break;
2227 }
2228
2229 case SYS_SENDTO:
2230 /* int sendto(int s, const void *msg, int len,
2231 unsigned int flags,
2232 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002233 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002234 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002235 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002236 ((UInt*)arg2)[1], /* msg */
2237 ((UInt*)arg2)[2] /* len */ );
sewardj8c824512002-04-14 04:16:48 +00002238 must_be_readable( tst, "socketcall.sendto(to)",
sewardjde4a1d02002-03-22 01:27:54 +00002239 ((UInt*)arg2)[4], /* to */
2240 ((UInt*)arg2)[5] /* tolen */ );
sewardj2e93c502002-04-12 11:12:52 +00002241 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002242 break;
2243
2244 case SYS_SEND:
2245 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002246 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002247 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002248 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002249 ((UInt*)arg2)[1], /* msg */
2250 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002251 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002252 break;
2253
2254 case SYS_RECVFROM:
2255 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2256 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002257 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002258 arg2, 6*sizeof(Addr) );
2259 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002260 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002261 ((UInt*)arg2)[5] /* fromlen */,
2262 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002263 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002264 ((UInt*)arg2)[4], /*from*/
2265 safe_dereference( (Addr)
2266 ((UInt*)arg2)[5], 0 ) );
2267 }
sewardj8c824512002-04-14 04:16:48 +00002268 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002269 ((UInt*)arg2)[1], /* buf */
2270 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002271 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002272 if (!VG_(is_kerror)(res) && res >= 0) {
2273 make_readable( ((UInt*)arg2)[1], /* buf */
2274 ((UInt*)arg2)[2] /* len */ );
2275 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2276 make_readable(
2277 ((UInt*)arg2)[4], /*from*/
2278 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2279 }
2280 }
2281 /* phew! */
2282 break;
2283
2284 case SYS_RECV:
2285 /* int recv(int s, void *buf, int len, unsigned int flags); */
2286 /* man 2 recv says:
2287 The recv call is normally used only on a connected socket
2288 (see connect(2)) and is identical to recvfrom with a NULL
2289 from parameter.
2290 */
sewardj8c824512002-04-14 04:16:48 +00002291 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002292 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002293 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002294 ((UInt*)arg2)[1], /* buf */
2295 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002296 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002297 if (!VG_(is_kerror)(res) && res >= 0
2298 && ((UInt*)arg2)[1] != (UInt)NULL) {
2299 make_readable( ((UInt*)arg2)[1], /* buf */
2300 ((UInt*)arg2)[2] /* len */ );
2301 }
2302 break;
2303
2304 case SYS_CONNECT: {
2305 struct sockaddr *sa;
2306 /* int connect(int sockfd,
2307 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002308 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002309 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002310 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002311 ((UInt*)arg2)[1], /* serv_addr */
2312 sizeof (sa_family_t));
2313 sa = (struct sockaddr *) (((UInt*)arg2)[1]);
2314 if (sa->sa_family == AF_UNIX)
sewardj8c824512002-04-14 04:16:48 +00002315 must_be_readable_asciiz( tst,
sewardjde4a1d02002-03-22 01:27:54 +00002316 "socketcall.connect(serv_addr.sun_path)",
2317 (UInt) ((struct sockaddr_un *) sa)->sun_path);
2318 /* XXX There probably should be more cases here since not
2319 all of the struct sockaddr_XXX must be initialized. But
2320 wait until something pops up. */
2321 else
sewardj8c824512002-04-14 04:16:48 +00002322 must_be_readable( tst, "socketcall.connect(serv_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002323 ((UInt*)arg2)[1], /* serv_addr */
2324 ((UInt*)arg2)[2] /* addrlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002325 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002326 break;
2327 }
2328
2329 case SYS_SETSOCKOPT:
2330 /* int setsockopt(int s, int level, int optname,
2331 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002332 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002333 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002334 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002335 ((UInt*)arg2)[3], /* optval */
2336 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002337 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002338 break;
2339
2340 case SYS_GETSOCKOPT:
2341 /* int setsockopt(int s, int level, int optname,
2342 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002343 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002344 arg2, 5*sizeof(Addr) );
2345 {
2346 Addr optval_p = ((UInt*)arg2)[3];
2347 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002348 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002349 UInt optlen_after;
2350 UInt optlen = safe_dereference ( optlen_p, 0 );
2351 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002352 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002353 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002354 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002355 optlen_after = safe_dereference ( optlen_p, 0 );
2356 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2357 make_readable( optval_p, optlen_after );
2358 }
2359 break;
2360
2361 case SYS_GETSOCKNAME:
2362 /* int getsockname(int s, struct sockaddr* name,
2363 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002364 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002365 arg2, 3*sizeof(Addr) );
2366 {
2367 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2368 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002369 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002370 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002371 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002372 if (!VG_(is_kerror)(res)) {
2373 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2374 if (namelen > 0
2375 && ((UInt*)arg2)[1] != (UInt)NULL)
2376 make_readable( ((UInt*)arg2)[1], namelen );
2377 }
2378 }
2379 break;
2380
2381 case SYS_GETPEERNAME:
2382 /* int getpeername(int s, struct sockaddr* name,
2383 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002384 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002385 arg2, 3*sizeof(Addr) );
2386 {
2387 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2388 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002389 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002390 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002391 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002392 if (!VG_(is_kerror)(res)) {
2393 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2394 if (namelen > 0
2395 && ((UInt*)arg2)[1] != (UInt)NULL)
2396 make_readable( ((UInt*)arg2)[1], namelen );
2397 }
2398 }
2399 break;
2400
2401 case SYS_SHUTDOWN:
2402 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002403 must_be_readable( tst, "socketcall.shutdown(args)",
2404 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002405 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002406 break;
2407
2408 case SYS_SENDMSG:
2409 {
2410 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2411
2412 /* this causes warnings, and I don't get why. glibc bug?
2413 * (after all it's glibc providing the arguments array)
2414 must_be_readable( "socketcall.sendmsg(args)",
2415 arg2, 3*sizeof(Addr) );
2416 */
2417
2418 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002419 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002420
sewardj2e93c502002-04-12 11:12:52 +00002421 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002422 break;
2423 }
2424
2425 case SYS_RECVMSG:
2426 {
2427 /* int recvmsg(int s, struct msghdr *msg, int flags); */
2428
2429 /* this causes warnings, and I don't get why. glibc bug?
2430 * (after all it's glibc providing the arguments array)
2431 must_be_readable( "socketcall.recvmsg(args)",
2432 arg2, 3*sizeof(Addr) );
2433 */
2434
2435 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002436 msghdr_foreachfield ( tst, msg, must_be_writable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002437
sewardj2e93c502002-04-12 11:12:52 +00002438 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002439
2440 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002441 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002442
2443 break;
2444 }
2445
2446 default:
2447 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2448 VG_(panic)("... bye!\n");
2449 break; /*NOTREACHED*/
2450 }
2451 break;
2452
2453 case __NR_stat: /* syscall 106 */
2454 /* int stat(const char *file_name, struct stat *buf); */
2455 if (VG_(clo_trace_syscalls))
2456 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002457 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2458 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002459 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002460 if (!VG_(is_kerror)(res))
2461 make_readable( arg2, sizeof(struct stat) );
2462 break;
2463
2464 case __NR_statfs: /* syscall 99 */
2465 /* int statfs(const char *path, struct statfs *buf); */
2466 if (VG_(clo_trace_syscalls))
2467 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002468 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2469 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002470 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002471 if (!VG_(is_kerror)(res))
2472 make_readable( arg2, sizeof(struct statfs) );
2473 break;
2474
2475 case __NR_symlink: /* syscall 83 */
2476 /* int symlink(const char *oldpath, const char *newpath); */
2477 if (VG_(clo_trace_syscalls))
2478 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002479 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2480 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002481 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002482 break;
2483
2484# if defined(__NR_stat64)
2485 case __NR_stat64: /* syscall 195 */
2486 /* int stat64(const char *file_name, struct stat64 *buf); */
2487 if (VG_(clo_trace_syscalls))
2488 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002489 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2490 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002491 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002492 if (!VG_(is_kerror)(res))
2493 make_readable( arg2, sizeof(struct stat64) );
2494 break;
2495# endif
2496
2497# if defined(__NR_fstat64)
2498 case __NR_fstat64: /* syscall 197 */
2499 /* int fstat64(int filedes, struct stat64 *buf); */
2500 if (VG_(clo_trace_syscalls))
2501 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002502 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002503 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002504 if (!VG_(is_kerror)(res))
2505 make_readable( arg2, sizeof(struct stat64) );
2506 break;
2507# endif
2508
2509 case __NR_sysinfo: /* syscall 116 */
2510 /* int sysinfo(struct sysinfo *info); */
2511 if (VG_(clo_trace_syscalls))
2512 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002513 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002514 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002515 if (!VG_(is_kerror)(res))
2516 make_readable( arg1, sizeof(struct sysinfo) );
2517 break;
2518
2519 case __NR_time: /* syscall 13 */
2520 /* time_t time(time_t *t); */
2521 if (VG_(clo_trace_syscalls))
2522 VG_(printf)("time ( %p )\n",arg1);
2523 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002524 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002525 }
sewardj2e93c502002-04-12 11:12:52 +00002526 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002527 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2528 make_readable( arg1, sizeof(time_t) );
2529 }
2530 break;
2531
2532 case __NR_times: /* syscall 43 */
2533 /* clock_t times(struct tms *buf); */
2534 if (VG_(clo_trace_syscalls))
2535 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002536 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002537 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002538 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2539 make_readable( arg1, sizeof(struct tms) );
2540 }
2541 break;
2542
2543 case __NR_truncate: /* syscall 92 */
2544 /* int truncate(const char *path, size_t length); */
2545 if (VG_(clo_trace_syscalls))
2546 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002547 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002548 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002549 break;
2550
2551 case __NR_umask: /* syscall 60 */
2552 /* mode_t umask(mode_t mask); */
2553 if (VG_(clo_trace_syscalls))
2554 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002555 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002556 break;
2557
2558 case __NR_unlink: /* syscall 10 */
2559 /* int unlink(const char *pathname) */
2560 if (VG_(clo_trace_syscalls))
2561 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002562 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002563 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002564 break;
2565
2566 case __NR_uname: /* syscall 122 */
2567 /* int uname(struct utsname *buf); */
2568 if (VG_(clo_trace_syscalls))
2569 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002570 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002571 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002572 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2573 make_readable( arg1, sizeof(struct utsname) );
2574 }
2575 break;
2576
2577 case __NR_utime: /* syscall 30 */
2578 /* int utime(const char *filename, struct utimbuf *buf); */
2579 if (VG_(clo_trace_syscalls))
2580 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002581 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00002582 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002583 must_be_readable( tst, "utime(buf)", arg2,
2584 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00002585 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002586 break;
2587
2588 case __NR_wait4: /* syscall 114 */
2589 /* pid_t wait4(pid_t pid, int *status, int options,
2590 struct rusage *rusage) */
2591 if (VG_(clo_trace_syscalls))
2592 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
2593 arg1,arg2,arg3,arg4);
2594 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002595 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00002596 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002597 must_be_writable( tst, "wait4(rusage)", arg4,
2598 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00002599 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002600 if (!VG_(is_kerror)(res)) {
2601 if (arg2 != (Addr)NULL)
2602 make_readable( arg2, sizeof(int) );
2603 if (arg4 != (Addr)NULL)
2604 make_readable( arg4, sizeof(struct rusage) );
2605 }
2606 break;
2607
sewardjde4a1d02002-03-22 01:27:54 +00002608 case __NR_writev: { /* syscall 146 */
2609 /* int writev(int fd, const struct iovec * vector, size_t count); */
2610 UInt i;
2611 struct iovec * vec;
2612 if (VG_(clo_trace_syscalls))
2613 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002614 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002615 arg2, arg3 * sizeof(struct iovec) );
2616 /* ToDo: don't do any of the following if the vector is invalid */
2617 vec = (struct iovec *)arg2;
2618 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002619 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002620 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002621 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002622 break;
2623 }
2624
2625 /*-------------------------- SIGNALS --------------------------*/
2626
2627 /* Normally set to 1, so that Valgrind's signal-simulation machinery
2628 is engaged. Sometimes useful to disable (set to 0), for
2629 debugging purposes, to make clients more deterministic. */
2630# define SIGNAL_SIMULATION 1
2631
2632 case __NR_rt_sigaction:
2633 case __NR_sigaction:
2634 /* int sigaction(int signum, struct k_sigaction *act,
2635 struct k_sigaction *oldact); */
2636 if (VG_(clo_trace_syscalls))
2637 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
2638 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002639 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00002640 arg2, sizeof(vki_ksigaction));
2641 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002642 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00002643 arg3, sizeof(vki_ksigaction));
2644 /* We do this one ourselves! */
2645# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00002646 VG_(do__NR_sigaction)(tid);
2647 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00002648# else
2649 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00002650 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002651# endif
2652 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2653 make_readable( arg3, sizeof(vki_ksigaction));
2654 break;
2655
2656 case __NR_rt_sigprocmask:
2657 case __NR_sigprocmask:
2658 /* int sigprocmask(int how, k_sigset_t *set,
2659 k_sigset_t *oldset); */
2660 if (VG_(clo_trace_syscalls))
2661 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
2662 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002663 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00002664 arg2, sizeof(vki_ksigset_t));
2665 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002666 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00002667 arg3, sizeof(vki_ksigset_t));
sewardj2e93c502002-04-12 11:12:52 +00002668 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002669 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2670 make_readable( arg3, sizeof(vki_ksigset_t));
2671# if SIGNAL_SIMULATION
2672 /* For the reason why both the kernel and Valgrind process
2673 sigprocmask, see the detailed comment at
2674 vg_do__NR_sigprocmask(). */
2675 VG_(do__NR_sigprocmask) ( arg1 /*how*/, (vki_ksigset_t*) arg2 );
2676# endif
2677 break;
2678
2679 default:
2680 VG_(message)
2681 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
2682 VG_(message)
2683 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
2684 VG_(message)
2685 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
2686 VG_(unimplemented)("no wrapper for the above system call");
2687 vg_assert(3+3 == 7);
2688 break; /*NOTREACHED*/
2689 }
2690
sewardjde4a1d02002-03-22 01:27:54 +00002691 /* { void zzzmemscan(void); zzzmemscan(); } */
2692
sewardjde4a1d02002-03-22 01:27:54 +00002693 if (! VG_(first_and_last_secondaries_look_plausible))
2694 sane_before_call = False;
2695
2696 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00002697 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00002698 VG_(message)(Vg_DebugMsg,
2699 "probable sanity check failure for syscall number %d\n",
2700 syscallno );
2701 VG_(panic)("aborting due to the above ... bye!");
2702 }
2703
2704 VGP_POPCC;
2705}
2706
2707
sewardj2e93c502002-04-12 11:12:52 +00002708
2709/* Perform pre- and post- actions for a blocking syscall, but do not
2710 do the syscall itself. If res is NULL, the pre-syscall actions are
2711 to be performed. If res is non-NULL, the post-syscall actions are
2712 to be performed, and *res is assumed to hold the result of the
2713 syscall. This slightly strange scheme makes it impossible to
2714 mistakenly use the value of *res in the pre-syscall actions.
2715
2716 This doesn't actually do the syscall itself, it is important to
2717 observe.
2718
2719 Because %eax is used both for the syscall number before the call
2720 and the result value afterwards, we can't reliably use it to get
2721 the syscall number. So the caller has to pass it explicitly.
2722*/
sewardj8c824512002-04-14 04:16:48 +00002723void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00002724 Int syscallno,
2725 Int* /*IN*/ res )
2726{
2727 Bool sane_before_post = True;
2728 Bool sane_after_post = True;
2729 ThreadState* tst = VG_(get_thread_state)( tid );
2730 UInt arg1 = tst->m_ebx;
2731 UInt arg2 = tst->m_ecx;
2732 UInt arg3 = tst->m_edx;
2733 /*
2734 UInt arg4 = tst->m_esi;
2735 UInt arg5 = tst->m_edi;
2736 */
2737 VGP_PUSHCC(VgpSyscall);
2738
2739 if (res != NULL
2740 && ! VG_(first_and_last_secondaries_look_plausible))
2741 sane_before_post = False;
2742
2743 switch (syscallno) {
2744
2745 case __NR_read: /* syscall 3 */
2746 /* size_t read(int fd, void *buf, size_t count); */
2747 if (res == NULL) {
2748 /* PRE */
2749 if (VG_(clo_trace_syscalls))
2750 VG_(printf)(
2751 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
2752 VG_(getpid)(), tid,
2753 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002754 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002755 } else {
2756 /* POST */
2757 if (VG_(clo_trace_syscalls))
2758 VG_(printf)(
2759 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
2760 VG_(getpid)(), tid,
2761 arg1, arg2, arg3, *res);
2762 if (!VG_(is_kerror)(*res) && *res > 0) {
2763 make_readable( arg2, *res );
2764 }
2765 }
2766 break;
2767
2768 case __NR_write: /* syscall 4 */
2769 /* size_t write(int fd, const void *buf, size_t count); */
2770 if (res == NULL) {
2771 /* PRE */
2772 if (VG_(clo_trace_syscalls))
2773 VG_(printf)(
2774 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
2775 VG_(getpid)(), tid,
2776 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002777 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002778 } else {
2779 /* POST */
2780 if (VG_(clo_trace_syscalls))
2781 VG_(printf)(
2782 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
2783 VG_(getpid)(), tid,
2784 arg1, arg2, arg3, *res);
2785 }
2786 break;
2787
2788 default:
2789 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
2790 syscallno);
2791 VG_(panic)("check_known_blocking_syscall");
2792 /*NOTREACHED*/
2793 break;
2794 }
2795
2796 if (res != NULL) { /* only check after syscall */
2797 if (! VG_(first_and_last_secondaries_look_plausible))
2798 sane_after_post = False;
2799
2800 if (sane_before_post && (!sane_after_post)) {
2801 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
2802 VG_(message)(Vg_DebugMsg,
2803 "probable sanity check failure for syscall number %d\n",
2804 syscallno );
2805 VG_(panic)("aborting due to the above ... bye!");
2806 }
2807 }
2808
2809 VGP_POPCC;
2810}
2811
2812
sewardjde4a1d02002-03-22 01:27:54 +00002813/*--------------------------------------------------------------------*/
2814/*--- end vg_syscall_mem.c ---*/
2815/*--------------------------------------------------------------------*/