blob: 5e8e6dd4ed9da417513f216de1ef386ad22364cf [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
13 Julian_Seward@muraroa.demon.co.uk
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file LICENSE.
31*/
32
33#include "vg_include.h"
34
35/* vg_unsafe.h should NOT be included into any file except this
36 one. */
37#include "vg_unsafe.h"
38
39
40/* All system calls are channelled through vg_wrap_syscall. It does
41 three things:
42
43 * optionally, checks the permissions for the args to the call
44
45 * perform the syscall, usually by passing it along to the kernel
46 unmodified. However, because we simulate signals ourselves,
47 signal-related syscalls are routed to vg_signal.c, and are not
48 delivered to the kernel.
49
50 * Update the permission maps following the syscall.
51
52 A magical piece of assembly code, vg_do_syscall(), in vg_syscall.S
53 does the tricky bit of passing a syscall to the kernel, whilst
54 having the simulator retain control.
55*/
56
57static void make_noaccess ( Addr a, UInt len )
58{
59 if (VG_(clo_instrument))
60 VGM_(make_noaccess) ( a, len );
61}
62
63static void make_writable ( Addr a, UInt len )
64{
65 if (VG_(clo_instrument))
66 VGM_(make_writable) ( a, len );
67}
68
69static void make_readable ( Addr a, UInt len )
70{
71 if (VG_(clo_instrument))
72 VGM_(make_readable) ( a, len );
73}
74
75static void make_readwritable ( Addr a, UInt len )
76{
77 if (VG_(clo_instrument))
78 VGM_(make_readwritable) ( a, len );
79}
80
81static
sewardj8c824512002-04-14 04:16:48 +000082void must_be_writable ( ThreadState* tst,
83 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000084{
85 Bool ok;
86 Addr bad_addr;
87 /* VG_(message)(Vg_DebugMsg,"must be writable: %x .. %x",
88 base,base+size-1); */
89 if (!VG_(clo_instrument))
90 return;
91 ok = VGM_(check_writable) ( base, size, &bad_addr );
92 if (!ok)
sewardj8c824512002-04-14 04:16:48 +000093 VG_(record_param_err) ( tst, bad_addr, True, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +000094}
95
96static
sewardj8c824512002-04-14 04:16:48 +000097void must_be_readable ( ThreadState* tst,
98 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000099{
100 Bool ok;
101 Addr bad_addr;
102 /* VG_(message)(Vg_DebugMsg,"must be readable: %x .. %x",
103 base,base+size-1); */
104 if (!VG_(clo_instrument))
105 return;
106 ok = VGM_(check_readable) ( base, size, &bad_addr );
107 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000108 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000109}
110
111static
sewardj8c824512002-04-14 04:16:48 +0000112void must_be_readable_asciiz ( ThreadState* tst,
113 Char* syscall_name, UInt str )
sewardjde4a1d02002-03-22 01:27:54 +0000114{
115 Bool ok = True;
116 Addr bad_addr;
117 /* VG_(message)(Vg_DebugMsg,"must be readable asciiz: 0x%x",str); */
118 if (!VG_(clo_instrument))
119 return;
120 ok = VGM_(check_readable_asciiz) ( (Addr)str, &bad_addr );
121 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000122 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000123}
124
125
126/* Set memory permissions, based on PROT_* values for mmap/mprotect,
127 into the permissions our scheme understands. Dunno if this is
128 really correct. */
129
130static void approximate_mmap_permissions ( Addr a, UInt len, UInt prot )
131{
132 /* PROT_READ and PROT_WRITE --> readable
133 PROT_READ only --> readable
134 PROT_WRITE only --> writable
135 NEITHER --> noaccess
136 */
137 if (prot & PROT_READ)
138 make_readable(a,len);
139 else
140 if (prot & PROT_WRITE)
141 make_writable(a,len);
142 else
143 make_noaccess(a,len);
144}
145
146
147/* Dereference a pointer, but only after checking that it's
148 safe to do so. If not, return the default.
149*/
150static
151UInt safe_dereference ( Addr aa, UInt defawlt )
152{
153 if (!VG_(clo_instrument))
154 return * (UInt*)aa;
155 if (VGM_(check_readable)(aa,4,NULL))
156 return * (UInt*)aa;
157 else
158 return defawlt;
159}
160
161
162/* Is this a Linux kernel error return value? */
163/* From:
164 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
165 linux/i386/sysdep.h?
166 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
167
168 QUOTE:
169
170 Linux uses a negative return value to indicate syscall errors,
171 unlike most Unices, which use the condition codes' carry flag.
172
173 Since version 2.1 the return value of a system call might be
174 negative even if the call succeeded. E.g., the `lseek' system call
175 might return a large offset. Therefore we must not anymore test
176 for < 0, but test for a real error by making sure the value in %eax
177 is a real error number. Linus said he will make sure the no syscall
178 returns a value in -1 .. -4095 as a valid result so we can savely
179 test with -4095.
180
181 END QUOTE
182*/
183Bool VG_(is_kerror) ( Int res )
184{
185 if (res >= -4095 && res <= -1)
186 return True;
187 else
188 return False;
189}
190
191static
192UInt get_shm_size ( Int shmid )
193{
194 struct shmid_ds buf;
195 long __res;
196 __asm__ volatile ( "int $0x80"
197 : "=a" (__res)
198 : "0" (__NR_ipc),
199 "b" ((long)(24) /*IPCOP_shmctl*/),
200 "c" ((long)(shmid)),
201 "d" ((long)(IPC_STAT)),
202 "S" ((long)(0)),
203 "D" ((long)(&buf)) );
204 if ( VG_(is_kerror) ( __res ) )
205 return 0;
206
207 return buf.shm_segsz;
208}
209
210static
sewardj8c824512002-04-14 04:16:48 +0000211Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000212{
213 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
214 Char *result = VG_(malloc) ( aid, len );
215 VG_(strcpy) ( result, s1 );
216 VG_(strcat) ( result, s2 );
217 return result;
218}
219
220static
sewardj8c824512002-04-14 04:16:48 +0000221void must_be_readable_sendmsg ( ThreadState* tst,
222 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000223{
224 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000225 must_be_readable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000226 VG_(free) ( VG_AR_TRANSIENT, outmsg );
227}
228
229static
sewardj8c824512002-04-14 04:16:48 +0000230void must_be_writable_recvmsg ( ThreadState* tst,
231 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000232{
233 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000234 must_be_writable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000235 VG_(free) ( VG_AR_TRANSIENT, outmsg );
236}
237
238static
sewardj8c824512002-04-14 04:16:48 +0000239void make_readable_recvmsg ( ThreadState* tst,
240 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000241{
242 make_readable( base, size );
243}
244
245static
sewardj8c824512002-04-14 04:16:48 +0000246void msghdr_foreachfield (
247 ThreadState* tst,
248 struct msghdr *msg,
249 void (*foreach_func)( ThreadState*, Char *, UInt, UInt )
250 )
sewardjde4a1d02002-03-22 01:27:54 +0000251{
252 if ( !msg )
253 return;
254
sewardj8c824512002-04-14 04:16:48 +0000255 foreach_func ( tst, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000256
257 if ( msg->msg_name )
sewardj8c824512002-04-14 04:16:48 +0000258 foreach_func ( tst,
259 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000260 (Addr)msg->msg_name, msg->msg_namelen );
261
262 if ( msg->msg_iov ) {
263 struct iovec *iov = msg->msg_iov;
264 UInt i;
265
sewardj8c824512002-04-14 04:16:48 +0000266 foreach_func ( tst,
267 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000268 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
269
270 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
sewardj8c824512002-04-14 04:16:48 +0000271 foreach_func ( tst,
272 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000273 (Addr)iov->iov_base, iov->iov_len );
274 }
275
276 if ( msg->msg_control )
sewardj8c824512002-04-14 04:16:48 +0000277 foreach_func ( tst,
278 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000279 (Addr)msg->msg_control, msg->msg_controllen );
280}
281
282
283/* Records the current end of the data segment so we can make sense of
284 calls to brk(). Initial value set by hdm_init_memory_audit(). */
285Addr VGM_(curr_dataseg_end);
286
287
sewardj2e93c502002-04-12 11:12:52 +0000288
sewardjde4a1d02002-03-22 01:27:54 +0000289/* The Main Entertainment ... */
290
sewardj2e93c502002-04-12 11:12:52 +0000291void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +0000292{
sewardj2e93c502002-04-12 11:12:52 +0000293 Bool sane_before_call = True;
294 Bool sane_after_call = True;
295 ThreadState* tst = VG_(get_thread_state)( tid );
296 UInt syscallno = tst->m_eax;
297 UInt arg1 = tst->m_ebx;
298 UInt arg2 = tst->m_ecx;
299 UInt arg3 = tst->m_edx;
300 UInt arg4 = tst->m_esi;
301 UInt arg5 = tst->m_edi;
sewardjde4a1d02002-03-22 01:27:54 +0000302
303 /* Do not make this unsigned! */
304 Int res;
305
sewardjde4a1d02002-03-22 01:27:54 +0000306 VGP_PUSHCC(VgpSyscall);
307
308 /* Since buggy syscall wrappers sometimes break this, we may as well
309 check ourselves. */
310 if (! VG_(first_and_last_secondaries_look_plausible))
311 sane_before_call = False;
312
313 /* the syscall no is in %eax. For syscalls with <= 5 args,
314 args 1 .. 5 to the syscall are in %ebx %ecx %edx %esi %edi.
315 For calls with > 5 args, %ebx points to a lump of memory
316 containing the args.
317
318 The result is returned in %eax. If this value >= 0, the call
319 succeeded, and this is the return value. If < 0, it failed, and
320 the negation of this value is errno. To be more specific,
321 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
322 (kernel 2.4.9 sources, include/asm-i386/errno.h)
323 then it indicates an error. Otherwise it doesn't.
324
325 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
326 (inclusive?) indicate error returns. Not sure where the -4095
327 comes from.
328 */
329
330 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000331 VG_(printf)("SYSCALL[%d,%d](%3d): ",
332 VG_(getpid)(), tid, syscallno);
sewardjde4a1d02002-03-22 01:27:54 +0000333
334 switch (syscallno) {
335
336 case __NR_sigaltstack:
337 VG_(unimplemented)
338 ("client signals on alternative stack (SA_ONSTACK)");
339 break;
340
341 case __NR_clone:
342 VG_(unimplemented)
343 ("clone(): Valgrind doesn't support threads; sorry.");
344 break;
345
346# if defined(__NR_modify_ldt)
347 case __NR_modify_ldt:
348 VG_(unimplemented)
349 ("modify_ldt(): I (JRS) haven't investigated this yet; sorry.");
350 break;
351# endif
352
sewardj73f1f072002-03-29 14:22:46 +0000353 /* !!!!!!!!!! New, untested syscalls !!!!!!!!!!!!!!!!!!!!! */
354
355 case __NR_nice: /* syscall 34 */
356 /* int nice(int inc); */
357 if (VG_(clo_trace_syscalls))
358 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000359 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000360 break;
361
sewardjde4a1d02002-03-22 01:27:54 +0000362 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
363
sewardjd7f07662002-03-24 10:49:46 +0000364# if defined(__NR_setresgid32)
365 case __NR_setresgid32: /* syscall 210 */
366 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
367 if (VG_(clo_trace_syscalls))
368 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000369 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000370 break;
371# endif
372
sewardjde4a1d02002-03-22 01:27:54 +0000373# if defined(__NR_setfsuid32)
374 case __NR_setfsuid32: /* syscall 215 */
375 /* int setfsuid(uid_t fsuid); */
376 if (VG_(clo_trace_syscalls))
377 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000378 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000379 break;
380# endif
381
382# if defined(__NR__sysctl)
383 case __NR__sysctl:
384 /* int _sysctl(struct __sysctl_args *args); */
385 if (VG_(clo_trace_syscalls))
386 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000387 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000388 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000389 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000390 if (!VG_(is_kerror)(res))
391 make_readable ( arg1, sizeof(struct __sysctl_args) );
392 break;
393# endif
394
395# if defined(__NR_sched_getscheduler)
396 case __NR_sched_getscheduler:
397 /* int sched_getscheduler(pid_t pid); */
398 if (VG_(clo_trace_syscalls))
399 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000400 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000401 break;
402# endif
403
404# if defined(__NR_sched_setscheduler)
405 case __NR_sched_setscheduler:
406 /* int sched_setscheduler(pid_t pid, int policy,
407 const struct sched_param *p); */
408 if (VG_(clo_trace_syscalls))
409 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
410 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000411 must_be_readable( tst,
412 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000413 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000414 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000415 break;
416# endif
417
418# if defined(__NR_mlockall)
419 case __NR_mlockall:
420 /* int mlockall(int flags); */
421 if (VG_(clo_trace_syscalls))
422 VG_(printf)("mlockall ( %x )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000423 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000424 break;
425# endif
426
427# if defined(__NR_munlockall)
428 case __NR_munlockall:
429 /* int munlockall(void); */
430 if (VG_(clo_trace_syscalls))
431 VG_(printf)("munlockall ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000432 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000433 break;
434# endif
435
436#if defined(__NR_sched_get_priority_max)
437 case __NR_sched_get_priority_max:
438 /* int sched_get_priority_max(int policy); */
439 if (VG_(clo_trace_syscalls))
440 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000441 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000442 break;
443# endif
444
445# if defined(__NR_setfsgid)
446 case __NR_setfsgid: /* syscall 139 */
447 /* int setfsgid(gid_t gid); */
448 if (VG_(clo_trace_syscalls))
449 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000450 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000451 break;
452# endif
453
454# if defined(__NR_setregid)
455 case __NR_setregid: /* syscall 71 */
456 /* int setregid(gid_t rgid, gid_t egid); */
457 if (VG_(clo_trace_syscalls))
458 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +0000459 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000460 break;
461# endif
462
463# if defined(__NR_setresuid)
464 case __NR_setresuid: /* syscall 164 */
465 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
466 if (VG_(clo_trace_syscalls))
467 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000468 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000469 break;
470# endif
471
472# if defined(__NR_setfsuid)
473 case __NR_setfsuid: /* syscall 138 */
474 /* int setfsuid(uid_t uid); */
475 if (VG_(clo_trace_syscalls))
476 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000477 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000478 break;
479# endif
480
481 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
482
483# if defined(__NR_sendfile)
484 case __NR_sendfile: /* syscall 187 */
485 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
486 size_t count) */
487 if (VG_(clo_trace_syscalls))
488 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000489 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000490 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000491 if (!VG_(is_kerror)(res)) {
492 make_readable( arg3, sizeof( off_t ) );
493 }
494 break;
495# endif
496
497 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
498
499# if defined(__NR_pwrite)
500 case __NR_pwrite: /* syscall 181 */
501 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
502 off_t offset); */
503 if (VG_(clo_trace_syscalls))
504 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000505 must_be_readable( tst, "pwrite(buf)", 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 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
511
512 case __NR_sync: /* syscall 36 */
513 /* int sync(); */
514 if (VG_(clo_trace_syscalls))
515 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000516 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000517 break;
518
519 case __NR_fstatfs: /* syscall 100 */
520 /* int fstatfs(int fd, struct statfs *buf); */
521 if (VG_(clo_trace_syscalls))
522 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000523 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000524 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000525 if (!VG_(is_kerror)(res))
526 make_readable( arg2, sizeof(struct statfs) );
527 break;
528
529 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
530
531 case __NR_pause: /* syscall 29 */
532 /* int pause(void); */
533 if (VG_(clo_trace_syscalls))
534 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000535 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000536 break;
537
538 case __NR_getsid: /* syscall 147 */
539 /* pid_t getsid(pid_t pid); */
540 if (VG_(clo_trace_syscalls))
541 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000542 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000543 break;
544
545# if defined(__NR_pread)
546 case __NR_pread: /* syscall 180 */
547 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
548 if (VG_(clo_trace_syscalls))
549 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000550 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000551 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000552 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000553 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
554 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000555 arg1, arg2, arg3, arg4, res);
556 if (!VG_(is_kerror)(res) && res > 0) {
557 make_readable( arg2, res );
558 }
559 break;
560# endif
561
562 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
563
564 case __NR_mknod: /* syscall 14 */
565 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
566 if (VG_(clo_trace_syscalls))
567 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000568 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000569 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000570 break;
571
572 case __NR_flock: /* syscall 143 */
573 /* int flock(int fd, int operation); */
574 if (VG_(clo_trace_syscalls))
575 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000576 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000577 break;
578
579# if defined(__NR_rt_sigsuspend)
580 /* Viewed with great suspicion by me, but, hey, let's do it
581 anyway ... */
582 case __NR_rt_sigsuspend: /* syscall 179 */
583 /* int sigsuspend(const sigset_t *mask); */
584 if (VG_(clo_trace_syscalls))
585 VG_(printf)("sigsuspend ( %p )\n", arg1 );
586 if (arg1 != (Addr)NULL) {
587 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000588 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000589 sizeof(vki_ksigset_t) );
590 }
sewardj2e93c502002-04-12 11:12:52 +0000591 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000592 break;
593# endif
594
595 case __NR_init_module: /* syscall 128 */
596 /* int init_module(const char *name, struct module *image); */
597 if (VG_(clo_trace_syscalls))
598 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000599 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
600 must_be_readable( tst, "init_module(image)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000601 sizeof(struct module) );
sewardj2e93c502002-04-12 11:12:52 +0000602 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000603 break;
604
605 case __NR_ioperm: /* syscall 101 */
606 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
607 if (VG_(clo_trace_syscalls))
608 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000609 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000610 break;
611
612 case __NR_capget: /* syscall 184 */
613 /* int capget(cap_user_header_t header, cap_user_data_t data); */
614 if (VG_(clo_trace_syscalls))
615 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000616 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000617 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000618 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000619 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000620 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000621 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
622 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
623 break;
624
625 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
626
627 case __NR_execve:
628 /* int execve (const char *filename,
629 char *const argv [],
630 char *const envp[]); */
631 if (VG_(clo_trace_syscalls))
632 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
633 arg1, arg1, arg2, arg3);
634 /* Make any binding for LD_PRELOAD disappear, so that child
635 processes don't get traced into. */
636 if (!VG_(clo_trace_children)) {
637 Int i;
638 Char** envp = (Char**)arg3;
639 for (i = 0; envp[i] != NULL; i++) {
640 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) {
641 VG_(mash_LD_PRELOAD_string)(&envp[i][11]);
642 }
643 }
644 }
sewardj2e93c502002-04-12 11:12:52 +0000645 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000646 /* Should we still be alive here? Don't think so. */
647 /* Actually, above comment is wrong. execve can fail, just
648 like any other syscall -- typically the file to exec does
649 not exist. Hence: */
650 vg_assert(VG_(is_kerror)(res));
651 break;
652
653 case __NR_exit: /* syscall 1 */
654 /* void _exit(int status); */
655 if (VG_(clo_trace_syscalls))
656 VG_(printf)("exit ( %d )\n", arg1);
657 VG_(message)(Vg_UserMsg,
658 "Warning: client exiting by calling exit(%d). Bye!",
659 arg1);
660
sewardj2e93c502002-04-12 11:12:52 +0000661 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000662 /* Definitely should not be alive here :) */
663 break;
664
665 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
666
667 case __NR_access: /* syscall 33 */
668 /* int access(const char *pathname, int mode); */
669 if (VG_(clo_trace_syscalls))
670 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000671 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000672 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000673 break;
674
675 case __NR_alarm: /* syscall 27 */
676 /* unsigned int alarm(unsigned int seconds); */
677 if (VG_(clo_trace_syscalls))
678 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000679 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000680 break;
681
682 case __NR_brk: /* syscall 45 */
683 /* Haven't a clue if this is really right. */
684 /* int brk(void *end_data_segment); */
685 if (VG_(clo_trace_syscalls))
686 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000687 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000688 if (VG_(clo_trace_syscalls))
689 VG_(printf)("0x%x\n", res);
690
691 if (!VG_(is_kerror)(res)) {
692 if (arg1 == 0) {
693 /* Just asking where the current end is. (???) */
694 VGM_(curr_dataseg_end) = res;
695 } else
696 if (arg1 < VGM_(curr_dataseg_end)) {
697 /* shrinking the data segment. */
698 make_noaccess( (Addr)arg1,
699 VGM_(curr_dataseg_end)-arg1 );
700 VGM_(curr_dataseg_end) = arg1;
701 } else
702 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
703 /* asked for more memory, and got it */
704 /*
705 VG_(printf)("BRK: new area %x .. %x\n",
706 VGM_(curr_dataseg_end, arg1-1 );
707 */
708 make_writable ( (Addr)VGM_(curr_dataseg_end),
709 arg1-VGM_(curr_dataseg_end) );
710 VGM_(curr_dataseg_end) = arg1;
711 }
712 }
713 break;
714
715 case __NR_chdir: /* syscall 12 */
716 /* int chdir(const char *path); */
717 if (VG_(clo_trace_syscalls))
718 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +0000719 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000720 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000721 break;
722
723 case __NR_chmod: /* syscall 15 */
724 /* int chmod(const char *path, mode_t mode); */
725 if (VG_(clo_trace_syscalls))
726 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000727 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000728 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000729 break;
730
731# if defined(__NR_chown32)
732 case __NR_chown32: /* syscall 212 */
733# endif
734# if defined(__NR_lchown32)
735 case __NR_lchown32: /* syscall 198 */
736# endif
737 case __NR_chown: /* syscall 16 */
738 /* int chown(const char *path, uid_t owner, gid_t group); */
739 if (VG_(clo_trace_syscalls))
740 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000741 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000742 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000743 break;
744
745 case __NR_close: /* syscall 6 */
746 /* int close(int fd); */
747 if (VG_(clo_trace_syscalls))
748 VG_(printf)("close ( %d )\n",arg1);
749 /* Detect and negate attempts by the client to close Valgrind's
750 logfile fd ... */
751 if (arg1 == VG_(clo_logfile_fd)) {
752 VG_(message)(Vg_UserMsg,
753 "Warning: client attempted to close "
754 "Valgrind's logfile fd (%d).",
755 VG_(clo_logfile_fd));
756 VG_(message)(Vg_UserMsg,
757 " Use --logfile-fd=<number> to select an "
758 "alternative logfile fd." );
759 } else {
sewardj2e93c502002-04-12 11:12:52 +0000760 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000761 }
762 break;
763
764 case __NR_dup: /* syscall 41 */
765 /* int dup(int oldfd); */
766 if (VG_(clo_trace_syscalls))
767 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000768 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000769 if (VG_(clo_trace_syscalls))
770 VG_(printf)("%d\n", res);
771 break;
772
773 case __NR_dup2: /* syscall 63 */
774 /* int dup2(int oldfd, int newfd); */
775 if (VG_(clo_trace_syscalls))
776 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000777 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000778 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000779 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
780 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000781 arg1, arg2, res);
782 break;
783
784 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +0000785 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +0000786 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000787 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
788 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000789 break;
790
791 case __NR_fchdir: /* syscall 133 */
792 /* int fchdir(int fd); */
793 if (VG_(clo_trace_syscalls))
794 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000795 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000796 break;
797
sewardj2f0de322002-03-24 10:17:25 +0000798# if defined(__NR_fchown32)
799 case __NR_fchown32: /* syscall 207 */
800# endif
801 case __NR_fchown: /* syscall 95 */
802 /* int fchown(int filedes, uid_t owner, gid_t group); */
803 if (VG_(clo_trace_syscalls))
804 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +0000805 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +0000806 break;
807
sewardjde4a1d02002-03-22 01:27:54 +0000808 case __NR_fchmod: /* syscall 94 */
809 /* int fchmod(int fildes, mode_t mode); */
810 if (VG_(clo_trace_syscalls))
811 VG_(printf)("fchmod ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000812 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000813 break;
sewardj2f0de322002-03-24 10:17:25 +0000814
sewardjde4a1d02002-03-22 01:27:54 +0000815# if defined(__NR_fcntl64)
816 case __NR_fcntl64: /* syscall 221 */
817 /* I don't know what the prototype for this is supposed to be. */
818 /* ??? int fcntl(int fd, int cmd); */
819 if (VG_(clo_trace_syscalls))
820 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000821 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000822 break;
823# endif
824
825 case __NR_fstat: /* syscall 108 */
826 /* int fstat(int filedes, struct stat *buf); */
827 if (VG_(clo_trace_syscalls))
828 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000829 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +0000830 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000831 if (!VG_(is_kerror)(res))
832 make_readable( arg2, sizeof(struct stat) );
833 break;
834
835 case __NR_vfork: /* syscall 190 */
836 /* pid_t vfork(void); */
837 if (VG_(clo_trace_syscalls))
838 VG_(printf)("vfork ( ) ... becomes ... ");
839 /* KLUDGE: we prefer to do a fork rather than vfork.
840 vfork gives a SIGSEGV, and the stated semantics looks
841 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +0000842 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +0000843 /* fall through ... */
844 case __NR_fork: /* syscall 2 */
845 /* pid_t fork(void); */
846 if (VG_(clo_trace_syscalls))
847 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000848 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000849 break;
850
851 case __NR_fsync: /* syscall 118 */
852 /* int fsync(int fd); */
853 if (VG_(clo_trace_syscalls))
854 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000855 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000856 break;
857
858 case __NR_ftruncate: /* syscall 93 */
859 /* int ftruncate(int fd, size_t length); */
860 if (VG_(clo_trace_syscalls))
861 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +0000862 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000863 break;
864
sewardj2f0de322002-03-24 10:17:25 +0000865# if defined(__NR_ftruncate64)
866 case __NR_ftruncate64: /* syscall 194 */
867 /* int ftruncate64(int fd, off64_t length); */
868 if (VG_(clo_trace_syscalls))
869 VG_(printf)("ftruncate64 ( %d, %lld )\n",
870 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +0000871 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000872 break;
873# endif
874
875 case __NR_getdents: /* syscall 141 */
876 /* int getdents(unsigned int fd, struct dirent *dirp,
877 unsigned int count); */
878 if (VG_(clo_trace_syscalls))
879 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000880 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000881 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000882 if (!VG_(is_kerror)(res) && res > 0)
883 make_readable( arg2, res );
884 break;
885
886# if defined(__NR_getdents64)
887 case __NR_getdents64: /* syscall 220 */
888 /* int getdents(unsigned int fd, struct dirent64 *dirp,
889 unsigned int count); */
890 if (VG_(clo_trace_syscalls))
891 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000892 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000893 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000894 if (!VG_(is_kerror)(res) && res > 0)
895 make_readable( arg2, res );
896 break;
897# endif
898
899# if defined(__NR_getgroups32)
900 case __NR_getgroups32: /* syscall 205 */
901# endif
902 case __NR_getgroups: /* syscall 80 */
903 /* int getgroups(int size, gid_t list[]); */
904 if (VG_(clo_trace_syscalls))
905 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
906 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +0000907 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000908 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +0000909 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000910 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
911 make_readable ( arg2, res * sizeof(gid_t) );
912 break;
913
914 case __NR_getcwd: /* syscall 183 */
915 /* char *getcwd(char *buf, size_t size); */
916 if (VG_(clo_trace_syscalls))
917 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000918 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
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 != (Addr)NULL)
921 make_readable ( arg1, arg2 );
922 /* Not really right -- really we should have the asciiz
923 string starting at arg1 readable, or up to arg2 bytes,
924 whichever finishes first. */
925 break;
926
927 case __NR_geteuid: /* syscall 49 */
928 /* uid_t geteuid(void); */
929 if (VG_(clo_trace_syscalls))
930 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000931 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000932 break;
933
934# if defined(__NR_geteuid32)
935 case __NR_geteuid32: /* syscall 201 */
936 /* ?? uid_t geteuid32(void); */
937 if (VG_(clo_trace_syscalls))
938 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000939 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000940 break;
941# endif
942
943 case __NR_getegid: /* syscall 50 */
944 /* gid_t getegid(void); */
945 if (VG_(clo_trace_syscalls))
946 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000947 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000948 break;
949
950# if defined(__NR_getegid32)
951 case __NR_getegid32: /* syscall 202 */
952 /* gid_t getegid32(void); */
953 if (VG_(clo_trace_syscalls))
954 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000955 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000956 break;
957# endif
958
959 case __NR_getgid: /* syscall 47 */
960 /* gid_t getgid(void); */
961 if (VG_(clo_trace_syscalls))
962 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000963 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000964 break;
965
966# if defined(__NR_getgid32)
967 case __NR_getgid32: /* syscall 200 */
968 /* gid_t getgid32(void); */
969 if (VG_(clo_trace_syscalls))
970 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000971 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000972 break;
973# endif
974
975 case __NR_getpid: /* syscall 20 */
976 /* pid_t getpid(void); */
977 if (VG_(clo_trace_syscalls))
978 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000979 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000980 break;
981
982 case __NR_getpgid: /* syscall 132 */
983 /* pid_t getpgid(pid_t pid); */
984 if (VG_(clo_trace_syscalls))
985 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000986 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000987 break;
988
989 case __NR_getpgrp: /* syscall 65 */
990 /* pid_t getpprp(void); */
991 if (VG_(clo_trace_syscalls))
992 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +0000993 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000994 break;
995
996 case __NR_getppid: /* syscall 64 */
997 /* pid_t getppid(void); */
998 if (VG_(clo_trace_syscalls))
999 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001000 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001001 break;
1002
1003 case __NR_getresgid: /* syscall 171 */
1004 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1005 if (VG_(clo_trace_syscalls))
1006 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001007 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1008 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1009 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001010 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001011 if (!VG_(is_kerror)(res) && res == 0) {
1012 make_readable ( arg1, sizeof(gid_t) );
1013 make_readable ( arg2, sizeof(gid_t) );
1014 make_readable ( arg3, sizeof(gid_t) );
1015 }
1016 break;
1017
1018# if defined(__NR_getresgid32)
1019 case __NR_getresgid32: /* syscall 211 */
1020 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1021 if (VG_(clo_trace_syscalls))
1022 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001023 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1024 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1025 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001026 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001027 if (!VG_(is_kerror)(res) && res == 0) {
1028 make_readable ( arg1, sizeof(gid_t) );
1029 make_readable ( arg2, sizeof(gid_t) );
1030 make_readable ( arg3, sizeof(gid_t) );
1031 }
1032 break;
1033# endif
1034
1035 case __NR_getresuid: /* syscall 165 */
1036 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1037 if (VG_(clo_trace_syscalls))
1038 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001039 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1040 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1041 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001042 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001043 if (!VG_(is_kerror)(res) && res == 0) {
1044 make_readable ( arg1, sizeof(uid_t) );
1045 make_readable ( arg2, sizeof(uid_t) );
1046 make_readable ( arg3, sizeof(uid_t) );
1047 }
1048 break;
1049
1050# if defined(__NR_getresuid32)
1051 case __NR_getresuid32: /* syscall 209 */
1052 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1053 if (VG_(clo_trace_syscalls))
1054 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001055 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1056 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1057 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001058 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001059 if (!VG_(is_kerror)(res) && res == 0) {
1060 make_readable ( arg1, sizeof(uid_t) );
1061 make_readable ( arg2, sizeof(uid_t) );
1062 make_readable ( arg3, sizeof(uid_t) );
1063 }
1064 break;
1065# endif
1066
1067# if defined(__NR_ugetrlimit)
1068 case __NR_ugetrlimit: /* syscall 191 */
1069# endif
1070 case __NR_getrlimit: /* syscall 76 */
1071 /* int getrlimit (int resource, struct rlimit *rlim); */
1072 if (VG_(clo_trace_syscalls))
1073 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001074 must_be_writable( tst, "getrlimit(rlim)", arg2,
1075 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001076 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001077 if (!VG_(is_kerror)(res) && res == 0)
1078 make_readable( arg2, sizeof(struct rlimit) );
1079 break;
1080
1081 case __NR_getrusage: /* syscall 77 */
1082 /* int getrusage (int who, struct rusage *usage); */
1083 if (VG_(clo_trace_syscalls))
1084 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001085 must_be_writable( tst, "getrusage(usage)", arg2,
1086 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001087 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001088 if (!VG_(is_kerror)(res) && res == 0)
1089 make_readable(arg2, sizeof(struct rusage) );
1090 break;
1091
1092 case __NR_gettimeofday: /* syscall 78 */
1093 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1094 if (VG_(clo_trace_syscalls))
1095 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001096 must_be_writable( tst, "gettimeofday(tv)", arg1,
1097 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001098 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001099 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001100 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001101 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001102 if (!VG_(is_kerror)(res) && res == 0) {
1103 make_readable( arg1, sizeof(struct timeval) );
1104 if (arg2 != 0)
1105 make_readable( arg2, sizeof(struct timezone) );
1106 }
1107 break;
1108
1109 case __NR_getuid: /* syscall 24 */
1110 /* uid_t getuid(void); */
1111 if (VG_(clo_trace_syscalls))
1112 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001113 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001114 break;
1115
1116# if defined(__NR_getuid32)
1117 case __NR_getuid32: /* syscall 199 */
1118 /* ???uid_t getuid32(void); */
1119 if (VG_(clo_trace_syscalls))
1120 VG_(printf)("getuid32 ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001121 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001122 break;
1123# endif
1124
1125 case __NR_ipc: /* syscall 117 */
1126 /* int ipc ( unsigned int call, int first, int second,
1127 int third, void *ptr, long fifth); */
1128 {
sewardj2e93c502002-04-12 11:12:52 +00001129 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001130
1131 if (VG_(clo_trace_syscalls))
1132 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1133 arg1,arg2,arg3,arg4,arg5,arg6);
1134 switch (arg1 /* call */) {
1135 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001136 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001137 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001138 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001139 break;
sewardj5b9e3502002-03-29 04:35:08 +00001140 case 2: /* IPCOP_semget */
1141 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001142 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001143 break;
1144 case 11: /* IPCOP_msgsnd */
1145 {
1146 struct msgbuf *msgp = (struct msgbuf *)arg5;
1147 Int msgsz = arg3;
1148
sewardj8c824512002-04-14 04:16:48 +00001149 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001150 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001151 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001152 (UInt)msgp->mtext, msgsz );
1153
sewardj2e93c502002-04-12 11:12:52 +00001154 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001155 break;
1156 }
1157 case 12: /* IPCOP_msgrcv */
1158 {
1159 struct msgbuf *msgp = ((struct ipc_kludge *)arg5)->msgp;
1160 Int msgsz = arg3;
1161
sewardj8c824512002-04-14 04:16:48 +00001162 must_be_writable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001163 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001164 must_be_writable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001165 (UInt)msgp->mtext, msgsz );
1166
sewardj2e93c502002-04-12 11:12:52 +00001167 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001168
1169 if ( !VG_(is_kerror)(res) && res > 0 ) {
1170 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1171 make_readable ( (UInt)msgp->mtext, res );
1172 }
1173 break;
1174 }
1175 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001176 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001177 break;
1178 case 14: /* IPCOP_msgctl */
1179 {
1180 switch (arg3 /* cmd */) {
1181 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001182 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001183 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001184 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001185 if ( !VG_(is_kerror)(res) && res > 0 ) {
1186 make_readable ( arg5, sizeof(struct msqid_ds) );
1187 }
1188 break;
1189 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001190 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001191 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001192 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001193 break;
1194 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001195 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001196 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001197 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001198 if ( !VG_(is_kerror)(res) && res > 0 ) {
1199 make_readable ( arg5, sizeof(struct msqid64_ds) );
1200 }
1201 break;
1202 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001203 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001204 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001205 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001206 break;
1207 default:
sewardj2e93c502002-04-12 11:12:52 +00001208 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001209 break;
1210 }
1211 break;
1212 }
sewardjde4a1d02002-03-22 01:27:54 +00001213 case 21: /* IPCOP_shmat */
1214 {
1215 Int shmid = arg2;
1216 Int shmflag = arg3;
1217 UInt addr;
1218
sewardj2e93c502002-04-12 11:12:52 +00001219 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001220
1221 if ( VG_(is_kerror) ( res ) )
1222 break;
1223
1224 /* force readability. before the syscall it is
1225 * indeed uninitialized, as can be seen in
1226 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1227 make_readable ( arg4, sizeof( ULong ) );
1228
1229 addr = safe_dereference ( arg4, 0 );
1230 if ( addr > 0 ) {
1231 UInt segmentSize = get_shm_size ( shmid );
1232 if ( segmentSize > 0 ) {
1233 if ( shmflag & SHM_RDONLY )
1234 make_readable ( addr, segmentSize );
1235 else
1236 make_readwritable ( addr, segmentSize );
1237 }
1238 }
1239 break;
1240 }
1241 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001242 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001243 /* ### FIXME: this should call make_noaccess on the
1244 * area passed to shmdt. But there's no way to
1245 * figure out the size of the shared memory segment
1246 * just from the address... Maybe we want to keep a
1247 * copy of the exiting mappings inside valgrind? */
1248 break;
1249 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001250 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001251 break;
1252 case 24: /* IPCOP_shmctl */
1253 {
1254 if ( arg3 > 0 ) {
sewardj8c824512002-04-14 04:16:48 +00001255 must_be_readable ( tst, "shmctl(buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001256 sizeof( struct shmid_ds ) );
1257
1258 if ( arg2 == SHM_STAT )
sewardj8c824512002-04-14 04:16:48 +00001259 must_be_writable( tst, "shmctl(IPC_STAT,buf)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001260 sizeof( struct shmid_ds ) );
1261 }
1262
sewardj2e93c502002-04-12 11:12:52 +00001263 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001264 break;
1265 }
1266 default:
1267 VG_(message)(Vg_DebugMsg,
1268 "FATAL: unhandled syscall(ipc) %d",
1269 arg1 );
1270 VG_(panic)("... bye!\n");
1271 break; /*NOTREACHED*/
1272 }
1273 }
1274 break;
1275
1276 case __NR_ioctl: /* syscall 54 */
1277 /* int ioctl(int d, int request, ...)
1278 [The "third" argument is traditionally char *argp,
1279 and will be so named for this discussion.]
1280 */
1281 /*
1282 VG_(message)(
1283 Vg_DebugMsg,
1284 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1285 arg2,arg1,arg3);
1286 */
1287 if (VG_(clo_trace_syscalls))
1288 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1289 switch (arg2 /* request */) {
1290 case TCSETS:
1291 case TCSETSW:
1292 case TCSETSF:
sewardj8c824512002-04-14 04:16:48 +00001293 must_be_readable( tst, "ioctl(TCSETSW)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001294 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001295 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001296 break;
1297 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001298 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001299 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001300 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001301 if (!VG_(is_kerror)(res) && res == 0)
1302 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1303 break;
sewardj2f0de322002-03-24 10:17:25 +00001304 case TCSETA:
sewardj8c824512002-04-14 04:16:48 +00001305 must_be_readable( tst, "ioctl(TCSETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001306 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001307 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001308 break;
1309 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001310 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001311 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001312 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001313 if (!VG_(is_kerror)(res) && res == 0)
1314 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1315 break;
sewardjde4a1d02002-03-22 01:27:54 +00001316 case TCSBRK:
1317 case TCSBRKP:
1318 case TCFLSH:
1319 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001320 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001321 break;
1322 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001323 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001324 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001325 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001326 if (!VG_(is_kerror)(res) && res == 0)
1327 make_readable ( arg3, sizeof(struct winsize) );
1328 break;
1329 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001330 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001331 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001332 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001333 break;
sewardj19fe3d02002-03-29 04:39:00 +00001334 case TIOCGPGRP:
1335 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001336 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001337 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001338 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001339 if (!VG_(is_kerror)(res) && res == 0)
1340 make_readable ( arg3, sizeof(pid_t) );
sewardjde4a1d02002-03-22 01:27:54 +00001341 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001342 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001343 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001344 if (!VG_(is_kerror)(res) && res == 0)
1345 make_readable ( arg3, sizeof(int));
1346 break;
sewardj73f1f072002-03-29 14:22:46 +00001347 case TIOCSCTTY:
1348 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001349 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001350 break;
sewardjde4a1d02002-03-22 01:27:54 +00001351 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001352 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001353 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001354 break;
1355 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001356 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001357 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001358 break;
1359 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001360 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001361 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001362 break;
1363 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001364 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001365 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001366 if (!VG_(is_kerror)(res) && res == 0)
1367 make_readable( arg3, sizeof(int) );
1368 break;
1369
1370 /* If you get compilation problems here, change the #if
1371 1 to #if 0 and get rid of <scsi/sg.h> in
1372 vg_unsafe.h. */
1373# if 1
1374 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001375 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1376 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001377 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001378 break;
1379# if defined(SG_IO)
1380 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001381 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001382 sizeof(struct sg_io_hdr) );
sewardj2e93c502002-04-12 11:12:52 +00001383 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001384 if (!VG_(is_kerror)(res) && res == 0)
1385 make_readable (arg3, sizeof(struct sg_io_hdr));
1386 break;
1387# endif /* SG_IO */
1388 case SG_GET_SCSI_ID:
1389 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001390 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001391 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001392 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001393 if (!VG_(is_kerror)(res) && res == 0)
1394 make_readable (arg3, sizeof(struct sg_scsi_id));
1395 break;
1396 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001397 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001398 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 SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001402 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1403 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001404 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001405 break;
1406 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001407 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001408 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001409 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001410 if (!VG_(is_kerror)(res) && res == 0)
1411 make_readable (arg3, sizeof(int));
1412 break;
1413 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001414 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1415 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001416 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001417 if (!VG_(is_kerror)(res) && res == 0)
1418 make_readable (arg3, sizeof(int));
1419 break;
1420 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001421 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001422 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001423 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001424 break;
1425# endif
1426
1427 case IIOCGETCPS:
1428 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1429 * when KERNEL was. I never saw a larger value than 64 though */
1430# ifndef ISDN_MAX_CHANNELS
1431# define ISDN_MAX_CHANNELS 64
1432# endif
sewardj8c824512002-04-14 04:16:48 +00001433 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001434 ISDN_MAX_CHANNELS
1435 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001436 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001437 if (!VG_(is_kerror)(res) && res == 0)
1438 make_readable ( arg3, ISDN_MAX_CHANNELS
1439 * 2 * sizeof(unsigned long) );
1440 break;
1441 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001442 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001443 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1444 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001445 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001446 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001447 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001448 if (!VG_(is_kerror)(res) && res == 0)
1449 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1450 break;
1451
1452 /* These all use struct ifreq AFAIK */
1453 case SIOCGIFINDEX:
1454 case SIOCGIFFLAGS: /* get flags */
1455 case SIOCGIFHWADDR: /* Get hardware address */
1456 case SIOCGIFMTU: /* get MTU size */
1457 case SIOCGIFADDR: /* get PA address */
1458 case SIOCGIFNETMASK: /* get network PA mask */
1459 case SIOCGIFMETRIC: /* get metric */
1460 case SIOCGIFMAP: /* Get device parameters */
1461 case SIOCGIFTXQLEN: /* Get the tx queue length */
1462 case SIOCGIFDSTADDR: /* get remote PA address */
1463 case SIOCGIFBRDADDR: /* get broadcast PA address */
1464 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001465 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001466 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001467 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001468 if (!VG_(is_kerror)(res) && res == 0)
1469 make_readable (arg3, sizeof(struct ifreq));
1470 break;
1471 case SIOCGIFCONF: /* get iface list */
1472 /* WAS:
1473 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1474 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001475 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001476 if (!VG_(is_kerror)(res) && res == 0)
1477 make_readable (arg3, sizeof(struct ifconf));
1478 */
sewardj8c824512002-04-14 04:16:48 +00001479 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001480 sizeof(struct ifconf));
1481 if ( arg3 ) {
1482 // TODO len must be readable and writable
1483 // buf pointer only needs to be readable
1484 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001485 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001486 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1487 }
sewardj2e93c502002-04-12 11:12:52 +00001488 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001489 if (!VG_(is_kerror)(res) && res == 0 && arg3 ) {
1490 struct ifconf *ifc = (struct ifconf *) arg3;
1491 make_readable ( (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1492 }
1493 break;
1494 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001495 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001496 sizeof(struct timeval));
sewardj2e93c502002-04-12 11:12:52 +00001497 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001498 if (!VG_(is_kerror)(res) && res == 0)
1499 make_readable (arg3, sizeof(struct timeval));
1500 break;
1501 case SIOCGRARP: /* get RARP table entry */
1502 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001503 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001504 sizeof(struct arpreq));
sewardj2e93c502002-04-12 11:12:52 +00001505 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001506 if (!VG_(is_kerror)(res) && res == 0)
1507 make_readable (arg3, sizeof(struct arpreq));
1508 break;
1509
1510 case SIOCSIFFLAGS: /* set flags */
1511 case SIOCSIFMAP: /* Set device parameters */
1512 case SIOCSIFTXQLEN: /* Set the tx queue length */
1513 case SIOCSIFDSTADDR: /* set remote PA address */
1514 case SIOCSIFBRDADDR: /* set broadcast PA address */
1515 case SIOCSIFNETMASK: /* set network PA mask */
1516 case SIOCSIFMETRIC: /* set metric */
1517 case SIOCSIFADDR: /* set PA address */
1518 case SIOCSIFMTU: /* set MTU size */
1519 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001520 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001521 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001522 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001523 break;
1524 /* Routing table calls. */
1525 case SIOCADDRT: /* add routing table entry */
1526 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001527 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001528 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001529 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001530 break;
1531
1532 /* RARP cache control calls. */
1533 case SIOCDRARP: /* delete RARP table entry */
1534 case SIOCSRARP: /* set RARP table entry */
1535 /* ARP cache control calls. */
1536 case SIOCSARP: /* set ARP table entry */
1537 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001538 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001539 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001540 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001541 break;
1542
1543 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001544 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001545 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001546 break;
1547
1548 /* linux/soundcard interface (OSS) */
1549 case SNDCTL_SEQ_GETOUTCOUNT:
1550 case SNDCTL_SEQ_GETINCOUNT:
1551 case SNDCTL_SEQ_PERCMODE:
1552 case SNDCTL_SEQ_TESTMIDI:
1553 case SNDCTL_SEQ_RESETSAMPLES:
1554 case SNDCTL_SEQ_NRSYNTHS:
1555 case SNDCTL_SEQ_NRMIDIS:
1556 case SNDCTL_SEQ_GETTIME:
1557 case SNDCTL_DSP_GETFMTS:
1558 case SNDCTL_DSP_GETTRIGGER:
1559 case SNDCTL_DSP_GETODELAY:
1560# if defined(SNDCTL_DSP_GETSPDIF)
1561 case SNDCTL_DSP_GETSPDIF:
1562# endif
1563 case SNDCTL_DSP_GETCAPS:
1564 case SOUND_PCM_READ_RATE:
1565 case SOUND_PCM_READ_CHANNELS:
1566 case SOUND_PCM_READ_BITS:
1567 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1568 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001569 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1570 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001571 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001572 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001573 if (!VG_(is_kerror)(res) && res == 0)
1574 make_readable (arg3, sizeof(int));
1575 break;
1576 case SNDCTL_SEQ_CTRLRATE:
1577 case SNDCTL_DSP_SPEED:
1578 case SNDCTL_DSP_STEREO:
1579 case SNDCTL_DSP_GETBLKSIZE:
1580 case SNDCTL_DSP_CHANNELS:
1581 case SOUND_PCM_WRITE_FILTER:
1582 case SNDCTL_DSP_SUBDIVIDE:
1583 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001584# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001585 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001586# endif
1587# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001588 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001589# endif
sewardjde4a1d02002-03-22 01:27:54 +00001590 case SNDCTL_TMR_TIMEBASE:
1591 case SNDCTL_TMR_TEMPO:
1592 case SNDCTL_TMR_SOURCE:
1593 case SNDCTL_MIDI_PRETIME:
1594 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001595 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1596 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001597 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001598 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1599 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001600 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001601 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001602 break;
1603 case SNDCTL_DSP_GETOSPACE:
1604 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001605 must_be_writable(tst,
1606 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001607 "(SIOR, audio_buf_info))", arg3,
1608 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001609 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001610 if (!VG_(is_kerror)(res) && res == 0)
1611 make_readable (arg3, sizeof(audio_buf_info));
1612 break;
1613 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001614 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001615 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001616 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001617 break;
1618
1619 /* We don't have any specific information on it, so
1620 try to do something reasonable based on direction and
1621 size bits. The encoding scheme is described in
1622 /usr/include/asm/ioctl.h. */
1623 default: {
1624 UInt dir = _IOC_DIR(arg2);
1625 UInt size = _IOC_SIZE(arg2);
1626 if (/* size == 0 || */ dir == _IOC_NONE) {
1627 VG_(message)(Vg_UserMsg,
1628 "Warning: noted but unhandled ioctl 0x%x"
1629 " with no size/direction hints",
1630 arg2);
1631 VG_(message)(Vg_UserMsg,
1632 " This could cause spurious value errors"
1633 " to appear.");
1634 VG_(message)(Vg_UserMsg,
1635 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
1636 " writing a proper wrapper." );
1637 } else {
1638 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001639 must_be_readable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001640 if ((dir & _IOC_WRITE) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00001641 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00001642 }
sewardj2e93c502002-04-12 11:12:52 +00001643 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001644 if (size > 0 && (dir & _IOC_WRITE)
1645 && !VG_(is_kerror)(res) && res == 0)
1646 make_readable (arg3, size);
1647 break;
1648 }
1649 }
1650 break;
1651
1652 case __NR_kill: /* syscall 37 */
1653 /* int kill(pid_t pid, int sig); */
1654 if (VG_(clo_trace_syscalls))
1655 VG_(printf)("kill ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001656 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001657 break;
1658
1659 case __NR_link: /* syscall 9 */
1660 /* int link(const char *oldpath, const char *newpath); */
1661 if (VG_(clo_trace_syscalls))
1662 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00001663 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
1664 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00001665 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001666 break;
1667
1668 case __NR_lseek: /* syscall 19 */
1669 /* off_t lseek(int fildes, off_t offset, int whence); */
1670 if (VG_(clo_trace_syscalls))
1671 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001672 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001673 break;
1674
1675 case __NR__llseek: /* syscall 140 */
1676 /* int _llseek(unsigned int fd, unsigned long offset_high,
1677 unsigned long offset_low,
1678 loff_t * result, unsigned int whence); */
1679 if (VG_(clo_trace_syscalls))
1680 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
1681 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00001682 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00001683 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001684 if (!VG_(is_kerror)(res) && res == 0)
1685 make_readable( arg4, sizeof(loff_t) );
1686 break;
1687
1688 case __NR_lstat: /* syscall 107 */
1689 /* int lstat(const char *file_name, struct stat *buf); */
1690 if (VG_(clo_trace_syscalls))
1691 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001692 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
1693 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001694 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001695 if (!VG_(is_kerror)(res) && res == 0) {
1696 make_readable( arg2, sizeof(struct stat) );
1697 }
1698 break;
1699
1700# if defined(__NR_lstat64)
1701 case __NR_lstat64: /* syscall 196 */
1702 /* int lstat64(const char *file_name, struct stat64 *buf); */
1703 if (VG_(clo_trace_syscalls))
1704 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001705 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
1706 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00001707 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001708 if (!VG_(is_kerror)(res) && res == 0) {
1709 make_readable( arg2, sizeof(struct stat64) );
1710 }
1711 break;
1712# endif
1713
1714 case __NR_mkdir: /* syscall 39 */
1715 /* int mkdir(const char *pathname, mode_t mode); */
1716 if (VG_(clo_trace_syscalls))
1717 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001718 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001719 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001720 break;
1721
1722# if defined(__NR_mmap2)
1723 case __NR_mmap2: /* syscall 192 */
1724 /* My impression is that this is exactly like __NR_mmap
1725 except that all 6 args are passed in regs, rather than in
1726 a memory-block. */
1727 /* void* mmap(void *start, size_t length, int prot,
1728 int flags, int fd, off_t offset);
1729 */
1730 {
sewardj2e93c502002-04-12 11:12:52 +00001731 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001732 if (VG_(clo_trace_syscalls))
1733 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
1734 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00001735 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001736 /* !!! shouldn't we also be doing the symtab loading stuff as
1737 in __NR_mmap ? */
1738 if (!VG_(is_kerror)(res))
1739 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1740 }
1741 break;
1742# endif
1743
1744 case __NR_mmap: /* syscall 90 */
1745 /* void* mmap(void *start, size_t length, int prot,
1746 int flags, int fd, off_t offset);
1747 */
1748 {
1749 Bool arg_block_readable
1750 = VG_(clo_instrument)
1751 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
1752 : True;
sewardj8c824512002-04-14 04:16:48 +00001753 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00001754 if (arg_block_readable) {
1755 UInt* arg_block = (UInt*)arg1;
1756 UInt arg6;
1757 arg1 = arg_block[0];
1758 arg2 = arg_block[1];
1759 arg3 = arg_block[2];
1760 arg4 = arg_block[3];
1761 arg5 = arg_block[4];
1762 arg6 = arg_block[5];
1763 if (VG_(clo_trace_syscalls))
1764 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
1765 arg1, arg2, arg3, arg4, arg5, arg6 );
1766 }
sewardj2e93c502002-04-12 11:12:52 +00001767 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001768 if (arg_block_readable && !VG_(is_kerror)(res))
1769 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
1770 if (arg_block_readable && !VG_(is_kerror)(res)
1771 && (arg3 & PROT_EXEC)) {
1772 /* The client mmap'ed a segment with executable
1773 permissions. Tell the symbol-table loader, so that it
1774 has an opportunity to pick up more symbols if this mmap
1775 was caused by the client loading a new .so via
1776 dlopen(). This is important for debugging KDE. */
1777 VG_(read_symbols)();
1778 }
1779 }
1780
1781 break;
1782
1783 case __NR_mprotect: /* syscall 125 */
1784 /* int mprotect(const void *addr, size_t len, int prot); */
1785 /* should addr .. addr+len-1 be checked before the call? */
1786 if (VG_(clo_trace_syscalls))
1787 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001788 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001789 if (!VG_(is_kerror)(res))
1790 approximate_mmap_permissions ( arg1, arg2, arg3 );
1791 break;
1792
1793 case __NR_munmap: /* syscall 91 */
1794 /* int munmap(void *start, size_t length); */
1795 /* should start .. start+length-1 be checked before the call? */
1796 if (VG_(clo_trace_syscalls))
1797 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001798 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001799 if (!VG_(is_kerror)(res)) {
1800 /* Mash around start and length so that the area passed to
1801 make_noaccess() exactly covers an integral number of
1802 pages. If we don't do that, our idea of addressible
1803 memory diverges from that of the kernel's, which causes
1804 the leak detector to crash. */
1805 Addr start = arg1;
1806 Addr length = arg2;
1807 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
1808 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
1809 /*
1810 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
1811 arg1, arg2, start, length, (arg1!=start || arg2!=length)
1812 ? "CHANGE" : "");
1813 */
1814 make_noaccess( start, length );
1815 /* Tell our symbol table machinery about this, so that if
1816 this happens to be a .so being unloaded, the relevant
1817 symbols are removed too. */
1818 VG_(symtab_notify_munmap) ( start, length );
1819 }
1820 break;
1821
1822 case __NR_nanosleep: /* syscall 162 */
1823 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
1824 if (VG_(clo_trace_syscalls))
1825 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001826 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00001827 sizeof(struct timespec) );
1828 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00001829 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001830 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00001831 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001832 /* Somewhat bogus ... is only written by the kernel if
1833 res == -1 && errno == EINTR. */
1834 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
1835 make_readable ( arg2, sizeof(struct timespec) );
1836 break;
1837
1838 case __NR__newselect: /* syscall 142 */
1839 /* int select(int n,
1840 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1841 struct timeval *timeout);
1842 */
1843 if (VG_(clo_trace_syscalls))
1844 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
1845 arg1,arg2,arg3,arg4,arg5);
1846 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001847 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001848 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
1849 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00001850 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00001851 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
1852 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00001853 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00001854 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
1855 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00001856 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00001857 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00001858 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001859 break;
1860
1861 case __NR_open: /* syscall 5 */
1862 /* int open(const char *pathname, int flags); */
1863 if (VG_(clo_trace_syscalls))
1864 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001865 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001866 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001867 if (VG_(clo_trace_syscalls))
1868 VG_(printf)("%d\n",res);
1869 break;
1870
1871 case __NR_pipe: /* syscall 42 */
1872 /* int pipe(int filedes[2]); */
1873 if (VG_(clo_trace_syscalls))
1874 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001875 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001876 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001877 if (!VG_(is_kerror)(res))
1878 make_readable ( arg1, 2*sizeof(int) );
1879 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00001880 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
1881 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001882 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
1883 break;
1884
1885 case __NR_poll: /* syscall 168 */
1886 /* struct pollfd {
1887 int fd; -- file descriptor
1888 short events; -- requested events
1889 short revents; -- returned events
1890 };
1891 int poll(struct pollfd *ufds, unsigned int nfds,
1892 int timeout)
1893 */
1894 if (VG_(clo_trace_syscalls))
1895 VG_(printf)("poll ( %d, %d, %d )\n",arg1,arg2,arg3);
1896 /* In fact some parts of this struct should be readable too.
1897 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00001898 must_be_writable( tst, "poll(ufds)",
1899 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00001900 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001901 if (!VG_(is_kerror)(res) && res > 0) {
1902 Int i;
1903 struct pollfd * arr = (struct pollfd *)arg1;
1904 for (i = 0; i < arg2; i++)
1905 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
1906 }
1907 break;
1908
sewardjde4a1d02002-03-22 01:27:54 +00001909 case __NR_readlink: /* syscall 85 */
1910 /* int readlink(const char *path, char *buf, size_t bufsiz); */
1911 if (VG_(clo_trace_syscalls))
1912 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001913 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
1914 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001915 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001916 if (!VG_(is_kerror)(res) && res > 0) {
1917 make_readable ( arg2, res );
1918 }
1919 break;
1920
1921 case __NR_readv: { /* syscall 145 */
1922 /* int readv(int fd, const struct iovec * vector, size_t count); */
1923 UInt i;
1924 struct iovec * vec;
1925 if (VG_(clo_trace_syscalls))
1926 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001927 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00001928 arg2, arg3 * sizeof(struct iovec) );
1929 /* ToDo: don't do any of the following if the vector is invalid */
1930 vec = (struct iovec *)arg2;
1931 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00001932 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00001933 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00001934 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001935 if (!VG_(is_kerror)(res) && res > 0) {
1936 /* res holds the number of bytes read. */
1937 for (i = 0; i < arg3; i++) {
1938 Int nReadThisBuf = vec[i].iov_len;
1939 if (nReadThisBuf > res) nReadThisBuf = res;
1940 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
1941 res -= nReadThisBuf;
1942 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
1943 }
1944 }
1945 break;
1946 }
1947
1948 case __NR_rename: /* syscall 38 */
1949 /* int rename(const char *oldpath, const char *newpath); */
1950 if (VG_(clo_trace_syscalls))
1951 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00001952 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
1953 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00001954 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001955 break;
1956
1957 case __NR_rmdir: /* syscall 40 */
1958 /* int rmdir(const char *pathname); */
1959 if (VG_(clo_trace_syscalls))
1960 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00001961 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001962 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001963 break;
1964
1965 case __NR_sched_setparam:
1966 case __NR_sched_getparam:
1967 case __NR_sched_yield:
1968 case __NR_sched_get_priority_min:
1969 if (VG_(clo_instrument)) {
1970 VG_(message)(Vg_UserMsg,
1971 "Warning: noted but unhandled __NR_sched_* syscall (%d).",
1972 syscallno);
1973 VG_(message)(Vg_UserMsg,
1974 " This could cause spurious value errors"
1975 " to appear.");
1976 }
sewardj2e93c502002-04-12 11:12:52 +00001977 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001978 break;
1979
1980 case __NR_select: /* syscall 82 */
1981 /* struct sel_arg_struct {
1982 unsigned long n;
1983 fd_set *inp, *outp, *exp;
1984 struct timeval *tvp;
1985 };
1986 int old_select(struct sel_arg_struct *arg);
1987 */
1988 {
1989 Bool arg_block_readable
1990 = VG_(clo_instrument)
1991 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
1992 : True;
sewardj8c824512002-04-14 04:16:48 +00001993 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00001994 if (arg_block_readable) {
1995 UInt* arg_struct = (UInt*)arg1;
1996 arg1 = arg_struct[0];
1997 arg2 = arg_struct[1];
1998 arg3 = arg_struct[2];
1999 arg4 = arg_struct[3];
2000 arg5 = arg_struct[4];
2001
2002 if (VG_(clo_trace_syscalls))
2003 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2004 arg1,arg2,arg3,arg4,arg5);
2005 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002006 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002007 arg1/8 /* __FD_SETSIZE/8 */ );
2008 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002009 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002010 arg1/8 /* __FD_SETSIZE/8 */ );
2011 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002012 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002013 arg1/8 /* __FD_SETSIZE/8 */ );
2014 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002015 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002016 sizeof(struct timeval) );
2017 }
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_setitimer: /* syscall 104 */
2023 /* setitimer(int which, const struct itimerval *value,
2024 struct itimerval *ovalue); */
2025 if (VG_(clo_trace_syscalls))
2026 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002027 must_be_readable(tst, "setitimer(value)",
sewardjde4a1d02002-03-22 01:27:54 +00002028 arg2, sizeof(struct itimerval) );
2029 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002030 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002031 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002032 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002033 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2034 make_readable(arg3, sizeof(struct itimerval));
2035 }
2036 break;
2037
2038# if defined(__NR_setfsgid32)
2039 case __NR_setfsgid32: /* syscall 216 */
2040 /* int setfsgid(uid_t fsgid); */
2041 if (VG_(clo_trace_syscalls))
2042 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002043 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002044 break;
2045# endif
2046
2047# if defined(__NR_setgid32)
2048 case __NR_setgid32: /* syscall 214 */
2049# endif
2050 case __NR_setgid: /* syscall 46 */
2051 /* int setgid(gid_t gid); */
2052 if (VG_(clo_trace_syscalls))
2053 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002054 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002055 break;
2056
2057 case __NR_setsid: /* syscall 66 */
2058 /* pid_t setsid(void); */
2059 if (VG_(clo_trace_syscalls))
2060 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002061 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002062 break;
2063
2064# if defined(__NR_setgroups32)
2065 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002066# endif
2067 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002068 /* int setgroups(size_t size, const gid_t *list); */
2069 if (VG_(clo_trace_syscalls))
2070 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2071 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002072 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002073 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002074 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002075 break;
sewardjde4a1d02002-03-22 01:27:54 +00002076
2077 case __NR_setpgid: /* syscall 57 */
2078 /* int setpgid(pid_t pid, pid_t pgid); */
2079 if (VG_(clo_trace_syscalls))
2080 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002081 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002082 break;
2083
2084# if defined(__NR_setregid32)
2085 case __NR_setregid32: /* syscall 204 */
2086 /* int setregid(gid_t rgid, gid_t egid); */
2087 if (VG_(clo_trace_syscalls))
2088 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002089 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002090 break;
2091# endif
2092
2093# if defined(__NR_setresuid32)
2094 case __NR_setresuid32: /* syscall 208 */
2095 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2096 if (VG_(clo_trace_syscalls))
2097 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002098 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002099 break;
2100# endif
2101
2102# if defined(__NR_setreuid32)
2103 case __NR_setreuid32: /* syscall 203 */
2104# endif
2105 case __NR_setreuid: /* syscall 70 */
2106 /* int setreuid(uid_t ruid, uid_t euid); */
2107 if (VG_(clo_trace_syscalls))
2108 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002109 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002110 break;
2111
2112 case __NR_setrlimit: /* syscall 75 */
2113 /* int setrlimit (int resource, const struct rlimit *rlim); */
2114 if (VG_(clo_trace_syscalls))
2115 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002116 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002117 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002118 break;
2119
2120# if defined(__NR_setuid32)
2121 case __NR_setuid32: /* syscall 213 */
2122# endif
2123 case __NR_setuid: /* syscall 23 */
2124 /* int setuid(uid_t uid); */
2125 if (VG_(clo_trace_syscalls))
2126 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002127 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002128 break;
2129
2130 case __NR_socketcall: /* syscall 102 */
2131 /* int socketcall(int call, unsigned long *args); */
2132 if (VG_(clo_trace_syscalls))
2133 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2134 switch (arg1 /* request */) {
2135
2136 case SYS_SOCKETPAIR:
2137 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002138 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002139 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002140 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002141 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002142 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002143 if (!VG_(is_kerror)(res))
2144 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2145 break;
2146
2147 case SYS_SOCKET:
2148 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002149 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002150 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002151 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002152 break;
2153
2154 case SYS_BIND:
2155 /* int bind(int sockfd, struct sockaddr *my_addr,
2156 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002157 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002158 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002159 must_be_readable( tst, "socketcall.bind(my_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002160 ((UInt*)arg2)[1], ((UInt*)arg2)[2] );
sewardj2e93c502002-04-12 11:12:52 +00002161 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002162 break;
2163
2164 case SYS_LISTEN:
2165 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002166 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002167 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002168 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002169 break;
2170
2171 case SYS_ACCEPT: {
2172 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2173 Addr addr;
2174 Addr p_addrlen;
2175 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002176 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002177 arg2, 3*sizeof(Addr) );
2178 addr = ((UInt*)arg2)[1];
2179 p_addrlen = ((UInt*)arg2)[2];
2180 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002181 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002182 p_addrlen, sizeof(int) );
2183 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002184 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002185 addr, addrlen_in );
2186 }
sewardj2e93c502002-04-12 11:12:52 +00002187 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002188 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2189 addrlen_out = safe_dereference( p_addrlen, 0 );
2190 if (addrlen_out > 0)
2191 make_readable( addr, addrlen_out );
2192 }
2193 break;
2194 }
2195
2196 case SYS_SENDTO:
2197 /* int sendto(int s, const void *msg, int len,
2198 unsigned int flags,
2199 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002200 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002201 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002202 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002203 ((UInt*)arg2)[1], /* msg */
2204 ((UInt*)arg2)[2] /* len */ );
sewardj8c824512002-04-14 04:16:48 +00002205 must_be_readable( tst, "socketcall.sendto(to)",
sewardjde4a1d02002-03-22 01:27:54 +00002206 ((UInt*)arg2)[4], /* to */
2207 ((UInt*)arg2)[5] /* tolen */ );
sewardj2e93c502002-04-12 11:12:52 +00002208 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002209 break;
2210
2211 case SYS_SEND:
2212 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002213 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002214 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002215 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002216 ((UInt*)arg2)[1], /* msg */
2217 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002218 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002219 break;
2220
2221 case SYS_RECVFROM:
2222 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2223 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002224 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002225 arg2, 6*sizeof(Addr) );
2226 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002227 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002228 ((UInt*)arg2)[5] /* fromlen */,
2229 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002230 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002231 ((UInt*)arg2)[4], /*from*/
2232 safe_dereference( (Addr)
2233 ((UInt*)arg2)[5], 0 ) );
2234 }
sewardj8c824512002-04-14 04:16:48 +00002235 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002236 ((UInt*)arg2)[1], /* buf */
2237 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002238 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002239 if (!VG_(is_kerror)(res) && res >= 0) {
2240 make_readable( ((UInt*)arg2)[1], /* buf */
2241 ((UInt*)arg2)[2] /* len */ );
2242 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2243 make_readable(
2244 ((UInt*)arg2)[4], /*from*/
2245 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2246 }
2247 }
2248 /* phew! */
2249 break;
2250
2251 case SYS_RECV:
2252 /* int recv(int s, void *buf, int len, unsigned int flags); */
2253 /* man 2 recv says:
2254 The recv call is normally used only on a connected socket
2255 (see connect(2)) and is identical to recvfrom with a NULL
2256 from parameter.
2257 */
sewardj8c824512002-04-14 04:16:48 +00002258 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002259 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002260 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002261 ((UInt*)arg2)[1], /* buf */
2262 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002263 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002264 if (!VG_(is_kerror)(res) && res >= 0
2265 && ((UInt*)arg2)[1] != (UInt)NULL) {
2266 make_readable( ((UInt*)arg2)[1], /* buf */
2267 ((UInt*)arg2)[2] /* len */ );
2268 }
2269 break;
2270
2271 case SYS_CONNECT: {
2272 struct sockaddr *sa;
2273 /* int connect(int sockfd,
2274 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002275 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002276 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002277 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002278 ((UInt*)arg2)[1], /* serv_addr */
2279 sizeof (sa_family_t));
2280 sa = (struct sockaddr *) (((UInt*)arg2)[1]);
2281 if (sa->sa_family == AF_UNIX)
sewardj8c824512002-04-14 04:16:48 +00002282 must_be_readable_asciiz( tst,
sewardjde4a1d02002-03-22 01:27:54 +00002283 "socketcall.connect(serv_addr.sun_path)",
2284 (UInt) ((struct sockaddr_un *) sa)->sun_path);
2285 /* XXX There probably should be more cases here since not
2286 all of the struct sockaddr_XXX must be initialized. But
2287 wait until something pops up. */
2288 else
sewardj8c824512002-04-14 04:16:48 +00002289 must_be_readable( tst, "socketcall.connect(serv_addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002290 ((UInt*)arg2)[1], /* serv_addr */
2291 ((UInt*)arg2)[2] /* addrlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002292 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002293 break;
2294 }
2295
2296 case SYS_SETSOCKOPT:
2297 /* int setsockopt(int s, int level, int optname,
2298 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002299 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002300 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002301 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002302 ((UInt*)arg2)[3], /* optval */
2303 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002304 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002305 break;
2306
2307 case SYS_GETSOCKOPT:
2308 /* int setsockopt(int s, int level, int optname,
2309 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002310 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002311 arg2, 5*sizeof(Addr) );
2312 {
2313 Addr optval_p = ((UInt*)arg2)[3];
2314 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002315 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002316 UInt optlen_after;
2317 UInt optlen = safe_dereference ( optlen_p, 0 );
2318 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002319 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002320 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002321 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002322 optlen_after = safe_dereference ( optlen_p, 0 );
2323 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2324 make_readable( optval_p, optlen_after );
2325 }
2326 break;
2327
2328 case SYS_GETSOCKNAME:
2329 /* int getsockname(int s, struct sockaddr* name,
2330 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002331 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002332 arg2, 3*sizeof(Addr) );
2333 {
2334 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2335 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002336 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002337 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002338 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002339 if (!VG_(is_kerror)(res)) {
2340 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2341 if (namelen > 0
2342 && ((UInt*)arg2)[1] != (UInt)NULL)
2343 make_readable( ((UInt*)arg2)[1], namelen );
2344 }
2345 }
2346 break;
2347
2348 case SYS_GETPEERNAME:
2349 /* int getpeername(int s, struct sockaddr* name,
2350 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002351 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002352 arg2, 3*sizeof(Addr) );
2353 {
2354 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2355 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002356 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002357 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002358 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002359 if (!VG_(is_kerror)(res)) {
2360 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2361 if (namelen > 0
2362 && ((UInt*)arg2)[1] != (UInt)NULL)
2363 make_readable( ((UInt*)arg2)[1], namelen );
2364 }
2365 }
2366 break;
2367
2368 case SYS_SHUTDOWN:
2369 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002370 must_be_readable( tst, "socketcall.shutdown(args)",
2371 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002372 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002373 break;
2374
2375 case SYS_SENDMSG:
2376 {
2377 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2378
2379 /* this causes warnings, and I don't get why. glibc bug?
2380 * (after all it's glibc providing the arguments array)
2381 must_be_readable( "socketcall.sendmsg(args)",
2382 arg2, 3*sizeof(Addr) );
2383 */
2384
2385 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002386 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002387
sewardj2e93c502002-04-12 11:12:52 +00002388 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002389 break;
2390 }
2391
2392 case SYS_RECVMSG:
2393 {
2394 /* int recvmsg(int s, struct msghdr *msg, int flags); */
2395
2396 /* this causes warnings, and I don't get why. glibc bug?
2397 * (after all it's glibc providing the arguments array)
2398 must_be_readable( "socketcall.recvmsg(args)",
2399 arg2, 3*sizeof(Addr) );
2400 */
2401
2402 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002403 msghdr_foreachfield ( tst, msg, must_be_writable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002404
sewardj2e93c502002-04-12 11:12:52 +00002405 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002406
2407 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002408 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002409
2410 break;
2411 }
2412
2413 default:
2414 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2415 VG_(panic)("... bye!\n");
2416 break; /*NOTREACHED*/
2417 }
2418 break;
2419
2420 case __NR_stat: /* syscall 106 */
2421 /* int stat(const char *file_name, struct stat *buf); */
2422 if (VG_(clo_trace_syscalls))
2423 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002424 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2425 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002426 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002427 if (!VG_(is_kerror)(res))
2428 make_readable( arg2, sizeof(struct stat) );
2429 break;
2430
2431 case __NR_statfs: /* syscall 99 */
2432 /* int statfs(const char *path, struct statfs *buf); */
2433 if (VG_(clo_trace_syscalls))
2434 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002435 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2436 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002437 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002438 if (!VG_(is_kerror)(res))
2439 make_readable( arg2, sizeof(struct statfs) );
2440 break;
2441
2442 case __NR_symlink: /* syscall 83 */
2443 /* int symlink(const char *oldpath, const char *newpath); */
2444 if (VG_(clo_trace_syscalls))
2445 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002446 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2447 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002448 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002449 break;
2450
2451# if defined(__NR_stat64)
2452 case __NR_stat64: /* syscall 195 */
2453 /* int stat64(const char *file_name, struct stat64 *buf); */
2454 if (VG_(clo_trace_syscalls))
2455 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002456 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2457 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002458 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002459 if (!VG_(is_kerror)(res))
2460 make_readable( arg2, sizeof(struct stat64) );
2461 break;
2462# endif
2463
2464# if defined(__NR_fstat64)
2465 case __NR_fstat64: /* syscall 197 */
2466 /* int fstat64(int filedes, struct stat64 *buf); */
2467 if (VG_(clo_trace_syscalls))
2468 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002469 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002470 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002471 if (!VG_(is_kerror)(res))
2472 make_readable( arg2, sizeof(struct stat64) );
2473 break;
2474# endif
2475
2476 case __NR_sysinfo: /* syscall 116 */
2477 /* int sysinfo(struct sysinfo *info); */
2478 if (VG_(clo_trace_syscalls))
2479 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002480 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002481 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002482 if (!VG_(is_kerror)(res))
2483 make_readable( arg1, sizeof(struct sysinfo) );
2484 break;
2485
2486 case __NR_time: /* syscall 13 */
2487 /* time_t time(time_t *t); */
2488 if (VG_(clo_trace_syscalls))
2489 VG_(printf)("time ( %p )\n",arg1);
2490 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002491 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002492 }
sewardj2e93c502002-04-12 11:12:52 +00002493 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002494 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2495 make_readable( arg1, sizeof(time_t) );
2496 }
2497 break;
2498
2499 case __NR_times: /* syscall 43 */
2500 /* clock_t times(struct tms *buf); */
2501 if (VG_(clo_trace_syscalls))
2502 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002503 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002504 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002505 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2506 make_readable( arg1, sizeof(struct tms) );
2507 }
2508 break;
2509
2510 case __NR_truncate: /* syscall 92 */
2511 /* int truncate(const char *path, size_t length); */
2512 if (VG_(clo_trace_syscalls))
2513 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002514 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002515 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002516 break;
2517
2518 case __NR_umask: /* syscall 60 */
2519 /* mode_t umask(mode_t mask); */
2520 if (VG_(clo_trace_syscalls))
2521 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002522 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002523 break;
2524
2525 case __NR_unlink: /* syscall 10 */
2526 /* int unlink(const char *pathname) */
2527 if (VG_(clo_trace_syscalls))
2528 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002529 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002530 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002531 break;
2532
2533 case __NR_uname: /* syscall 122 */
2534 /* int uname(struct utsname *buf); */
2535 if (VG_(clo_trace_syscalls))
2536 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002537 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002538 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002539 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2540 make_readable( arg1, sizeof(struct utsname) );
2541 }
2542 break;
2543
2544 case __NR_utime: /* syscall 30 */
2545 /* int utime(const char *filename, struct utimbuf *buf); */
2546 if (VG_(clo_trace_syscalls))
2547 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002548 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00002549 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002550 must_be_readable( tst, "utime(buf)", arg2,
2551 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00002552 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002553 break;
2554
2555 case __NR_wait4: /* syscall 114 */
2556 /* pid_t wait4(pid_t pid, int *status, int options,
2557 struct rusage *rusage) */
2558 if (VG_(clo_trace_syscalls))
2559 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
2560 arg1,arg2,arg3,arg4);
2561 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002562 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00002563 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002564 must_be_writable( tst, "wait4(rusage)", arg4,
2565 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00002566 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002567 if (!VG_(is_kerror)(res)) {
2568 if (arg2 != (Addr)NULL)
2569 make_readable( arg2, sizeof(int) );
2570 if (arg4 != (Addr)NULL)
2571 make_readable( arg4, sizeof(struct rusage) );
2572 }
2573 break;
2574
sewardjde4a1d02002-03-22 01:27:54 +00002575 case __NR_writev: { /* syscall 146 */
2576 /* int writev(int fd, const struct iovec * vector, size_t count); */
2577 UInt i;
2578 struct iovec * vec;
2579 if (VG_(clo_trace_syscalls))
2580 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002581 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002582 arg2, arg3 * sizeof(struct iovec) );
2583 /* ToDo: don't do any of the following if the vector is invalid */
2584 vec = (struct iovec *)arg2;
2585 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002586 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002587 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002588 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002589 break;
2590 }
2591
2592 /*-------------------------- SIGNALS --------------------------*/
2593
2594 /* Normally set to 1, so that Valgrind's signal-simulation machinery
2595 is engaged. Sometimes useful to disable (set to 0), for
2596 debugging purposes, to make clients more deterministic. */
2597# define SIGNAL_SIMULATION 1
2598
2599 case __NR_rt_sigaction:
2600 case __NR_sigaction:
2601 /* int sigaction(int signum, struct k_sigaction *act,
2602 struct k_sigaction *oldact); */
2603 if (VG_(clo_trace_syscalls))
2604 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
2605 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002606 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00002607 arg2, sizeof(vki_ksigaction));
2608 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002609 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00002610 arg3, sizeof(vki_ksigaction));
2611 /* We do this one ourselves! */
2612# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00002613 VG_(do__NR_sigaction)(tid);
2614 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00002615# else
2616 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00002617 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002618# endif
2619 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2620 make_readable( arg3, sizeof(vki_ksigaction));
2621 break;
2622
2623 case __NR_rt_sigprocmask:
2624 case __NR_sigprocmask:
2625 /* int sigprocmask(int how, k_sigset_t *set,
2626 k_sigset_t *oldset); */
2627 if (VG_(clo_trace_syscalls))
2628 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
2629 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002630 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00002631 arg2, sizeof(vki_ksigset_t));
2632 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002633 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00002634 arg3, sizeof(vki_ksigset_t));
sewardj2e93c502002-04-12 11:12:52 +00002635 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002636 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2637 make_readable( arg3, sizeof(vki_ksigset_t));
2638# if SIGNAL_SIMULATION
2639 /* For the reason why both the kernel and Valgrind process
2640 sigprocmask, see the detailed comment at
2641 vg_do__NR_sigprocmask(). */
2642 VG_(do__NR_sigprocmask) ( arg1 /*how*/, (vki_ksigset_t*) arg2 );
2643# endif
2644 break;
2645
2646 default:
2647 VG_(message)
2648 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
2649 VG_(message)
2650 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
2651 VG_(message)
2652 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
2653 VG_(unimplemented)("no wrapper for the above system call");
2654 vg_assert(3+3 == 7);
2655 break; /*NOTREACHED*/
2656 }
2657
sewardjde4a1d02002-03-22 01:27:54 +00002658 /* { void zzzmemscan(void); zzzmemscan(); } */
2659
sewardjde4a1d02002-03-22 01:27:54 +00002660 if (! VG_(first_and_last_secondaries_look_plausible))
2661 sane_before_call = False;
2662
2663 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00002664 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00002665 VG_(message)(Vg_DebugMsg,
2666 "probable sanity check failure for syscall number %d\n",
2667 syscallno );
2668 VG_(panic)("aborting due to the above ... bye!");
2669 }
2670
2671 VGP_POPCC;
2672}
2673
2674
sewardj2e93c502002-04-12 11:12:52 +00002675
2676/* Perform pre- and post- actions for a blocking syscall, but do not
2677 do the syscall itself. If res is NULL, the pre-syscall actions are
2678 to be performed. If res is non-NULL, the post-syscall actions are
2679 to be performed, and *res is assumed to hold the result of the
2680 syscall. This slightly strange scheme makes it impossible to
2681 mistakenly use the value of *res in the pre-syscall actions.
2682
2683 This doesn't actually do the syscall itself, it is important to
2684 observe.
2685
2686 Because %eax is used both for the syscall number before the call
2687 and the result value afterwards, we can't reliably use it to get
2688 the syscall number. So the caller has to pass it explicitly.
2689*/
sewardj8c824512002-04-14 04:16:48 +00002690void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00002691 Int syscallno,
2692 Int* /*IN*/ res )
2693{
2694 Bool sane_before_post = True;
2695 Bool sane_after_post = True;
2696 ThreadState* tst = VG_(get_thread_state)( tid );
2697 UInt arg1 = tst->m_ebx;
2698 UInt arg2 = tst->m_ecx;
2699 UInt arg3 = tst->m_edx;
2700 /*
2701 UInt arg4 = tst->m_esi;
2702 UInt arg5 = tst->m_edi;
2703 */
2704 VGP_PUSHCC(VgpSyscall);
2705
2706 if (res != NULL
2707 && ! VG_(first_and_last_secondaries_look_plausible))
2708 sane_before_post = False;
2709
2710 switch (syscallno) {
2711
2712 case __NR_read: /* syscall 3 */
2713 /* size_t read(int fd, void *buf, size_t count); */
2714 if (res == NULL) {
2715 /* PRE */
2716 if (VG_(clo_trace_syscalls))
2717 VG_(printf)(
2718 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
2719 VG_(getpid)(), tid,
2720 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002721 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002722 } else {
2723 /* POST */
2724 if (VG_(clo_trace_syscalls))
2725 VG_(printf)(
2726 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
2727 VG_(getpid)(), tid,
2728 arg1, arg2, arg3, *res);
2729 if (!VG_(is_kerror)(*res) && *res > 0) {
2730 make_readable( arg2, *res );
2731 }
2732 }
2733 break;
2734
2735 case __NR_write: /* syscall 4 */
2736 /* size_t write(int fd, const void *buf, size_t count); */
2737 if (res == NULL) {
2738 /* PRE */
2739 if (VG_(clo_trace_syscalls))
2740 VG_(printf)(
2741 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
2742 VG_(getpid)(), tid,
2743 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00002744 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002745 } else {
2746 /* POST */
2747 if (VG_(clo_trace_syscalls))
2748 VG_(printf)(
2749 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
2750 VG_(getpid)(), tid,
2751 arg1, arg2, arg3, *res);
2752 }
2753 break;
2754
2755 default:
2756 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
2757 syscallno);
2758 VG_(panic)("check_known_blocking_syscall");
2759 /*NOTREACHED*/
2760 break;
2761 }
2762
2763 if (res != NULL) { /* only check after syscall */
2764 if (! VG_(first_and_last_secondaries_look_plausible))
2765 sane_after_post = False;
2766
2767 if (sane_before_post && (!sane_after_post)) {
2768 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
2769 VG_(message)(Vg_DebugMsg,
2770 "probable sanity check failure for syscall number %d\n",
2771 syscallno );
2772 VG_(panic)("aborting due to the above ... bye!");
2773 }
2774 }
2775
2776 VGP_POPCC;
2777}
2778
2779
sewardjde4a1d02002-03-22 01:27:54 +00002780/*--------------------------------------------------------------------*/
2781/*--- end vg_syscall_mem.c ---*/
2782/*--------------------------------------------------------------------*/