blob: 52157ca099677ee16d673d7882d1ea3a5ecd0124 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Update the byte permission maps following a system call. ---*/
4/*--- vg_syscall_mem.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_include.h"
33
34/* vg_unsafe.h should NOT be included into any file except this
35 one. */
36#include "vg_unsafe.h"
37
38
39/* All system calls are channelled through vg_wrap_syscall. It does
40 three things:
41
42 * optionally, checks the permissions for the args to the call
43
44 * perform the syscall, usually by passing it along to the kernel
45 unmodified. However, because we simulate signals ourselves,
46 signal-related syscalls are routed to vg_signal.c, and are not
47 delivered to the kernel.
48
49 * Update the permission maps following the syscall.
50
51 A magical piece of assembly code, vg_do_syscall(), in vg_syscall.S
52 does the tricky bit of passing a syscall to the kernel, whilst
53 having the simulator retain control.
54*/
55
56static void make_noaccess ( Addr a, UInt len )
57{
58 if (VG_(clo_instrument))
59 VGM_(make_noaccess) ( a, len );
60}
61
62static void make_writable ( Addr a, UInt len )
63{
64 if (VG_(clo_instrument))
65 VGM_(make_writable) ( a, len );
66}
67
68static void make_readable ( Addr a, UInt len )
69{
70 if (VG_(clo_instrument))
71 VGM_(make_readable) ( a, len );
72}
73
74static void make_readwritable ( Addr a, UInt len )
75{
76 if (VG_(clo_instrument))
77 VGM_(make_readwritable) ( a, len );
78}
79
80static
sewardj8c824512002-04-14 04:16:48 +000081void must_be_writable ( ThreadState* tst,
82 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000083{
84 Bool ok;
85 Addr bad_addr;
86 /* VG_(message)(Vg_DebugMsg,"must be writable: %x .. %x",
87 base,base+size-1); */
88 if (!VG_(clo_instrument))
89 return;
90 ok = VGM_(check_writable) ( base, size, &bad_addr );
91 if (!ok)
sewardj8c824512002-04-14 04:16:48 +000092 VG_(record_param_err) ( tst, bad_addr, True, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +000093}
94
95static
sewardj8c824512002-04-14 04:16:48 +000096void must_be_readable ( ThreadState* tst,
97 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000098{
99 Bool ok;
100 Addr bad_addr;
101 /* VG_(message)(Vg_DebugMsg,"must be readable: %x .. %x",
102 base,base+size-1); */
103 if (!VG_(clo_instrument))
104 return;
105 ok = VGM_(check_readable) ( base, size, &bad_addr );
106 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000107 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000108}
109
110static
sewardj8c824512002-04-14 04:16:48 +0000111void must_be_readable_asciiz ( ThreadState* tst,
112 Char* syscall_name, UInt str )
sewardjde4a1d02002-03-22 01:27:54 +0000113{
114 Bool ok = True;
115 Addr bad_addr;
116 /* VG_(message)(Vg_DebugMsg,"must be readable asciiz: 0x%x",str); */
117 if (!VG_(clo_instrument))
118 return;
119 ok = VGM_(check_readable_asciiz) ( (Addr)str, &bad_addr );
120 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000121 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000122}
123
124
125/* Set memory permissions, based on PROT_* values for mmap/mprotect,
126 into the permissions our scheme understands. Dunno if this is
127 really correct. */
128
129static void approximate_mmap_permissions ( Addr a, UInt len, UInt prot )
130{
131 /* PROT_READ and PROT_WRITE --> readable
132 PROT_READ only --> readable
133 PROT_WRITE only --> writable
134 NEITHER --> noaccess
135 */
136 if (prot & PROT_READ)
137 make_readable(a,len);
138 else
139 if (prot & PROT_WRITE)
140 make_writable(a,len);
141 else
142 make_noaccess(a,len);
143}
144
145
146/* Dereference a pointer, but only after checking that it's
147 safe to do so. If not, return the default.
148*/
149static
150UInt safe_dereference ( Addr aa, UInt defawlt )
151{
152 if (!VG_(clo_instrument))
153 return * (UInt*)aa;
154 if (VGM_(check_readable)(aa,4,NULL))
155 return * (UInt*)aa;
156 else
157 return defawlt;
158}
159
160
161/* Is this a Linux kernel error return value? */
162/* From:
163 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
164 linux/i386/sysdep.h?
165 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
166
167 QUOTE:
168
169 Linux uses a negative return value to indicate syscall errors,
170 unlike most Unices, which use the condition codes' carry flag.
171
172 Since version 2.1 the return value of a system call might be
173 negative even if the call succeeded. E.g., the `lseek' system call
174 might return a large offset. Therefore we must not anymore test
175 for < 0, but test for a real error by making sure the value in %eax
176 is a real error number. Linus said he will make sure the no syscall
177 returns a value in -1 .. -4095 as a valid result so we can savely
178 test with -4095.
179
180 END QUOTE
181*/
182Bool VG_(is_kerror) ( Int res )
183{
184 if (res >= -4095 && res <= -1)
185 return True;
186 else
187 return False;
188}
189
190static
191UInt get_shm_size ( Int shmid )
192{
193 struct shmid_ds buf;
194 long __res;
195 __asm__ volatile ( "int $0x80"
196 : "=a" (__res)
197 : "0" (__NR_ipc),
198 "b" ((long)(24) /*IPCOP_shmctl*/),
199 "c" ((long)(shmid)),
200 "d" ((long)(IPC_STAT)),
201 "S" ((long)(0)),
202 "D" ((long)(&buf)) );
203 if ( VG_(is_kerror) ( __res ) )
204 return 0;
205
206 return buf.shm_segsz;
207}
208
209static
sewardj8c824512002-04-14 04:16:48 +0000210Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000211{
212 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
213 Char *result = VG_(malloc) ( aid, len );
214 VG_(strcpy) ( result, s1 );
215 VG_(strcat) ( result, s2 );
216 return result;
217}
218
219static
sewardj8c824512002-04-14 04:16:48 +0000220void must_be_readable_sendmsg ( ThreadState* tst,
221 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000222{
223 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000224 must_be_readable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000225 VG_(free) ( VG_AR_TRANSIENT, outmsg );
226}
227
228static
sewardj8c824512002-04-14 04:16:48 +0000229void must_be_writable_recvmsg ( ThreadState* tst,
230 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000231{
232 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000233 must_be_writable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000234 VG_(free) ( VG_AR_TRANSIENT, outmsg );
235}
236
237static
sewardj8c824512002-04-14 04:16:48 +0000238void make_readable_recvmsg ( ThreadState* tst,
239 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000240{
241 make_readable( base, size );
242}
243
244static
sewardj8c824512002-04-14 04:16:48 +0000245void msghdr_foreachfield (
246 ThreadState* tst,
247 struct msghdr *msg,
248 void (*foreach_func)( ThreadState*, Char *, UInt, UInt )
249 )
sewardjde4a1d02002-03-22 01:27:54 +0000250{
251 if ( !msg )
252 return;
253
sewardj8c824512002-04-14 04:16:48 +0000254 foreach_func ( tst, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000255
256 if ( msg->msg_name )
sewardj8c824512002-04-14 04:16:48 +0000257 foreach_func ( tst,
258 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000259 (Addr)msg->msg_name, msg->msg_namelen );
260
261 if ( msg->msg_iov ) {
262 struct iovec *iov = msg->msg_iov;
263 UInt i;
264
sewardj8c824512002-04-14 04:16:48 +0000265 foreach_func ( tst,
266 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000267 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
268
269 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
sewardj8c824512002-04-14 04:16:48 +0000270 foreach_func ( tst,
271 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000272 (Addr)iov->iov_base, iov->iov_len );
273 }
274
275 if ( msg->msg_control )
sewardj8c824512002-04-14 04:16:48 +0000276 foreach_func ( tst,
277 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000278 (Addr)msg->msg_control, msg->msg_controllen );
279}
280
281
282/* Records the current end of the data segment so we can make sense of
283 calls to brk(). Initial value set by hdm_init_memory_audit(). */
284Addr VGM_(curr_dataseg_end);
285
286
sewardj2e93c502002-04-12 11:12:52 +0000287
sewardjde4a1d02002-03-22 01:27:54 +0000288/* The Main Entertainment ... */
289
sewardj2e93c502002-04-12 11:12:52 +0000290void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +0000291{
sewardj2e93c502002-04-12 11:12:52 +0000292 Bool sane_before_call = True;
293 Bool sane_after_call = True;
294 ThreadState* tst = VG_(get_thread_state)( tid );
295 UInt syscallno = tst->m_eax;
296 UInt arg1 = tst->m_ebx;
297 UInt arg2 = tst->m_ecx;
298 UInt arg3 = tst->m_edx;
299 UInt arg4 = tst->m_esi;
300 UInt arg5 = tst->m_edi;
sewardjde4a1d02002-03-22 01:27:54 +0000301
302 /* Do not make this unsigned! */
303 Int res;
304
sewardjde4a1d02002-03-22 01:27:54 +0000305 VGP_PUSHCC(VgpSyscall);
306
307 /* Since buggy syscall wrappers sometimes break this, we may as well
308 check ourselves. */
309 if (! VG_(first_and_last_secondaries_look_plausible))
310 sane_before_call = False;
311
312 /* the syscall no is in %eax. For syscalls with <= 5 args,
313 args 1 .. 5 to the syscall are in %ebx %ecx %edx %esi %edi.
314 For calls with > 5 args, %ebx points to a lump of memory
315 containing the args.
316
317 The result is returned in %eax. If this value >= 0, the call
318 succeeded, and this is the return value. If < 0, it failed, and
319 the negation of this value is errno. To be more specific,
320 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
321 (kernel 2.4.9 sources, include/asm-i386/errno.h)
322 then it indicates an error. Otherwise it doesn't.
323
324 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
325 (inclusive?) indicate error returns. Not sure where the -4095
326 comes from.
327 */
328
329 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000330 VG_(printf)("SYSCALL[%d,%d](%3d): ",
331 VG_(getpid)(), tid, syscallno);
sewardjde4a1d02002-03-22 01:27:54 +0000332
333 switch (syscallno) {
334
335 case __NR_sigaltstack:
336 VG_(unimplemented)
337 ("client signals on alternative stack (SA_ONSTACK)");
338 break;
339
340 case __NR_clone:
341 VG_(unimplemented)
sewardj827d95b2002-04-16 02:09:31 +0000342 ("clone(): not supported by Valgrind.\n "
343 "We do now support programs linked against\n "
344 "libpthread.so, though. Re-run with -v and ensure that\n "
345 "you are picking up Valgrind's implementation of libpthread.so.");
sewardjde4a1d02002-03-22 01:27:54 +0000346 break;
347
348# if defined(__NR_modify_ldt)
349 case __NR_modify_ldt:
350 VG_(unimplemented)
351 ("modify_ldt(): I (JRS) haven't investigated this yet; sorry.");
352 break;
353# endif
354
sewardj73f1f072002-03-29 14:22:46 +0000355 /* !!!!!!!!!! New, untested syscalls !!!!!!!!!!!!!!!!!!!!! */
356
sewardj6e435c02002-04-24 02:24:44 +0000357# if defined(__NR_madvise)
358 case __NR_madvise: /* syscall 219 */
359 /* int madvise(void *start, size_t length, int advice ); */
360 if (VG_(clo_trace_syscalls))
361 VG_(printf)("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
362 KERNEL_DO_SYSCALL(tid,res);
363 break;
364# endif
365
sewardj6af4b5d2002-04-16 04:40:49 +0000366# if defined(__NR_mremap)
367 /* Is this really right? Perhaps it should copy the permissions
368 from the old area into the new. Unclear from the Linux man
369 pages what this really does. Also, the flags don't look like
370 they mean the same as the standard mmap flags, so that's
371 probably wrong too. */
372 case __NR_mremap: /* syscall 163 */
373 /* void* mremap(void * old_address, size_t old_size,
374 size_t new_size, unsigned long flags); */
375 if (VG_(clo_trace_syscalls))
376 VG_(printf)("mremap ( %p, %d, %d, 0x%x )\n",
377 arg1, arg2, arg3, arg4);
378 must_be_writable ( tst, "mremap(old_address)", arg1, arg2 );
379 KERNEL_DO_SYSCALL(tid,res);
380 if (!VG_(is_kerror)(res)) {
381 /* Copied from munmap() wrapper. */
382 Addr start = arg1;
383 Addr length = arg2;
384 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
385 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
386 make_noaccess( start, length );
387 VG_(symtab_notify_munmap) ( start, length );
388 approximate_mmap_permissions( (Addr)res, arg3, arg4 );
389 }
390 break;
391# endif
392
sewardj73f1f072002-03-29 14:22:46 +0000393 case __NR_nice: /* syscall 34 */
394 /* int nice(int inc); */
395 if (VG_(clo_trace_syscalls))
396 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000397 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000398 break;
399
sewardjde4a1d02002-03-22 01:27:54 +0000400 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
401
sewardjd7f07662002-03-24 10:49:46 +0000402# if defined(__NR_setresgid32)
403 case __NR_setresgid32: /* syscall 210 */
404 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
405 if (VG_(clo_trace_syscalls))
406 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000407 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000408 break;
409# endif
410
sewardjde4a1d02002-03-22 01:27:54 +0000411# if defined(__NR_setfsuid32)
412 case __NR_setfsuid32: /* syscall 215 */
413 /* int setfsuid(uid_t fsuid); */
414 if (VG_(clo_trace_syscalls))
415 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000416 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000417 break;
418# endif
419
420# if defined(__NR__sysctl)
421 case __NR__sysctl:
422 /* int _sysctl(struct __sysctl_args *args); */
423 if (VG_(clo_trace_syscalls))
424 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000425 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000426 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000427 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000428 if (!VG_(is_kerror)(res))
429 make_readable ( arg1, sizeof(struct __sysctl_args) );
430 break;
431# endif
432
433# if defined(__NR_sched_getscheduler)
434 case __NR_sched_getscheduler:
435 /* int sched_getscheduler(pid_t pid); */
436 if (VG_(clo_trace_syscalls))
437 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000438 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000439 break;
440# endif
441
442# if defined(__NR_sched_setscheduler)
443 case __NR_sched_setscheduler:
444 /* int sched_setscheduler(pid_t pid, int policy,
445 const struct sched_param *p); */
446 if (VG_(clo_trace_syscalls))
447 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
448 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000449 must_be_readable( tst,
450 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000451 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000452 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000453 break;
454# endif
455
456# if defined(__NR_mlockall)
457 case __NR_mlockall:
458 /* int mlockall(int flags); */
459 if (VG_(clo_trace_syscalls))
460 VG_(printf)("mlockall ( %x )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000461 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000462 break;
463# endif
464
465# if defined(__NR_munlockall)
466 case __NR_munlockall:
467 /* int munlockall(void); */
468 if (VG_(clo_trace_syscalls))
469 VG_(printf)("munlockall ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000470 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000471 break;
472# endif
473
474#if defined(__NR_sched_get_priority_max)
475 case __NR_sched_get_priority_max:
476 /* int sched_get_priority_max(int policy); */
477 if (VG_(clo_trace_syscalls))
478 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000479 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000480 break;
481# endif
482
483# if defined(__NR_setfsgid)
484 case __NR_setfsgid: /* syscall 139 */
485 /* int setfsgid(gid_t gid); */
486 if (VG_(clo_trace_syscalls))
487 VG_(printf)("setfsgid ( %d )\n", arg1);
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_setregid)
493 case __NR_setregid: /* syscall 71 */
494 /* int setregid(gid_t rgid, gid_t egid); */
495 if (VG_(clo_trace_syscalls))
496 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
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_setresuid)
502 case __NR_setresuid: /* syscall 164 */
503 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
504 if (VG_(clo_trace_syscalls))
505 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000506 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000507 break;
508# endif
509
510# if defined(__NR_setfsuid)
511 case __NR_setfsuid: /* syscall 138 */
512 /* int setfsuid(uid_t uid); */
513 if (VG_(clo_trace_syscalls))
514 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000515 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000516 break;
517# endif
518
519 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
520
521# if defined(__NR_sendfile)
522 case __NR_sendfile: /* syscall 187 */
523 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
524 size_t count) */
525 if (VG_(clo_trace_syscalls))
526 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000527 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000528 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000529 if (!VG_(is_kerror)(res)) {
530 make_readable( arg3, sizeof( off_t ) );
531 }
532 break;
533# endif
534
535 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
536
537# if defined(__NR_pwrite)
538 case __NR_pwrite: /* syscall 181 */
539 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
540 off_t offset); */
541 if (VG_(clo_trace_syscalls))
542 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000543 must_be_readable( tst, "pwrite(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000544 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000545 break;
546# endif
547
548 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
549
550 case __NR_sync: /* syscall 36 */
551 /* int sync(); */
552 if (VG_(clo_trace_syscalls))
553 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000554 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000555 break;
556
557 case __NR_fstatfs: /* syscall 100 */
558 /* int fstatfs(int fd, struct statfs *buf); */
559 if (VG_(clo_trace_syscalls))
560 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000561 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000562 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000563 if (!VG_(is_kerror)(res))
564 make_readable( arg2, sizeof(struct statfs) );
565 break;
566
567 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
568
569 case __NR_pause: /* syscall 29 */
570 /* int pause(void); */
571 if (VG_(clo_trace_syscalls))
572 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000573 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000574 break;
575
576 case __NR_getsid: /* syscall 147 */
577 /* pid_t getsid(pid_t pid); */
578 if (VG_(clo_trace_syscalls))
579 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000580 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000581 break;
582
583# if defined(__NR_pread)
584 case __NR_pread: /* syscall 180 */
585 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
586 if (VG_(clo_trace_syscalls))
587 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000588 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000589 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000590 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000591 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
592 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000593 arg1, arg2, arg3, arg4, res);
594 if (!VG_(is_kerror)(res) && res > 0) {
595 make_readable( arg2, res );
596 }
597 break;
598# endif
599
600 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
601
602 case __NR_mknod: /* syscall 14 */
603 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
604 if (VG_(clo_trace_syscalls))
605 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000606 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000607 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000608 break;
609
610 case __NR_flock: /* syscall 143 */
611 /* int flock(int fd, int operation); */
612 if (VG_(clo_trace_syscalls))
613 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000614 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000615 break;
616
617# if defined(__NR_rt_sigsuspend)
618 /* Viewed with great suspicion by me, but, hey, let's do it
619 anyway ... */
620 case __NR_rt_sigsuspend: /* syscall 179 */
621 /* int sigsuspend(const sigset_t *mask); */
622 if (VG_(clo_trace_syscalls))
623 VG_(printf)("sigsuspend ( %p )\n", arg1 );
624 if (arg1 != (Addr)NULL) {
625 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000626 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000627 sizeof(vki_ksigset_t) );
628 }
sewardj2e93c502002-04-12 11:12:52 +0000629 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000630 break;
631# endif
632
633 case __NR_init_module: /* syscall 128 */
634 /* int init_module(const char *name, struct module *image); */
635 if (VG_(clo_trace_syscalls))
636 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000637 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
638 must_be_readable( tst, "init_module(image)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000639 sizeof(struct module) );
sewardj2e93c502002-04-12 11:12:52 +0000640 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000641 break;
642
643 case __NR_ioperm: /* syscall 101 */
644 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
645 if (VG_(clo_trace_syscalls))
646 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000647 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000648 break;
649
650 case __NR_capget: /* syscall 184 */
651 /* int capget(cap_user_header_t header, cap_user_data_t data); */
652 if (VG_(clo_trace_syscalls))
653 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000654 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000655 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000656 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000657 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000658 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000659 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
660 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
661 break;
662
663 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
664
665 case __NR_execve:
666 /* int execve (const char *filename,
667 char *const argv [],
668 char *const envp[]); */
669 if (VG_(clo_trace_syscalls))
670 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
671 arg1, arg1, arg2, arg3);
672 /* Make any binding for LD_PRELOAD disappear, so that child
673 processes don't get traced into. */
674 if (!VG_(clo_trace_children)) {
675 Int i;
676 Char** envp = (Char**)arg3;
677 for (i = 0; envp[i] != NULL; i++) {
678 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) {
679 VG_(mash_LD_PRELOAD_string)(&envp[i][11]);
680 }
681 }
682 }
sewardj2e93c502002-04-12 11:12:52 +0000683 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000684 /* Should we still be alive here? Don't think so. */
685 /* Actually, above comment is wrong. execve can fail, just
686 like any other syscall -- typically the file to exec does
687 not exist. Hence: */
688 vg_assert(VG_(is_kerror)(res));
689 break;
690
691 case __NR_exit: /* syscall 1 */
692 /* void _exit(int status); */
693 if (VG_(clo_trace_syscalls))
694 VG_(printf)("exit ( %d )\n", arg1);
695 VG_(message)(Vg_UserMsg,
696 "Warning: client exiting by calling exit(%d). Bye!",
697 arg1);
698
sewardj2e93c502002-04-12 11:12:52 +0000699 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000700 /* Definitely should not be alive here :) */
701 break;
702
703 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
704
705 case __NR_access: /* syscall 33 */
706 /* int access(const char *pathname, int mode); */
707 if (VG_(clo_trace_syscalls))
708 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000709 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000710 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000711 break;
712
713 case __NR_alarm: /* syscall 27 */
714 /* unsigned int alarm(unsigned int seconds); */
715 if (VG_(clo_trace_syscalls))
716 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000717 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000718 break;
719
720 case __NR_brk: /* syscall 45 */
721 /* Haven't a clue if this is really right. */
722 /* int brk(void *end_data_segment); */
723 if (VG_(clo_trace_syscalls))
724 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000725 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000726 if (VG_(clo_trace_syscalls))
727 VG_(printf)("0x%x\n", res);
728
729 if (!VG_(is_kerror)(res)) {
730 if (arg1 == 0) {
731 /* Just asking where the current end is. (???) */
732 VGM_(curr_dataseg_end) = res;
733 } else
734 if (arg1 < VGM_(curr_dataseg_end)) {
735 /* shrinking the data segment. */
736 make_noaccess( (Addr)arg1,
737 VGM_(curr_dataseg_end)-arg1 );
738 VGM_(curr_dataseg_end) = arg1;
739 } else
740 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
741 /* asked for more memory, and got it */
742 /*
743 VG_(printf)("BRK: new area %x .. %x\n",
744 VGM_(curr_dataseg_end, arg1-1 );
745 */
746 make_writable ( (Addr)VGM_(curr_dataseg_end),
747 arg1-VGM_(curr_dataseg_end) );
748 VGM_(curr_dataseg_end) = arg1;
749 }
750 }
751 break;
752
753 case __NR_chdir: /* syscall 12 */
754 /* int chdir(const char *path); */
755 if (VG_(clo_trace_syscalls))
756 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +0000757 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000758 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000759 break;
760
761 case __NR_chmod: /* syscall 15 */
762 /* int chmod(const char *path, mode_t mode); */
763 if (VG_(clo_trace_syscalls))
764 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000765 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000766 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000767 break;
768
769# if defined(__NR_chown32)
770 case __NR_chown32: /* syscall 212 */
771# endif
772# if defined(__NR_lchown32)
773 case __NR_lchown32: /* syscall 198 */
774# endif
775 case __NR_chown: /* syscall 16 */
776 /* int chown(const char *path, uid_t owner, gid_t group); */
777 if (VG_(clo_trace_syscalls))
778 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000779 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000780 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000781 break;
782
783 case __NR_close: /* syscall 6 */
784 /* int close(int fd); */
785 if (VG_(clo_trace_syscalls))
786 VG_(printf)("close ( %d )\n",arg1);
787 /* Detect and negate attempts by the client to close Valgrind's
788 logfile fd ... */
789 if (arg1 == VG_(clo_logfile_fd)) {
790 VG_(message)(Vg_UserMsg,
791 "Warning: client attempted to close "
792 "Valgrind's logfile fd (%d).",
793 VG_(clo_logfile_fd));
794 VG_(message)(Vg_UserMsg,
795 " Use --logfile-fd=<number> to select an "
796 "alternative logfile fd." );
797 } else {
sewardj2e93c502002-04-12 11:12:52 +0000798 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000799 }
800 break;
801
802 case __NR_dup: /* syscall 41 */
803 /* int dup(int oldfd); */
804 if (VG_(clo_trace_syscalls))
805 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000806 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000807 if (VG_(clo_trace_syscalls))
808 VG_(printf)("%d\n", res);
809 break;
810
811 case __NR_dup2: /* syscall 63 */
812 /* int dup2(int oldfd, int newfd); */
813 if (VG_(clo_trace_syscalls))
814 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000815 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000816 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000817 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
818 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000819 arg1, arg2, res);
820 break;
821
822 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +0000823 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +0000824 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000825 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
826 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000827 break;
828
829 case __NR_fchdir: /* syscall 133 */
830 /* int fchdir(int fd); */
831 if (VG_(clo_trace_syscalls))
832 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000833 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000834 break;
835
sewardj2f0de322002-03-24 10:17:25 +0000836# if defined(__NR_fchown32)
837 case __NR_fchown32: /* syscall 207 */
838# endif
839 case __NR_fchown: /* syscall 95 */
840 /* int fchown(int filedes, uid_t owner, gid_t group); */
841 if (VG_(clo_trace_syscalls))
842 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +0000843 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +0000844 break;
845
sewardjde4a1d02002-03-22 01:27:54 +0000846 case __NR_fchmod: /* syscall 94 */
847 /* int fchmod(int fildes, mode_t mode); */
848 if (VG_(clo_trace_syscalls))
849 VG_(printf)("fchmod ( %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;
sewardj2f0de322002-03-24 10:17:25 +0000852
sewardjde4a1d02002-03-22 01:27:54 +0000853# if defined(__NR_fcntl64)
854 case __NR_fcntl64: /* syscall 221 */
855 /* I don't know what the prototype for this is supposed to be. */
856 /* ??? int fcntl(int fd, int cmd); */
857 if (VG_(clo_trace_syscalls))
858 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000859 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000860 break;
861# endif
862
863 case __NR_fstat: /* syscall 108 */
864 /* int fstat(int filedes, struct stat *buf); */
865 if (VG_(clo_trace_syscalls))
866 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000867 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +0000868 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000869 if (!VG_(is_kerror)(res))
870 make_readable( arg2, sizeof(struct stat) );
871 break;
872
873 case __NR_vfork: /* syscall 190 */
874 /* pid_t vfork(void); */
875 if (VG_(clo_trace_syscalls))
876 VG_(printf)("vfork ( ) ... becomes ... ");
877 /* KLUDGE: we prefer to do a fork rather than vfork.
878 vfork gives a SIGSEGV, and the stated semantics looks
879 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +0000880 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +0000881 /* fall through ... */
882 case __NR_fork: /* syscall 2 */
883 /* pid_t fork(void); */
884 if (VG_(clo_trace_syscalls))
885 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000886 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000887 break;
888
889 case __NR_fsync: /* syscall 118 */
890 /* int fsync(int fd); */
891 if (VG_(clo_trace_syscalls))
892 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000893 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000894 break;
895
896 case __NR_ftruncate: /* syscall 93 */
897 /* int ftruncate(int fd, size_t length); */
898 if (VG_(clo_trace_syscalls))
899 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000900 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000901 break;
902
sewardj2f0de322002-03-24 10:17:25 +0000903# if defined(__NR_ftruncate64)
904 case __NR_ftruncate64: /* syscall 194 */
905 /* int ftruncate64(int fd, off64_t length); */
906 if (VG_(clo_trace_syscalls))
907 VG_(printf)("ftruncate64 ( %d, %lld )\n",
908 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +0000909 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000910 break;
911# endif
912
913 case __NR_getdents: /* syscall 141 */
914 /* int getdents(unsigned int fd, struct dirent *dirp,
915 unsigned int count); */
916 if (VG_(clo_trace_syscalls))
917 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000918 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000919 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000920 if (!VG_(is_kerror)(res) && res > 0)
921 make_readable( arg2, res );
922 break;
923
924# if defined(__NR_getdents64)
925 case __NR_getdents64: /* syscall 220 */
926 /* int getdents(unsigned int fd, struct dirent64 *dirp,
927 unsigned int count); */
928 if (VG_(clo_trace_syscalls))
929 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000930 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000931 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000932 if (!VG_(is_kerror)(res) && res > 0)
933 make_readable( arg2, res );
934 break;
935# endif
936
937# if defined(__NR_getgroups32)
938 case __NR_getgroups32: /* syscall 205 */
939# endif
940 case __NR_getgroups: /* syscall 80 */
941 /* int getgroups(int size, gid_t list[]); */
942 if (VG_(clo_trace_syscalls))
943 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
944 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +0000945 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000946 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +0000947 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000948 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
949 make_readable ( arg2, res * sizeof(gid_t) );
950 break;
951
952 case __NR_getcwd: /* syscall 183 */
953 /* char *getcwd(char *buf, size_t size); */
954 if (VG_(clo_trace_syscalls))
955 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000956 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000957 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000958 if (!VG_(is_kerror)(res) && res != (Addr)NULL)
959 make_readable ( arg1, arg2 );
960 /* Not really right -- really we should have the asciiz
961 string starting at arg1 readable, or up to arg2 bytes,
962 whichever finishes first. */
963 break;
964
965 case __NR_geteuid: /* syscall 49 */
966 /* uid_t geteuid(void); */
967 if (VG_(clo_trace_syscalls))
968 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000969 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000970 break;
971
972# if defined(__NR_geteuid32)
973 case __NR_geteuid32: /* syscall 201 */
974 /* ?? uid_t geteuid32(void); */
975 if (VG_(clo_trace_syscalls))
976 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000977 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000978 break;
979# endif
980
981 case __NR_getegid: /* syscall 50 */
982 /* gid_t getegid(void); */
983 if (VG_(clo_trace_syscalls))
984 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000985 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000986 break;
987
988# if defined(__NR_getegid32)
989 case __NR_getegid32: /* syscall 202 */
990 /* gid_t getegid32(void); */
991 if (VG_(clo_trace_syscalls))
992 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000993 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000994 break;
995# endif
996
997 case __NR_getgid: /* syscall 47 */
998 /* gid_t getgid(void); */
999 if (VG_(clo_trace_syscalls))
1000 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001001 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001002 break;
1003
1004# if defined(__NR_getgid32)
1005 case __NR_getgid32: /* syscall 200 */
1006 /* gid_t getgid32(void); */
1007 if (VG_(clo_trace_syscalls))
1008 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001009 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001010 break;
1011# endif
1012
1013 case __NR_getpid: /* syscall 20 */
1014 /* pid_t getpid(void); */
1015 if (VG_(clo_trace_syscalls))
1016 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001017 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001018 break;
1019
1020 case __NR_getpgid: /* syscall 132 */
1021 /* pid_t getpgid(pid_t pid); */
1022 if (VG_(clo_trace_syscalls))
1023 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001024 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001025 break;
1026
1027 case __NR_getpgrp: /* syscall 65 */
1028 /* pid_t getpprp(void); */
1029 if (VG_(clo_trace_syscalls))
1030 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001031 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001032 break;
1033
1034 case __NR_getppid: /* syscall 64 */
1035 /* pid_t getppid(void); */
1036 if (VG_(clo_trace_syscalls))
1037 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001038 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001039 break;
1040
1041 case __NR_getresgid: /* syscall 171 */
1042 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1043 if (VG_(clo_trace_syscalls))
1044 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001045 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1046 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1047 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001048 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001049 if (!VG_(is_kerror)(res) && res == 0) {
1050 make_readable ( arg1, sizeof(gid_t) );
1051 make_readable ( arg2, sizeof(gid_t) );
1052 make_readable ( arg3, sizeof(gid_t) );
1053 }
1054 break;
1055
1056# if defined(__NR_getresgid32)
1057 case __NR_getresgid32: /* syscall 211 */
1058 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1059 if (VG_(clo_trace_syscalls))
1060 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001061 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1062 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1063 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001064 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001065 if (!VG_(is_kerror)(res) && res == 0) {
1066 make_readable ( arg1, sizeof(gid_t) );
1067 make_readable ( arg2, sizeof(gid_t) );
1068 make_readable ( arg3, sizeof(gid_t) );
1069 }
1070 break;
1071# endif
1072
1073 case __NR_getresuid: /* syscall 165 */
1074 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1075 if (VG_(clo_trace_syscalls))
1076 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001077 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1078 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1079 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001080 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001081 if (!VG_(is_kerror)(res) && res == 0) {
1082 make_readable ( arg1, sizeof(uid_t) );
1083 make_readable ( arg2, sizeof(uid_t) );
1084 make_readable ( arg3, sizeof(uid_t) );
1085 }
1086 break;
1087
1088# if defined(__NR_getresuid32)
1089 case __NR_getresuid32: /* syscall 209 */
1090 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1091 if (VG_(clo_trace_syscalls))
1092 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001093 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1094 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1095 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001096 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001097 if (!VG_(is_kerror)(res) && res == 0) {
1098 make_readable ( arg1, sizeof(uid_t) );
1099 make_readable ( arg2, sizeof(uid_t) );
1100 make_readable ( arg3, sizeof(uid_t) );
1101 }
1102 break;
1103# endif
1104
1105# if defined(__NR_ugetrlimit)
1106 case __NR_ugetrlimit: /* syscall 191 */
1107# endif
1108 case __NR_getrlimit: /* syscall 76 */
1109 /* int getrlimit (int resource, struct rlimit *rlim); */
1110 if (VG_(clo_trace_syscalls))
1111 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001112 must_be_writable( tst, "getrlimit(rlim)", arg2,
1113 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001114 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001115 if (!VG_(is_kerror)(res) && res == 0)
1116 make_readable( arg2, sizeof(struct rlimit) );
1117 break;
1118
1119 case __NR_getrusage: /* syscall 77 */
1120 /* int getrusage (int who, struct rusage *usage); */
1121 if (VG_(clo_trace_syscalls))
1122 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001123 must_be_writable( tst, "getrusage(usage)", arg2,
1124 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001125 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001126 if (!VG_(is_kerror)(res) && res == 0)
1127 make_readable(arg2, sizeof(struct rusage) );
1128 break;
1129
1130 case __NR_gettimeofday: /* syscall 78 */
1131 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1132 if (VG_(clo_trace_syscalls))
1133 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001134 must_be_writable( tst, "gettimeofday(tv)", arg1,
1135 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001136 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001137 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001138 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001139 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001140 if (!VG_(is_kerror)(res) && res == 0) {
1141 make_readable( arg1, sizeof(struct timeval) );
1142 if (arg2 != 0)
1143 make_readable( arg2, sizeof(struct timezone) );
1144 }
1145 break;
1146
1147 case __NR_getuid: /* syscall 24 */
1148 /* uid_t getuid(void); */
1149 if (VG_(clo_trace_syscalls))
1150 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001151 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001152 break;
1153
1154# if defined(__NR_getuid32)
1155 case __NR_getuid32: /* syscall 199 */
1156 /* ???uid_t getuid32(void); */
1157 if (VG_(clo_trace_syscalls))
1158 VG_(printf)("getuid32 ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001159 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001160 break;
1161# endif
1162
1163 case __NR_ipc: /* syscall 117 */
1164 /* int ipc ( unsigned int call, int first, int second,
1165 int third, void *ptr, long fifth); */
1166 {
sewardj2e93c502002-04-12 11:12:52 +00001167 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001168
1169 if (VG_(clo_trace_syscalls))
1170 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1171 arg1,arg2,arg3,arg4,arg5,arg6);
1172 switch (arg1 /* call */) {
1173 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001174 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001175 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001176 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001177 break;
sewardj5b9e3502002-03-29 04:35:08 +00001178 case 2: /* IPCOP_semget */
1179 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001180 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001181 break;
1182 case 11: /* IPCOP_msgsnd */
1183 {
1184 struct msgbuf *msgp = (struct msgbuf *)arg5;
1185 Int msgsz = arg3;
1186
sewardj8c824512002-04-14 04:16:48 +00001187 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001188 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001189 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001190 (UInt)msgp->mtext, msgsz );
1191
sewardj2e93c502002-04-12 11:12:52 +00001192 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001193 break;
1194 }
1195 case 12: /* IPCOP_msgrcv */
1196 {
1197 struct msgbuf *msgp = ((struct ipc_kludge *)arg5)->msgp;
1198 Int msgsz = arg3;
1199
sewardj8c824512002-04-14 04:16:48 +00001200 must_be_writable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001201 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001202 must_be_writable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001203 (UInt)msgp->mtext, msgsz );
1204
sewardj2e93c502002-04-12 11:12:52 +00001205 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001206
1207 if ( !VG_(is_kerror)(res) && res > 0 ) {
1208 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1209 make_readable ( (UInt)msgp->mtext, res );
1210 }
1211 break;
1212 }
1213 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001214 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001215 break;
1216 case 14: /* IPCOP_msgctl */
1217 {
1218 switch (arg3 /* cmd */) {
1219 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001220 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001221 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001222 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001223 if ( !VG_(is_kerror)(res) && res > 0 ) {
1224 make_readable ( arg5, sizeof(struct msqid_ds) );
1225 }
1226 break;
1227 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001228 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001229 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001230 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001231 break;
sewardjc9add3b2002-04-16 01:58:19 +00001232# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001233 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001234 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001235 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001236 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001237 if ( !VG_(is_kerror)(res) && res > 0 ) {
1238 make_readable ( arg5, sizeof(struct msqid64_ds) );
1239 }
1240 break;
sewardjc9add3b2002-04-16 01:58:19 +00001241# endif
1242# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001243 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001244 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001245 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001246 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001247 break;
sewardjc9add3b2002-04-16 01:58:19 +00001248# endif
sewardj5b9e3502002-03-29 04:35:08 +00001249 default:
sewardj2e93c502002-04-12 11:12:52 +00001250 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001251 break;
1252 }
1253 break;
1254 }
sewardjde4a1d02002-03-22 01:27:54 +00001255 case 21: /* IPCOP_shmat */
1256 {
1257 Int shmid = arg2;
1258 Int shmflag = arg3;
1259 UInt addr;
1260
sewardj2e93c502002-04-12 11:12:52 +00001261 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001262
1263 if ( VG_(is_kerror) ( res ) )
1264 break;
1265
1266 /* force readability. before the syscall it is
1267 * indeed uninitialized, as can be seen in
1268 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1269 make_readable ( arg4, sizeof( ULong ) );
1270
1271 addr = safe_dereference ( arg4, 0 );
1272 if ( addr > 0 ) {
1273 UInt segmentSize = get_shm_size ( shmid );
1274 if ( segmentSize > 0 ) {
1275 if ( shmflag & SHM_RDONLY )
1276 make_readable ( addr, segmentSize );
1277 else
1278 make_readwritable ( addr, segmentSize );
1279 }
1280 }
1281 break;
1282 }
1283 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001284 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001285 /* ### FIXME: this should call make_noaccess on the
1286 * area passed to shmdt. But there's no way to
1287 * figure out the size of the shared memory segment
1288 * just from the address... Maybe we want to keep a
1289 * copy of the exiting mappings inside valgrind? */
1290 break;
1291 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001292 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001293 break;
1294 case 24: /* IPCOP_shmctl */
1295 {
1296 if ( arg3 > 0 ) {
sewardj8c824512002-04-14 04:16:48 +00001297 must_be_readable ( tst, "shmctl(buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001298 sizeof( struct shmid_ds ) );
1299
1300 if ( arg2 == SHM_STAT )
sewardj8c824512002-04-14 04:16:48 +00001301 must_be_writable( tst, "shmctl(IPC_STAT,buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001302 sizeof( struct shmid_ds ) );
1303 }
1304
sewardj2e93c502002-04-12 11:12:52 +00001305 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001306 break;
1307 }
1308 default:
1309 VG_(message)(Vg_DebugMsg,
1310 "FATAL: unhandled syscall(ipc) %d",
1311 arg1 );
1312 VG_(panic)("... bye!\n");
1313 break; /*NOTREACHED*/
1314 }
1315 }
1316 break;
1317
1318 case __NR_ioctl: /* syscall 54 */
1319 /* int ioctl(int d, int request, ...)
1320 [The "third" argument is traditionally char *argp,
1321 and will be so named for this discussion.]
1322 */
1323 /*
1324 VG_(message)(
1325 Vg_DebugMsg,
1326 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1327 arg2,arg1,arg3);
1328 */
1329 if (VG_(clo_trace_syscalls))
1330 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1331 switch (arg2 /* request */) {
1332 case TCSETS:
1333 case TCSETSW:
1334 case TCSETSF:
sewardj8c824512002-04-14 04:16:48 +00001335 must_be_readable( tst, "ioctl(TCSETSW)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001336 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001337 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001338 break;
1339 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001340 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001341 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001342 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001343 if (!VG_(is_kerror)(res) && res == 0)
1344 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1345 break;
sewardj2f0de322002-03-24 10:17:25 +00001346 case TCSETA:
sewardj8c824512002-04-14 04:16:48 +00001347 must_be_readable( tst, "ioctl(TCSETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001348 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001349 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001350 break;
1351 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001352 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001353 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001354 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001355 if (!VG_(is_kerror)(res) && res == 0)
1356 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1357 break;
sewardjde4a1d02002-03-22 01:27:54 +00001358 case TCSBRK:
1359 case TCSBRKP:
1360 case TCFLSH:
1361 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001362 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001363 break;
1364 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001365 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001366 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001367 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001368 if (!VG_(is_kerror)(res) && res == 0)
1369 make_readable ( arg3, sizeof(struct winsize) );
1370 break;
1371 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001372 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001373 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001374 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001375 break;
sewardj19fe3d02002-03-29 04:39:00 +00001376 case TIOCGPGRP:
1377 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001378 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001379 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001380 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001381 if (!VG_(is_kerror)(res) && res == 0)
1382 make_readable ( arg3, sizeof(pid_t) );
sewardjde4a1d02002-03-22 01:27:54 +00001383 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001384 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001385 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001386 if (!VG_(is_kerror)(res) && res == 0)
1387 make_readable ( arg3, sizeof(int));
1388 break;
sewardj73f1f072002-03-29 14:22:46 +00001389 case TIOCSCTTY:
1390 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001391 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001392 break;
sewardjde4a1d02002-03-22 01:27:54 +00001393 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001394 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001395 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001396 break;
1397 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001398 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001399 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001400 break;
1401 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001402 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001403 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001404 break;
1405 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001406 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001407 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001408 if (!VG_(is_kerror)(res) && res == 0)
1409 make_readable( arg3, sizeof(int) );
1410 break;
1411
1412 /* If you get compilation problems here, change the #if
1413 1 to #if 0 and get rid of <scsi/sg.h> in
1414 vg_unsafe.h. */
1415# if 1
1416 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001417 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1418 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001419 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001420 break;
1421# if defined(SG_IO)
1422 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001423 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001424 sizeof(struct sg_io_hdr) );
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_io_hdr));
1428 break;
1429# endif /* SG_IO */
1430 case SG_GET_SCSI_ID:
1431 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001432 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001433 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001434 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001435 if (!VG_(is_kerror)(res) && res == 0)
1436 make_readable (arg3, sizeof(struct sg_scsi_id));
1437 break;
1438 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001439 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001440 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001441 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001442 break;
1443 case SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001444 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1445 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001446 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001447 break;
1448 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001449 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001450 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001451 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001452 if (!VG_(is_kerror)(res) && res == 0)
1453 make_readable (arg3, sizeof(int));
1454 break;
1455 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001456 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1457 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001458 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001459 if (!VG_(is_kerror)(res) && res == 0)
1460 make_readable (arg3, sizeof(int));
1461 break;
1462 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001463 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001464 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001465 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001466 break;
1467# endif
1468
1469 case IIOCGETCPS:
1470 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1471 * when KERNEL was. I never saw a larger value than 64 though */
1472# ifndef ISDN_MAX_CHANNELS
1473# define ISDN_MAX_CHANNELS 64
1474# endif
sewardj8c824512002-04-14 04:16:48 +00001475 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001476 ISDN_MAX_CHANNELS
1477 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001478 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001479 if (!VG_(is_kerror)(res) && res == 0)
1480 make_readable ( arg3, ISDN_MAX_CHANNELS
1481 * 2 * sizeof(unsigned long) );
1482 break;
1483 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001484 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001485 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1486 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001487 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001488 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001489 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001490 if (!VG_(is_kerror)(res) && res == 0)
1491 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1492 break;
1493
1494 /* These all use struct ifreq AFAIK */
1495 case SIOCGIFINDEX:
1496 case SIOCGIFFLAGS: /* get flags */
1497 case SIOCGIFHWADDR: /* Get hardware address */
1498 case SIOCGIFMTU: /* get MTU size */
1499 case SIOCGIFADDR: /* get PA address */
1500 case SIOCGIFNETMASK: /* get network PA mask */
1501 case SIOCGIFMETRIC: /* get metric */
1502 case SIOCGIFMAP: /* Get device parameters */
1503 case SIOCGIFTXQLEN: /* Get the tx queue length */
1504 case SIOCGIFDSTADDR: /* get remote PA address */
1505 case SIOCGIFBRDADDR: /* get broadcast PA address */
1506 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001507 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001508 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001509 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001510 if (!VG_(is_kerror)(res) && res == 0)
1511 make_readable (arg3, sizeof(struct ifreq));
1512 break;
1513 case SIOCGIFCONF: /* get iface list */
1514 /* WAS:
1515 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1516 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001517 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001518 if (!VG_(is_kerror)(res) && res == 0)
1519 make_readable (arg3, sizeof(struct ifconf));
1520 */
sewardj8c824512002-04-14 04:16:48 +00001521 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001522 sizeof(struct ifconf));
1523 if ( arg3 ) {
1524 // TODO len must be readable and writable
1525 // buf pointer only needs to be readable
1526 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001527 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001528 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1529 }
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 && arg3 ) {
1532 struct ifconf *ifc = (struct ifconf *) arg3;
1533 make_readable ( (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1534 }
1535 break;
1536 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001537 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001538 sizeof(struct timeval));
sewardj2e93c502002-04-12 11:12:52 +00001539 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001540 if (!VG_(is_kerror)(res) && res == 0)
1541 make_readable (arg3, sizeof(struct timeval));
1542 break;
1543 case SIOCGRARP: /* get RARP table entry */
1544 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001545 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001546 sizeof(struct arpreq));
sewardj2e93c502002-04-12 11:12:52 +00001547 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001548 if (!VG_(is_kerror)(res) && res == 0)
1549 make_readable (arg3, sizeof(struct arpreq));
1550 break;
1551
1552 case SIOCSIFFLAGS: /* set flags */
1553 case SIOCSIFMAP: /* Set device parameters */
1554 case SIOCSIFTXQLEN: /* Set the tx queue length */
1555 case SIOCSIFDSTADDR: /* set remote PA address */
1556 case SIOCSIFBRDADDR: /* set broadcast PA address */
1557 case SIOCSIFNETMASK: /* set network PA mask */
1558 case SIOCSIFMETRIC: /* set metric */
1559 case SIOCSIFADDR: /* set PA address */
1560 case SIOCSIFMTU: /* set MTU size */
1561 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001562 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001563 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001564 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001565 break;
1566 /* Routing table calls. */
1567 case SIOCADDRT: /* add routing table entry */
1568 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001569 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001570 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001571 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001572 break;
1573
1574 /* RARP cache control calls. */
1575 case SIOCDRARP: /* delete RARP table entry */
1576 case SIOCSRARP: /* set RARP table entry */
1577 /* ARP cache control calls. */
1578 case SIOCSARP: /* set ARP table entry */
1579 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001580 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001581 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001582 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001583 break;
1584
1585 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001586 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001587 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001588 break;
1589
1590 /* linux/soundcard interface (OSS) */
1591 case SNDCTL_SEQ_GETOUTCOUNT:
1592 case SNDCTL_SEQ_GETINCOUNT:
1593 case SNDCTL_SEQ_PERCMODE:
1594 case SNDCTL_SEQ_TESTMIDI:
1595 case SNDCTL_SEQ_RESETSAMPLES:
1596 case SNDCTL_SEQ_NRSYNTHS:
1597 case SNDCTL_SEQ_NRMIDIS:
1598 case SNDCTL_SEQ_GETTIME:
1599 case SNDCTL_DSP_GETFMTS:
1600 case SNDCTL_DSP_GETTRIGGER:
1601 case SNDCTL_DSP_GETODELAY:
1602# if defined(SNDCTL_DSP_GETSPDIF)
1603 case SNDCTL_DSP_GETSPDIF:
1604# endif
1605 case SNDCTL_DSP_GETCAPS:
1606 case SOUND_PCM_READ_RATE:
1607 case SOUND_PCM_READ_CHANNELS:
1608 case SOUND_PCM_READ_BITS:
1609 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1610 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001611 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1612 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001613 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001614 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001615 if (!VG_(is_kerror)(res) && res == 0)
1616 make_readable (arg3, sizeof(int));
1617 break;
1618 case SNDCTL_SEQ_CTRLRATE:
1619 case SNDCTL_DSP_SPEED:
1620 case SNDCTL_DSP_STEREO:
1621 case SNDCTL_DSP_GETBLKSIZE:
1622 case SNDCTL_DSP_CHANNELS:
1623 case SOUND_PCM_WRITE_FILTER:
1624 case SNDCTL_DSP_SUBDIVIDE:
1625 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001626# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001627 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001628# endif
1629# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001630 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001631# endif
sewardjde4a1d02002-03-22 01:27:54 +00001632 case SNDCTL_TMR_TIMEBASE:
1633 case SNDCTL_TMR_TEMPO:
1634 case SNDCTL_TMR_SOURCE:
1635 case SNDCTL_MIDI_PRETIME:
1636 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001637 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1638 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001639 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001640 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1641 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001642 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001643 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001644 break;
1645 case SNDCTL_DSP_GETOSPACE:
1646 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001647 must_be_writable(tst,
1648 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001649 "(SIOR, audio_buf_info))", arg3,
1650 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001651 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001652 if (!VG_(is_kerror)(res) && res == 0)
1653 make_readable (arg3, sizeof(audio_buf_info));
1654 break;
1655 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001656 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001657 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001658 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001659 break;
1660
1661 /* We don't have any specific information on it, so
1662 try to do something reasonable based on direction and
1663 size bits. The encoding scheme is described in
1664 /usr/include/asm/ioctl.h. */
1665 default: {
1666 UInt dir = _IOC_DIR(arg2);
1667 UInt size = _IOC_SIZE(arg2);
1668 if (/* size == 0 || */ dir == _IOC_NONE) {
1669 VG_(message)(Vg_UserMsg,
1670 "Warning: noted but unhandled ioctl 0x%x"
1671 " with no size/direction hints",
1672 arg2);
1673 VG_(message)(Vg_UserMsg,
1674 " This could cause spurious value errors"
1675 " to appear.");
1676 VG_(message)(Vg_UserMsg,
1677 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
1678 " writing a proper wrapper." );
1679 } else {
1680 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001681 must_be_readable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001682 if ((dir & _IOC_WRITE) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001683 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001684 }
sewardj2e93c502002-04-12 11:12:52 +00001685 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001686 if (size > 0 && (dir & _IOC_WRITE)
1687 && !VG_(is_kerror)(res) && res == 0)
1688 make_readable (arg3, size);
1689 break;
1690 }
1691 }
1692 break;
1693
1694 case __NR_kill: /* syscall 37 */
1695 /* int kill(pid_t pid, int sig); */
1696 if (VG_(clo_trace_syscalls))
1697 VG_(printf)("kill ( %d, %d )\n", arg1,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_link: /* syscall 9 */
1702 /* int link(const char *oldpath, const char *newpath); */
1703 if (VG_(clo_trace_syscalls))
1704 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00001705 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
1706 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00001707 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001708 break;
1709
1710 case __NR_lseek: /* syscall 19 */
1711 /* off_t lseek(int fildes, off_t offset, int whence); */
1712 if (VG_(clo_trace_syscalls))
1713 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001714 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001715 break;
1716
1717 case __NR__llseek: /* syscall 140 */
1718 /* int _llseek(unsigned int fd, unsigned long offset_high,
1719 unsigned long offset_low,
1720 loff_t * result, unsigned int whence); */
1721 if (VG_(clo_trace_syscalls))
1722 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
1723 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00001724 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00001725 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001726 if (!VG_(is_kerror)(res) && res == 0)
1727 make_readable( arg4, sizeof(loff_t) );
1728 break;
1729
1730 case __NR_lstat: /* syscall 107 */
1731 /* int lstat(const char *file_name, struct stat *buf); */
1732 if (VG_(clo_trace_syscalls))
1733 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001734 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
1735 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001736 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001737 if (!VG_(is_kerror)(res) && res == 0) {
1738 make_readable( arg2, sizeof(struct stat) );
1739 }
1740 break;
1741
1742# if defined(__NR_lstat64)
1743 case __NR_lstat64: /* syscall 196 */
1744 /* int lstat64(const char *file_name, struct stat64 *buf); */
1745 if (VG_(clo_trace_syscalls))
1746 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001747 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
1748 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00001749 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001750 if (!VG_(is_kerror)(res) && res == 0) {
1751 make_readable( arg2, sizeof(struct stat64) );
1752 }
1753 break;
1754# endif
1755
1756 case __NR_mkdir: /* syscall 39 */
1757 /* int mkdir(const char *pathname, mode_t mode); */
1758 if (VG_(clo_trace_syscalls))
1759 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001760 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001761 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001762 break;
1763
1764# if defined(__NR_mmap2)
1765 case __NR_mmap2: /* syscall 192 */
1766 /* My impression is that this is exactly like __NR_mmap
1767 except that all 6 args are passed in regs, rather than in
1768 a memory-block. */
1769 /* void* mmap(void *start, size_t length, int prot,
1770 int flags, int fd, off_t offset);
1771 */
1772 {
sewardj2e93c502002-04-12 11:12:52 +00001773 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001774 if (VG_(clo_trace_syscalls))
1775 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
1776 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00001777 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001778 /* !!! shouldn't we also be doing the symtab loading stuff as
1779 in __NR_mmap ? */
1780 if (!VG_(is_kerror)(res))
1781 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1782 }
1783 break;
1784# endif
1785
1786 case __NR_mmap: /* syscall 90 */
1787 /* void* mmap(void *start, size_t length, int prot,
1788 int flags, int fd, off_t offset);
1789 */
1790 {
1791 Bool arg_block_readable
1792 = VG_(clo_instrument)
1793 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
1794 : True;
sewardj8c824512002-04-14 04:16:48 +00001795 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00001796 if (arg_block_readable) {
1797 UInt* arg_block = (UInt*)arg1;
1798 UInt arg6;
1799 arg1 = arg_block[0];
1800 arg2 = arg_block[1];
1801 arg3 = arg_block[2];
1802 arg4 = arg_block[3];
1803 arg5 = arg_block[4];
1804 arg6 = arg_block[5];
1805 if (VG_(clo_trace_syscalls))
1806 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
1807 arg1, arg2, arg3, arg4, arg5, arg6 );
1808 }
sewardj2e93c502002-04-12 11:12:52 +00001809 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001810 if (arg_block_readable && !VG_(is_kerror)(res))
1811 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1812 if (arg_block_readable && !VG_(is_kerror)(res)
1813 && (arg3 & PROT_EXEC)) {
1814 /* The client mmap'ed a segment with executable
1815 permissions. Tell the symbol-table loader, so that it
1816 has an opportunity to pick up more symbols if this mmap
1817 was caused by the client loading a new .so via
1818 dlopen(). This is important for debugging KDE. */
1819 VG_(read_symbols)();
1820 }
1821 }
1822
1823 break;
1824
1825 case __NR_mprotect: /* syscall 125 */
1826 /* int mprotect(const void *addr, size_t len, int prot); */
1827 /* should addr .. addr+len-1 be checked before the call? */
1828 if (VG_(clo_trace_syscalls))
1829 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001830 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001831 if (!VG_(is_kerror)(res))
1832 approximate_mmap_permissions ( arg1, arg2, arg3 );
1833 break;
1834
1835 case __NR_munmap: /* syscall 91 */
1836 /* int munmap(void *start, size_t length); */
1837 /* should start .. start+length-1 be checked before the call? */
1838 if (VG_(clo_trace_syscalls))
1839 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001840 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001841 if (!VG_(is_kerror)(res)) {
1842 /* Mash around start and length so that the area passed to
1843 make_noaccess() exactly covers an integral number of
1844 pages. If we don't do that, our idea of addressible
1845 memory diverges from that of the kernel's, which causes
1846 the leak detector to crash. */
1847 Addr start = arg1;
1848 Addr length = arg2;
1849 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
1850 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
1851 /*
1852 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
1853 arg1, arg2, start, length, (arg1!=start || arg2!=length)
1854 ? "CHANGE" : "");
1855 */
1856 make_noaccess( start, length );
1857 /* Tell our symbol table machinery about this, so that if
1858 this happens to be a .so being unloaded, the relevant
1859 symbols are removed too. */
1860 VG_(symtab_notify_munmap) ( start, length );
1861 }
1862 break;
1863
1864 case __NR_nanosleep: /* syscall 162 */
1865 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
1866 if (VG_(clo_trace_syscalls))
1867 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001868 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00001869 sizeof(struct timespec) );
1870 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00001871 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001872 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00001873 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001874 /* Somewhat bogus ... is only written by the kernel if
1875 res == -1 && errno == EINTR. */
1876 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
1877 make_readable ( arg2, sizeof(struct timespec) );
1878 break;
1879
1880 case __NR__newselect: /* syscall 142 */
1881 /* int select(int n,
1882 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1883 struct timeval *timeout);
1884 */
1885 if (VG_(clo_trace_syscalls))
1886 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
1887 arg1,arg2,arg3,arg4,arg5);
1888 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001889 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001890 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
1891 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00001892 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00001893 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
1894 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00001895 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001896 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
1897 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00001898 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00001899 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00001900 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001901 break;
1902
1903 case __NR_open: /* syscall 5 */
1904 /* int open(const char *pathname, int flags); */
1905 if (VG_(clo_trace_syscalls))
1906 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001907 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001908 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001909 if (VG_(clo_trace_syscalls))
1910 VG_(printf)("%d\n",res);
1911 break;
1912
1913 case __NR_pipe: /* syscall 42 */
1914 /* int pipe(int filedes[2]); */
1915 if (VG_(clo_trace_syscalls))
1916 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001917 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001918 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001919 if (!VG_(is_kerror)(res))
1920 make_readable ( arg1, 2*sizeof(int) );
1921 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00001922 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
1923 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001924 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
1925 break;
1926
1927 case __NR_poll: /* syscall 168 */
1928 /* struct pollfd {
1929 int fd; -- file descriptor
1930 short events; -- requested events
1931 short revents; -- returned events
1932 };
1933 int poll(struct pollfd *ufds, unsigned int nfds,
1934 int timeout)
1935 */
1936 if (VG_(clo_trace_syscalls))
1937 VG_(printf)("poll ( %d, %d, %d )\n",arg1,arg2,arg3);
1938 /* In fact some parts of this struct should be readable too.
1939 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00001940 must_be_writable( tst, "poll(ufds)",
1941 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00001942 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001943 if (!VG_(is_kerror)(res) && res > 0) {
1944 Int i;
1945 struct pollfd * arr = (struct pollfd *)arg1;
1946 for (i = 0; i < arg2; i++)
1947 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
1948 }
1949 break;
1950
sewardjde4a1d02002-03-22 01:27:54 +00001951 case __NR_readlink: /* syscall 85 */
1952 /* int readlink(const char *path, char *buf, size_t bufsiz); */
1953 if (VG_(clo_trace_syscalls))
1954 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001955 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
1956 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001957 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001958 if (!VG_(is_kerror)(res) && res > 0) {
1959 make_readable ( arg2, res );
1960 }
1961 break;
1962
1963 case __NR_readv: { /* syscall 145 */
1964 /* int readv(int fd, const struct iovec * vector, size_t count); */
1965 UInt i;
1966 struct iovec * vec;
1967 if (VG_(clo_trace_syscalls))
1968 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001969 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00001970 arg2, arg3 * sizeof(struct iovec) );
1971 /* ToDo: don't do any of the following if the vector is invalid */
1972 vec = (struct iovec *)arg2;
1973 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00001974 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00001975 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00001976 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001977 if (!VG_(is_kerror)(res) && res > 0) {
1978 /* res holds the number of bytes read. */
1979 for (i = 0; i < arg3; i++) {
1980 Int nReadThisBuf = vec[i].iov_len;
1981 if (nReadThisBuf > res) nReadThisBuf = res;
1982 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
1983 res -= nReadThisBuf;
1984 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
1985 }
1986 }
1987 break;
1988 }
1989
1990 case __NR_rename: /* syscall 38 */
1991 /* int rename(const char *oldpath, const char *newpath); */
1992 if (VG_(clo_trace_syscalls))
1993 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00001994 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
1995 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00001996 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001997 break;
1998
1999 case __NR_rmdir: /* syscall 40 */
2000 /* int rmdir(const char *pathname); */
2001 if (VG_(clo_trace_syscalls))
2002 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002003 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002004 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002005 break;
2006
2007 case __NR_sched_setparam:
2008 case __NR_sched_getparam:
2009 case __NR_sched_yield:
2010 case __NR_sched_get_priority_min:
2011 if (VG_(clo_instrument)) {
2012 VG_(message)(Vg_UserMsg,
2013 "Warning: noted but unhandled __NR_sched_* syscall (%d).",
2014 syscallno);
2015 VG_(message)(Vg_UserMsg,
2016 " This could cause spurious value errors"
2017 " to appear.");
2018 }
sewardj2e93c502002-04-12 11:12:52 +00002019 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002020 break;
2021
2022 case __NR_select: /* syscall 82 */
2023 /* struct sel_arg_struct {
2024 unsigned long n;
2025 fd_set *inp, *outp, *exp;
2026 struct timeval *tvp;
2027 };
2028 int old_select(struct sel_arg_struct *arg);
2029 */
2030 {
2031 Bool arg_block_readable
2032 = VG_(clo_instrument)
2033 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
2034 : True;
sewardj8c824512002-04-14 04:16:48 +00002035 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002036 if (arg_block_readable) {
2037 UInt* arg_struct = (UInt*)arg1;
2038 arg1 = arg_struct[0];
2039 arg2 = arg_struct[1];
2040 arg3 = arg_struct[2];
2041 arg4 = arg_struct[3];
2042 arg5 = arg_struct[4];
2043
2044 if (VG_(clo_trace_syscalls))
2045 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2046 arg1,arg2,arg3,arg4,arg5);
2047 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002048 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002049 arg1/8 /* __FD_SETSIZE/8 */ );
2050 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002051 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002052 arg1/8 /* __FD_SETSIZE/8 */ );
2053 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002054 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002055 arg1/8 /* __FD_SETSIZE/8 */ );
2056 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002057 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002058 sizeof(struct timeval) );
2059 }
2060 }
sewardj2e93c502002-04-12 11:12:52 +00002061 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002062 break;
2063
2064 case __NR_setitimer: /* syscall 104 */
2065 /* setitimer(int which, const struct itimerval *value,
2066 struct itimerval *ovalue); */
2067 if (VG_(clo_trace_syscalls))
2068 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002069 must_be_readable(tst, "setitimer(value)",
sewardjde4a1d02002-03-22 01:27:54 +00002070 arg2, sizeof(struct itimerval) );
2071 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002072 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002073 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002074 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002075 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2076 make_readable(arg3, sizeof(struct itimerval));
2077 }
2078 break;
2079
2080# if defined(__NR_setfsgid32)
2081 case __NR_setfsgid32: /* syscall 216 */
2082 /* int setfsgid(uid_t fsgid); */
2083 if (VG_(clo_trace_syscalls))
2084 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002085 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002086 break;
2087# endif
2088
2089# if defined(__NR_setgid32)
2090 case __NR_setgid32: /* syscall 214 */
2091# endif
2092 case __NR_setgid: /* syscall 46 */
2093 /* int setgid(gid_t gid); */
2094 if (VG_(clo_trace_syscalls))
2095 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002096 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002097 break;
2098
2099 case __NR_setsid: /* syscall 66 */
2100 /* pid_t setsid(void); */
2101 if (VG_(clo_trace_syscalls))
2102 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002103 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002104 break;
2105
2106# if defined(__NR_setgroups32)
2107 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002108# endif
2109 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002110 /* int setgroups(size_t size, const gid_t *list); */
2111 if (VG_(clo_trace_syscalls))
2112 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2113 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002114 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002115 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002116 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002117 break;
sewardjde4a1d02002-03-22 01:27:54 +00002118
2119 case __NR_setpgid: /* syscall 57 */
2120 /* int setpgid(pid_t pid, pid_t pgid); */
2121 if (VG_(clo_trace_syscalls))
2122 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002123 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002124 break;
2125
2126# if defined(__NR_setregid32)
2127 case __NR_setregid32: /* syscall 204 */
2128 /* int setregid(gid_t rgid, gid_t egid); */
2129 if (VG_(clo_trace_syscalls))
2130 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
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_setresuid32)
2136 case __NR_setresuid32: /* syscall 208 */
2137 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2138 if (VG_(clo_trace_syscalls))
2139 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002140 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002141 break;
2142# endif
2143
2144# if defined(__NR_setreuid32)
2145 case __NR_setreuid32: /* syscall 203 */
2146# endif
2147 case __NR_setreuid: /* syscall 70 */
2148 /* int setreuid(uid_t ruid, uid_t euid); */
2149 if (VG_(clo_trace_syscalls))
2150 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002151 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002152 break;
2153
2154 case __NR_setrlimit: /* syscall 75 */
2155 /* int setrlimit (int resource, const struct rlimit *rlim); */
2156 if (VG_(clo_trace_syscalls))
2157 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002158 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002159 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002160 break;
2161
2162# if defined(__NR_setuid32)
2163 case __NR_setuid32: /* syscall 213 */
2164# endif
2165 case __NR_setuid: /* syscall 23 */
2166 /* int setuid(uid_t uid); */
2167 if (VG_(clo_trace_syscalls))
2168 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002169 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002170 break;
2171
2172 case __NR_socketcall: /* syscall 102 */
2173 /* int socketcall(int call, unsigned long *args); */
2174 if (VG_(clo_trace_syscalls))
2175 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2176 switch (arg1 /* request */) {
2177
2178 case SYS_SOCKETPAIR:
2179 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002180 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002181 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002182 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002183 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002184 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002185 if (!VG_(is_kerror)(res))
2186 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2187 break;
2188
2189 case SYS_SOCKET:
2190 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002191 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002192 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002193 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002194 break;
2195
2196 case SYS_BIND:
2197 /* int bind(int sockfd, struct sockaddr *my_addr,
2198 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002199 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002200 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002201 must_be_readable( tst, "socketcall.bind(my_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002202 ((UInt*)arg2)[1], ((UInt*)arg2)[2] );
sewardj2e93c502002-04-12 11:12:52 +00002203 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002204 break;
2205
2206 case SYS_LISTEN:
2207 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002208 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002209 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002210 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002211 break;
2212
2213 case SYS_ACCEPT: {
2214 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2215 Addr addr;
2216 Addr p_addrlen;
2217 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002218 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002219 arg2, 3*sizeof(Addr) );
2220 addr = ((UInt*)arg2)[1];
2221 p_addrlen = ((UInt*)arg2)[2];
2222 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002223 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002224 p_addrlen, sizeof(int) );
2225 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002226 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002227 addr, addrlen_in );
2228 }
sewardj2e93c502002-04-12 11:12:52 +00002229 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002230 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2231 addrlen_out = safe_dereference( p_addrlen, 0 );
2232 if (addrlen_out > 0)
2233 make_readable( addr, addrlen_out );
2234 }
2235 break;
2236 }
2237
2238 case SYS_SENDTO:
2239 /* int sendto(int s, const void *msg, int len,
2240 unsigned int flags,
2241 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002242 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002243 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002244 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002245 ((UInt*)arg2)[1], /* msg */
2246 ((UInt*)arg2)[2] /* len */ );
sewardj8c824512002-04-14 04:16:48 +00002247 must_be_readable( tst, "socketcall.sendto(to)",
sewardjde4a1d02002-03-22 01:27:54 +00002248 ((UInt*)arg2)[4], /* to */
2249 ((UInt*)arg2)[5] /* tolen */ );
sewardj2e93c502002-04-12 11:12:52 +00002250 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002251 break;
2252
2253 case SYS_SEND:
2254 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002255 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002256 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002257 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002258 ((UInt*)arg2)[1], /* msg */
2259 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002260 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002261 break;
2262
2263 case SYS_RECVFROM:
2264 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2265 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002266 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002267 arg2, 6*sizeof(Addr) );
2268 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002269 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002270 ((UInt*)arg2)[5] /* fromlen */,
2271 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002272 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002273 ((UInt*)arg2)[4], /*from*/
2274 safe_dereference( (Addr)
2275 ((UInt*)arg2)[5], 0 ) );
2276 }
sewardj8c824512002-04-14 04:16:48 +00002277 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002278 ((UInt*)arg2)[1], /* buf */
2279 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002280 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002281 if (!VG_(is_kerror)(res) && res >= 0) {
2282 make_readable( ((UInt*)arg2)[1], /* buf */
2283 ((UInt*)arg2)[2] /* len */ );
2284 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2285 make_readable(
2286 ((UInt*)arg2)[4], /*from*/
2287 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2288 }
2289 }
2290 /* phew! */
2291 break;
2292
2293 case SYS_RECV:
2294 /* int recv(int s, void *buf, int len, unsigned int flags); */
2295 /* man 2 recv says:
2296 The recv call is normally used only on a connected socket
2297 (see connect(2)) and is identical to recvfrom with a NULL
2298 from parameter.
2299 */
sewardj8c824512002-04-14 04:16:48 +00002300 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002301 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002302 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002303 ((UInt*)arg2)[1], /* buf */
2304 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002305 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002306 if (!VG_(is_kerror)(res) && res >= 0
2307 && ((UInt*)arg2)[1] != (UInt)NULL) {
2308 make_readable( ((UInt*)arg2)[1], /* buf */
2309 ((UInt*)arg2)[2] /* len */ );
2310 }
2311 break;
2312
2313 case SYS_CONNECT: {
2314 struct sockaddr *sa;
2315 /* int connect(int sockfd,
2316 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002317 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002318 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002319 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002320 ((UInt*)arg2)[1], /* serv_addr */
2321 sizeof (sa_family_t));
2322 sa = (struct sockaddr *) (((UInt*)arg2)[1]);
2323 if (sa->sa_family == AF_UNIX)
sewardj8c824512002-04-14 04:16:48 +00002324 must_be_readable_asciiz( tst,
sewardjde4a1d02002-03-22 01:27:54 +00002325 "socketcall.connect(serv_addr.sun_path)",
2326 (UInt) ((struct sockaddr_un *) sa)->sun_path);
2327 /* XXX There probably should be more cases here since not
2328 all of the struct sockaddr_XXX must be initialized. But
2329 wait until something pops up. */
2330 else
sewardj8c824512002-04-14 04:16:48 +00002331 must_be_readable( tst, "socketcall.connect(serv_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002332 ((UInt*)arg2)[1], /* serv_addr */
2333 ((UInt*)arg2)[2] /* addrlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002334 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002335 break;
2336 }
2337
2338 case SYS_SETSOCKOPT:
2339 /* int setsockopt(int s, int level, int optname,
2340 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002341 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002342 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002343 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002344 ((UInt*)arg2)[3], /* optval */
2345 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002346 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002347 break;
2348
2349 case SYS_GETSOCKOPT:
2350 /* int setsockopt(int s, int level, int optname,
2351 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002352 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002353 arg2, 5*sizeof(Addr) );
2354 {
2355 Addr optval_p = ((UInt*)arg2)[3];
2356 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002357 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002358 UInt optlen_after;
2359 UInt optlen = safe_dereference ( optlen_p, 0 );
2360 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002361 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002362 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002363 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002364 optlen_after = safe_dereference ( optlen_p, 0 );
2365 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2366 make_readable( optval_p, optlen_after );
2367 }
2368 break;
2369
2370 case SYS_GETSOCKNAME:
2371 /* int getsockname(int s, struct sockaddr* name,
2372 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002373 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002374 arg2, 3*sizeof(Addr) );
2375 {
2376 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2377 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002378 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002379 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002380 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002381 if (!VG_(is_kerror)(res)) {
2382 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2383 if (namelen > 0
2384 && ((UInt*)arg2)[1] != (UInt)NULL)
2385 make_readable( ((UInt*)arg2)[1], namelen );
2386 }
2387 }
2388 break;
2389
2390 case SYS_GETPEERNAME:
2391 /* int getpeername(int s, struct sockaddr* name,
2392 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002393 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002394 arg2, 3*sizeof(Addr) );
2395 {
2396 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2397 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002398 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002399 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002400 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002401 if (!VG_(is_kerror)(res)) {
2402 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2403 if (namelen > 0
2404 && ((UInt*)arg2)[1] != (UInt)NULL)
2405 make_readable( ((UInt*)arg2)[1], namelen );
2406 }
2407 }
2408 break;
2409
2410 case SYS_SHUTDOWN:
2411 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002412 must_be_readable( tst, "socketcall.shutdown(args)",
2413 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002414 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002415 break;
2416
2417 case SYS_SENDMSG:
2418 {
2419 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2420
2421 /* this causes warnings, and I don't get why. glibc bug?
2422 * (after all it's glibc providing the arguments array)
2423 must_be_readable( "socketcall.sendmsg(args)",
2424 arg2, 3*sizeof(Addr) );
2425 */
2426
2427 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002428 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002429
sewardj2e93c502002-04-12 11:12:52 +00002430 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002431 break;
2432 }
2433
2434 case SYS_RECVMSG:
2435 {
2436 /* int recvmsg(int s, struct msghdr *msg, int flags); */
2437
2438 /* this causes warnings, and I don't get why. glibc bug?
2439 * (after all it's glibc providing the arguments array)
2440 must_be_readable( "socketcall.recvmsg(args)",
2441 arg2, 3*sizeof(Addr) );
2442 */
2443
2444 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002445 msghdr_foreachfield ( tst, msg, must_be_writable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002446
sewardj2e93c502002-04-12 11:12:52 +00002447 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002448
2449 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002450 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002451
2452 break;
2453 }
2454
2455 default:
2456 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2457 VG_(panic)("... bye!\n");
2458 break; /*NOTREACHED*/
2459 }
2460 break;
2461
2462 case __NR_stat: /* syscall 106 */
2463 /* int stat(const char *file_name, struct stat *buf); */
2464 if (VG_(clo_trace_syscalls))
2465 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002466 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2467 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002468 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002469 if (!VG_(is_kerror)(res))
2470 make_readable( arg2, sizeof(struct stat) );
2471 break;
2472
2473 case __NR_statfs: /* syscall 99 */
2474 /* int statfs(const char *path, struct statfs *buf); */
2475 if (VG_(clo_trace_syscalls))
2476 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002477 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2478 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002479 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002480 if (!VG_(is_kerror)(res))
2481 make_readable( arg2, sizeof(struct statfs) );
2482 break;
2483
2484 case __NR_symlink: /* syscall 83 */
2485 /* int symlink(const char *oldpath, const char *newpath); */
2486 if (VG_(clo_trace_syscalls))
2487 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002488 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2489 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002490 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002491 break;
2492
2493# if defined(__NR_stat64)
2494 case __NR_stat64: /* syscall 195 */
2495 /* int stat64(const char *file_name, struct stat64 *buf); */
2496 if (VG_(clo_trace_syscalls))
2497 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002498 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2499 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002500 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002501 if (!VG_(is_kerror)(res))
2502 make_readable( arg2, sizeof(struct stat64) );
2503 break;
2504# endif
2505
2506# if defined(__NR_fstat64)
2507 case __NR_fstat64: /* syscall 197 */
2508 /* int fstat64(int filedes, struct stat64 *buf); */
2509 if (VG_(clo_trace_syscalls))
2510 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002511 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002512 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002513 if (!VG_(is_kerror)(res))
2514 make_readable( arg2, sizeof(struct stat64) );
2515 break;
2516# endif
2517
2518 case __NR_sysinfo: /* syscall 116 */
2519 /* int sysinfo(struct sysinfo *info); */
2520 if (VG_(clo_trace_syscalls))
2521 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002522 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002523 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002524 if (!VG_(is_kerror)(res))
2525 make_readable( arg1, sizeof(struct sysinfo) );
2526 break;
2527
2528 case __NR_time: /* syscall 13 */
2529 /* time_t time(time_t *t); */
2530 if (VG_(clo_trace_syscalls))
2531 VG_(printf)("time ( %p )\n",arg1);
2532 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002533 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002534 }
sewardj2e93c502002-04-12 11:12:52 +00002535 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002536 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2537 make_readable( arg1, sizeof(time_t) );
2538 }
2539 break;
2540
2541 case __NR_times: /* syscall 43 */
2542 /* clock_t times(struct tms *buf); */
2543 if (VG_(clo_trace_syscalls))
2544 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002545 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002546 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002547 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2548 make_readable( arg1, sizeof(struct tms) );
2549 }
2550 break;
2551
2552 case __NR_truncate: /* syscall 92 */
2553 /* int truncate(const char *path, size_t length); */
2554 if (VG_(clo_trace_syscalls))
2555 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002556 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002557 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002558 break;
2559
2560 case __NR_umask: /* syscall 60 */
2561 /* mode_t umask(mode_t mask); */
2562 if (VG_(clo_trace_syscalls))
2563 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002564 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002565 break;
2566
2567 case __NR_unlink: /* syscall 10 */
2568 /* int unlink(const char *pathname) */
2569 if (VG_(clo_trace_syscalls))
2570 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002571 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002572 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002573 break;
2574
2575 case __NR_uname: /* syscall 122 */
2576 /* int uname(struct utsname *buf); */
2577 if (VG_(clo_trace_syscalls))
2578 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002579 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002580 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002581 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2582 make_readable( arg1, sizeof(struct utsname) );
2583 }
2584 break;
2585
2586 case __NR_utime: /* syscall 30 */
2587 /* int utime(const char *filename, struct utimbuf *buf); */
2588 if (VG_(clo_trace_syscalls))
2589 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002590 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00002591 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002592 must_be_readable( tst, "utime(buf)", arg2,
2593 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00002594 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002595 break;
2596
2597 case __NR_wait4: /* syscall 114 */
2598 /* pid_t wait4(pid_t pid, int *status, int options,
2599 struct rusage *rusage) */
2600 if (VG_(clo_trace_syscalls))
2601 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
2602 arg1,arg2,arg3,arg4);
2603 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002604 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00002605 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002606 must_be_writable( tst, "wait4(rusage)", arg4,
2607 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00002608 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002609 if (!VG_(is_kerror)(res)) {
2610 if (arg2 != (Addr)NULL)
2611 make_readable( arg2, sizeof(int) );
2612 if (arg4 != (Addr)NULL)
2613 make_readable( arg4, sizeof(struct rusage) );
2614 }
2615 break;
2616
sewardjde4a1d02002-03-22 01:27:54 +00002617 case __NR_writev: { /* syscall 146 */
2618 /* int writev(int fd, const struct iovec * vector, size_t count); */
2619 UInt i;
2620 struct iovec * vec;
2621 if (VG_(clo_trace_syscalls))
2622 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002623 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002624 arg2, arg3 * sizeof(struct iovec) );
2625 /* ToDo: don't do any of the following if the vector is invalid */
2626 vec = (struct iovec *)arg2;
2627 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002628 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002629 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002630 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002631 break;
2632 }
2633
2634 /*-------------------------- SIGNALS --------------------------*/
2635
2636 /* Normally set to 1, so that Valgrind's signal-simulation machinery
2637 is engaged. Sometimes useful to disable (set to 0), for
2638 debugging purposes, to make clients more deterministic. */
2639# define SIGNAL_SIMULATION 1
2640
2641 case __NR_rt_sigaction:
2642 case __NR_sigaction:
2643 /* int sigaction(int signum, struct k_sigaction *act,
2644 struct k_sigaction *oldact); */
2645 if (VG_(clo_trace_syscalls))
2646 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
2647 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002648 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00002649 arg2, sizeof(vki_ksigaction));
2650 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002651 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00002652 arg3, sizeof(vki_ksigaction));
2653 /* We do this one ourselves! */
2654# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00002655 VG_(do__NR_sigaction)(tid);
2656 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00002657# else
2658 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00002659 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002660# endif
2661 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2662 make_readable( arg3, sizeof(vki_ksigaction));
2663 break;
2664
2665 case __NR_rt_sigprocmask:
2666 case __NR_sigprocmask:
2667 /* int sigprocmask(int how, k_sigset_t *set,
2668 k_sigset_t *oldset); */
2669 if (VG_(clo_trace_syscalls))
2670 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
2671 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002672 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00002673 arg2, sizeof(vki_ksigset_t));
2674 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002675 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00002676 arg3, sizeof(vki_ksigset_t));
sewardj2e93c502002-04-12 11:12:52 +00002677 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002678 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2679 make_readable( arg3, sizeof(vki_ksigset_t));
2680# if SIGNAL_SIMULATION
2681 /* For the reason why both the kernel and Valgrind process
2682 sigprocmask, see the detailed comment at
2683 vg_do__NR_sigprocmask(). */
2684 VG_(do__NR_sigprocmask) ( arg1 /*how*/, (vki_ksigset_t*) arg2 );
2685# endif
2686 break;
2687
2688 default:
2689 VG_(message)
2690 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
2691 VG_(message)
2692 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
2693 VG_(message)
2694 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
2695 VG_(unimplemented)("no wrapper for the above system call");
2696 vg_assert(3+3 == 7);
2697 break; /*NOTREACHED*/
2698 }
2699
sewardjde4a1d02002-03-22 01:27:54 +00002700 /* { void zzzmemscan(void); zzzmemscan(); } */
2701
sewardjde4a1d02002-03-22 01:27:54 +00002702 if (! VG_(first_and_last_secondaries_look_plausible))
2703 sane_before_call = False;
2704
2705 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00002706 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00002707 VG_(message)(Vg_DebugMsg,
2708 "probable sanity check failure for syscall number %d\n",
2709 syscallno );
2710 VG_(panic)("aborting due to the above ... bye!");
2711 }
2712
2713 VGP_POPCC;
2714}
2715
2716
sewardj2e93c502002-04-12 11:12:52 +00002717
2718/* Perform pre- and post- actions for a blocking syscall, but do not
2719 do the syscall itself. If res is NULL, the pre-syscall actions are
2720 to be performed. If res is non-NULL, the post-syscall actions are
2721 to be performed, and *res is assumed to hold the result of the
2722 syscall. This slightly strange scheme makes it impossible to
2723 mistakenly use the value of *res in the pre-syscall actions.
2724
2725 This doesn't actually do the syscall itself, it is important to
2726 observe.
2727
2728 Because %eax is used both for the syscall number before the call
2729 and the result value afterwards, we can't reliably use it to get
2730 the syscall number. So the caller has to pass it explicitly.
2731*/
sewardj8c824512002-04-14 04:16:48 +00002732void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00002733 Int syscallno,
2734 Int* /*IN*/ res )
2735{
2736 Bool sane_before_post = True;
2737 Bool sane_after_post = True;
2738 ThreadState* tst = VG_(get_thread_state)( tid );
2739 UInt arg1 = tst->m_ebx;
2740 UInt arg2 = tst->m_ecx;
2741 UInt arg3 = tst->m_edx;
2742 /*
2743 UInt arg4 = tst->m_esi;
2744 UInt arg5 = tst->m_edi;
2745 */
2746 VGP_PUSHCC(VgpSyscall);
2747
2748 if (res != NULL
2749 && ! VG_(first_and_last_secondaries_look_plausible))
2750 sane_before_post = False;
2751
2752 switch (syscallno) {
2753
2754 case __NR_read: /* syscall 3 */
2755 /* size_t read(int fd, void *buf, size_t count); */
2756 if (res == NULL) {
2757 /* PRE */
2758 if (VG_(clo_trace_syscalls))
2759 VG_(printf)(
2760 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
2761 VG_(getpid)(), tid,
2762 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002763 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002764 } else {
2765 /* POST */
2766 if (VG_(clo_trace_syscalls))
2767 VG_(printf)(
2768 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
2769 VG_(getpid)(), tid,
2770 arg1, arg2, arg3, *res);
2771 if (!VG_(is_kerror)(*res) && *res > 0) {
2772 make_readable( arg2, *res );
2773 }
2774 }
2775 break;
2776
2777 case __NR_write: /* syscall 4 */
2778 /* size_t write(int fd, const void *buf, size_t count); */
2779 if (res == NULL) {
2780 /* PRE */
2781 if (VG_(clo_trace_syscalls))
2782 VG_(printf)(
2783 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
2784 VG_(getpid)(), tid,
2785 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002786 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002787 } else {
2788 /* POST */
2789 if (VG_(clo_trace_syscalls))
2790 VG_(printf)(
2791 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
2792 VG_(getpid)(), tid,
2793 arg1, arg2, arg3, *res);
2794 }
2795 break;
2796
2797 default:
2798 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
2799 syscallno);
2800 VG_(panic)("check_known_blocking_syscall");
2801 /*NOTREACHED*/
2802 break;
2803 }
2804
2805 if (res != NULL) { /* only check after syscall */
2806 if (! VG_(first_and_last_secondaries_look_plausible))
2807 sane_after_post = False;
2808
2809 if (sane_before_post && (!sane_after_post)) {
2810 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
2811 VG_(message)(Vg_DebugMsg,
2812 "probable sanity check failure for syscall number %d\n",
2813 syscallno );
2814 VG_(panic)("aborting due to the above ... bye!");
2815 }
2816 }
2817
2818 VGP_POPCC;
2819}
2820
2821
sewardjde4a1d02002-03-22 01:27:54 +00002822/*--------------------------------------------------------------------*/
2823/*--- end vg_syscall_mem.c ---*/
2824/*--------------------------------------------------------------------*/