blob: 518c54aae23b757f97806e0197e09c027890a79c [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Update the byte permission maps following a system call. ---*/
4/*--- vg_syscall_mem.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_include.h"
33
34/* vg_unsafe.h should NOT be included into any file except this
35 one. */
36#include "vg_unsafe.h"
37
38
39/* All system calls are channelled through vg_wrap_syscall. It does
40 three things:
41
42 * optionally, checks the permissions for the args to the call
43
44 * perform the syscall, usually by passing it along to the kernel
45 unmodified. However, because we simulate signals ourselves,
46 signal-related syscalls are routed to vg_signal.c, and are not
47 delivered to the kernel.
48
49 * Update the permission maps following the syscall.
50
51 A magical piece of assembly code, vg_do_syscall(), in vg_syscall.S
52 does the tricky bit of passing a syscall to the kernel, whilst
53 having the simulator retain control.
54*/
55
56static void make_noaccess ( Addr a, UInt len )
57{
58 if (VG_(clo_instrument))
59 VGM_(make_noaccess) ( a, len );
60}
61
62static void make_writable ( Addr a, UInt len )
63{
64 if (VG_(clo_instrument))
65 VGM_(make_writable) ( a, len );
66}
67
68static void make_readable ( Addr a, UInt len )
69{
70 if (VG_(clo_instrument))
71 VGM_(make_readable) ( a, len );
72}
73
74static void make_readwritable ( Addr a, UInt len )
75{
76 if (VG_(clo_instrument))
77 VGM_(make_readwritable) ( a, len );
78}
79
80static
sewardj8c824512002-04-14 04:16:48 +000081void must_be_writable ( ThreadState* tst,
82 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000083{
84 Bool ok;
85 Addr bad_addr;
86 /* VG_(message)(Vg_DebugMsg,"must be writable: %x .. %x",
87 base,base+size-1); */
88 if (!VG_(clo_instrument))
89 return;
90 ok = VGM_(check_writable) ( base, size, &bad_addr );
91 if (!ok)
sewardj8c824512002-04-14 04:16:48 +000092 VG_(record_param_err) ( tst, bad_addr, True, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +000093}
94
95static
sewardj8c824512002-04-14 04:16:48 +000096void must_be_readable ( ThreadState* tst,
97 Char* syscall_name, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +000098{
99 Bool ok;
100 Addr bad_addr;
101 /* VG_(message)(Vg_DebugMsg,"must be readable: %x .. %x",
102 base,base+size-1); */
103 if (!VG_(clo_instrument))
104 return;
105 ok = VGM_(check_readable) ( base, size, &bad_addr );
106 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000107 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000108}
109
110static
sewardj8c824512002-04-14 04:16:48 +0000111void must_be_readable_asciiz ( ThreadState* tst,
112 Char* syscall_name, UInt str )
sewardjde4a1d02002-03-22 01:27:54 +0000113{
114 Bool ok = True;
115 Addr bad_addr;
116 /* VG_(message)(Vg_DebugMsg,"must be readable asciiz: 0x%x",str); */
117 if (!VG_(clo_instrument))
118 return;
119 ok = VGM_(check_readable_asciiz) ( (Addr)str, &bad_addr );
120 if (!ok)
sewardj8c824512002-04-14 04:16:48 +0000121 VG_(record_param_err) ( tst, bad_addr, False, syscall_name );
sewardjde4a1d02002-03-22 01:27:54 +0000122}
123
124
125/* Set memory permissions, based on PROT_* values for mmap/mprotect,
126 into the permissions our scheme understands. Dunno if this is
127 really correct. */
128
129static void approximate_mmap_permissions ( Addr a, UInt len, UInt prot )
130{
131 /* PROT_READ and PROT_WRITE --> readable
132 PROT_READ only --> readable
133 PROT_WRITE only --> writable
134 NEITHER --> noaccess
135 */
136 if (prot & PROT_READ)
137 make_readable(a,len);
138 else
139 if (prot & PROT_WRITE)
140 make_writable(a,len);
141 else
142 make_noaccess(a,len);
143}
144
145
146/* Dereference a pointer, but only after checking that it's
147 safe to do so. If not, return the default.
148*/
149static
150UInt safe_dereference ( Addr aa, UInt defawlt )
151{
152 if (!VG_(clo_instrument))
153 return * (UInt*)aa;
154 if (VGM_(check_readable)(aa,4,NULL))
155 return * (UInt*)aa;
156 else
157 return defawlt;
158}
159
160
161/* Is this a Linux kernel error return value? */
162/* From:
163 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
164 linux/i386/sysdep.h?
165 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
166
167 QUOTE:
168
169 Linux uses a negative return value to indicate syscall errors,
170 unlike most Unices, which use the condition codes' carry flag.
171
172 Since version 2.1 the return value of a system call might be
173 negative even if the call succeeded. E.g., the `lseek' system call
174 might return a large offset. Therefore we must not anymore test
175 for < 0, but test for a real error by making sure the value in %eax
176 is a real error number. Linus said he will make sure the no syscall
177 returns a value in -1 .. -4095 as a valid result so we can savely
178 test with -4095.
179
180 END QUOTE
181*/
182Bool VG_(is_kerror) ( Int res )
183{
184 if (res >= -4095 && res <= -1)
185 return True;
186 else
187 return False;
188}
189
190static
191UInt get_shm_size ( Int shmid )
192{
193 struct shmid_ds buf;
194 long __res;
195 __asm__ volatile ( "int $0x80"
196 : "=a" (__res)
197 : "0" (__NR_ipc),
198 "b" ((long)(24) /*IPCOP_shmctl*/),
199 "c" ((long)(shmid)),
200 "d" ((long)(IPC_STAT)),
201 "S" ((long)(0)),
202 "D" ((long)(&buf)) );
203 if ( VG_(is_kerror) ( __res ) )
204 return 0;
205
206 return buf.shm_segsz;
207}
208
209static
sewardj8c824512002-04-14 04:16:48 +0000210Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000211{
212 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
213 Char *result = VG_(malloc) ( aid, len );
214 VG_(strcpy) ( result, s1 );
215 VG_(strcat) ( result, s2 );
216 return result;
217}
218
219static
sewardj8c824512002-04-14 04:16:48 +0000220void must_be_readable_sendmsg ( ThreadState* tst,
221 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000222{
223 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000224 must_be_readable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000225 VG_(free) ( VG_AR_TRANSIENT, outmsg );
226}
227
228static
sewardj8c824512002-04-14 04:16:48 +0000229void must_be_writable_recvmsg ( ThreadState* tst,
230 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000231{
232 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
sewardj8c824512002-04-14 04:16:48 +0000233 must_be_writable ( tst, outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000234 VG_(free) ( VG_AR_TRANSIENT, outmsg );
235}
236
237static
sewardj8c824512002-04-14 04:16:48 +0000238void make_readable_recvmsg ( ThreadState* tst,
239 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000240{
241 make_readable( base, size );
242}
243
244static
sewardj8c824512002-04-14 04:16:48 +0000245void msghdr_foreachfield (
246 ThreadState* tst,
247 struct msghdr *msg,
248 void (*foreach_func)( ThreadState*, Char *, UInt, UInt )
249 )
sewardjde4a1d02002-03-22 01:27:54 +0000250{
251 if ( !msg )
252 return;
253
sewardj8c824512002-04-14 04:16:48 +0000254 foreach_func ( tst, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000255
256 if ( msg->msg_name )
sewardj8c824512002-04-14 04:16:48 +0000257 foreach_func ( tst,
258 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000259 (Addr)msg->msg_name, msg->msg_namelen );
260
261 if ( msg->msg_iov ) {
262 struct iovec *iov = msg->msg_iov;
263 UInt i;
264
sewardj8c824512002-04-14 04:16:48 +0000265 foreach_func ( tst,
266 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000267 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
268
269 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
sewardj8c824512002-04-14 04:16:48 +0000270 foreach_func ( tst,
271 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000272 (Addr)iov->iov_base, iov->iov_len );
273 }
274
275 if ( msg->msg_control )
sewardj8c824512002-04-14 04:16:48 +0000276 foreach_func ( tst,
277 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000278 (Addr)msg->msg_control, msg->msg_controllen );
279}
280
sewardjc483e8f2002-05-03 21:01:35 +0000281static
282void must_be_readable_sockaddr ( ThreadState* tst,
283 Char *description,
284 struct sockaddr *sa, UInt salen )
285{
286 Char *outmsg = VG_(malloc) ( VG_AR_TRANSIENT, strlen( description ) + 30 );
287
288 VG_(sprintf) ( outmsg, description, ".sa_family" );
289 must_be_readable( tst, outmsg, (UInt) &sa->sa_family, sizeof (sa_family_t));
290
291 switch (sa->sa_family) {
292
293 case AF_UNIX:
294 VG_(sprintf) ( outmsg, description, ".sun_path" );
295 must_be_readable_asciiz( tst, outmsg,
296 (UInt) ((struct sockaddr_un *) sa)->sun_path);
297 break;
298
299 case AF_INET:
300 VG_(sprintf) ( outmsg, description, ".sin_port" );
301 must_be_readable( tst, outmsg,
302 (UInt) &((struct sockaddr_in *) sa)->sin_port,
sewardj32102152002-05-04 10:28:17 +0000303 sizeof (((struct sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000304 VG_(sprintf) ( outmsg, description, ".sin_addr" );
305 must_be_readable( tst, outmsg,
306 (UInt) &((struct sockaddr_in *) sa)->sin_addr,
307 sizeof (struct in_addr));
308 break;
309
310 case AF_INET6:
311 VG_(sprintf) ( outmsg, description, ".sin6_port" );
312 must_be_readable( tst, outmsg,
313 (UInt) &((struct sockaddr_in6 *) sa)->sin6_port,
sewardj32102152002-05-04 10:28:17 +0000314 sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000315 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
316 must_be_readable( tst, outmsg,
317 (UInt) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
318 sizeof (uint32_t));
319 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
320 must_be_readable( tst, outmsg,
321 (UInt) &((struct sockaddr_in6 *) sa)->sin6_addr,
322 sizeof (struct in6_addr));
sewardj32102152002-05-04 10:28:17 +0000323# ifndef GLIBC_2_1
sewardjc483e8f2002-05-03 21:01:35 +0000324 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
325 must_be_readable( tst, outmsg,
326 (UInt) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
327 sizeof (uint32_t));
sewardj32102152002-05-04 10:28:17 +0000328# endif
sewardjc483e8f2002-05-03 21:01:35 +0000329 break;
330
331 default:
332 VG_(sprintf) ( outmsg, description, "" );
333 must_be_readable( tst, outmsg, (UInt) sa, salen );
334 break;
335 }
336
337 VG_(free) ( VG_AR_TRANSIENT, outmsg );
338}
339
sewardjde4a1d02002-03-22 01:27:54 +0000340
341/* Records the current end of the data segment so we can make sense of
342 calls to brk(). Initial value set by hdm_init_memory_audit(). */
343Addr VGM_(curr_dataseg_end);
344
345
sewardj2e93c502002-04-12 11:12:52 +0000346
sewardjde4a1d02002-03-22 01:27:54 +0000347/* The Main Entertainment ... */
348
sewardj2e93c502002-04-12 11:12:52 +0000349void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +0000350{
sewardj018f7622002-05-15 21:13:39 +0000351 ThreadState* tst;
352 Bool sane_before_call, sane_after_call;
353 UInt syscallno, arg1, arg2, arg3, arg4, arg5;
sewardjde4a1d02002-03-22 01:27:54 +0000354 /* Do not make this unsigned! */
355 Int res;
356
sewardjde4a1d02002-03-22 01:27:54 +0000357 VGP_PUSHCC(VgpSyscall);
358
sewardj018f7622002-05-15 21:13:39 +0000359 vg_assert(VG_(is_valid_tid)(tid));
360 sane_before_call = True;
361 sane_after_call = True;
362 tst = & VG_(threads)[tid];
363 syscallno = tst->m_eax;
364 arg1 = tst->m_ebx;
365 arg2 = tst->m_ecx;
366 arg3 = tst->m_edx;
367 arg4 = tst->m_esi;
368 arg5 = tst->m_edi;
369
sewardjde4a1d02002-03-22 01:27:54 +0000370 /* Since buggy syscall wrappers sometimes break this, we may as well
371 check ourselves. */
sewardj126a41f2002-05-07 23:45:03 +0000372 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardjde4a1d02002-03-22 01:27:54 +0000373 sane_before_call = False;
374
375 /* the syscall no is in %eax. For syscalls with <= 5 args,
376 args 1 .. 5 to the syscall are in %ebx %ecx %edx %esi %edi.
377 For calls with > 5 args, %ebx points to a lump of memory
378 containing the args.
379
380 The result is returned in %eax. If this value >= 0, the call
381 succeeded, and this is the return value. If < 0, it failed, and
382 the negation of this value is errno. To be more specific,
383 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
384 (kernel 2.4.9 sources, include/asm-i386/errno.h)
385 then it indicates an error. Otherwise it doesn't.
386
387 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
388 (inclusive?) indicate error returns. Not sure where the -4095
389 comes from.
390 */
391
392 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000393 VG_(printf)("SYSCALL[%d,%d](%3d): ",
394 VG_(getpid)(), tid, syscallno);
sewardjde4a1d02002-03-22 01:27:54 +0000395
396 switch (syscallno) {
397
sewardj7e87e382002-05-03 19:09:05 +0000398 case __NR_exit:
399 VG_(panic)("syscall exit() not caught by the scheduler?!");
400 break;
401
sewardjde4a1d02002-03-22 01:27:54 +0000402 case __NR_clone:
403 VG_(unimplemented)
sewardj827d95b2002-04-16 02:09:31 +0000404 ("clone(): not supported by Valgrind.\n "
405 "We do now support programs linked against\n "
406 "libpthread.so, though. Re-run with -v and ensure that\n "
407 "you are picking up Valgrind's implementation of libpthread.so.");
sewardjde4a1d02002-03-22 01:27:54 +0000408 break;
409
410# if defined(__NR_modify_ldt)
411 case __NR_modify_ldt:
sewardjcfc39b22002-05-08 01:58:18 +0000412 VG_(nvidia_moan)();
sewardjde4a1d02002-03-22 01:27:54 +0000413 VG_(unimplemented)
sewardjcfc39b22002-05-08 01:58:18 +0000414 ("modify_ldt(): I (JRS) haven't investigated this yet; sorry.");
sewardjde4a1d02002-03-22 01:27:54 +0000415 break;
416# endif
417
sewardj73f1f072002-03-29 14:22:46 +0000418 /* !!!!!!!!!! New, untested syscalls !!!!!!!!!!!!!!!!!!!!! */
419
sewardj67f1d582002-05-24 02:11:32 +0000420# if defined(__NR_msync) /* syscall 144 */
421 case __NR_msync:
422 /* int msync(const void *start, size_t length, int flags); */
423 if (VG_(clo_trace_syscalls))
424 VG_(printf)("msync ( %p, %d, %d )\n", arg1,arg2,arg3);
425 must_be_readable( tst, "msync(start)", arg1, arg2 );
426 KERNEL_DO_SYSCALL(tid,res);
427 break;
428# endif
429
sewardj0ff15782002-05-18 13:24:24 +0000430# if defined(__NR_getpmsg) /* syscall 188 */
431 case __NR_getpmsg:
432 {
433 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
434 /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
435 int *bandp, int *flagsp); */
436 struct strbuf {
437 int maxlen; /* no. of bytes in buffer */
438 int len; /* no. of bytes returned */
439 caddr_t buf; /* pointer to data */
440 };
441 struct strbuf *ctrl;
442 struct strbuf *data;
443 if (VG_(clo_trace_syscalls))
444 VG_(printf)("getpmsg ( %d, %p, %p, %p, %p )\n",
445 arg1,arg2,arg3,arg4,arg5);
446 ctrl = (struct strbuf *)arg2;
447 data = (struct strbuf *)arg3;
448 if (ctrl && ctrl->maxlen > 0)
449 must_be_writable(tst, "getpmsg(ctrl)",
450 (UInt)ctrl->buf, ctrl->maxlen);
451 if (data && data->maxlen > 0)
452 must_be_writable(tst, "getpmsg(data)",
453 (UInt)data->buf, data->maxlen);
454 if (arg4)
455 must_be_writable(tst, "getpmsg(bandp)",
456 (UInt)arg4, sizeof(int));
457 if (arg5)
458 must_be_writable(tst, "getpmsg(flagsp)",
459 (UInt)arg5, sizeof(int));
460 KERNEL_DO_SYSCALL(tid,res);
461 if (!VG_(is_kerror)(res) && res == 0 && ctrl && ctrl->len > 0) {
462 make_readable( (UInt)ctrl->buf, ctrl->len);
463 }
464 if (!VG_(is_kerror)(res) && res == 0 && data && data->len > 0) {
465 make_readable( (UInt)data->buf, data->len);
466 }
467 }
468 break;
469# endif
470
471
472# if defined(__NR_putpmsg) /* syscall 189 */
473 case __NR_putpmsg:
474 {
475 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
476 /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
477 int band, int flags); */
478 struct strbuf {
479 int maxlen; /* no. of bytes in buffer */
480 int len; /* no. of bytes returned */
481 caddr_t buf; /* pointer to data */
482 };
483 struct strbuf *ctrl;
484 struct strbuf *data;
485 if (VG_(clo_trace_syscalls))
486 VG_(printf)("putpmsg ( %d, %p, %p, %d, %d )\n",
487 arg1,arg2,arg3,arg4,arg5);
488 ctrl = (struct strbuf *)arg2;
489 data = (struct strbuf *)arg3;
490 if (ctrl && ctrl->len > 0)
491 must_be_readable(tst, "putpmsg(ctrl)",
492 (UInt)ctrl->buf, ctrl->len);
493 if (data && data->len > 0)
494 must_be_readable(tst, "putpmsg(data)",
495 (UInt)data->buf, data->len);
496 KERNEL_DO_SYSCALL(tid,res);
497 }
498 break;
499# endif
500
sewardj9e631f72002-05-18 11:01:06 +0000501 case __NR_getitimer: /* syscall 105 */
502 /* int getitimer(int which, struct itimerval *value); */
503 if (VG_(clo_trace_syscalls))
504 VG_(printf)("getitimer ( %d, %p )\n", arg1, arg2);
505 must_be_writable( tst, "getitimer(timer)", arg2,
506 sizeof(struct itimerval) );
507 KERNEL_DO_SYSCALL(tid,res);
508 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL) {
509 make_readable(arg2, sizeof(struct itimerval));
510 }
511 break;
512
sewardjd354bb32002-05-10 22:58:14 +0000513# if defined(__NR_syslog)
514 case __NR_syslog: /* syscall 103 */
515 /* int syslog(int type, char *bufp, int len); */
516 if (VG_(clo_trace_syscalls))
517 VG_(printf)("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
518 switch(arg1) {
519 case 2: case 3: case 4:
520 must_be_writable( tst, "syslog(buf)", arg2, arg3);
521 break;
522 default:
523 break;
524 }
525 KERNEL_DO_SYSCALL(tid, res);
526 if (!VG_(is_kerror)(res)) {
527 switch (arg1) {
528 case 2: case 3: case 4:
529 make_readable( arg2, arg3 );
530 break;
531 default:
532 break;
533 }
534 }
535 break;
536# endif
537
sewardjf4afb002002-05-10 21:01:34 +0000538 case __NR_personality: /* syscall 136 */
sewardjd354bb32002-05-10 22:58:14 +0000539 /* int personality(unsigned long persona); */
sewardjf4afb002002-05-10 21:01:34 +0000540 if (VG_(clo_trace_syscalls))
541 VG_(printf)("personality ( %d )\n", arg1);
542 KERNEL_DO_SYSCALL(tid,res);
543 break;
544
sewardjfb617112002-05-03 21:07:55 +0000545 case __NR_chroot: /* syscall 61 */
546 /* int chroot(const char *path); */
547 if (VG_(clo_trace_syscalls))
548 VG_(printf)("chroot ( %p )\n", arg1);
549 must_be_readable_asciiz( tst, "chroot(path)", arg1 );
550 KERNEL_DO_SYSCALL(tid,res);
551 break;
552
sewardj6e435c02002-04-24 02:24:44 +0000553# if defined(__NR_madvise)
554 case __NR_madvise: /* syscall 219 */
555 /* int madvise(void *start, size_t length, int advice ); */
556 if (VG_(clo_trace_syscalls))
557 VG_(printf)("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
558 KERNEL_DO_SYSCALL(tid,res);
559 break;
560# endif
561
sewardj6af4b5d2002-04-16 04:40:49 +0000562# if defined(__NR_mremap)
563 /* Is this really right? Perhaps it should copy the permissions
564 from the old area into the new. Unclear from the Linux man
565 pages what this really does. Also, the flags don't look like
566 they mean the same as the standard mmap flags, so that's
567 probably wrong too. */
568 case __NR_mremap: /* syscall 163 */
569 /* void* mremap(void * old_address, size_t old_size,
570 size_t new_size, unsigned long flags); */
571 if (VG_(clo_trace_syscalls))
572 VG_(printf)("mremap ( %p, %d, %d, 0x%x )\n",
573 arg1, arg2, arg3, arg4);
574 must_be_writable ( tst, "mremap(old_address)", arg1, arg2 );
575 KERNEL_DO_SYSCALL(tid,res);
576 if (!VG_(is_kerror)(res)) {
577 /* Copied from munmap() wrapper. */
sewardj18d75132002-05-16 11:06:21 +0000578 Bool munmap_exe;
sewardj6af4b5d2002-04-16 04:40:49 +0000579 Addr start = arg1;
580 Addr length = arg2;
581 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
582 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
583 make_noaccess( start, length );
sewardj18d75132002-05-16 11:06:21 +0000584 munmap_exe = VG_(symtab_notify_munmap) ( start, length );
585 if (munmap_exe)
586 VG_(invalidate_translations) ( start, length );
sewardj6af4b5d2002-04-16 04:40:49 +0000587 approximate_mmap_permissions( (Addr)res, arg3, arg4 );
588 }
589 break;
590# endif
591
sewardj73f1f072002-03-29 14:22:46 +0000592 case __NR_nice: /* syscall 34 */
593 /* int nice(int inc); */
594 if (VG_(clo_trace_syscalls))
595 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000596 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000597 break;
598
sewardjde4a1d02002-03-22 01:27:54 +0000599 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
600
sewardjd7f07662002-03-24 10:49:46 +0000601# if defined(__NR_setresgid32)
602 case __NR_setresgid32: /* syscall 210 */
603 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
604 if (VG_(clo_trace_syscalls))
605 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000606 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000607 break;
608# endif
609
sewardjde4a1d02002-03-22 01:27:54 +0000610# if defined(__NR_setfsuid32)
611 case __NR_setfsuid32: /* syscall 215 */
612 /* int setfsuid(uid_t fsuid); */
613 if (VG_(clo_trace_syscalls))
614 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000615 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000616 break;
617# endif
618
619# if defined(__NR__sysctl)
620 case __NR__sysctl:
621 /* int _sysctl(struct __sysctl_args *args); */
622 if (VG_(clo_trace_syscalls))
623 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000624 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000625 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000626 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000627 if (!VG_(is_kerror)(res))
628 make_readable ( arg1, sizeof(struct __sysctl_args) );
629 break;
630# endif
631
632# if defined(__NR_sched_getscheduler)
633 case __NR_sched_getscheduler:
634 /* int sched_getscheduler(pid_t pid); */
635 if (VG_(clo_trace_syscalls))
636 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000637 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000638 break;
639# endif
640
641# if defined(__NR_sched_setscheduler)
642 case __NR_sched_setscheduler:
643 /* int sched_setscheduler(pid_t pid, int policy,
644 const struct sched_param *p); */
645 if (VG_(clo_trace_syscalls))
646 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
647 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000648 must_be_readable( tst,
649 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000650 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000651 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000652 break;
653# endif
654
655# if defined(__NR_mlockall)
656 case __NR_mlockall:
657 /* int mlockall(int flags); */
658 if (VG_(clo_trace_syscalls))
659 VG_(printf)("mlockall ( %x )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000660 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000661 break;
662# endif
663
664# if defined(__NR_munlockall)
665 case __NR_munlockall:
666 /* int munlockall(void); */
667 if (VG_(clo_trace_syscalls))
668 VG_(printf)("munlockall ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000669 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000670 break;
671# endif
672
673#if defined(__NR_sched_get_priority_max)
674 case __NR_sched_get_priority_max:
675 /* int sched_get_priority_max(int policy); */
676 if (VG_(clo_trace_syscalls))
677 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000678 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000679 break;
680# endif
681
sewardj9dfb4a72002-04-27 01:56:30 +0000682#if defined(__NR_sched_get_priority_min)
683 case __NR_sched_get_priority_min: /* syscall 160 */
684 /* int sched_get_priority_min(int policy); */
685 if (VG_(clo_trace_syscalls))
686 VG_(printf)("sched_get_priority_min ( %d )\n", arg1);
687 KERNEL_DO_SYSCALL(tid,res);
688 break;
689# endif
690
691#if defined(__NR_setpriority)
692 case __NR_setpriority: /* syscall 97 */
693 /* int setpriority(int which, int who, int prio); */
694 if (VG_(clo_trace_syscalls))
695 VG_(printf)("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
696 KERNEL_DO_SYSCALL(tid,res);
697 break;
698# endif
699
sewardjde5ac182002-04-27 02:13:24 +0000700#if defined(__NR_getpriority)
701 case __NR_getpriority: /* syscall 96 */
702 /* int getpriority(int which, int who); */
703 if (VG_(clo_trace_syscalls))
704 VG_(printf)("getpriority ( %d, %d )\n", arg1, arg2);
705 KERNEL_DO_SYSCALL(tid,res);
706 break;
707# endif
708
sewardjde4a1d02002-03-22 01:27:54 +0000709# if defined(__NR_setfsgid)
710 case __NR_setfsgid: /* syscall 139 */
711 /* int setfsgid(gid_t gid); */
712 if (VG_(clo_trace_syscalls))
713 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000714 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000715 break;
716# endif
717
718# if defined(__NR_setregid)
719 case __NR_setregid: /* syscall 71 */
720 /* int setregid(gid_t rgid, gid_t egid); */
721 if (VG_(clo_trace_syscalls))
722 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +0000723 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000724 break;
725# endif
726
727# if defined(__NR_setresuid)
728 case __NR_setresuid: /* syscall 164 */
729 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
730 if (VG_(clo_trace_syscalls))
731 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000732 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000733 break;
734# endif
735
736# if defined(__NR_setfsuid)
737 case __NR_setfsuid: /* syscall 138 */
738 /* int setfsuid(uid_t uid); */
739 if (VG_(clo_trace_syscalls))
740 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000741 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000742 break;
743# endif
744
745 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
746
747# if defined(__NR_sendfile)
748 case __NR_sendfile: /* syscall 187 */
749 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
750 size_t count) */
751 if (VG_(clo_trace_syscalls))
752 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000753 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000754 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000755 if (!VG_(is_kerror)(res)) {
756 make_readable( arg3, sizeof( off_t ) );
757 }
758 break;
759# endif
760
761 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
762
763# if defined(__NR_pwrite)
764 case __NR_pwrite: /* syscall 181 */
765 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
766 off_t offset); */
767 if (VG_(clo_trace_syscalls))
768 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000769 must_be_readable( tst, "pwrite(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000770 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000771 break;
772# endif
773
774 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
775
776 case __NR_sync: /* syscall 36 */
777 /* int sync(); */
778 if (VG_(clo_trace_syscalls))
779 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000780 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000781 break;
782
783 case __NR_fstatfs: /* syscall 100 */
784 /* int fstatfs(int fd, struct statfs *buf); */
785 if (VG_(clo_trace_syscalls))
786 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000787 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000788 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000789 if (!VG_(is_kerror)(res))
790 make_readable( arg2, sizeof(struct statfs) );
791 break;
792
793 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
794
795 case __NR_pause: /* syscall 29 */
796 /* int pause(void); */
797 if (VG_(clo_trace_syscalls))
798 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000799 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000800 break;
801
802 case __NR_getsid: /* syscall 147 */
803 /* pid_t getsid(pid_t pid); */
804 if (VG_(clo_trace_syscalls))
805 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000806 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000807 break;
808
809# if defined(__NR_pread)
810 case __NR_pread: /* syscall 180 */
811 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
812 if (VG_(clo_trace_syscalls))
813 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000814 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000815 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000816 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000817 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
818 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000819 arg1, arg2, arg3, arg4, res);
820 if (!VG_(is_kerror)(res) && res > 0) {
821 make_readable( arg2, res );
822 }
823 break;
824# endif
825
826 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
827
828 case __NR_mknod: /* syscall 14 */
829 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
830 if (VG_(clo_trace_syscalls))
831 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000832 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000833 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000834 break;
835
836 case __NR_flock: /* syscall 143 */
837 /* int flock(int fd, int operation); */
838 if (VG_(clo_trace_syscalls))
839 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000840 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000841 break;
842
843# if defined(__NR_rt_sigsuspend)
844 /* Viewed with great suspicion by me, but, hey, let's do it
845 anyway ... */
846 case __NR_rt_sigsuspend: /* syscall 179 */
847 /* int sigsuspend(const sigset_t *mask); */
848 if (VG_(clo_trace_syscalls))
849 VG_(printf)("sigsuspend ( %p )\n", arg1 );
850 if (arg1 != (Addr)NULL) {
851 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000852 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000853 sizeof(vki_ksigset_t) );
854 }
sewardj2e93c502002-04-12 11:12:52 +0000855 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000856 break;
857# endif
858
859 case __NR_init_module: /* syscall 128 */
860 /* int init_module(const char *name, struct module *image); */
861 if (VG_(clo_trace_syscalls))
862 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000863 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
864 must_be_readable( tst, "init_module(image)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000865 sizeof(struct module) );
sewardj2e93c502002-04-12 11:12:52 +0000866 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000867 break;
868
869 case __NR_ioperm: /* syscall 101 */
870 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
871 if (VG_(clo_trace_syscalls))
872 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000873 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000874 break;
875
876 case __NR_capget: /* syscall 184 */
877 /* int capget(cap_user_header_t header, cap_user_data_t data); */
878 if (VG_(clo_trace_syscalls))
879 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000880 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000881 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000882 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000883 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000884 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000885 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
886 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
887 break;
888
889 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
890
891 case __NR_execve:
892 /* int execve (const char *filename,
893 char *const argv [],
894 char *const envp[]); */
895 if (VG_(clo_trace_syscalls))
896 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
897 arg1, arg1, arg2, arg3);
sewardjccef2e62002-05-29 19:26:32 +0000898 /* Resistance is futile. Nuke all other threads. POSIX
899 mandates this. */
900 VG_(nuke_all_threads_except)( tid );
sewardjde4a1d02002-03-22 01:27:54 +0000901 /* Make any binding for LD_PRELOAD disappear, so that child
902 processes don't get traced into. */
903 if (!VG_(clo_trace_children)) {
904 Int i;
905 Char** envp = (Char**)arg3;
sewardj3e1eb1f2002-05-18 13:14:17 +0000906 Char* ld_preload_str = NULL;
907 Char* ld_library_path_str = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000908 for (i = 0; envp[i] != NULL; i++) {
sewardj3e1eb1f2002-05-18 13:14:17 +0000909 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
910 ld_preload_str = &envp[i][11];
911 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
912 ld_library_path_str = &envp[i][16];
sewardjde4a1d02002-03-22 01:27:54 +0000913 }
sewardj3e1eb1f2002-05-18 13:14:17 +0000914 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
915 ld_preload_str, ld_library_path_str );
sewardjde4a1d02002-03-22 01:27:54 +0000916 }
sewardj2e93c502002-04-12 11:12:52 +0000917 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000918 /* Should we still be alive here? Don't think so. */
919 /* Actually, above comment is wrong. execve can fail, just
920 like any other syscall -- typically the file to exec does
921 not exist. Hence: */
922 vg_assert(VG_(is_kerror)(res));
923 break;
924
sewardjde4a1d02002-03-22 01:27:54 +0000925 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
926
927 case __NR_access: /* syscall 33 */
928 /* int access(const char *pathname, int mode); */
929 if (VG_(clo_trace_syscalls))
930 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000931 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000932 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000933 break;
934
935 case __NR_alarm: /* syscall 27 */
936 /* unsigned int alarm(unsigned int seconds); */
937 if (VG_(clo_trace_syscalls))
938 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000939 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000940 break;
941
942 case __NR_brk: /* syscall 45 */
943 /* Haven't a clue if this is really right. */
944 /* int brk(void *end_data_segment); */
945 if (VG_(clo_trace_syscalls))
946 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000947 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000948 if (VG_(clo_trace_syscalls))
949 VG_(printf)("0x%x\n", res);
950
951 if (!VG_(is_kerror)(res)) {
952 if (arg1 == 0) {
953 /* Just asking where the current end is. (???) */
954 VGM_(curr_dataseg_end) = res;
955 } else
956 if (arg1 < VGM_(curr_dataseg_end)) {
957 /* shrinking the data segment. */
958 make_noaccess( (Addr)arg1,
959 VGM_(curr_dataseg_end)-arg1 );
960 VGM_(curr_dataseg_end) = arg1;
961 } else
962 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
963 /* asked for more memory, and got it */
964 /*
965 VG_(printf)("BRK: new area %x .. %x\n",
966 VGM_(curr_dataseg_end, arg1-1 );
967 */
968 make_writable ( (Addr)VGM_(curr_dataseg_end),
969 arg1-VGM_(curr_dataseg_end) );
970 VGM_(curr_dataseg_end) = arg1;
971 }
972 }
973 break;
974
975 case __NR_chdir: /* syscall 12 */
976 /* int chdir(const char *path); */
977 if (VG_(clo_trace_syscalls))
978 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +0000979 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000980 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000981 break;
982
983 case __NR_chmod: /* syscall 15 */
984 /* int chmod(const char *path, mode_t mode); */
985 if (VG_(clo_trace_syscalls))
986 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000987 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000988 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000989 break;
990
991# if defined(__NR_chown32)
992 case __NR_chown32: /* syscall 212 */
993# endif
994# if defined(__NR_lchown32)
995 case __NR_lchown32: /* syscall 198 */
996# endif
997 case __NR_chown: /* syscall 16 */
998 /* int chown(const char *path, uid_t owner, gid_t group); */
999 if (VG_(clo_trace_syscalls))
1000 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001001 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00001002 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001003 break;
1004
1005 case __NR_close: /* syscall 6 */
1006 /* int close(int fd); */
1007 if (VG_(clo_trace_syscalls))
1008 VG_(printf)("close ( %d )\n",arg1);
1009 /* Detect and negate attempts by the client to close Valgrind's
1010 logfile fd ... */
1011 if (arg1 == VG_(clo_logfile_fd)) {
1012 VG_(message)(Vg_UserMsg,
1013 "Warning: client attempted to close "
1014 "Valgrind's logfile fd (%d).",
1015 VG_(clo_logfile_fd));
1016 VG_(message)(Vg_UserMsg,
1017 " Use --logfile-fd=<number> to select an "
1018 "alternative logfile fd." );
1019 } else {
sewardj2e93c502002-04-12 11:12:52 +00001020 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001021 }
1022 break;
1023
1024 case __NR_dup: /* syscall 41 */
1025 /* int dup(int oldfd); */
1026 if (VG_(clo_trace_syscalls))
1027 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001028 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001029 if (VG_(clo_trace_syscalls))
1030 VG_(printf)("%d\n", res);
1031 break;
1032
1033 case __NR_dup2: /* syscall 63 */
1034 /* int dup2(int oldfd, int newfd); */
1035 if (VG_(clo_trace_syscalls))
1036 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001037 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001038 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +00001039 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
1040 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001041 arg1, arg2, res);
1042 break;
1043
1044 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +00001045 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +00001046 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +00001047 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
1048 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001049 break;
1050
1051 case __NR_fchdir: /* syscall 133 */
1052 /* int fchdir(int fd); */
1053 if (VG_(clo_trace_syscalls))
1054 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001055 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001056 break;
1057
sewardj2f0de322002-03-24 10:17:25 +00001058# if defined(__NR_fchown32)
1059 case __NR_fchown32: /* syscall 207 */
1060# endif
1061 case __NR_fchown: /* syscall 95 */
1062 /* int fchown(int filedes, uid_t owner, gid_t group); */
1063 if (VG_(clo_trace_syscalls))
1064 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001065 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001066 break;
1067
sewardjde4a1d02002-03-22 01:27:54 +00001068 case __NR_fchmod: /* syscall 94 */
1069 /* int fchmod(int fildes, mode_t mode); */
1070 if (VG_(clo_trace_syscalls))
1071 VG_(printf)("fchmod ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001072 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001073 break;
sewardj2f0de322002-03-24 10:17:25 +00001074
sewardjde4a1d02002-03-22 01:27:54 +00001075# if defined(__NR_fcntl64)
1076 case __NR_fcntl64: /* syscall 221 */
1077 /* I don't know what the prototype for this is supposed to be. */
1078 /* ??? int fcntl(int fd, int cmd); */
1079 if (VG_(clo_trace_syscalls))
1080 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001081 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001082 break;
1083# endif
1084
1085 case __NR_fstat: /* syscall 108 */
1086 /* int fstat(int filedes, struct stat *buf); */
1087 if (VG_(clo_trace_syscalls))
1088 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001089 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001090 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001091 if (!VG_(is_kerror)(res))
1092 make_readable( arg2, sizeof(struct stat) );
1093 break;
1094
1095 case __NR_vfork: /* syscall 190 */
1096 /* pid_t vfork(void); */
1097 if (VG_(clo_trace_syscalls))
1098 VG_(printf)("vfork ( ) ... becomes ... ");
1099 /* KLUDGE: we prefer to do a fork rather than vfork.
1100 vfork gives a SIGSEGV, and the stated semantics looks
1101 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +00001102 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +00001103 /* fall through ... */
1104 case __NR_fork: /* syscall 2 */
1105 /* pid_t fork(void); */
1106 if (VG_(clo_trace_syscalls))
1107 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001108 KERNEL_DO_SYSCALL(tid,res);
sewardjccef2e62002-05-29 19:26:32 +00001109 if (res == 0) {
1110 /* I am the child. Nuke all other threads which I might
1111 have inherited from my parent. POSIX mandates this. */
1112 VG_(nuke_all_threads_except)( tid );
1113 }
sewardjde4a1d02002-03-22 01:27:54 +00001114 break;
1115
1116 case __NR_fsync: /* syscall 118 */
1117 /* int fsync(int fd); */
1118 if (VG_(clo_trace_syscalls))
1119 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001120 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001121 break;
1122
1123 case __NR_ftruncate: /* syscall 93 */
1124 /* int ftruncate(int fd, size_t length); */
1125 if (VG_(clo_trace_syscalls))
1126 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001127 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001128 break;
1129
sewardj2f0de322002-03-24 10:17:25 +00001130# if defined(__NR_ftruncate64)
1131 case __NR_ftruncate64: /* syscall 194 */
1132 /* int ftruncate64(int fd, off64_t length); */
1133 if (VG_(clo_trace_syscalls))
1134 VG_(printf)("ftruncate64 ( %d, %lld )\n",
1135 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +00001136 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001137 break;
1138# endif
1139
1140 case __NR_getdents: /* syscall 141 */
1141 /* int getdents(unsigned int fd, struct dirent *dirp,
1142 unsigned int count); */
1143 if (VG_(clo_trace_syscalls))
1144 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001145 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001146 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001147 if (!VG_(is_kerror)(res) && res > 0)
1148 make_readable( arg2, res );
1149 break;
1150
1151# if defined(__NR_getdents64)
1152 case __NR_getdents64: /* syscall 220 */
1153 /* int getdents(unsigned int fd, struct dirent64 *dirp,
1154 unsigned int count); */
1155 if (VG_(clo_trace_syscalls))
1156 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001157 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001158 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001159 if (!VG_(is_kerror)(res) && res > 0)
1160 make_readable( arg2, res );
1161 break;
1162# endif
1163
1164# if defined(__NR_getgroups32)
1165 case __NR_getgroups32: /* syscall 205 */
1166# endif
1167 case __NR_getgroups: /* syscall 80 */
1168 /* int getgroups(int size, gid_t list[]); */
1169 if (VG_(clo_trace_syscalls))
1170 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
1171 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00001172 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001173 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001174 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001175 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
1176 make_readable ( arg2, res * sizeof(gid_t) );
1177 break;
1178
1179 case __NR_getcwd: /* syscall 183 */
1180 /* char *getcwd(char *buf, size_t size); */
1181 if (VG_(clo_trace_syscalls))
1182 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001183 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +00001184 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001185 if (!VG_(is_kerror)(res) && res != (Addr)NULL)
1186 make_readable ( arg1, arg2 );
1187 /* Not really right -- really we should have the asciiz
1188 string starting at arg1 readable, or up to arg2 bytes,
1189 whichever finishes first. */
1190 break;
1191
1192 case __NR_geteuid: /* syscall 49 */
1193 /* uid_t geteuid(void); */
1194 if (VG_(clo_trace_syscalls))
1195 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001196 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001197 break;
1198
1199# if defined(__NR_geteuid32)
1200 case __NR_geteuid32: /* syscall 201 */
1201 /* ?? uid_t geteuid32(void); */
1202 if (VG_(clo_trace_syscalls))
1203 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001204 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001205 break;
1206# endif
1207
1208 case __NR_getegid: /* syscall 50 */
1209 /* gid_t getegid(void); */
1210 if (VG_(clo_trace_syscalls))
1211 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001212 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001213 break;
1214
1215# if defined(__NR_getegid32)
1216 case __NR_getegid32: /* syscall 202 */
1217 /* gid_t getegid32(void); */
1218 if (VG_(clo_trace_syscalls))
1219 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001220 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001221 break;
1222# endif
1223
1224 case __NR_getgid: /* syscall 47 */
1225 /* gid_t getgid(void); */
1226 if (VG_(clo_trace_syscalls))
1227 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001228 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001229 break;
1230
1231# if defined(__NR_getgid32)
1232 case __NR_getgid32: /* syscall 200 */
1233 /* gid_t getgid32(void); */
1234 if (VG_(clo_trace_syscalls))
1235 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001236 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001237 break;
1238# endif
1239
1240 case __NR_getpid: /* syscall 20 */
1241 /* pid_t getpid(void); */
1242 if (VG_(clo_trace_syscalls))
1243 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001244 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001245 break;
1246
1247 case __NR_getpgid: /* syscall 132 */
1248 /* pid_t getpgid(pid_t pid); */
1249 if (VG_(clo_trace_syscalls))
1250 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001251 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001252 break;
1253
1254 case __NR_getpgrp: /* syscall 65 */
1255 /* pid_t getpprp(void); */
1256 if (VG_(clo_trace_syscalls))
1257 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001258 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001259 break;
1260
1261 case __NR_getppid: /* syscall 64 */
1262 /* pid_t getppid(void); */
1263 if (VG_(clo_trace_syscalls))
1264 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001265 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001266 break;
1267
1268 case __NR_getresgid: /* syscall 171 */
1269 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1270 if (VG_(clo_trace_syscalls))
1271 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001272 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1273 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1274 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001275 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001276 if (!VG_(is_kerror)(res) && res == 0) {
1277 make_readable ( arg1, sizeof(gid_t) );
1278 make_readable ( arg2, sizeof(gid_t) );
1279 make_readable ( arg3, sizeof(gid_t) );
1280 }
1281 break;
1282
1283# if defined(__NR_getresgid32)
1284 case __NR_getresgid32: /* syscall 211 */
1285 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1286 if (VG_(clo_trace_syscalls))
1287 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001288 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1289 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1290 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001291 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001292 if (!VG_(is_kerror)(res) && res == 0) {
1293 make_readable ( arg1, sizeof(gid_t) );
1294 make_readable ( arg2, sizeof(gid_t) );
1295 make_readable ( arg3, sizeof(gid_t) );
1296 }
1297 break;
1298# endif
1299
1300 case __NR_getresuid: /* syscall 165 */
1301 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1302 if (VG_(clo_trace_syscalls))
1303 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001304 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1305 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1306 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001307 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001308 if (!VG_(is_kerror)(res) && res == 0) {
1309 make_readable ( arg1, sizeof(uid_t) );
1310 make_readable ( arg2, sizeof(uid_t) );
1311 make_readable ( arg3, sizeof(uid_t) );
1312 }
1313 break;
1314
1315# if defined(__NR_getresuid32)
1316 case __NR_getresuid32: /* syscall 209 */
1317 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1318 if (VG_(clo_trace_syscalls))
1319 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001320 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1321 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1322 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001323 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001324 if (!VG_(is_kerror)(res) && res == 0) {
1325 make_readable ( arg1, sizeof(uid_t) );
1326 make_readable ( arg2, sizeof(uid_t) );
1327 make_readable ( arg3, sizeof(uid_t) );
1328 }
1329 break;
1330# endif
1331
1332# if defined(__NR_ugetrlimit)
1333 case __NR_ugetrlimit: /* syscall 191 */
1334# endif
1335 case __NR_getrlimit: /* syscall 76 */
1336 /* int getrlimit (int resource, struct rlimit *rlim); */
1337 if (VG_(clo_trace_syscalls))
1338 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001339 must_be_writable( tst, "getrlimit(rlim)", arg2,
1340 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001341 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001342 if (!VG_(is_kerror)(res) && res == 0)
1343 make_readable( arg2, sizeof(struct rlimit) );
1344 break;
1345
1346 case __NR_getrusage: /* syscall 77 */
1347 /* int getrusage (int who, struct rusage *usage); */
1348 if (VG_(clo_trace_syscalls))
1349 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001350 must_be_writable( tst, "getrusage(usage)", arg2,
1351 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001352 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001353 if (!VG_(is_kerror)(res) && res == 0)
1354 make_readable(arg2, sizeof(struct rusage) );
1355 break;
1356
1357 case __NR_gettimeofday: /* syscall 78 */
1358 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1359 if (VG_(clo_trace_syscalls))
1360 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001361 must_be_writable( tst, "gettimeofday(tv)", arg1,
1362 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001363 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001364 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001365 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001366 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001367 if (!VG_(is_kerror)(res) && res == 0) {
1368 make_readable( arg1, sizeof(struct timeval) );
1369 if (arg2 != 0)
1370 make_readable( arg2, sizeof(struct timezone) );
1371 }
1372 break;
1373
1374 case __NR_getuid: /* syscall 24 */
1375 /* uid_t getuid(void); */
1376 if (VG_(clo_trace_syscalls))
1377 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001378 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001379 break;
1380
1381# if defined(__NR_getuid32)
1382 case __NR_getuid32: /* syscall 199 */
1383 /* ???uid_t getuid32(void); */
1384 if (VG_(clo_trace_syscalls))
1385 VG_(printf)("getuid32 ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001386 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001387 break;
1388# endif
1389
1390 case __NR_ipc: /* syscall 117 */
1391 /* int ipc ( unsigned int call, int first, int second,
1392 int third, void *ptr, long fifth); */
1393 {
sewardj2e93c502002-04-12 11:12:52 +00001394 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001395
1396 if (VG_(clo_trace_syscalls))
1397 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1398 arg1,arg2,arg3,arg4,arg5,arg6);
1399 switch (arg1 /* call */) {
1400 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001401 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001402 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001403 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001404 break;
sewardj5b9e3502002-03-29 04:35:08 +00001405 case 2: /* IPCOP_semget */
1406 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001407 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001408 break;
1409 case 11: /* IPCOP_msgsnd */
1410 {
1411 struct msgbuf *msgp = (struct msgbuf *)arg5;
1412 Int msgsz = arg3;
1413
sewardj8c824512002-04-14 04:16:48 +00001414 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001415 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001416 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001417 (UInt)msgp->mtext, msgsz );
1418
sewardj2e93c502002-04-12 11:12:52 +00001419 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001420 break;
1421 }
1422 case 12: /* IPCOP_msgrcv */
1423 {
sewardj59c255c2002-04-27 02:06:15 +00001424 struct msgbuf *msgp;
sewardj5b9e3502002-03-29 04:35:08 +00001425 Int msgsz = arg3;
sewardj59c255c2002-04-27 02:06:15 +00001426
1427 msgp = (struct msgbuf *)safe_dereference(
1428 (Addr) (&((struct ipc_kludge *)arg5)->msgp), 0 );
sewardj5b9e3502002-03-29 04:35:08 +00001429
sewardj59c255c2002-04-27 02:06:15 +00001430 must_be_writable ( tst, "msgrcv(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001431 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj59c255c2002-04-27 02:06:15 +00001432 must_be_writable ( tst, "msgrcv(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001433 (UInt)msgp->mtext, msgsz );
1434
sewardj2e93c502002-04-12 11:12:52 +00001435 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001436
1437 if ( !VG_(is_kerror)(res) && res > 0 ) {
1438 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1439 make_readable ( (UInt)msgp->mtext, res );
1440 }
1441 break;
1442 }
1443 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001444 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001445 break;
1446 case 14: /* IPCOP_msgctl */
1447 {
1448 switch (arg3 /* cmd */) {
1449 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001450 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001451 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001452 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001453 if ( !VG_(is_kerror)(res) && res > 0 ) {
1454 make_readable ( arg5, sizeof(struct msqid_ds) );
1455 }
1456 break;
1457 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001458 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001459 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001460 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001461 break;
sewardjc9add3b2002-04-16 01:58:19 +00001462# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001463 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001464 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001465 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001466 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001467 if ( !VG_(is_kerror)(res) && res > 0 ) {
1468 make_readable ( arg5, sizeof(struct msqid64_ds) );
1469 }
1470 break;
sewardjc9add3b2002-04-16 01:58:19 +00001471# endif
1472# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001473 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001474 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001475 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001476 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001477 break;
sewardjc9add3b2002-04-16 01:58:19 +00001478# endif
sewardj5b9e3502002-03-29 04:35:08 +00001479 default:
sewardj2e93c502002-04-12 11:12:52 +00001480 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001481 break;
1482 }
1483 break;
1484 }
sewardjde4a1d02002-03-22 01:27:54 +00001485 case 21: /* IPCOP_shmat */
1486 {
1487 Int shmid = arg2;
1488 Int shmflag = arg3;
1489 UInt addr;
1490
sewardj2e93c502002-04-12 11:12:52 +00001491 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001492
1493 if ( VG_(is_kerror) ( res ) )
1494 break;
1495
1496 /* force readability. before the syscall it is
1497 * indeed uninitialized, as can be seen in
1498 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1499 make_readable ( arg4, sizeof( ULong ) );
1500
1501 addr = safe_dereference ( arg4, 0 );
1502 if ( addr > 0 ) {
1503 UInt segmentSize = get_shm_size ( shmid );
1504 if ( segmentSize > 0 ) {
1505 if ( shmflag & SHM_RDONLY )
1506 make_readable ( addr, segmentSize );
1507 else
1508 make_readwritable ( addr, segmentSize );
1509 }
1510 }
1511 break;
1512 }
1513 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001514 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001515 /* ### FIXME: this should call make_noaccess on the
1516 * area passed to shmdt. But there's no way to
1517 * figure out the size of the shared memory segment
1518 * just from the address... Maybe we want to keep a
1519 * copy of the exiting mappings inside valgrind? */
1520 break;
1521 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001522 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001523 break;
1524 case 24: /* IPCOP_shmctl */
sewardj2390bb52002-05-09 17:45:06 +00001525 /* Subject: shmctl: The True Story
1526 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
1527 From: Reuben Thomas <rrt@mupsych.org>
1528 To: Julian Seward <jseward@acm.org>
1529
1530 1. As you suggested, the syscall subop is in arg1.
1531
1532 2. There are a couple more twists, so the arg order
1533 is actually:
1534
1535 arg1 syscall subop
1536 arg2 file desc
1537 arg3 shm operation code (can have IPC_64 set)
1538 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
1539 is defined?
1540 arg5 pointer to buffer
1541
1542 3. With this in mind, I've amended the case as below:
1543 */
1544 {
1545 UInt cmd = arg3;
1546 Bool out_arg = False;
1547 if ( arg5 ) {
1548# if defined(IPC_64)
1549 cmd = cmd & (~IPC_64);
1550# endif
sewardj2a8cda12002-05-10 22:51:26 +00001551 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
sewardj2390bb52002-05-09 17:45:06 +00001552 if ( out_arg )
1553 must_be_writable( tst,
1554 "shmctl(SHM_STAT or IPC_STAT,buf)",
1555 arg5, sizeof(struct shmid_ds) );
1556 else
1557 must_be_readable( tst,
1558 "shmctl(SHM_XXXX,buf)",
1559 arg5, sizeof(struct shmid_ds) );
1560 }
1561 KERNEL_DO_SYSCALL(tid,res);
1562 if ( arg5 && !VG_(is_kerror)(res) && res == 0 && out_arg )
1563 make_readable( arg5, sizeof(struct shmid_ds) );
sewardjde4a1d02002-03-22 01:27:54 +00001564 }
sewardj84b380a2002-05-08 01:31:15 +00001565 break;
sewardjde4a1d02002-03-22 01:27:54 +00001566 default:
1567 VG_(message)(Vg_DebugMsg,
1568 "FATAL: unhandled syscall(ipc) %d",
1569 arg1 );
1570 VG_(panic)("... bye!\n");
1571 break; /*NOTREACHED*/
1572 }
1573 }
1574 break;
1575
1576 case __NR_ioctl: /* syscall 54 */
1577 /* int ioctl(int d, int request, ...)
1578 [The "third" argument is traditionally char *argp,
1579 and will be so named for this discussion.]
1580 */
1581 /*
1582 VG_(message)(
1583 Vg_DebugMsg,
1584 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1585 arg2,arg1,arg3);
1586 */
1587 if (VG_(clo_trace_syscalls))
1588 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1589 switch (arg2 /* request */) {
1590 case TCSETS:
1591 case TCSETSW:
1592 case TCSETSF:
sewardj730e4d32002-05-09 18:40:45 +00001593 must_be_readable( tst, "ioctl(TCSET{S,SW,SF})", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001594 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001595 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001596 break;
1597 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001598 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001599 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001600 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001601 if (!VG_(is_kerror)(res) && res == 0)
1602 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1603 break;
sewardj2f0de322002-03-24 10:17:25 +00001604 case TCSETA:
sewardj730e4d32002-05-09 18:40:45 +00001605 case TCSETAW:
1606 case TCSETAF:
1607 must_be_readable( tst, "ioctl(TCSET{A,AW,AF})", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001608 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001609 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001610 break;
1611 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001612 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001613 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001614 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001615 if (!VG_(is_kerror)(res) && res == 0)
1616 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1617 break;
sewardjde4a1d02002-03-22 01:27:54 +00001618 case TCSBRK:
sewardj835021e2002-05-22 12:03:54 +00001619 case TCXONC:
sewardjde4a1d02002-03-22 01:27:54 +00001620 case TCSBRKP:
1621 case TCFLSH:
1622 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001623 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001624 break;
1625 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001626 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001627 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001628 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001629 if (!VG_(is_kerror)(res) && res == 0)
1630 make_readable ( arg3, sizeof(struct winsize) );
1631 break;
1632 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001633 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001634 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001635 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001636 break;
sewardj19fe3d02002-03-29 04:39:00 +00001637 case TIOCGPGRP:
1638 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001639 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001640 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001641 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001642 if (!VG_(is_kerror)(res) && res == 0)
1643 make_readable ( arg3, sizeof(pid_t) );
sewardja4da9372002-05-21 00:44:02 +00001644 break;
1645 case TIOCSPGRP:
1646 /* Set a process group ID? */
1647 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
1648 sizeof(pid_t) );
1649 KERNEL_DO_SYSCALL(tid,res);
1650 if (!VG_(is_kerror)(res) && res == 0)
1651 make_readable ( arg3, sizeof(pid_t) );
1652 break;
sewardjde4a1d02002-03-22 01:27:54 +00001653 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001654 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001655 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001656 if (!VG_(is_kerror)(res) && res == 0)
1657 make_readable ( arg3, sizeof(int));
1658 break;
sewardj73f1f072002-03-29 14:22:46 +00001659 case TIOCSCTTY:
1660 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001661 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001662 break;
sewardjde4a1d02002-03-22 01:27:54 +00001663 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001664 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001665 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001666 break;
1667 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001668 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001669 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001670 break;
1671 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001672 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001673 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001674 break;
1675 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001676 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001677 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001678 if (!VG_(is_kerror)(res) && res == 0)
1679 make_readable( arg3, sizeof(int) );
1680 break;
1681
1682 /* If you get compilation problems here, change the #if
1683 1 to #if 0 and get rid of <scsi/sg.h> in
1684 vg_unsafe.h. */
1685# if 1
1686 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001687 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1688 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001689 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001690 break;
1691# if defined(SG_IO)
1692 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001693 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001694 sizeof(struct sg_io_hdr) );
sewardj2e93c502002-04-12 11:12:52 +00001695 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001696 if (!VG_(is_kerror)(res) && res == 0)
1697 make_readable (arg3, sizeof(struct sg_io_hdr));
1698 break;
1699# endif /* SG_IO */
1700 case SG_GET_SCSI_ID:
1701 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001702 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001703 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001704 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001705 if (!VG_(is_kerror)(res) && res == 0)
1706 make_readable (arg3, sizeof(struct sg_scsi_id));
1707 break;
1708 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001709 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001710 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001711 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001712 break;
1713 case SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001714 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1715 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001716 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001717 break;
1718 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001719 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001720 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001721 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001722 if (!VG_(is_kerror)(res) && res == 0)
1723 make_readable (arg3, sizeof(int));
1724 break;
1725 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001726 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1727 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001728 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001729 if (!VG_(is_kerror)(res) && res == 0)
1730 make_readable (arg3, sizeof(int));
1731 break;
1732 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001733 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001734 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001735 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001736 break;
1737# endif
1738
1739 case IIOCGETCPS:
1740 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1741 * when KERNEL was. I never saw a larger value than 64 though */
1742# ifndef ISDN_MAX_CHANNELS
1743# define ISDN_MAX_CHANNELS 64
1744# endif
sewardj8c824512002-04-14 04:16:48 +00001745 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001746 ISDN_MAX_CHANNELS
1747 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001748 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001749 if (!VG_(is_kerror)(res) && res == 0)
1750 make_readable ( arg3, ISDN_MAX_CHANNELS
1751 * 2 * sizeof(unsigned long) );
1752 break;
1753 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001754 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001755 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1756 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001757 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001758 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001759 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001760 if (!VG_(is_kerror)(res) && res == 0)
1761 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1762 break;
1763
1764 /* These all use struct ifreq AFAIK */
1765 case SIOCGIFINDEX:
1766 case SIOCGIFFLAGS: /* get flags */
1767 case SIOCGIFHWADDR: /* Get hardware address */
1768 case SIOCGIFMTU: /* get MTU size */
1769 case SIOCGIFADDR: /* get PA address */
1770 case SIOCGIFNETMASK: /* get network PA mask */
1771 case SIOCGIFMETRIC: /* get metric */
1772 case SIOCGIFMAP: /* Get device parameters */
1773 case SIOCGIFTXQLEN: /* Get the tx queue length */
1774 case SIOCGIFDSTADDR: /* get remote PA address */
1775 case SIOCGIFBRDADDR: /* get broadcast PA address */
1776 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001777 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001778 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001779 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001780 if (!VG_(is_kerror)(res) && res == 0)
1781 make_readable (arg3, sizeof(struct ifreq));
1782 break;
1783 case SIOCGIFCONF: /* get iface list */
1784 /* WAS:
1785 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1786 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001787 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001788 if (!VG_(is_kerror)(res) && res == 0)
1789 make_readable (arg3, sizeof(struct ifconf));
1790 */
sewardj8c824512002-04-14 04:16:48 +00001791 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001792 sizeof(struct ifconf));
1793 if ( arg3 ) {
1794 // TODO len must be readable and writable
1795 // buf pointer only needs to be readable
1796 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001797 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001798 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1799 }
sewardj2e93c502002-04-12 11:12:52 +00001800 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001801 if (!VG_(is_kerror)(res) && res == 0 && arg3 ) {
1802 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj402c9362002-05-24 11:57:36 +00001803 if (ifc->ifc_buf != NULL)
1804 make_readable ( (Addr)(ifc->ifc_buf),
1805 (UInt)(ifc->ifc_len) );
sewardjde4a1d02002-03-22 01:27:54 +00001806 }
1807 break;
1808 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001809 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001810 sizeof(struct timeval));
sewardj2e93c502002-04-12 11:12:52 +00001811 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001812 if (!VG_(is_kerror)(res) && res == 0)
1813 make_readable (arg3, sizeof(struct timeval));
1814 break;
1815 case SIOCGRARP: /* get RARP table entry */
1816 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001817 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001818 sizeof(struct arpreq));
sewardj2e93c502002-04-12 11:12:52 +00001819 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001820 if (!VG_(is_kerror)(res) && res == 0)
1821 make_readable (arg3, sizeof(struct arpreq));
1822 break;
1823
1824 case SIOCSIFFLAGS: /* set flags */
1825 case SIOCSIFMAP: /* Set device parameters */
1826 case SIOCSIFTXQLEN: /* Set the tx queue length */
1827 case SIOCSIFDSTADDR: /* set remote PA address */
1828 case SIOCSIFBRDADDR: /* set broadcast PA address */
1829 case SIOCSIFNETMASK: /* set network PA mask */
1830 case SIOCSIFMETRIC: /* set metric */
1831 case SIOCSIFADDR: /* set PA address */
1832 case SIOCSIFMTU: /* set MTU size */
1833 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001834 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001835 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001836 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001837 break;
1838 /* Routing table calls. */
1839 case SIOCADDRT: /* add routing table entry */
1840 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001841 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001842 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001843 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001844 break;
1845
1846 /* RARP cache control calls. */
1847 case SIOCDRARP: /* delete RARP table entry */
1848 case SIOCSRARP: /* set RARP table entry */
1849 /* ARP cache control calls. */
1850 case SIOCSARP: /* set ARP table entry */
1851 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001852 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001853 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001854 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001855 break;
1856
1857 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001858 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001859 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001860 break;
1861
1862 /* linux/soundcard interface (OSS) */
1863 case SNDCTL_SEQ_GETOUTCOUNT:
1864 case SNDCTL_SEQ_GETINCOUNT:
1865 case SNDCTL_SEQ_PERCMODE:
1866 case SNDCTL_SEQ_TESTMIDI:
1867 case SNDCTL_SEQ_RESETSAMPLES:
1868 case SNDCTL_SEQ_NRSYNTHS:
1869 case SNDCTL_SEQ_NRMIDIS:
1870 case SNDCTL_SEQ_GETTIME:
1871 case SNDCTL_DSP_GETFMTS:
1872 case SNDCTL_DSP_GETTRIGGER:
1873 case SNDCTL_DSP_GETODELAY:
1874# if defined(SNDCTL_DSP_GETSPDIF)
1875 case SNDCTL_DSP_GETSPDIF:
1876# endif
1877 case SNDCTL_DSP_GETCAPS:
1878 case SOUND_PCM_READ_RATE:
1879 case SOUND_PCM_READ_CHANNELS:
1880 case SOUND_PCM_READ_BITS:
1881 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1882 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001883 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1884 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001885 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001886 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001887 if (!VG_(is_kerror)(res) && res == 0)
1888 make_readable (arg3, sizeof(int));
1889 break;
1890 case SNDCTL_SEQ_CTRLRATE:
1891 case SNDCTL_DSP_SPEED:
1892 case SNDCTL_DSP_STEREO:
1893 case SNDCTL_DSP_GETBLKSIZE:
1894 case SNDCTL_DSP_CHANNELS:
1895 case SOUND_PCM_WRITE_FILTER:
1896 case SNDCTL_DSP_SUBDIVIDE:
1897 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001898# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001899 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001900# endif
1901# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001902 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001903# endif
sewardjde4a1d02002-03-22 01:27:54 +00001904 case SNDCTL_TMR_TIMEBASE:
1905 case SNDCTL_TMR_TEMPO:
1906 case SNDCTL_TMR_SOURCE:
1907 case SNDCTL_MIDI_PRETIME:
1908 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001909 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1910 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001911 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001912 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1913 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001914 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001915 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001916 break;
1917 case SNDCTL_DSP_GETOSPACE:
1918 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001919 must_be_writable(tst,
1920 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001921 "(SIOR, audio_buf_info))", arg3,
1922 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001923 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001924 if (!VG_(is_kerror)(res) && res == 0)
1925 make_readable (arg3, sizeof(audio_buf_info));
1926 break;
1927 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001928 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001929 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001930 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001931 break;
sewardj0aa4c252002-04-27 02:20:14 +00001932
1933 /* Real Time Clock (/dev/rtc) ioctls */
sewardjfbe18b92002-05-10 00:46:59 +00001934# ifndef GLIBC_2_1
sewardj0aa4c252002-04-27 02:20:14 +00001935 case RTC_UIE_ON:
1936 case RTC_UIE_OFF:
1937 case RTC_AIE_ON:
1938 case RTC_AIE_OFF:
1939 case RTC_PIE_ON:
1940 case RTC_PIE_OFF:
1941 case RTC_IRQP_SET:
1942 KERNEL_DO_SYSCALL(tid,res);
1943 break;
1944 case RTC_RD_TIME:
1945 case RTC_ALM_READ:
1946 must_be_writable(tst, "ioctl(RTC_RD_TIME/ALM_READ)", arg3,
1947 sizeof(struct rtc_time));
1948 KERNEL_DO_SYSCALL(tid,res);
1949 if (!VG_(is_kerror) && res == 0)
1950 make_readable(arg3, sizeof(struct rtc_time));
1951 break;
1952 case RTC_ALM_SET:
1953 must_be_readable(tst, "ioctl(RTC_ALM_SET)", arg3,
1954 sizeof(struct rtc_time));
1955 KERNEL_DO_SYSCALL(tid,res);
1956 break;
1957 case RTC_IRQP_READ:
1958 must_be_writable(tst, "ioctl(RTC_IRQP_READ)", arg3,
1959 sizeof(unsigned long));
1960 KERNEL_DO_SYSCALL(tid,res);
1961 if(!VG_(is_kerror) && res == 0)
1962 make_readable(arg3, sizeof(unsigned long));
1963 break;
sewardjfbe18b92002-05-10 00:46:59 +00001964# endif /* GLIBC_2_1 */
sewardjeea0f2e2002-04-27 02:28:19 +00001965
1966 /* CD ROM stuff (??) */
1967 case CDROMSUBCHNL:
1968 must_be_readable(tst, "ioctl(CDROMSUBCHNL (cdsc_format, char))",
1969 (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format),
1970 sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
1971 must_be_writable(tst, "ioctl(CDROMSUBCHNL)", arg3,
1972 sizeof(struct cdrom_subchnl));
1973 KERNEL_DO_SYSCALL(tid,res);
1974 if (!VG_(is_kerror)(res) && res == 0)
1975 make_readable (arg3, sizeof(struct cdrom_subchnl));
1976 break;
1977 case CDROMREADTOCHDR:
1978 must_be_writable(tst, "ioctl(CDROMREADTOCHDR)", arg3,
1979 sizeof(struct cdrom_tochdr));
1980 KERNEL_DO_SYSCALL(tid,res);
1981 if (!VG_(is_kerror)(res) && res == 0)
1982 make_readable (arg3, sizeof(struct cdrom_tochdr));
1983 break;
1984 case CDROMREADTOCENTRY:
1985 must_be_readable(tst, "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
1986 (int) &(((struct cdrom_tocentry *) arg3)->cdte_format),
1987 sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
1988 must_be_readable(tst, "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
1989 (int) &(((struct cdrom_tocentry *) arg3)->cdte_track),
1990 sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
1991 must_be_writable(tst, "ioctl(CDROMREADTOCENTRY)", arg3,
1992 sizeof(struct cdrom_tocentry));
1993 KERNEL_DO_SYSCALL(tid,res);
1994 if (!VG_(is_kerror)(res) && res == 0)
1995 make_readable (arg3, sizeof(struct cdrom_tochdr));
1996 break;
1997 case CDROMPLAYMSF:
1998 must_be_readable(tst, "ioctl(CDROMPLAYMSF)", arg3,
1999 sizeof(struct cdrom_msf));
2000 KERNEL_DO_SYSCALL(tid,res);
2001 break;
sewardjde4a1d02002-03-22 01:27:54 +00002002 /* We don't have any specific information on it, so
2003 try to do something reasonable based on direction and
2004 size bits. The encoding scheme is described in
sewardja4da9372002-05-21 00:44:02 +00002005 /usr/include/asm/ioctl.h.
2006
2007 According to Simon Hausmann, _IOC_READ means the kernel
2008 writes a value to the ioctl value passed from the user
2009 space and the other way around with _IOC_WRITE. */
sewardjde4a1d02002-03-22 01:27:54 +00002010 default: {
2011 UInt dir = _IOC_DIR(arg2);
2012 UInt size = _IOC_SIZE(arg2);
2013 if (/* size == 0 || */ dir == _IOC_NONE) {
2014 VG_(message)(Vg_UserMsg,
2015 "Warning: noted but unhandled ioctl 0x%x"
2016 " with no size/direction hints",
2017 arg2);
2018 VG_(message)(Vg_UserMsg,
2019 " This could cause spurious value errors"
2020 " to appear.");
2021 VG_(message)(Vg_UserMsg,
2022 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
2023 " writing a proper wrapper." );
2024 } else {
sewardjde4a1d02002-03-22 01:27:54 +00002025 if ((dir & _IOC_WRITE) && size > 0)
sewardja4da9372002-05-21 00:44:02 +00002026 must_be_readable(tst, "ioctl(generic)", arg3, size);
2027 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00002028 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00002029 }
sewardj2e93c502002-04-12 11:12:52 +00002030 KERNEL_DO_SYSCALL(tid,res);
sewardja4da9372002-05-21 00:44:02 +00002031 if (size > 0 && (dir & _IOC_READ)
sewardjde4a1d02002-03-22 01:27:54 +00002032 && !VG_(is_kerror)(res) && res == 0)
2033 make_readable (arg3, size);
2034 break;
2035 }
2036 }
2037 break;
2038
2039 case __NR_kill: /* syscall 37 */
2040 /* int kill(pid_t pid, int sig); */
2041 if (VG_(clo_trace_syscalls))
2042 VG_(printf)("kill ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00002043 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002044 break;
2045
2046 case __NR_link: /* syscall 9 */
2047 /* int link(const char *oldpath, const char *newpath); */
2048 if (VG_(clo_trace_syscalls))
2049 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00002050 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
2051 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00002052 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002053 break;
2054
2055 case __NR_lseek: /* syscall 19 */
2056 /* off_t lseek(int fildes, off_t offset, int whence); */
2057 if (VG_(clo_trace_syscalls))
2058 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00002059 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002060 break;
2061
2062 case __NR__llseek: /* syscall 140 */
2063 /* int _llseek(unsigned int fd, unsigned long offset_high,
2064 unsigned long offset_low,
2065 loff_t * result, unsigned int whence); */
2066 if (VG_(clo_trace_syscalls))
2067 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
2068 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00002069 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00002070 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002071 if (!VG_(is_kerror)(res) && res == 0)
2072 make_readable( arg4, sizeof(loff_t) );
2073 break;
2074
2075 case __NR_lstat: /* syscall 107 */
2076 /* int lstat(const char *file_name, struct stat *buf); */
2077 if (VG_(clo_trace_syscalls))
2078 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002079 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
2080 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002081 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002082 if (!VG_(is_kerror)(res) && res == 0) {
2083 make_readable( arg2, sizeof(struct stat) );
2084 }
2085 break;
2086
2087# if defined(__NR_lstat64)
2088 case __NR_lstat64: /* syscall 196 */
2089 /* int lstat64(const char *file_name, struct stat64 *buf); */
2090 if (VG_(clo_trace_syscalls))
2091 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002092 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
2093 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002094 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002095 if (!VG_(is_kerror)(res) && res == 0) {
2096 make_readable( arg2, sizeof(struct stat64) );
2097 }
2098 break;
2099# endif
2100
2101 case __NR_mkdir: /* syscall 39 */
2102 /* int mkdir(const char *pathname, mode_t mode); */
2103 if (VG_(clo_trace_syscalls))
2104 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002105 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002106 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002107 break;
2108
2109# if defined(__NR_mmap2)
2110 case __NR_mmap2: /* syscall 192 */
2111 /* My impression is that this is exactly like __NR_mmap
2112 except that all 6 args are passed in regs, rather than in
2113 a memory-block. */
2114 /* void* mmap(void *start, size_t length, int prot,
2115 int flags, int fd, off_t offset);
2116 */
2117 {
sewardj2e93c502002-04-12 11:12:52 +00002118 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00002119 if (VG_(clo_trace_syscalls))
2120 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
2121 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00002122 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002123 /* !!! shouldn't we also be doing the symtab loading stuff as
2124 in __NR_mmap ? */
2125 if (!VG_(is_kerror)(res))
2126 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
2127 }
2128 break;
2129# endif
2130
2131 case __NR_mmap: /* syscall 90 */
2132 /* void* mmap(void *start, size_t length, int prot,
2133 int flags, int fd, off_t offset);
2134 */
2135 {
2136 Bool arg_block_readable
2137 = VG_(clo_instrument)
2138 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
2139 : True;
sewardj8c824512002-04-14 04:16:48 +00002140 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002141 if (arg_block_readable) {
2142 UInt* arg_block = (UInt*)arg1;
2143 UInt arg6;
2144 arg1 = arg_block[0];
2145 arg2 = arg_block[1];
2146 arg3 = arg_block[2];
2147 arg4 = arg_block[3];
2148 arg5 = arg_block[4];
2149 arg6 = arg_block[5];
2150 if (VG_(clo_trace_syscalls))
2151 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
2152 arg1, arg2, arg3, arg4, arg5, arg6 );
2153 }
sewardj2e93c502002-04-12 11:12:52 +00002154 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002155 if (arg_block_readable && !VG_(is_kerror)(res))
2156 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
2157 if (arg_block_readable && !VG_(is_kerror)(res)
2158 && (arg3 & PROT_EXEC)) {
2159 /* The client mmap'ed a segment with executable
2160 permissions. Tell the symbol-table loader, so that it
2161 has an opportunity to pick up more symbols if this mmap
2162 was caused by the client loading a new .so via
2163 dlopen(). This is important for debugging KDE. */
2164 VG_(read_symbols)();
2165 }
2166 }
2167
2168 break;
2169
2170 case __NR_mprotect: /* syscall 125 */
2171 /* int mprotect(const void *addr, size_t len, int prot); */
2172 /* should addr .. addr+len-1 be checked before the call? */
2173 if (VG_(clo_trace_syscalls))
2174 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00002175 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002176 if (!VG_(is_kerror)(res))
2177 approximate_mmap_permissions ( arg1, arg2, arg3 );
2178 break;
2179
2180 case __NR_munmap: /* syscall 91 */
2181 /* int munmap(void *start, size_t length); */
2182 /* should start .. start+length-1 be checked before the call? */
2183 if (VG_(clo_trace_syscalls))
2184 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00002185 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002186 if (!VG_(is_kerror)(res)) {
2187 /* Mash around start and length so that the area passed to
2188 make_noaccess() exactly covers an integral number of
2189 pages. If we don't do that, our idea of addressible
2190 memory diverges from that of the kernel's, which causes
2191 the leak detector to crash. */
sewardj18d75132002-05-16 11:06:21 +00002192 Bool munmap_exe;
sewardjde4a1d02002-03-22 01:27:54 +00002193 Addr start = arg1;
2194 Addr length = arg2;
2195 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
2196 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
2197 /*
2198 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
2199 arg1, arg2, start, length, (arg1!=start || arg2!=length)
2200 ? "CHANGE" : "");
2201 */
2202 make_noaccess( start, length );
2203 /* Tell our symbol table machinery about this, so that if
2204 this happens to be a .so being unloaded, the relevant
2205 symbols are removed too. */
sewardj18d75132002-05-16 11:06:21 +00002206 munmap_exe = VG_(symtab_notify_munmap) ( start, length );
2207 if (munmap_exe)
2208 VG_(invalidate_translations) ( start, length );
sewardjde4a1d02002-03-22 01:27:54 +00002209 }
2210 break;
2211
2212 case __NR_nanosleep: /* syscall 162 */
2213 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
2214 if (VG_(clo_trace_syscalls))
2215 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002216 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00002217 sizeof(struct timespec) );
2218 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002219 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002220 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00002221 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002222 /* Somewhat bogus ... is only written by the kernel if
2223 res == -1 && errno == EINTR. */
2224 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
2225 make_readable ( arg2, sizeof(struct timespec) );
2226 break;
2227
2228 case __NR__newselect: /* syscall 142 */
2229 /* int select(int n,
2230 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
2231 struct timeval *timeout);
2232 */
2233 if (VG_(clo_trace_syscalls))
2234 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
2235 arg1,arg2,arg3,arg4,arg5);
2236 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00002237 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00002238 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
2239 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00002240 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00002241 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
2242 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00002243 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00002244 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
2245 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00002246 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002247 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00002248 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002249 break;
2250
2251 case __NR_open: /* syscall 5 */
2252 /* int open(const char *pathname, int flags); */
2253 if (VG_(clo_trace_syscalls))
2254 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002255 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002256 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002257 if (VG_(clo_trace_syscalls))
2258 VG_(printf)("%d\n",res);
2259 break;
2260
2261 case __NR_pipe: /* syscall 42 */
2262 /* int pipe(int filedes[2]); */
2263 if (VG_(clo_trace_syscalls))
2264 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002265 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002266 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002267 if (!VG_(is_kerror)(res))
2268 make_readable ( arg1, 2*sizeof(int) );
2269 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00002270 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
2271 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00002272 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
2273 break;
2274
2275 case __NR_poll: /* syscall 168 */
2276 /* struct pollfd {
2277 int fd; -- file descriptor
2278 short events; -- requested events
2279 short revents; -- returned events
2280 };
2281 int poll(struct pollfd *ufds, unsigned int nfds,
2282 int timeout)
2283 */
2284 if (VG_(clo_trace_syscalls))
sewardja4da9372002-05-21 00:44:02 +00002285 VG_(printf)("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
sewardjde4a1d02002-03-22 01:27:54 +00002286 /* In fact some parts of this struct should be readable too.
2287 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00002288 must_be_writable( tst, "poll(ufds)",
2289 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00002290 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002291 if (!VG_(is_kerror)(res) && res > 0) {
2292 Int i;
2293 struct pollfd * arr = (struct pollfd *)arg1;
2294 for (i = 0; i < arg2; i++)
2295 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
2296 }
2297 break;
2298
sewardjde4a1d02002-03-22 01:27:54 +00002299 case __NR_readlink: /* syscall 85 */
2300 /* int readlink(const char *path, char *buf, size_t bufsiz); */
2301 if (VG_(clo_trace_syscalls))
2302 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002303 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
2304 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002305 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002306 if (!VG_(is_kerror)(res) && res > 0) {
2307 make_readable ( arg2, res );
2308 }
2309 break;
2310
2311 case __NR_readv: { /* syscall 145 */
2312 /* int readv(int fd, const struct iovec * vector, size_t count); */
2313 UInt i;
2314 struct iovec * vec;
2315 if (VG_(clo_trace_syscalls))
2316 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002317 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002318 arg2, arg3 * sizeof(struct iovec) );
2319 /* ToDo: don't do any of the following if the vector is invalid */
2320 vec = (struct iovec *)arg2;
2321 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002322 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002323 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002324 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002325 if (!VG_(is_kerror)(res) && res > 0) {
2326 /* res holds the number of bytes read. */
2327 for (i = 0; i < arg3; i++) {
2328 Int nReadThisBuf = vec[i].iov_len;
2329 if (nReadThisBuf > res) nReadThisBuf = res;
2330 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
2331 res -= nReadThisBuf;
2332 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
2333 }
2334 }
2335 break;
2336 }
2337
2338 case __NR_rename: /* syscall 38 */
2339 /* int rename(const char *oldpath, const char *newpath); */
2340 if (VG_(clo_trace_syscalls))
2341 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00002342 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
2343 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002344 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002345 break;
2346
2347 case __NR_rmdir: /* syscall 40 */
2348 /* int rmdir(const char *pathname); */
2349 if (VG_(clo_trace_syscalls))
2350 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002351 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002352 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002353 break;
2354
sewardja4d4e482002-05-03 21:18:11 +00002355 case __NR_sched_setparam: /* syscall 154 */
2356 /* int sched_setparam(pid_t pid, const struct sched_param *p); */
sewardj705d3cb2002-05-23 13:13:12 +00002357 if (VG_(clo_trace_syscalls))
sewardja4d4e482002-05-03 21:18:11 +00002358 VG_(printf)("sched_setparam ( %d, %p )\n", arg1, arg2 );
2359 must_be_readable( tst, "sched_setparam(ptr)",
2360 arg2, sizeof(struct sched_param) );
2361 KERNEL_DO_SYSCALL(tid,res);
2362 if (!VG_(is_kerror)(res))
2363 make_readable( arg2, sizeof(struct sched_param) );
2364 break;
2365
2366 case __NR_sched_getparam: /* syscall 155 */
2367 /* int sched_getparam(pid_t pid, struct sched_param *p); */
sewardj705d3cb2002-05-23 13:13:12 +00002368 if (VG_(clo_trace_syscalls))
sewardja4d4e482002-05-03 21:18:11 +00002369 VG_(printf)("sched_getparam ( %d, %p )\n", arg1, arg2 );
2370 must_be_writable( tst, "sched_getparam(ptr)",
2371 arg2, sizeof(struct sched_param) );
2372 KERNEL_DO_SYSCALL(tid,res);
2373 if (!VG_(is_kerror)(res))
2374 make_readable( arg2, sizeof(struct sched_param) );
2375 break;
2376
2377 case __NR_sched_yield: /* syscall 158 */
2378 /* int sched_yield(void); */
sewardj705d3cb2002-05-23 13:13:12 +00002379 if (VG_(clo_trace_syscalls))
sewardja4d4e482002-05-03 21:18:11 +00002380 VG_(printf)("sched_yield ()\n" );
sewardj2e93c502002-04-12 11:12:52 +00002381 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002382 break;
2383
2384 case __NR_select: /* syscall 82 */
2385 /* struct sel_arg_struct {
2386 unsigned long n;
2387 fd_set *inp, *outp, *exp;
2388 struct timeval *tvp;
2389 };
2390 int old_select(struct sel_arg_struct *arg);
2391 */
2392 {
2393 Bool arg_block_readable
2394 = VG_(clo_instrument)
2395 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
2396 : True;
sewardj8c824512002-04-14 04:16:48 +00002397 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002398 if (arg_block_readable) {
2399 UInt* arg_struct = (UInt*)arg1;
2400 arg1 = arg_struct[0];
2401 arg2 = arg_struct[1];
2402 arg3 = arg_struct[2];
2403 arg4 = arg_struct[3];
2404 arg5 = arg_struct[4];
2405
2406 if (VG_(clo_trace_syscalls))
2407 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2408 arg1,arg2,arg3,arg4,arg5);
2409 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002410 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002411 arg1/8 /* __FD_SETSIZE/8 */ );
2412 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002413 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002414 arg1/8 /* __FD_SETSIZE/8 */ );
2415 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002416 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002417 arg1/8 /* __FD_SETSIZE/8 */ );
2418 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002419 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002420 sizeof(struct timeval) );
2421 }
2422 }
sewardj2e93c502002-04-12 11:12:52 +00002423 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002424 break;
2425
2426 case __NR_setitimer: /* syscall 104 */
2427 /* setitimer(int which, const struct itimerval *value,
2428 struct itimerval *ovalue); */
2429 if (VG_(clo_trace_syscalls))
2430 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj55314d42002-05-23 17:14:54 +00002431 if (arg2 != (Addr)NULL)
2432 must_be_readable(tst, "setitimer(value)",
2433 arg2, sizeof(struct itimerval) );
sewardjde4a1d02002-03-22 01:27:54 +00002434 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002435 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002436 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002437 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002438 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2439 make_readable(arg3, sizeof(struct itimerval));
2440 }
2441 break;
2442
2443# if defined(__NR_setfsgid32)
2444 case __NR_setfsgid32: /* syscall 216 */
2445 /* int setfsgid(uid_t fsgid); */
2446 if (VG_(clo_trace_syscalls))
2447 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002448 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002449 break;
2450# endif
2451
2452# if defined(__NR_setgid32)
2453 case __NR_setgid32: /* syscall 214 */
2454# endif
2455 case __NR_setgid: /* syscall 46 */
2456 /* int setgid(gid_t gid); */
2457 if (VG_(clo_trace_syscalls))
2458 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002459 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002460 break;
2461
2462 case __NR_setsid: /* syscall 66 */
2463 /* pid_t setsid(void); */
2464 if (VG_(clo_trace_syscalls))
2465 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002466 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002467 break;
2468
2469# if defined(__NR_setgroups32)
2470 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002471# endif
2472 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002473 /* int setgroups(size_t size, const gid_t *list); */
2474 if (VG_(clo_trace_syscalls))
2475 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2476 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002477 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002478 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002479 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002480 break;
sewardjde4a1d02002-03-22 01:27:54 +00002481
2482 case __NR_setpgid: /* syscall 57 */
2483 /* int setpgid(pid_t pid, pid_t pgid); */
2484 if (VG_(clo_trace_syscalls))
2485 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002486 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002487 break;
2488
2489# if defined(__NR_setregid32)
2490 case __NR_setregid32: /* syscall 204 */
2491 /* int setregid(gid_t rgid, gid_t egid); */
2492 if (VG_(clo_trace_syscalls))
2493 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002494 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002495 break;
2496# endif
2497
2498# if defined(__NR_setresuid32)
2499 case __NR_setresuid32: /* syscall 208 */
2500 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2501 if (VG_(clo_trace_syscalls))
2502 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002503 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002504 break;
2505# endif
2506
2507# if defined(__NR_setreuid32)
2508 case __NR_setreuid32: /* syscall 203 */
2509# endif
2510 case __NR_setreuid: /* syscall 70 */
2511 /* int setreuid(uid_t ruid, uid_t euid); */
2512 if (VG_(clo_trace_syscalls))
2513 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002514 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002515 break;
2516
2517 case __NR_setrlimit: /* syscall 75 */
2518 /* int setrlimit (int resource, const struct rlimit *rlim); */
2519 if (VG_(clo_trace_syscalls))
2520 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002521 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002522 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002523 break;
2524
2525# if defined(__NR_setuid32)
2526 case __NR_setuid32: /* syscall 213 */
2527# endif
2528 case __NR_setuid: /* syscall 23 */
2529 /* int setuid(uid_t uid); */
2530 if (VG_(clo_trace_syscalls))
2531 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002532 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002533 break;
2534
2535 case __NR_socketcall: /* syscall 102 */
2536 /* int socketcall(int call, unsigned long *args); */
2537 if (VG_(clo_trace_syscalls))
2538 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2539 switch (arg1 /* request */) {
2540
2541 case SYS_SOCKETPAIR:
2542 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002543 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002544 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002545 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002546 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002547 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002548 if (!VG_(is_kerror)(res))
2549 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2550 break;
2551
2552 case SYS_SOCKET:
2553 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002554 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002555 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002556 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002557 break;
2558
2559 case SYS_BIND:
2560 /* int bind(int sockfd, struct sockaddr *my_addr,
2561 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002562 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002563 arg2, 3*sizeof(Addr) );
sewardjc483e8f2002-05-03 21:01:35 +00002564 must_be_readable_sockaddr( tst, "socketcall.bind(my_addr.%s)",
2565 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
sewardj2e93c502002-04-12 11:12:52 +00002566 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002567 break;
sewardjc483e8f2002-05-03 21:01:35 +00002568
sewardjde4a1d02002-03-22 01:27:54 +00002569 case SYS_LISTEN:
2570 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002571 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002572 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002573 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002574 break;
2575
2576 case SYS_ACCEPT: {
2577 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2578 Addr addr;
2579 Addr p_addrlen;
2580 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002581 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002582 arg2, 3*sizeof(Addr) );
2583 addr = ((UInt*)arg2)[1];
2584 p_addrlen = ((UInt*)arg2)[2];
2585 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002586 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002587 p_addrlen, sizeof(int) );
2588 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002589 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002590 addr, addrlen_in );
2591 }
sewardj2e93c502002-04-12 11:12:52 +00002592 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002593 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2594 addrlen_out = safe_dereference( p_addrlen, 0 );
2595 if (addrlen_out > 0)
2596 make_readable( addr, addrlen_out );
2597 }
2598 break;
2599 }
2600
2601 case SYS_SENDTO:
2602 /* int sendto(int s, const void *msg, int len,
2603 unsigned int flags,
2604 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002605 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002606 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002607 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002608 ((UInt*)arg2)[1], /* msg */
2609 ((UInt*)arg2)[2] /* len */ );
sewardjc483e8f2002-05-03 21:01:35 +00002610 must_be_readable_sockaddr( tst, "socketcall.sendto(to.%s)",
2611 (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
sewardj2e93c502002-04-12 11:12:52 +00002612 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002613 break;
2614
2615 case SYS_SEND:
2616 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002617 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002618 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002619 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002620 ((UInt*)arg2)[1], /* msg */
2621 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002622 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002623 break;
2624
2625 case SYS_RECVFROM:
2626 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2627 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002628 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002629 arg2, 6*sizeof(Addr) );
2630 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002631 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002632 ((UInt*)arg2)[5] /* fromlen */,
2633 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002634 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002635 ((UInt*)arg2)[4], /*from*/
2636 safe_dereference( (Addr)
2637 ((UInt*)arg2)[5], 0 ) );
2638 }
sewardj8c824512002-04-14 04:16:48 +00002639 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002640 ((UInt*)arg2)[1], /* buf */
2641 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002642 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002643 if (!VG_(is_kerror)(res) && res >= 0) {
2644 make_readable( ((UInt*)arg2)[1], /* buf */
2645 ((UInt*)arg2)[2] /* len */ );
2646 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2647 make_readable(
2648 ((UInt*)arg2)[4], /*from*/
2649 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2650 }
2651 }
2652 /* phew! */
2653 break;
2654
2655 case SYS_RECV:
2656 /* int recv(int s, void *buf, int len, unsigned int flags); */
2657 /* man 2 recv says:
2658 The recv call is normally used only on a connected socket
2659 (see connect(2)) and is identical to recvfrom with a NULL
2660 from parameter.
2661 */
sewardj8c824512002-04-14 04:16:48 +00002662 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002663 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002664 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002665 ((UInt*)arg2)[1], /* buf */
2666 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002667 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002668 if (!VG_(is_kerror)(res) && res >= 0
2669 && ((UInt*)arg2)[1] != (UInt)NULL) {
2670 make_readable( ((UInt*)arg2)[1], /* buf */
2671 ((UInt*)arg2)[2] /* len */ );
2672 }
2673 break;
2674
sewardjc483e8f2002-05-03 21:01:35 +00002675 case SYS_CONNECT:
sewardjde4a1d02002-03-22 01:27:54 +00002676 /* int connect(int sockfd,
2677 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002678 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002679 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002680 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002681 ((UInt*)arg2)[1], /* serv_addr */
2682 sizeof (sa_family_t));
sewardjc483e8f2002-05-03 21:01:35 +00002683 must_be_readable_sockaddr( tst,
2684 "socketcall.connect(serv_addr.%s)",
2685 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
sewardj2e93c502002-04-12 11:12:52 +00002686 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002687 break;
sewardjde4a1d02002-03-22 01:27:54 +00002688
2689 case SYS_SETSOCKOPT:
2690 /* int setsockopt(int s, int level, int optname,
2691 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002692 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002693 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002694 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002695 ((UInt*)arg2)[3], /* optval */
2696 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002697 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002698 break;
2699
2700 case SYS_GETSOCKOPT:
2701 /* int setsockopt(int s, int level, int optname,
2702 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002703 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002704 arg2, 5*sizeof(Addr) );
2705 {
2706 Addr optval_p = ((UInt*)arg2)[3];
2707 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002708 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002709 UInt optlen_after;
2710 UInt optlen = safe_dereference ( optlen_p, 0 );
2711 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002712 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002713 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002714 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002715 optlen_after = safe_dereference ( optlen_p, 0 );
2716 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2717 make_readable( optval_p, optlen_after );
2718 }
2719 break;
2720
2721 case SYS_GETSOCKNAME:
2722 /* int getsockname(int s, struct sockaddr* name,
2723 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002724 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002725 arg2, 3*sizeof(Addr) );
2726 {
2727 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2728 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002729 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002730 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002731 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002732 if (!VG_(is_kerror)(res)) {
2733 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2734 if (namelen > 0
2735 && ((UInt*)arg2)[1] != (UInt)NULL)
2736 make_readable( ((UInt*)arg2)[1], namelen );
2737 }
2738 }
2739 break;
2740
2741 case SYS_GETPEERNAME:
2742 /* int getpeername(int s, struct sockaddr* name,
2743 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002744 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002745 arg2, 3*sizeof(Addr) );
2746 {
2747 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2748 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002749 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002750 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002751 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002752 if (!VG_(is_kerror)(res)) {
2753 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2754 if (namelen > 0
2755 && ((UInt*)arg2)[1] != (UInt)NULL)
2756 make_readable( ((UInt*)arg2)[1], namelen );
2757 }
2758 }
2759 break;
2760
2761 case SYS_SHUTDOWN:
2762 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002763 must_be_readable( tst, "socketcall.shutdown(args)",
2764 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002765 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002766 break;
2767
2768 case SYS_SENDMSG:
2769 {
2770 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2771
2772 /* this causes warnings, and I don't get why. glibc bug?
2773 * (after all it's glibc providing the arguments array)
2774 must_be_readable( "socketcall.sendmsg(args)",
2775 arg2, 3*sizeof(Addr) );
2776 */
2777
2778 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002779 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002780
sewardj2e93c502002-04-12 11:12:52 +00002781 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002782 break;
2783 }
2784
2785 case SYS_RECVMSG:
2786 {
2787 /* int recvmsg(int s, struct msghdr *msg, int flags); */
2788
2789 /* this causes warnings, and I don't get why. glibc bug?
2790 * (after all it's glibc providing the arguments array)
2791 must_be_readable( "socketcall.recvmsg(args)",
2792 arg2, 3*sizeof(Addr) );
2793 */
2794
2795 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002796 msghdr_foreachfield ( tst, msg, must_be_writable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002797
sewardj2e93c502002-04-12 11:12:52 +00002798 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002799
2800 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002801 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002802
2803 break;
2804 }
2805
2806 default:
2807 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2808 VG_(panic)("... bye!\n");
2809 break; /*NOTREACHED*/
2810 }
2811 break;
2812
2813 case __NR_stat: /* syscall 106 */
2814 /* int stat(const char *file_name, struct stat *buf); */
2815 if (VG_(clo_trace_syscalls))
2816 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002817 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2818 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002819 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002820 if (!VG_(is_kerror)(res))
2821 make_readable( arg2, sizeof(struct stat) );
2822 break;
2823
2824 case __NR_statfs: /* syscall 99 */
2825 /* int statfs(const char *path, struct statfs *buf); */
2826 if (VG_(clo_trace_syscalls))
2827 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002828 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2829 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002830 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002831 if (!VG_(is_kerror)(res))
2832 make_readable( arg2, sizeof(struct statfs) );
2833 break;
2834
2835 case __NR_symlink: /* syscall 83 */
2836 /* int symlink(const char *oldpath, const char *newpath); */
2837 if (VG_(clo_trace_syscalls))
2838 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002839 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2840 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002841 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002842 break;
2843
2844# if defined(__NR_stat64)
2845 case __NR_stat64: /* syscall 195 */
2846 /* int stat64(const char *file_name, struct stat64 *buf); */
2847 if (VG_(clo_trace_syscalls))
2848 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002849 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2850 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002851 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002852 if (!VG_(is_kerror)(res))
2853 make_readable( arg2, sizeof(struct stat64) );
2854 break;
2855# endif
2856
2857# if defined(__NR_fstat64)
2858 case __NR_fstat64: /* syscall 197 */
2859 /* int fstat64(int filedes, struct stat64 *buf); */
2860 if (VG_(clo_trace_syscalls))
2861 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002862 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002863 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002864 if (!VG_(is_kerror)(res))
2865 make_readable( arg2, sizeof(struct stat64) );
2866 break;
2867# endif
2868
2869 case __NR_sysinfo: /* syscall 116 */
2870 /* int sysinfo(struct sysinfo *info); */
2871 if (VG_(clo_trace_syscalls))
2872 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002873 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002874 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002875 if (!VG_(is_kerror)(res))
2876 make_readable( arg1, sizeof(struct sysinfo) );
2877 break;
2878
2879 case __NR_time: /* syscall 13 */
2880 /* time_t time(time_t *t); */
2881 if (VG_(clo_trace_syscalls))
2882 VG_(printf)("time ( %p )\n",arg1);
2883 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002884 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002885 }
sewardj2e93c502002-04-12 11:12:52 +00002886 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002887 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2888 make_readable( arg1, sizeof(time_t) );
2889 }
2890 break;
2891
2892 case __NR_times: /* syscall 43 */
2893 /* clock_t times(struct tms *buf); */
2894 if (VG_(clo_trace_syscalls))
2895 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002896 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002897 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002898 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2899 make_readable( arg1, sizeof(struct tms) );
2900 }
2901 break;
2902
2903 case __NR_truncate: /* syscall 92 */
2904 /* int truncate(const char *path, size_t length); */
2905 if (VG_(clo_trace_syscalls))
2906 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002907 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002908 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002909 break;
2910
2911 case __NR_umask: /* syscall 60 */
2912 /* mode_t umask(mode_t mask); */
2913 if (VG_(clo_trace_syscalls))
2914 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002915 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002916 break;
2917
2918 case __NR_unlink: /* syscall 10 */
2919 /* int unlink(const char *pathname) */
2920 if (VG_(clo_trace_syscalls))
2921 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002922 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002923 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002924 break;
2925
2926 case __NR_uname: /* syscall 122 */
2927 /* int uname(struct utsname *buf); */
2928 if (VG_(clo_trace_syscalls))
2929 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002930 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002931 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002932 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2933 make_readable( arg1, sizeof(struct utsname) );
2934 }
2935 break;
2936
2937 case __NR_utime: /* syscall 30 */
2938 /* int utime(const char *filename, struct utimbuf *buf); */
2939 if (VG_(clo_trace_syscalls))
2940 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002941 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00002942 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002943 must_be_readable( tst, "utime(buf)", arg2,
2944 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00002945 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002946 break;
2947
2948 case __NR_wait4: /* syscall 114 */
2949 /* pid_t wait4(pid_t pid, int *status, int options,
2950 struct rusage *rusage) */
2951 if (VG_(clo_trace_syscalls))
2952 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
2953 arg1,arg2,arg3,arg4);
2954 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002955 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00002956 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002957 must_be_writable( tst, "wait4(rusage)", arg4,
2958 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00002959 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002960 if (!VG_(is_kerror)(res)) {
2961 if (arg2 != (Addr)NULL)
2962 make_readable( arg2, sizeof(int) );
2963 if (arg4 != (Addr)NULL)
2964 make_readable( arg4, sizeof(struct rusage) );
2965 }
2966 break;
2967
sewardjde4a1d02002-03-22 01:27:54 +00002968 case __NR_writev: { /* syscall 146 */
2969 /* int writev(int fd, const struct iovec * vector, size_t count); */
2970 UInt i;
2971 struct iovec * vec;
2972 if (VG_(clo_trace_syscalls))
2973 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002974 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002975 arg2, arg3 * sizeof(struct iovec) );
2976 /* ToDo: don't do any of the following if the vector is invalid */
2977 vec = (struct iovec *)arg2;
2978 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002979 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002980 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002981 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002982 break;
2983 }
2984
2985 /*-------------------------- SIGNALS --------------------------*/
2986
2987 /* Normally set to 1, so that Valgrind's signal-simulation machinery
2988 is engaged. Sometimes useful to disable (set to 0), for
2989 debugging purposes, to make clients more deterministic. */
2990# define SIGNAL_SIMULATION 1
2991
sewardj2342c972002-05-22 23:34:20 +00002992 case __NR_sigaltstack: /* syscall 186 */
2993 /* int sigaltstack(const stack_t *ss, stack_t *oss); */
2994 if (VG_(clo_trace_syscalls))
2995 VG_(printf)("sigaltstack ( %p, %p )\n",arg1,arg2);
2996 if (arg1 != (UInt)NULL) {
2997 must_be_readable( tst, "sigaltstack(ss)",
2998 arg1, sizeof(vki_kstack_t) );
2999 }
3000 if (arg2 != (UInt)NULL) {
3001 must_be_writable( tst, "sigaltstack(ss)",
3002 arg1, sizeof(vki_kstack_t) );
3003 }
3004# if SIGNAL_SIMULATION
3005 VG_(do__NR_sigaltstack) (tid);
3006 res = tst->m_eax;
3007# else
3008 KERNEL_DO_SYSCALL(tid,res);
3009# endif
3010 if (!VG_(is_kerror)(res) && res == 0 && arg2 != (UInt)NULL)
3011 make_readable( arg2, sizeof(vki_kstack_t));
3012 break;
3013
sewardjde4a1d02002-03-22 01:27:54 +00003014 case __NR_rt_sigaction:
3015 case __NR_sigaction:
3016 /* int sigaction(int signum, struct k_sigaction *act,
3017 struct k_sigaction *oldact); */
3018 if (VG_(clo_trace_syscalls))
3019 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
3020 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003021 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00003022 arg2, sizeof(vki_ksigaction));
3023 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003024 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00003025 arg3, sizeof(vki_ksigaction));
3026 /* We do this one ourselves! */
3027# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00003028 VG_(do__NR_sigaction)(tid);
3029 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00003030# else
3031 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00003032 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00003033# endif
3034 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
3035 make_readable( arg3, sizeof(vki_ksigaction));
3036 break;
3037
3038 case __NR_rt_sigprocmask:
3039 case __NR_sigprocmask:
3040 /* int sigprocmask(int how, k_sigset_t *set,
3041 k_sigset_t *oldset); */
3042 if (VG_(clo_trace_syscalls))
3043 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
3044 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003045 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00003046 arg2, sizeof(vki_ksigset_t));
3047 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003048 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00003049 arg3, sizeof(vki_ksigset_t));
sewardj018f7622002-05-15 21:13:39 +00003050# if SIGNAL_SIMULATION
3051 VG_(do__NR_sigprocmask) ( tid,
3052 arg1 /*how*/,
3053 (vki_ksigset_t*) arg2,
3054 (vki_ksigset_t*) arg3 );
3055 res = tst->m_eax;
3056# else
sewardj2e93c502002-04-12 11:12:52 +00003057 KERNEL_DO_SYSCALL(tid,res);
sewardj018f7622002-05-15 21:13:39 +00003058# endif
sewardjde4a1d02002-03-22 01:27:54 +00003059 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
3060 make_readable( arg3, sizeof(vki_ksigset_t));
sewardjde4a1d02002-03-22 01:27:54 +00003061 break;
3062
3063 default:
3064 VG_(message)
3065 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
3066 VG_(message)
3067 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
3068 VG_(message)
3069 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
3070 VG_(unimplemented)("no wrapper for the above system call");
3071 vg_assert(3+3 == 7);
3072 break; /*NOTREACHED*/
3073 }
3074
sewardjde4a1d02002-03-22 01:27:54 +00003075 /* { void zzzmemscan(void); zzzmemscan(); } */
3076
sewardj126a41f2002-05-07 23:45:03 +00003077 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardjde4a1d02002-03-22 01:27:54 +00003078 sane_before_call = False;
3079
3080 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00003081 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00003082 VG_(message)(Vg_DebugMsg,
3083 "probable sanity check failure for syscall number %d\n",
3084 syscallno );
3085 VG_(panic)("aborting due to the above ... bye!");
3086 }
3087
3088 VGP_POPCC;
3089}
3090
3091
sewardj2e93c502002-04-12 11:12:52 +00003092
3093/* Perform pre- and post- actions for a blocking syscall, but do not
3094 do the syscall itself. If res is NULL, the pre-syscall actions are
3095 to be performed. If res is non-NULL, the post-syscall actions are
3096 to be performed, and *res is assumed to hold the result of the
3097 syscall. This slightly strange scheme makes it impossible to
3098 mistakenly use the value of *res in the pre-syscall actions.
3099
3100 This doesn't actually do the syscall itself, it is important to
3101 observe.
3102
3103 Because %eax is used both for the syscall number before the call
3104 and the result value afterwards, we can't reliably use it to get
3105 the syscall number. So the caller has to pass it explicitly.
3106*/
sewardj8c824512002-04-14 04:16:48 +00003107void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00003108 Int syscallno,
3109 Int* /*IN*/ res )
3110{
sewardj018f7622002-05-15 21:13:39 +00003111 ThreadState* tst;
3112 Bool sane_before_post, sane_after_post;
3113 UInt arg1, arg2, arg3;
3114
sewardj2e93c502002-04-12 11:12:52 +00003115 VGP_PUSHCC(VgpSyscall);
3116
sewardj018f7622002-05-15 21:13:39 +00003117 vg_assert(VG_(is_valid_tid)(tid));
3118 sane_before_post = True;
3119 sane_after_post = True;
3120 tst = & VG_(threads)[tid];
3121 arg1 = tst->m_ebx;
3122 arg2 = tst->m_ecx;
3123 arg3 = tst->m_edx;
3124 /*
3125 arg4 = tst->m_esi;
3126 arg5 = tst->m_edi;
3127 */
3128
sewardj2e93c502002-04-12 11:12:52 +00003129 if (res != NULL
sewardj126a41f2002-05-07 23:45:03 +00003130 && ! VG_(first_and_last_secondaries_look_plausible)())
sewardj2e93c502002-04-12 11:12:52 +00003131 sane_before_post = False;
3132
3133 switch (syscallno) {
3134
3135 case __NR_read: /* syscall 3 */
3136 /* size_t read(int fd, void *buf, size_t count); */
3137 if (res == NULL) {
3138 /* PRE */
3139 if (VG_(clo_trace_syscalls))
3140 VG_(printf)(
3141 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
3142 VG_(getpid)(), tid,
3143 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00003144 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00003145 } else {
3146 /* POST */
3147 if (VG_(clo_trace_syscalls))
3148 VG_(printf)(
3149 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
3150 VG_(getpid)(), tid,
3151 arg1, arg2, arg3, *res);
3152 if (!VG_(is_kerror)(*res) && *res > 0) {
3153 make_readable( arg2, *res );
3154 }
3155 }
3156 break;
3157
3158 case __NR_write: /* syscall 4 */
3159 /* size_t write(int fd, const void *buf, size_t count); */
3160 if (res == NULL) {
3161 /* PRE */
3162 if (VG_(clo_trace_syscalls))
3163 VG_(printf)(
3164 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
3165 VG_(getpid)(), tid,
3166 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00003167 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00003168 } else {
3169 /* POST */
3170 if (VG_(clo_trace_syscalls))
3171 VG_(printf)(
3172 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
3173 VG_(getpid)(), tid,
3174 arg1, arg2, arg3, *res);
3175 }
3176 break;
3177
3178 default:
3179 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
3180 syscallno);
3181 VG_(panic)("check_known_blocking_syscall");
3182 /*NOTREACHED*/
3183 break;
3184 }
3185
3186 if (res != NULL) { /* only check after syscall */
sewardj126a41f2002-05-07 23:45:03 +00003187 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardj2e93c502002-04-12 11:12:52 +00003188 sane_after_post = False;
3189
3190 if (sane_before_post && (!sane_after_post)) {
3191 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
3192 VG_(message)(Vg_DebugMsg,
3193 "probable sanity check failure for syscall number %d\n",
3194 syscallno );
3195 VG_(panic)("aborting due to the above ... bye!");
3196 }
3197 }
3198
3199 VGP_POPCC;
3200}
3201
3202
sewardjde4a1d02002-03-22 01:27:54 +00003203/*--------------------------------------------------------------------*/
3204/*--- end vg_syscall_mem.c ---*/
3205/*--------------------------------------------------------------------*/