blob: bdd3152d8ef02afe6b06f411e9ea24f205644a05 [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_sigaltstack:
403 VG_(unimplemented)
404 ("client signals on alternative stack (SA_ONSTACK)");
405 break;
406
407 case __NR_clone:
408 VG_(unimplemented)
sewardj827d95b2002-04-16 02:09:31 +0000409 ("clone(): not supported by Valgrind.\n "
410 "We do now support programs linked against\n "
411 "libpthread.so, though. Re-run with -v and ensure that\n "
412 "you are picking up Valgrind's implementation of libpthread.so.");
sewardjde4a1d02002-03-22 01:27:54 +0000413 break;
414
415# if defined(__NR_modify_ldt)
416 case __NR_modify_ldt:
sewardjcfc39b22002-05-08 01:58:18 +0000417 VG_(nvidia_moan)();
sewardjde4a1d02002-03-22 01:27:54 +0000418 VG_(unimplemented)
sewardjcfc39b22002-05-08 01:58:18 +0000419 ("modify_ldt(): I (JRS) haven't investigated this yet; sorry.");
sewardjde4a1d02002-03-22 01:27:54 +0000420 break;
421# endif
422
sewardj73f1f072002-03-29 14:22:46 +0000423 /* !!!!!!!!!! New, untested syscalls !!!!!!!!!!!!!!!!!!!!! */
424
sewardj0ff15782002-05-18 13:24:24 +0000425# if defined(__NR_getpmsg) /* syscall 188 */
426 case __NR_getpmsg:
427 {
428 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
429 /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
430 int *bandp, int *flagsp); */
431 struct strbuf {
432 int maxlen; /* no. of bytes in buffer */
433 int len; /* no. of bytes returned */
434 caddr_t buf; /* pointer to data */
435 };
436 struct strbuf *ctrl;
437 struct strbuf *data;
438 if (VG_(clo_trace_syscalls))
439 VG_(printf)("getpmsg ( %d, %p, %p, %p, %p )\n",
440 arg1,arg2,arg3,arg4,arg5);
441 ctrl = (struct strbuf *)arg2;
442 data = (struct strbuf *)arg3;
443 if (ctrl && ctrl->maxlen > 0)
444 must_be_writable(tst, "getpmsg(ctrl)",
445 (UInt)ctrl->buf, ctrl->maxlen);
446 if (data && data->maxlen > 0)
447 must_be_writable(tst, "getpmsg(data)",
448 (UInt)data->buf, data->maxlen);
449 if (arg4)
450 must_be_writable(tst, "getpmsg(bandp)",
451 (UInt)arg4, sizeof(int));
452 if (arg5)
453 must_be_writable(tst, "getpmsg(flagsp)",
454 (UInt)arg5, sizeof(int));
455 KERNEL_DO_SYSCALL(tid,res);
456 if (!VG_(is_kerror)(res) && res == 0 && ctrl && ctrl->len > 0) {
457 make_readable( (UInt)ctrl->buf, ctrl->len);
458 }
459 if (!VG_(is_kerror)(res) && res == 0 && data && data->len > 0) {
460 make_readable( (UInt)data->buf, data->len);
461 }
462 }
463 break;
464# endif
465
466
467# if defined(__NR_putpmsg) /* syscall 189 */
468 case __NR_putpmsg:
469 {
470 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
471 /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
472 int band, int flags); */
473 struct strbuf {
474 int maxlen; /* no. of bytes in buffer */
475 int len; /* no. of bytes returned */
476 caddr_t buf; /* pointer to data */
477 };
478 struct strbuf *ctrl;
479 struct strbuf *data;
480 if (VG_(clo_trace_syscalls))
481 VG_(printf)("putpmsg ( %d, %p, %p, %d, %d )\n",
482 arg1,arg2,arg3,arg4,arg5);
483 ctrl = (struct strbuf *)arg2;
484 data = (struct strbuf *)arg3;
485 if (ctrl && ctrl->len > 0)
486 must_be_readable(tst, "putpmsg(ctrl)",
487 (UInt)ctrl->buf, ctrl->len);
488 if (data && data->len > 0)
489 must_be_readable(tst, "putpmsg(data)",
490 (UInt)data->buf, data->len);
491 KERNEL_DO_SYSCALL(tid,res);
492 }
493 break;
494# endif
495
sewardj9e631f72002-05-18 11:01:06 +0000496 case __NR_getitimer: /* syscall 105 */
497 /* int getitimer(int which, struct itimerval *value); */
498 if (VG_(clo_trace_syscalls))
499 VG_(printf)("getitimer ( %d, %p )\n", arg1, arg2);
500 must_be_writable( tst, "getitimer(timer)", arg2,
501 sizeof(struct itimerval) );
502 KERNEL_DO_SYSCALL(tid,res);
503 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL) {
504 make_readable(arg2, sizeof(struct itimerval));
505 }
506 break;
507
sewardjd354bb32002-05-10 22:58:14 +0000508# if defined(__NR_syslog)
509 case __NR_syslog: /* syscall 103 */
510 /* int syslog(int type, char *bufp, int len); */
511 if (VG_(clo_trace_syscalls))
512 VG_(printf)("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
513 switch(arg1) {
514 case 2: case 3: case 4:
515 must_be_writable( tst, "syslog(buf)", arg2, arg3);
516 break;
517 default:
518 break;
519 }
520 KERNEL_DO_SYSCALL(tid, res);
521 if (!VG_(is_kerror)(res)) {
522 switch (arg1) {
523 case 2: case 3: case 4:
524 make_readable( arg2, arg3 );
525 break;
526 default:
527 break;
528 }
529 }
530 break;
531# endif
532
sewardjf4afb002002-05-10 21:01:34 +0000533 case __NR_personality: /* syscall 136 */
sewardjd354bb32002-05-10 22:58:14 +0000534 /* int personality(unsigned long persona); */
sewardjf4afb002002-05-10 21:01:34 +0000535 if (VG_(clo_trace_syscalls))
536 VG_(printf)("personality ( %d )\n", arg1);
537 KERNEL_DO_SYSCALL(tid,res);
538 break;
539
sewardjfb617112002-05-03 21:07:55 +0000540 case __NR_chroot: /* syscall 61 */
541 /* int chroot(const char *path); */
542 if (VG_(clo_trace_syscalls))
543 VG_(printf)("chroot ( %p )\n", arg1);
544 must_be_readable_asciiz( tst, "chroot(path)", arg1 );
545 KERNEL_DO_SYSCALL(tid,res);
546 break;
547
sewardj6e435c02002-04-24 02:24:44 +0000548# if defined(__NR_madvise)
549 case __NR_madvise: /* syscall 219 */
550 /* int madvise(void *start, size_t length, int advice ); */
551 if (VG_(clo_trace_syscalls))
552 VG_(printf)("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
553 KERNEL_DO_SYSCALL(tid,res);
554 break;
555# endif
556
sewardj6af4b5d2002-04-16 04:40:49 +0000557# if defined(__NR_mremap)
558 /* Is this really right? Perhaps it should copy the permissions
559 from the old area into the new. Unclear from the Linux man
560 pages what this really does. Also, the flags don't look like
561 they mean the same as the standard mmap flags, so that's
562 probably wrong too. */
563 case __NR_mremap: /* syscall 163 */
564 /* void* mremap(void * old_address, size_t old_size,
565 size_t new_size, unsigned long flags); */
566 if (VG_(clo_trace_syscalls))
567 VG_(printf)("mremap ( %p, %d, %d, 0x%x )\n",
568 arg1, arg2, arg3, arg4);
569 must_be_writable ( tst, "mremap(old_address)", arg1, arg2 );
570 KERNEL_DO_SYSCALL(tid,res);
571 if (!VG_(is_kerror)(res)) {
572 /* Copied from munmap() wrapper. */
sewardj18d75132002-05-16 11:06:21 +0000573 Bool munmap_exe;
sewardj6af4b5d2002-04-16 04:40:49 +0000574 Addr start = arg1;
575 Addr length = arg2;
576 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
577 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
578 make_noaccess( start, length );
sewardj18d75132002-05-16 11:06:21 +0000579 munmap_exe = VG_(symtab_notify_munmap) ( start, length );
580 if (munmap_exe)
581 VG_(invalidate_translations) ( start, length );
sewardj6af4b5d2002-04-16 04:40:49 +0000582 approximate_mmap_permissions( (Addr)res, arg3, arg4 );
583 }
584 break;
585# endif
586
sewardj73f1f072002-03-29 14:22:46 +0000587 case __NR_nice: /* syscall 34 */
588 /* int nice(int inc); */
589 if (VG_(clo_trace_syscalls))
590 VG_(printf)("nice ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000591 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +0000592 break;
593
sewardjde4a1d02002-03-22 01:27:54 +0000594 /* !!!!!!!!!! New, untested syscalls, 14 Mar 02 !!!!!!!!!! */
595
sewardjd7f07662002-03-24 10:49:46 +0000596# if defined(__NR_setresgid32)
597 case __NR_setresgid32: /* syscall 210 */
598 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
599 if (VG_(clo_trace_syscalls))
600 VG_(printf)("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000601 KERNEL_DO_SYSCALL(tid,res);
sewardjd7f07662002-03-24 10:49:46 +0000602 break;
603# endif
604
sewardjde4a1d02002-03-22 01:27:54 +0000605# if defined(__NR_setfsuid32)
606 case __NR_setfsuid32: /* syscall 215 */
607 /* int setfsuid(uid_t fsuid); */
608 if (VG_(clo_trace_syscalls))
609 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000610 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000611 break;
612# endif
613
614# if defined(__NR__sysctl)
615 case __NR__sysctl:
616 /* int _sysctl(struct __sysctl_args *args); */
617 if (VG_(clo_trace_syscalls))
618 VG_(printf)("_sysctl ( %p )\n", arg1 );
sewardj8c824512002-04-14 04:16:48 +0000619 must_be_writable ( tst, "_sysctl(args)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000620 sizeof(struct __sysctl_args) );
sewardj2e93c502002-04-12 11:12:52 +0000621 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000622 if (!VG_(is_kerror)(res))
623 make_readable ( arg1, sizeof(struct __sysctl_args) );
624 break;
625# endif
626
627# if defined(__NR_sched_getscheduler)
628 case __NR_sched_getscheduler:
629 /* int sched_getscheduler(pid_t pid); */
630 if (VG_(clo_trace_syscalls))
631 VG_(printf)("sched_getscheduler ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000632 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000633 break;
634# endif
635
636# if defined(__NR_sched_setscheduler)
637 case __NR_sched_setscheduler:
638 /* int sched_setscheduler(pid_t pid, int policy,
639 const struct sched_param *p); */
640 if (VG_(clo_trace_syscalls))
641 VG_(printf)("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
642 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +0000643 must_be_readable( tst,
644 "sched_setscheduler(struct sched_param *p)",
sewardjde4a1d02002-03-22 01:27:54 +0000645 arg3, sizeof(struct sched_param));
sewardj2e93c502002-04-12 11:12:52 +0000646 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000647 break;
648# endif
649
650# if defined(__NR_mlockall)
651 case __NR_mlockall:
652 /* int mlockall(int flags); */
653 if (VG_(clo_trace_syscalls))
654 VG_(printf)("mlockall ( %x )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000655 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000656 break;
657# endif
658
659# if defined(__NR_munlockall)
660 case __NR_munlockall:
661 /* int munlockall(void); */
662 if (VG_(clo_trace_syscalls))
663 VG_(printf)("munlockall ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000664 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000665 break;
666# endif
667
668#if defined(__NR_sched_get_priority_max)
669 case __NR_sched_get_priority_max:
670 /* int sched_get_priority_max(int policy); */
671 if (VG_(clo_trace_syscalls))
672 VG_(printf)("sched_get_priority_max ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000673 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000674 break;
675# endif
676
sewardj9dfb4a72002-04-27 01:56:30 +0000677#if defined(__NR_sched_get_priority_min)
678 case __NR_sched_get_priority_min: /* syscall 160 */
679 /* int sched_get_priority_min(int policy); */
680 if (VG_(clo_trace_syscalls))
681 VG_(printf)("sched_get_priority_min ( %d )\n", arg1);
682 KERNEL_DO_SYSCALL(tid,res);
683 break;
684# endif
685
686#if defined(__NR_setpriority)
687 case __NR_setpriority: /* syscall 97 */
688 /* int setpriority(int which, int who, int prio); */
689 if (VG_(clo_trace_syscalls))
690 VG_(printf)("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
691 KERNEL_DO_SYSCALL(tid,res);
692 break;
693# endif
694
sewardjde5ac182002-04-27 02:13:24 +0000695#if defined(__NR_getpriority)
696 case __NR_getpriority: /* syscall 96 */
697 /* int getpriority(int which, int who); */
698 if (VG_(clo_trace_syscalls))
699 VG_(printf)("getpriority ( %d, %d )\n", arg1, arg2);
700 KERNEL_DO_SYSCALL(tid,res);
701 break;
702# endif
703
sewardjde4a1d02002-03-22 01:27:54 +0000704# if defined(__NR_setfsgid)
705 case __NR_setfsgid: /* syscall 139 */
706 /* int setfsgid(gid_t gid); */
707 if (VG_(clo_trace_syscalls))
708 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000709 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000710 break;
711# endif
712
713# if defined(__NR_setregid)
714 case __NR_setregid: /* syscall 71 */
715 /* int setregid(gid_t rgid, gid_t egid); */
716 if (VG_(clo_trace_syscalls))
717 VG_(printf)("setregid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +0000718 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000719 break;
720# endif
721
722# if defined(__NR_setresuid)
723 case __NR_setresuid: /* syscall 164 */
724 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
725 if (VG_(clo_trace_syscalls))
726 VG_(printf)("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +0000727 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000728 break;
729# endif
730
731# if defined(__NR_setfsuid)
732 case __NR_setfsuid: /* syscall 138 */
733 /* int setfsuid(uid_t uid); */
734 if (VG_(clo_trace_syscalls))
735 VG_(printf)("setfsuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000736 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000737 break;
738# endif
739
740 /* !!!!!!!!!! New, untested syscalls, 8 Mar 02 !!!!!!!!!!! */
741
742# if defined(__NR_sendfile)
743 case __NR_sendfile: /* syscall 187 */
744 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
745 size_t count) */
746 if (VG_(clo_trace_syscalls))
747 VG_(printf)("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000748 must_be_writable( tst, "sendfile(offset)", arg3, sizeof(off_t) );
sewardj2e93c502002-04-12 11:12:52 +0000749 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000750 if (!VG_(is_kerror)(res)) {
751 make_readable( arg3, sizeof( off_t ) );
752 }
753 break;
754# endif
755
756 /* !!!!!!!!!! New, untested syscalls, 7 Mar 02 !!!!!!!!!!! */
757
758# if defined(__NR_pwrite)
759 case __NR_pwrite: /* syscall 181 */
760 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
761 off_t offset); */
762 if (VG_(clo_trace_syscalls))
763 VG_(printf)("pwrite ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
sewardj8c824512002-04-14 04:16:48 +0000764 must_be_readable( tst, "pwrite(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000765 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000766 break;
767# endif
768
769 /* !!!!!!!!!! New, untested syscalls, 6 Mar 02 !!!!!!!!!!! */
770
771 case __NR_sync: /* syscall 36 */
772 /* int sync(); */
773 if (VG_(clo_trace_syscalls))
774 VG_(printf)("sync ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000775 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000776 break;
777
778 case __NR_fstatfs: /* syscall 100 */
779 /* int fstatfs(int fd, struct statfs *buf); */
780 if (VG_(clo_trace_syscalls))
781 VG_(printf)("fstatfs ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000782 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +0000783 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000784 if (!VG_(is_kerror)(res))
785 make_readable( arg2, sizeof(struct statfs) );
786 break;
787
788 /* !!!!!!!!!! New, untested syscalls, 4 Mar 02 !!!!!!!!!!! */
789
790 case __NR_pause: /* syscall 29 */
791 /* int pause(void); */
792 if (VG_(clo_trace_syscalls))
793 VG_(printf)("pause ( )\n");
sewardj2e93c502002-04-12 11:12:52 +0000794 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000795 break;
796
797 case __NR_getsid: /* syscall 147 */
798 /* pid_t getsid(pid_t pid); */
799 if (VG_(clo_trace_syscalls))
800 VG_(printf)("getsid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000801 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000802 break;
803
804# if defined(__NR_pread)
805 case __NR_pread: /* syscall 180 */
806 /* ssize_t pread(int fd, void *buf, size_t count, off_t offset); */
807 if (VG_(clo_trace_syscalls))
808 VG_(printf)("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
sewardj8c824512002-04-14 04:16:48 +0000809 must_be_writable( tst, "pread(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000810 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000811 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +0000812 VG_(printf)("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
813 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +0000814 arg1, arg2, arg3, arg4, res);
815 if (!VG_(is_kerror)(res) && res > 0) {
816 make_readable( arg2, res );
817 }
818 break;
819# endif
820
821 /* !!!!!!!!!! New, untested syscalls, 27 Feb 02 !!!!!!!!!! */
822
823 case __NR_mknod: /* syscall 14 */
824 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
825 if (VG_(clo_trace_syscalls))
826 VG_(printf)("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
sewardj8c824512002-04-14 04:16:48 +0000827 must_be_readable_asciiz( tst, "mknod(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000828 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000829 break;
830
831 case __NR_flock: /* syscall 143 */
832 /* int flock(int fd, int operation); */
833 if (VG_(clo_trace_syscalls))
834 VG_(printf)("flock ( %d, %d )\n", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +0000835 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000836 break;
837
838# if defined(__NR_rt_sigsuspend)
839 /* Viewed with great suspicion by me, but, hey, let's do it
840 anyway ... */
841 case __NR_rt_sigsuspend: /* syscall 179 */
842 /* int sigsuspend(const sigset_t *mask); */
843 if (VG_(clo_trace_syscalls))
844 VG_(printf)("sigsuspend ( %p )\n", arg1 );
845 if (arg1 != (Addr)NULL) {
846 /* above NULL test is paranoia */
sewardj8c824512002-04-14 04:16:48 +0000847 must_be_readable( tst, "sigsuspend(mask)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000848 sizeof(vki_ksigset_t) );
849 }
sewardj2e93c502002-04-12 11:12:52 +0000850 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000851 break;
852# endif
853
854 case __NR_init_module: /* syscall 128 */
855 /* int init_module(const char *name, struct module *image); */
856 if (VG_(clo_trace_syscalls))
857 VG_(printf)("init_module ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000858 must_be_readable_asciiz( tst, "init_module(name)", arg1 );
859 must_be_readable( tst, "init_module(image)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000860 sizeof(struct module) );
sewardj2e93c502002-04-12 11:12:52 +0000861 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000862 break;
863
864 case __NR_ioperm: /* syscall 101 */
865 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
866 if (VG_(clo_trace_syscalls))
867 VG_(printf)("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +0000868 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000869 break;
870
871 case __NR_capget: /* syscall 184 */
872 /* int capget(cap_user_header_t header, cap_user_data_t data); */
873 if (VG_(clo_trace_syscalls))
874 VG_(printf)("capget ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +0000875 must_be_readable( tst, "capget(header)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +0000876 sizeof(vki_cap_user_header_t) );
sewardj8c824512002-04-14 04:16:48 +0000877 must_be_writable( tst, "capget(data)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +0000878 sizeof( vki_cap_user_data_t) );
sewardj2e93c502002-04-12 11:12:52 +0000879 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000880 if (!VG_(is_kerror)(res) && arg2 != (Addr)NULL)
881 make_readable ( arg2, sizeof( vki_cap_user_data_t) );
882 break;
883
884 /* !!!!!!!!!!!!!!!!!!!!! mutant ones !!!!!!!!!!!!!!!!!!!!! */
885
886 case __NR_execve:
887 /* int execve (const char *filename,
888 char *const argv [],
889 char *const envp[]); */
890 if (VG_(clo_trace_syscalls))
891 VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
892 arg1, arg1, arg2, arg3);
893 /* Make any binding for LD_PRELOAD disappear, so that child
894 processes don't get traced into. */
895 if (!VG_(clo_trace_children)) {
896 Int i;
897 Char** envp = (Char**)arg3;
sewardj3e1eb1f2002-05-18 13:14:17 +0000898 Char* ld_preload_str = NULL;
899 Char* ld_library_path_str = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000900 for (i = 0; envp[i] != NULL; i++) {
sewardj3e1eb1f2002-05-18 13:14:17 +0000901 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
902 ld_preload_str = &envp[i][11];
903 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
904 ld_library_path_str = &envp[i][16];
sewardjde4a1d02002-03-22 01:27:54 +0000905 }
sewardj3e1eb1f2002-05-18 13:14:17 +0000906 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
907 ld_preload_str, ld_library_path_str );
sewardjde4a1d02002-03-22 01:27:54 +0000908 }
sewardj2e93c502002-04-12 11:12:52 +0000909 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000910 /* Should we still be alive here? Don't think so. */
911 /* Actually, above comment is wrong. execve can fail, just
912 like any other syscall -- typically the file to exec does
913 not exist. Hence: */
914 vg_assert(VG_(is_kerror)(res));
915 break;
916
sewardjde4a1d02002-03-22 01:27:54 +0000917 /* !!!!!!!!!!!!!!!!!!!!! end !!!!!!!!!!!!!!!!!!!!! */
918
919 case __NR_access: /* syscall 33 */
920 /* int access(const char *pathname, int mode); */
921 if (VG_(clo_trace_syscalls))
922 VG_(printf)("access ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000923 must_be_readable_asciiz( tst, "access(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000924 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000925 break;
926
927 case __NR_alarm: /* syscall 27 */
928 /* unsigned int alarm(unsigned int seconds); */
929 if (VG_(clo_trace_syscalls))
930 VG_(printf)("alarm ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +0000931 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000932 break;
933
934 case __NR_brk: /* syscall 45 */
935 /* Haven't a clue if this is really right. */
936 /* int brk(void *end_data_segment); */
937 if (VG_(clo_trace_syscalls))
938 VG_(printf)("brk ( %p ) --> ",arg1);
sewardj2e93c502002-04-12 11:12:52 +0000939 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000940 if (VG_(clo_trace_syscalls))
941 VG_(printf)("0x%x\n", res);
942
943 if (!VG_(is_kerror)(res)) {
944 if (arg1 == 0) {
945 /* Just asking where the current end is. (???) */
946 VGM_(curr_dataseg_end) = res;
947 } else
948 if (arg1 < VGM_(curr_dataseg_end)) {
949 /* shrinking the data segment. */
950 make_noaccess( (Addr)arg1,
951 VGM_(curr_dataseg_end)-arg1 );
952 VGM_(curr_dataseg_end) = arg1;
953 } else
954 if (arg1 > VGM_(curr_dataseg_end) && res != 0) {
955 /* asked for more memory, and got it */
956 /*
957 VG_(printf)("BRK: new area %x .. %x\n",
958 VGM_(curr_dataseg_end, arg1-1 );
959 */
960 make_writable ( (Addr)VGM_(curr_dataseg_end),
961 arg1-VGM_(curr_dataseg_end) );
962 VGM_(curr_dataseg_end) = arg1;
963 }
964 }
965 break;
966
967 case __NR_chdir: /* syscall 12 */
968 /* int chdir(const char *path); */
969 if (VG_(clo_trace_syscalls))
970 VG_(printf)("chdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +0000971 must_be_readable_asciiz( tst, "chdir(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000972 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000973 break;
974
975 case __NR_chmod: /* syscall 15 */
976 /* int chmod(const char *path, mode_t mode); */
977 if (VG_(clo_trace_syscalls))
978 VG_(printf)("chmod ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +0000979 must_be_readable_asciiz( tst, "chmod(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000980 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000981 break;
982
983# if defined(__NR_chown32)
984 case __NR_chown32: /* syscall 212 */
985# endif
986# if defined(__NR_lchown32)
987 case __NR_lchown32: /* syscall 198 */
988# endif
989 case __NR_chown: /* syscall 16 */
990 /* int chown(const char *path, uid_t owner, gid_t group); */
991 if (VG_(clo_trace_syscalls))
992 VG_(printf)("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +0000993 must_be_readable_asciiz( tst, "chown(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +0000994 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +0000995 break;
996
997 case __NR_close: /* syscall 6 */
998 /* int close(int fd); */
999 if (VG_(clo_trace_syscalls))
1000 VG_(printf)("close ( %d )\n",arg1);
1001 /* Detect and negate attempts by the client to close Valgrind's
1002 logfile fd ... */
1003 if (arg1 == VG_(clo_logfile_fd)) {
1004 VG_(message)(Vg_UserMsg,
1005 "Warning: client attempted to close "
1006 "Valgrind's logfile fd (%d).",
1007 VG_(clo_logfile_fd));
1008 VG_(message)(Vg_UserMsg,
1009 " Use --logfile-fd=<number> to select an "
1010 "alternative logfile fd." );
1011 } else {
sewardj2e93c502002-04-12 11:12:52 +00001012 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001013 }
1014 break;
1015
1016 case __NR_dup: /* syscall 41 */
1017 /* int dup(int oldfd); */
1018 if (VG_(clo_trace_syscalls))
1019 VG_(printf)("dup ( %d ) --> ", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001020 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001021 if (VG_(clo_trace_syscalls))
1022 VG_(printf)("%d\n", res);
1023 break;
1024
1025 case __NR_dup2: /* syscall 63 */
1026 /* int dup2(int oldfd, int newfd); */
1027 if (VG_(clo_trace_syscalls))
1028 VG_(printf)("dup2 ( %d, %d ) ...\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001029 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001030 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +00001031 VG_(printf)("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
1032 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00001033 arg1, arg2, res);
1034 break;
1035
1036 case __NR_fcntl: /* syscall 55 */
sewardj2e93c502002-04-12 11:12:52 +00001037 /* int fcntl(int fd, int cmd, int arg); */
sewardjde4a1d02002-03-22 01:27:54 +00001038 if (VG_(clo_trace_syscalls))
sewardj2e93c502002-04-12 11:12:52 +00001039 VG_(printf)("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
1040 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001041 break;
1042
1043 case __NR_fchdir: /* syscall 133 */
1044 /* int fchdir(int fd); */
1045 if (VG_(clo_trace_syscalls))
1046 VG_(printf)("fchdir ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001047 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001048 break;
1049
sewardj2f0de322002-03-24 10:17:25 +00001050# if defined(__NR_fchown32)
1051 case __NR_fchown32: /* syscall 207 */
1052# endif
1053 case __NR_fchown: /* syscall 95 */
1054 /* int fchown(int filedes, uid_t owner, gid_t group); */
1055 if (VG_(clo_trace_syscalls))
1056 VG_(printf)("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00001057 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001058 break;
1059
sewardjde4a1d02002-03-22 01:27:54 +00001060 case __NR_fchmod: /* syscall 94 */
1061 /* int fchmod(int fildes, mode_t mode); */
1062 if (VG_(clo_trace_syscalls))
1063 VG_(printf)("fchmod ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001064 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001065 break;
sewardj2f0de322002-03-24 10:17:25 +00001066
sewardjde4a1d02002-03-22 01:27:54 +00001067# if defined(__NR_fcntl64)
1068 case __NR_fcntl64: /* syscall 221 */
1069 /* I don't know what the prototype for this is supposed to be. */
1070 /* ??? int fcntl(int fd, int cmd); */
1071 if (VG_(clo_trace_syscalls))
1072 VG_(printf)("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001073 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001074 break;
1075# endif
1076
1077 case __NR_fstat: /* syscall 108 */
1078 /* int fstat(int filedes, struct stat *buf); */
1079 if (VG_(clo_trace_syscalls))
1080 VG_(printf)("fstat ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001081 must_be_writable( tst, "fstat", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00001082 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001083 if (!VG_(is_kerror)(res))
1084 make_readable( arg2, sizeof(struct stat) );
1085 break;
1086
1087 case __NR_vfork: /* syscall 190 */
1088 /* pid_t vfork(void); */
1089 if (VG_(clo_trace_syscalls))
1090 VG_(printf)("vfork ( ) ... becomes ... ");
1091 /* KLUDGE: we prefer to do a fork rather than vfork.
1092 vfork gives a SIGSEGV, and the stated semantics looks
1093 pretty much impossible for us. */
sewardj2e93c502002-04-12 11:12:52 +00001094 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +00001095 /* fall through ... */
1096 case __NR_fork: /* syscall 2 */
1097 /* pid_t fork(void); */
1098 if (VG_(clo_trace_syscalls))
1099 VG_(printf)("fork ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001100 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001101 break;
1102
1103 case __NR_fsync: /* syscall 118 */
1104 /* int fsync(int fd); */
1105 if (VG_(clo_trace_syscalls))
1106 VG_(printf)("fsync ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001107 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001108 break;
1109
1110 case __NR_ftruncate: /* syscall 93 */
1111 /* int ftruncate(int fd, size_t length); */
1112 if (VG_(clo_trace_syscalls))
1113 VG_(printf)("ftruncate ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00001114 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001115 break;
1116
sewardj2f0de322002-03-24 10:17:25 +00001117# if defined(__NR_ftruncate64)
1118 case __NR_ftruncate64: /* syscall 194 */
1119 /* int ftruncate64(int fd, off64_t length); */
1120 if (VG_(clo_trace_syscalls))
1121 VG_(printf)("ftruncate64 ( %d, %lld )\n",
1122 arg1,arg2|((long long) arg3 << 32));
sewardj2e93c502002-04-12 11:12:52 +00001123 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001124 break;
1125# endif
1126
1127 case __NR_getdents: /* syscall 141 */
1128 /* int getdents(unsigned int fd, struct dirent *dirp,
1129 unsigned int count); */
1130 if (VG_(clo_trace_syscalls))
1131 VG_(printf)("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001132 must_be_writable( tst, "getdents(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001133 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001134 if (!VG_(is_kerror)(res) && res > 0)
1135 make_readable( arg2, res );
1136 break;
1137
1138# if defined(__NR_getdents64)
1139 case __NR_getdents64: /* syscall 220 */
1140 /* int getdents(unsigned int fd, struct dirent64 *dirp,
1141 unsigned int count); */
1142 if (VG_(clo_trace_syscalls))
1143 VG_(printf)("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001144 must_be_writable( tst, "getdents64(dirp)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00001145 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001146 if (!VG_(is_kerror)(res) && res > 0)
1147 make_readable( arg2, res );
1148 break;
1149# endif
1150
1151# if defined(__NR_getgroups32)
1152 case __NR_getgroups32: /* syscall 205 */
1153# endif
1154 case __NR_getgroups: /* syscall 80 */
1155 /* int getgroups(int size, gid_t list[]); */
1156 if (VG_(clo_trace_syscalls))
1157 VG_(printf)("getgroups ( %d, %p )\n", arg1, arg2);
1158 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00001159 must_be_writable ( tst, "getgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001160 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001161 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001162 if (arg1 > 0 && !VG_(is_kerror)(res) && res > 0)
1163 make_readable ( arg2, res * sizeof(gid_t) );
1164 break;
1165
1166 case __NR_getcwd: /* syscall 183 */
1167 /* char *getcwd(char *buf, size_t size); */
1168 if (VG_(clo_trace_syscalls))
1169 VG_(printf)("getcwd ( %p, %d )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001170 must_be_writable( tst, "getcwd(buf)", arg1, arg2 );
sewardj2e93c502002-04-12 11:12:52 +00001171 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001172 if (!VG_(is_kerror)(res) && res != (Addr)NULL)
1173 make_readable ( arg1, arg2 );
1174 /* Not really right -- really we should have the asciiz
1175 string starting at arg1 readable, or up to arg2 bytes,
1176 whichever finishes first. */
1177 break;
1178
1179 case __NR_geteuid: /* syscall 49 */
1180 /* uid_t geteuid(void); */
1181 if (VG_(clo_trace_syscalls))
1182 VG_(printf)("geteuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001183 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001184 break;
1185
1186# if defined(__NR_geteuid32)
1187 case __NR_geteuid32: /* syscall 201 */
1188 /* ?? uid_t geteuid32(void); */
1189 if (VG_(clo_trace_syscalls))
1190 VG_(printf)("geteuid32(?) ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001191 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001192 break;
1193# endif
1194
1195 case __NR_getegid: /* syscall 50 */
1196 /* gid_t getegid(void); */
1197 if (VG_(clo_trace_syscalls))
1198 VG_(printf)("getegid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001199 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001200 break;
1201
1202# if defined(__NR_getegid32)
1203 case __NR_getegid32: /* syscall 202 */
1204 /* gid_t getegid32(void); */
1205 if (VG_(clo_trace_syscalls))
1206 VG_(printf)("getegid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001207 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001208 break;
1209# endif
1210
1211 case __NR_getgid: /* syscall 47 */
1212 /* gid_t getgid(void); */
1213 if (VG_(clo_trace_syscalls))
1214 VG_(printf)("getgid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001215 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001216 break;
1217
1218# if defined(__NR_getgid32)
1219 case __NR_getgid32: /* syscall 200 */
1220 /* gid_t getgid32(void); */
1221 if (VG_(clo_trace_syscalls))
1222 VG_(printf)("getgid32 ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001223 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001224 break;
1225# endif
1226
1227 case __NR_getpid: /* syscall 20 */
1228 /* pid_t getpid(void); */
1229 if (VG_(clo_trace_syscalls))
1230 VG_(printf)("getpid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001231 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001232 break;
1233
1234 case __NR_getpgid: /* syscall 132 */
1235 /* pid_t getpgid(pid_t pid); */
1236 if (VG_(clo_trace_syscalls))
1237 VG_(printf)("getpgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00001238 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001239 break;
1240
1241 case __NR_getpgrp: /* syscall 65 */
1242 /* pid_t getpprp(void); */
1243 if (VG_(clo_trace_syscalls))
1244 VG_(printf)("getpgrp ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001245 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001246 break;
1247
1248 case __NR_getppid: /* syscall 64 */
1249 /* pid_t getppid(void); */
1250 if (VG_(clo_trace_syscalls))
1251 VG_(printf)("getppid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00001252 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001253 break;
1254
1255 case __NR_getresgid: /* syscall 171 */
1256 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1257 if (VG_(clo_trace_syscalls))
1258 VG_(printf)("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001259 must_be_writable ( tst, "getresgid(rgid)", arg1, sizeof(gid_t) );
1260 must_be_writable ( tst, "getresgid(egid)", arg2, sizeof(gid_t) );
1261 must_be_writable ( tst, "getresgid(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001262 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001263 if (!VG_(is_kerror)(res) && res == 0) {
1264 make_readable ( arg1, sizeof(gid_t) );
1265 make_readable ( arg2, sizeof(gid_t) );
1266 make_readable ( arg3, sizeof(gid_t) );
1267 }
1268 break;
1269
1270# if defined(__NR_getresgid32)
1271 case __NR_getresgid32: /* syscall 211 */
1272 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1273 if (VG_(clo_trace_syscalls))
1274 VG_(printf)("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001275 must_be_writable ( tst, "getresgid32(rgid)", arg1, sizeof(gid_t) );
1276 must_be_writable ( tst, "getresgid32(egid)", arg2, sizeof(gid_t) );
1277 must_be_writable ( tst, "getresgid32(sgid)", arg3, sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001278 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001279 if (!VG_(is_kerror)(res) && res == 0) {
1280 make_readable ( arg1, sizeof(gid_t) );
1281 make_readable ( arg2, sizeof(gid_t) );
1282 make_readable ( arg3, sizeof(gid_t) );
1283 }
1284 break;
1285# endif
1286
1287 case __NR_getresuid: /* syscall 165 */
1288 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1289 if (VG_(clo_trace_syscalls))
1290 VG_(printf)("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001291 must_be_writable ( tst, "getresuid(ruid)", arg1, sizeof(uid_t) );
1292 must_be_writable ( tst, "getresuid(euid)", arg2, sizeof(uid_t) );
1293 must_be_writable ( tst, "getresuid(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001294 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001295 if (!VG_(is_kerror)(res) && res == 0) {
1296 make_readable ( arg1, sizeof(uid_t) );
1297 make_readable ( arg2, sizeof(uid_t) );
1298 make_readable ( arg3, sizeof(uid_t) );
1299 }
1300 break;
1301
1302# if defined(__NR_getresuid32)
1303 case __NR_getresuid32: /* syscall 209 */
1304 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1305 if (VG_(clo_trace_syscalls))
1306 VG_(printf)("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00001307 must_be_writable ( tst, "getresuid32(ruid)", arg1, sizeof(uid_t) );
1308 must_be_writable ( tst, "getresuid32(euid)", arg2, sizeof(uid_t) );
1309 must_be_writable ( tst, "getresuid32(suid)", arg3, sizeof(uid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001310 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001311 if (!VG_(is_kerror)(res) && res == 0) {
1312 make_readable ( arg1, sizeof(uid_t) );
1313 make_readable ( arg2, sizeof(uid_t) );
1314 make_readable ( arg3, sizeof(uid_t) );
1315 }
1316 break;
1317# endif
1318
1319# if defined(__NR_ugetrlimit)
1320 case __NR_ugetrlimit: /* syscall 191 */
1321# endif
1322 case __NR_getrlimit: /* syscall 76 */
1323 /* int getrlimit (int resource, struct rlimit *rlim); */
1324 if (VG_(clo_trace_syscalls))
1325 VG_(printf)("getrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001326 must_be_writable( tst, "getrlimit(rlim)", arg2,
1327 sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00001328 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001329 if (!VG_(is_kerror)(res) && res == 0)
1330 make_readable( arg2, sizeof(struct rlimit) );
1331 break;
1332
1333 case __NR_getrusage: /* syscall 77 */
1334 /* int getrusage (int who, struct rusage *usage); */
1335 if (VG_(clo_trace_syscalls))
1336 VG_(printf)("getrusage ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001337 must_be_writable( tst, "getrusage(usage)", arg2,
1338 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00001339 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001340 if (!VG_(is_kerror)(res) && res == 0)
1341 make_readable(arg2, sizeof(struct rusage) );
1342 break;
1343
1344 case __NR_gettimeofday: /* syscall 78 */
1345 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1346 if (VG_(clo_trace_syscalls))
1347 VG_(printf)("gettimeofday ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00001348 must_be_writable( tst, "gettimeofday(tv)", arg1,
1349 sizeof(struct timeval) );
sewardjde4a1d02002-03-22 01:27:54 +00001350 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00001351 must_be_writable( tst, "gettimeofday(tz)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00001352 sizeof(struct timezone) );
sewardj2e93c502002-04-12 11:12:52 +00001353 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001354 if (!VG_(is_kerror)(res) && res == 0) {
1355 make_readable( arg1, sizeof(struct timeval) );
1356 if (arg2 != 0)
1357 make_readable( arg2, sizeof(struct timezone) );
1358 }
1359 break;
1360
1361 case __NR_getuid: /* syscall 24 */
1362 /* uid_t getuid(void); */
1363 if (VG_(clo_trace_syscalls))
1364 VG_(printf)("getuid ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001365 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001366 break;
1367
1368# if defined(__NR_getuid32)
1369 case __NR_getuid32: /* syscall 199 */
1370 /* ???uid_t getuid32(void); */
1371 if (VG_(clo_trace_syscalls))
1372 VG_(printf)("getuid32 ( )\n");
sewardj2e93c502002-04-12 11:12:52 +00001373 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001374 break;
1375# endif
1376
1377 case __NR_ipc: /* syscall 117 */
1378 /* int ipc ( unsigned int call, int first, int second,
1379 int third, void *ptr, long fifth); */
1380 {
sewardj2e93c502002-04-12 11:12:52 +00001381 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00001382
1383 if (VG_(clo_trace_syscalls))
1384 VG_(printf)("ipc ( %d, %d, %d, %d, %p, %d )\n",
1385 arg1,arg2,arg3,arg4,arg5,arg6);
1386 switch (arg1 /* call */) {
1387 case 1: /* IPCOP_semop */
sewardj8c824512002-04-14 04:16:48 +00001388 must_be_readable ( tst, "semop(sops)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001389 arg3 * sizeof(struct sembuf) );
sewardj2e93c502002-04-12 11:12:52 +00001390 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001391 break;
sewardj5b9e3502002-03-29 04:35:08 +00001392 case 2: /* IPCOP_semget */
1393 case 3: /* IPCOP_semctl */
sewardj2e93c502002-04-12 11:12:52 +00001394 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001395 break;
1396 case 11: /* IPCOP_msgsnd */
1397 {
1398 struct msgbuf *msgp = (struct msgbuf *)arg5;
1399 Int msgsz = arg3;
1400
sewardj8c824512002-04-14 04:16:48 +00001401 must_be_readable ( tst, "msgsnd(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001402 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj8c824512002-04-14 04:16:48 +00001403 must_be_readable ( tst, "msgsnd(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001404 (UInt)msgp->mtext, msgsz );
1405
sewardj2e93c502002-04-12 11:12:52 +00001406 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001407 break;
1408 }
1409 case 12: /* IPCOP_msgrcv */
1410 {
sewardj59c255c2002-04-27 02:06:15 +00001411 struct msgbuf *msgp;
sewardj5b9e3502002-03-29 04:35:08 +00001412 Int msgsz = arg3;
sewardj59c255c2002-04-27 02:06:15 +00001413
1414 msgp = (struct msgbuf *)safe_dereference(
1415 (Addr) (&((struct ipc_kludge *)arg5)->msgp), 0 );
sewardj5b9e3502002-03-29 04:35:08 +00001416
sewardj59c255c2002-04-27 02:06:15 +00001417 must_be_writable ( tst, "msgrcv(msgp->mtype)",
sewardj5b9e3502002-03-29 04:35:08 +00001418 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
sewardj59c255c2002-04-27 02:06:15 +00001419 must_be_writable ( tst, "msgrcv(msgp->mtext)",
sewardj5b9e3502002-03-29 04:35:08 +00001420 (UInt)msgp->mtext, msgsz );
1421
sewardj2e93c502002-04-12 11:12:52 +00001422 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001423
1424 if ( !VG_(is_kerror)(res) && res > 0 ) {
1425 make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1426 make_readable ( (UInt)msgp->mtext, res );
1427 }
1428 break;
1429 }
1430 case 13: /* IPCOP_msgget */
sewardj2e93c502002-04-12 11:12:52 +00001431 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001432 break;
1433 case 14: /* IPCOP_msgctl */
1434 {
1435 switch (arg3 /* cmd */) {
1436 case IPC_STAT:
sewardj8c824512002-04-14 04:16:48 +00001437 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001438 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001439 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001440 if ( !VG_(is_kerror)(res) && res > 0 ) {
1441 make_readable ( arg5, sizeof(struct msqid_ds) );
1442 }
1443 break;
1444 case IPC_SET:
sewardj8c824512002-04-14 04:16:48 +00001445 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001446 sizeof(struct msqid_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001447 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001448 break;
sewardjc9add3b2002-04-16 01:58:19 +00001449# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001450 case IPC_STAT|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001451 must_be_writable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001452 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001453 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001454 if ( !VG_(is_kerror)(res) && res > 0 ) {
1455 make_readable ( arg5, sizeof(struct msqid64_ds) );
1456 }
1457 break;
sewardjc9add3b2002-04-16 01:58:19 +00001458# endif
1459# if defined(IPC_64)
sewardj5b9e3502002-03-29 04:35:08 +00001460 case IPC_SET|IPC_64:
sewardj8c824512002-04-14 04:16:48 +00001461 must_be_readable ( tst, "msgctl(buf)", arg5,
sewardj5b9e3502002-03-29 04:35:08 +00001462 sizeof(struct msqid64_ds) );
sewardj2e93c502002-04-12 11:12:52 +00001463 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001464 break;
sewardjc9add3b2002-04-16 01:58:19 +00001465# endif
sewardj5b9e3502002-03-29 04:35:08 +00001466 default:
sewardj2e93c502002-04-12 11:12:52 +00001467 KERNEL_DO_SYSCALL(tid,res);
sewardj5b9e3502002-03-29 04:35:08 +00001468 break;
1469 }
1470 break;
1471 }
sewardjde4a1d02002-03-22 01:27:54 +00001472 case 21: /* IPCOP_shmat */
1473 {
1474 Int shmid = arg2;
1475 Int shmflag = arg3;
1476 UInt addr;
1477
sewardj2e93c502002-04-12 11:12:52 +00001478 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001479
1480 if ( VG_(is_kerror) ( res ) )
1481 break;
1482
1483 /* force readability. before the syscall it is
1484 * indeed uninitialized, as can be seen in
1485 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1486 make_readable ( arg4, sizeof( ULong ) );
1487
1488 addr = safe_dereference ( arg4, 0 );
1489 if ( addr > 0 ) {
1490 UInt segmentSize = get_shm_size ( shmid );
1491 if ( segmentSize > 0 ) {
1492 if ( shmflag & SHM_RDONLY )
1493 make_readable ( addr, segmentSize );
1494 else
1495 make_readwritable ( addr, segmentSize );
1496 }
1497 }
1498 break;
1499 }
1500 case 22: /* IPCOP_shmdt */
sewardj2e93c502002-04-12 11:12:52 +00001501 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001502 /* ### FIXME: this should call make_noaccess on the
1503 * area passed to shmdt. But there's no way to
1504 * figure out the size of the shared memory segment
1505 * just from the address... Maybe we want to keep a
1506 * copy of the exiting mappings inside valgrind? */
1507 break;
1508 case 23: /* IPCOP_shmget */
sewardj2e93c502002-04-12 11:12:52 +00001509 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001510 break;
1511 case 24: /* IPCOP_shmctl */
sewardj2390bb52002-05-09 17:45:06 +00001512 /* Subject: shmctl: The True Story
1513 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
1514 From: Reuben Thomas <rrt@mupsych.org>
1515 To: Julian Seward <jseward@acm.org>
1516
1517 1. As you suggested, the syscall subop is in arg1.
1518
1519 2. There are a couple more twists, so the arg order
1520 is actually:
1521
1522 arg1 syscall subop
1523 arg2 file desc
1524 arg3 shm operation code (can have IPC_64 set)
1525 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
1526 is defined?
1527 arg5 pointer to buffer
1528
1529 3. With this in mind, I've amended the case as below:
1530 */
1531 {
1532 UInt cmd = arg3;
1533 Bool out_arg = False;
1534 if ( arg5 ) {
1535# if defined(IPC_64)
1536 cmd = cmd & (~IPC_64);
1537# endif
sewardj2a8cda12002-05-10 22:51:26 +00001538 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
sewardj2390bb52002-05-09 17:45:06 +00001539 if ( out_arg )
1540 must_be_writable( tst,
1541 "shmctl(SHM_STAT or IPC_STAT,buf)",
1542 arg5, sizeof(struct shmid_ds) );
1543 else
1544 must_be_readable( tst,
1545 "shmctl(SHM_XXXX,buf)",
1546 arg5, sizeof(struct shmid_ds) );
1547 }
1548 KERNEL_DO_SYSCALL(tid,res);
1549 if ( arg5 && !VG_(is_kerror)(res) && res == 0 && out_arg )
1550 make_readable( arg5, sizeof(struct shmid_ds) );
sewardjde4a1d02002-03-22 01:27:54 +00001551 }
sewardj84b380a2002-05-08 01:31:15 +00001552 break;
sewardjde4a1d02002-03-22 01:27:54 +00001553 default:
1554 VG_(message)(Vg_DebugMsg,
1555 "FATAL: unhandled syscall(ipc) %d",
1556 arg1 );
1557 VG_(panic)("... bye!\n");
1558 break; /*NOTREACHED*/
1559 }
1560 }
1561 break;
1562
1563 case __NR_ioctl: /* syscall 54 */
1564 /* int ioctl(int d, int request, ...)
1565 [The "third" argument is traditionally char *argp,
1566 and will be so named for this discussion.]
1567 */
1568 /*
1569 VG_(message)(
1570 Vg_DebugMsg,
1571 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
1572 arg2,arg1,arg3);
1573 */
1574 if (VG_(clo_trace_syscalls))
1575 VG_(printf)("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
1576 switch (arg2 /* request */) {
1577 case TCSETS:
1578 case TCSETSW:
1579 case TCSETSF:
sewardj730e4d32002-05-09 18:40:45 +00001580 must_be_readable( tst, "ioctl(TCSET{S,SW,SF})", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001581 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001582 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001583 break;
1584 case TCGETS:
sewardj8c824512002-04-14 04:16:48 +00001585 must_be_writable( tst, "ioctl(TCGETS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001586 VKI_SIZEOF_STRUCT_TERMIOS );
sewardj2e93c502002-04-12 11:12:52 +00001587 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001588 if (!VG_(is_kerror)(res) && res == 0)
1589 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIOS );
1590 break;
sewardj2f0de322002-03-24 10:17:25 +00001591 case TCSETA:
sewardj730e4d32002-05-09 18:40:45 +00001592 case TCSETAW:
1593 case TCSETAF:
1594 must_be_readable( tst, "ioctl(TCSET{A,AW,AF})", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001595 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001596 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001597 break;
1598 case TCGETA:
sewardj8c824512002-04-14 04:16:48 +00001599 must_be_writable( tst, "ioctl(TCGETA)", arg3,
sewardj2f0de322002-03-24 10:17:25 +00001600 VKI_SIZEOF_STRUCT_TERMIO );
sewardj2e93c502002-04-12 11:12:52 +00001601 KERNEL_DO_SYSCALL(tid,res);
sewardj2f0de322002-03-24 10:17:25 +00001602 if (!VG_(is_kerror)(res) && res == 0)
1603 make_readable ( arg3, VKI_SIZEOF_STRUCT_TERMIO );
1604 break;
sewardjde4a1d02002-03-22 01:27:54 +00001605 case TCSBRK:
1606 case TCSBRKP:
1607 case TCFLSH:
1608 /* These just take an int by value */
sewardj2e93c502002-04-12 11:12:52 +00001609 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001610 break;
1611 case TIOCGWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001612 must_be_writable( tst, "ioctl(TIOCGWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001613 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001614 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001615 if (!VG_(is_kerror)(res) && res == 0)
1616 make_readable ( arg3, sizeof(struct winsize) );
1617 break;
1618 case TIOCSWINSZ:
sewardj8c824512002-04-14 04:16:48 +00001619 must_be_readable( tst, "ioctl(TIOCSWINSZ)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001620 sizeof(struct winsize) );
sewardj2e93c502002-04-12 11:12:52 +00001621 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001622 break;
sewardj19fe3d02002-03-29 04:39:00 +00001623 case TIOCGPGRP:
1624 /* Get process group ID for foreground processing group. */
sewardj8c824512002-04-14 04:16:48 +00001625 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
sewardj19fe3d02002-03-29 04:39:00 +00001626 sizeof(pid_t) );
sewardj2e93c502002-04-12 11:12:52 +00001627 KERNEL_DO_SYSCALL(tid,res);
sewardj19fe3d02002-03-29 04:39:00 +00001628 if (!VG_(is_kerror)(res) && res == 0)
1629 make_readable ( arg3, sizeof(pid_t) );
sewardja4da9372002-05-21 00:44:02 +00001630 break;
1631 case TIOCSPGRP:
1632 /* Set a process group ID? */
1633 must_be_writable( tst, "ioctl(TIOCGPGRP)", arg3,
1634 sizeof(pid_t) );
1635 KERNEL_DO_SYSCALL(tid,res);
1636 if (!VG_(is_kerror)(res) && res == 0)
1637 make_readable ( arg3, sizeof(pid_t) );
1638 break;
sewardjde4a1d02002-03-22 01:27:54 +00001639 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
sewardj8c824512002-04-14 04:16:48 +00001640 must_be_writable(tst, "ioctl(TIOCGPTN)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001641 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001642 if (!VG_(is_kerror)(res) && res == 0)
1643 make_readable ( arg3, sizeof(int));
1644 break;
sewardj73f1f072002-03-29 14:22:46 +00001645 case TIOCSCTTY:
1646 /* Just takes an int value. */
sewardj2e93c502002-04-12 11:12:52 +00001647 KERNEL_DO_SYSCALL(tid,res);
sewardj73f1f072002-03-29 14:22:46 +00001648 break;
sewardjde4a1d02002-03-22 01:27:54 +00001649 case TIOCSPTLCK: /* Lock/unlock Pty */
sewardj8c824512002-04-14 04:16:48 +00001650 must_be_readable( tst, "ioctl(TIOCSPTLCK)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001651 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001652 break;
1653 case FIONBIO:
sewardj8c824512002-04-14 04:16:48 +00001654 must_be_readable( tst, "ioctl(FIONBIO)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001655 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001656 break;
1657 case FIOASYNC:
sewardj8c824512002-04-14 04:16:48 +00001658 must_be_readable( tst, "ioctl(FIOASYNC)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001659 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001660 break;
1661 case FIONREAD:
sewardj8c824512002-04-14 04:16:48 +00001662 must_be_writable( tst, "ioctl(FIONREAD)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001663 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001664 if (!VG_(is_kerror)(res) && res == 0)
1665 make_readable( arg3, sizeof(int) );
1666 break;
1667
1668 /* If you get compilation problems here, change the #if
1669 1 to #if 0 and get rid of <scsi/sg.h> in
1670 vg_unsafe.h. */
1671# if 1
1672 case SG_SET_COMMAND_Q:
sewardj8c824512002-04-14 04:16:48 +00001673 must_be_readable( tst, "ioctl(SG_SET_COMMAND_Q)",
1674 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001675 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001676 break;
1677# if defined(SG_IO)
1678 case SG_IO:
sewardj8c824512002-04-14 04:16:48 +00001679 must_be_writable( tst, "ioctl(SG_IO)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001680 sizeof(struct sg_io_hdr) );
sewardj2e93c502002-04-12 11:12:52 +00001681 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001682 if (!VG_(is_kerror)(res) && res == 0)
1683 make_readable (arg3, sizeof(struct sg_io_hdr));
1684 break;
1685# endif /* SG_IO */
1686 case SG_GET_SCSI_ID:
1687 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
sewardj8c824512002-04-14 04:16:48 +00001688 must_be_writable( tst, "ioctl(SG_GET_SCSI_ID)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001689 sizeof(struct sg_scsi_id) );
sewardj2e93c502002-04-12 11:12:52 +00001690 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001691 if (!VG_(is_kerror)(res) && res == 0)
1692 make_readable (arg3, sizeof(struct sg_scsi_id));
1693 break;
1694 case SG_SET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001695 must_be_readable( tst, "ioctl(SG_SET_RESERVED_SIZE)",
sewardjde4a1d02002-03-22 01:27:54 +00001696 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001697 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001698 break;
1699 case SG_SET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001700 must_be_readable( tst, "ioctl(SG_SET_TIMEOUT)", arg3,
1701 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001702 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001703 break;
1704 case SG_GET_RESERVED_SIZE:
sewardj8c824512002-04-14 04:16:48 +00001705 must_be_writable( tst, "ioctl(SG_GET_RESERVED_SIZE)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001706 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001707 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001708 if (!VG_(is_kerror)(res) && res == 0)
1709 make_readable (arg3, sizeof(int));
1710 break;
1711 case SG_GET_TIMEOUT:
sewardj8c824512002-04-14 04:16:48 +00001712 must_be_writable( tst, "ioctl(SG_GET_TIMEOUT)", arg3,
1713 sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001714 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001715 if (!VG_(is_kerror)(res) && res == 0)
1716 make_readable (arg3, sizeof(int));
1717 break;
1718 case SG_GET_VERSION_NUM:
sewardj8c824512002-04-14 04:16:48 +00001719 must_be_readable( tst, "ioctl(SG_GET_VERSION_NUM)",
sewardjde4a1d02002-03-22 01:27:54 +00001720 arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001721 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001722 break;
1723# endif
1724
1725 case IIOCGETCPS:
1726 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
1727 * when KERNEL was. I never saw a larger value than 64 though */
1728# ifndef ISDN_MAX_CHANNELS
1729# define ISDN_MAX_CHANNELS 64
1730# endif
sewardj8c824512002-04-14 04:16:48 +00001731 must_be_writable( tst, "ioctl(IIOCGETCPS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001732 ISDN_MAX_CHANNELS
1733 * 2 * sizeof(unsigned long) );
sewardj2e93c502002-04-12 11:12:52 +00001734 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001735 if (!VG_(is_kerror)(res) && res == 0)
1736 make_readable ( arg3, ISDN_MAX_CHANNELS
1737 * 2 * sizeof(unsigned long) );
1738 break;
1739 case IIOCNETGPN:
sewardj8c824512002-04-14 04:16:48 +00001740 must_be_readable( tst, "ioctl(IIOCNETGPN)",
sewardjde4a1d02002-03-22 01:27:54 +00001741 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
1742 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
sewardj8c824512002-04-14 04:16:48 +00001743 must_be_writable( tst, "ioctl(IIOCNETGPN)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001744 sizeof(isdn_net_ioctl_phone) );
sewardj2e93c502002-04-12 11:12:52 +00001745 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001746 if (!VG_(is_kerror)(res) && res == 0)
1747 make_readable ( arg3, sizeof(isdn_net_ioctl_phone) );
1748 break;
1749
1750 /* These all use struct ifreq AFAIK */
1751 case SIOCGIFINDEX:
1752 case SIOCGIFFLAGS: /* get flags */
1753 case SIOCGIFHWADDR: /* Get hardware address */
1754 case SIOCGIFMTU: /* get MTU size */
1755 case SIOCGIFADDR: /* get PA address */
1756 case SIOCGIFNETMASK: /* get network PA mask */
1757 case SIOCGIFMETRIC: /* get metric */
1758 case SIOCGIFMAP: /* Get device parameters */
1759 case SIOCGIFTXQLEN: /* Get the tx queue length */
1760 case SIOCGIFDSTADDR: /* get remote PA address */
1761 case SIOCGIFBRDADDR: /* get broadcast PA address */
1762 case SIOCGIFNAME: /* get iface name */
sewardj8c824512002-04-14 04:16:48 +00001763 must_be_writable(tst, "ioctl(SIOCGIFINDEX)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001764 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001765 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001766 if (!VG_(is_kerror)(res) && res == 0)
1767 make_readable (arg3, sizeof(struct ifreq));
1768 break;
1769 case SIOCGIFCONF: /* get iface list */
1770 /* WAS:
1771 must_be_writable("ioctl(SIOCGIFCONF)", arg3,
1772 sizeof(struct ifconf));
sewardj2e93c502002-04-12 11:12:52 +00001773 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001774 if (!VG_(is_kerror)(res) && res == 0)
1775 make_readable (arg3, sizeof(struct ifconf));
1776 */
sewardj8c824512002-04-14 04:16:48 +00001777 must_be_readable(tst, "ioctl(SIOCGIFCONF)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001778 sizeof(struct ifconf));
1779 if ( arg3 ) {
1780 // TODO len must be readable and writable
1781 // buf pointer only needs to be readable
1782 struct ifconf *ifc = (struct ifconf *) arg3;
sewardj8c824512002-04-14 04:16:48 +00001783 must_be_writable(tst, "ioctl(SIOCGIFCONF).ifc_buf",
sewardjde4a1d02002-03-22 01:27:54 +00001784 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1785 }
sewardj2e93c502002-04-12 11:12:52 +00001786 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001787 if (!VG_(is_kerror)(res) && res == 0 && arg3 ) {
1788 struct ifconf *ifc = (struct ifconf *) arg3;
1789 make_readable ( (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
1790 }
1791 break;
1792 case SIOCGSTAMP:
sewardj8c824512002-04-14 04:16:48 +00001793 must_be_writable(tst, "ioctl(SIOCGSTAMP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001794 sizeof(struct timeval));
sewardj2e93c502002-04-12 11:12:52 +00001795 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001796 if (!VG_(is_kerror)(res) && res == 0)
1797 make_readable (arg3, sizeof(struct timeval));
1798 break;
1799 case SIOCGRARP: /* get RARP table entry */
1800 case SIOCGARP: /* get ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001801 must_be_writable(tst, "ioctl(SIOCGARP)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001802 sizeof(struct arpreq));
sewardj2e93c502002-04-12 11:12:52 +00001803 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001804 if (!VG_(is_kerror)(res) && res == 0)
1805 make_readable (arg3, sizeof(struct arpreq));
1806 break;
1807
1808 case SIOCSIFFLAGS: /* set flags */
1809 case SIOCSIFMAP: /* Set device parameters */
1810 case SIOCSIFTXQLEN: /* Set the tx queue length */
1811 case SIOCSIFDSTADDR: /* set remote PA address */
1812 case SIOCSIFBRDADDR: /* set broadcast PA address */
1813 case SIOCSIFNETMASK: /* set network PA mask */
1814 case SIOCSIFMETRIC: /* set metric */
1815 case SIOCSIFADDR: /* set PA address */
1816 case SIOCSIFMTU: /* set MTU size */
1817 case SIOCSIFHWADDR: /* set hardware address */
sewardj8c824512002-04-14 04:16:48 +00001818 must_be_readable(tst,"ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001819 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001820 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001821 break;
1822 /* Routing table calls. */
1823 case SIOCADDRT: /* add routing table entry */
1824 case SIOCDELRT: /* delete routing table entry */
sewardj8c824512002-04-14 04:16:48 +00001825 must_be_readable(tst,"ioctl(SIOCADDRT/DELRT)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001826 sizeof(struct rtentry));
sewardj2e93c502002-04-12 11:12:52 +00001827 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001828 break;
1829
1830 /* RARP cache control calls. */
1831 case SIOCDRARP: /* delete RARP table entry */
1832 case SIOCSRARP: /* set RARP table entry */
1833 /* ARP cache control calls. */
1834 case SIOCSARP: /* set ARP table entry */
1835 case SIOCDARP: /* delete ARP table entry */
sewardj8c824512002-04-14 04:16:48 +00001836 must_be_readable(tst, "ioctl(SIOCSIFFLAGS)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001837 sizeof(struct ifreq));
sewardj2e93c502002-04-12 11:12:52 +00001838 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001839 break;
1840
1841 case SIOCSPGRP:
sewardj8c824512002-04-14 04:16:48 +00001842 must_be_readable( tst, "ioctl(SIOCSPGRP)", arg3, sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00001843 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001844 break;
1845
1846 /* linux/soundcard interface (OSS) */
1847 case SNDCTL_SEQ_GETOUTCOUNT:
1848 case SNDCTL_SEQ_GETINCOUNT:
1849 case SNDCTL_SEQ_PERCMODE:
1850 case SNDCTL_SEQ_TESTMIDI:
1851 case SNDCTL_SEQ_RESETSAMPLES:
1852 case SNDCTL_SEQ_NRSYNTHS:
1853 case SNDCTL_SEQ_NRMIDIS:
1854 case SNDCTL_SEQ_GETTIME:
1855 case SNDCTL_DSP_GETFMTS:
1856 case SNDCTL_DSP_GETTRIGGER:
1857 case SNDCTL_DSP_GETODELAY:
1858# if defined(SNDCTL_DSP_GETSPDIF)
1859 case SNDCTL_DSP_GETSPDIF:
1860# endif
1861 case SNDCTL_DSP_GETCAPS:
1862 case SOUND_PCM_READ_RATE:
1863 case SOUND_PCM_READ_CHANNELS:
1864 case SOUND_PCM_READ_BITS:
1865 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
1866 case SOUND_PCM_READ_FILTER:
sewardj8c824512002-04-14 04:16:48 +00001867 must_be_writable(tst,"ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
1868 arg3,
sewardjde4a1d02002-03-22 01:27:54 +00001869 sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001870 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001871 if (!VG_(is_kerror)(res) && res == 0)
1872 make_readable (arg3, sizeof(int));
1873 break;
1874 case SNDCTL_SEQ_CTRLRATE:
1875 case SNDCTL_DSP_SPEED:
1876 case SNDCTL_DSP_STEREO:
1877 case SNDCTL_DSP_GETBLKSIZE:
1878 case SNDCTL_DSP_CHANNELS:
1879 case SOUND_PCM_WRITE_FILTER:
1880 case SNDCTL_DSP_SUBDIVIDE:
1881 case SNDCTL_DSP_SETFRAGMENT:
sewardj8a5089d2002-03-24 11:43:56 +00001882# if defined(SNDCTL_DSP_GETCHANNELMASK)
sewardjde4a1d02002-03-22 01:27:54 +00001883 case SNDCTL_DSP_GETCHANNELMASK:
sewardj8a5089d2002-03-24 11:43:56 +00001884# endif
1885# if defined(SNDCTL_DSP_BIND_CHANNEL)
sewardjde4a1d02002-03-22 01:27:54 +00001886 case SNDCTL_DSP_BIND_CHANNEL:
sewardj8a5089d2002-03-24 11:43:56 +00001887# endif
sewardjde4a1d02002-03-22 01:27:54 +00001888 case SNDCTL_TMR_TIMEBASE:
1889 case SNDCTL_TMR_TEMPO:
1890 case SNDCTL_TMR_SOURCE:
1891 case SNDCTL_MIDI_PRETIME:
1892 case SNDCTL_MIDI_MPUMODE:
sewardj8c824512002-04-14 04:16:48 +00001893 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1894 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001895 arg3, sizeof(int));
sewardj8c824512002-04-14 04:16:48 +00001896 must_be_writable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX "
1897 "(SIOWR, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001898 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001899 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001900 break;
1901 case SNDCTL_DSP_GETOSPACE:
1902 case SNDCTL_DSP_GETISPACE:
sewardj8c824512002-04-14 04:16:48 +00001903 must_be_writable(tst,
1904 "ioctl(SNDCTL_XXX|SOUND_XXX "
sewardjde4a1d02002-03-22 01:27:54 +00001905 "(SIOR, audio_buf_info))", arg3,
1906 sizeof(audio_buf_info));
sewardj2e93c502002-04-12 11:12:52 +00001907 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001908 if (!VG_(is_kerror)(res) && res == 0)
1909 make_readable (arg3, sizeof(audio_buf_info));
1910 break;
1911 case SNDCTL_DSP_SETTRIGGER:
sewardj8c824512002-04-14 04:16:48 +00001912 must_be_readable(tst, "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
sewardjde4a1d02002-03-22 01:27:54 +00001913 arg3, sizeof(int));
sewardj2e93c502002-04-12 11:12:52 +00001914 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00001915 break;
sewardj0aa4c252002-04-27 02:20:14 +00001916
1917 /* Real Time Clock (/dev/rtc) ioctls */
sewardjfbe18b92002-05-10 00:46:59 +00001918# ifndef GLIBC_2_1
sewardj0aa4c252002-04-27 02:20:14 +00001919 case RTC_UIE_ON:
1920 case RTC_UIE_OFF:
1921 case RTC_AIE_ON:
1922 case RTC_AIE_OFF:
1923 case RTC_PIE_ON:
1924 case RTC_PIE_OFF:
1925 case RTC_IRQP_SET:
1926 KERNEL_DO_SYSCALL(tid,res);
1927 break;
1928 case RTC_RD_TIME:
1929 case RTC_ALM_READ:
1930 must_be_writable(tst, "ioctl(RTC_RD_TIME/ALM_READ)", arg3,
1931 sizeof(struct rtc_time));
1932 KERNEL_DO_SYSCALL(tid,res);
1933 if (!VG_(is_kerror) && res == 0)
1934 make_readable(arg3, sizeof(struct rtc_time));
1935 break;
1936 case RTC_ALM_SET:
1937 must_be_readable(tst, "ioctl(RTC_ALM_SET)", arg3,
1938 sizeof(struct rtc_time));
1939 KERNEL_DO_SYSCALL(tid,res);
1940 break;
1941 case RTC_IRQP_READ:
1942 must_be_writable(tst, "ioctl(RTC_IRQP_READ)", arg3,
1943 sizeof(unsigned long));
1944 KERNEL_DO_SYSCALL(tid,res);
1945 if(!VG_(is_kerror) && res == 0)
1946 make_readable(arg3, sizeof(unsigned long));
1947 break;
sewardjfbe18b92002-05-10 00:46:59 +00001948# endif /* GLIBC_2_1 */
sewardjeea0f2e2002-04-27 02:28:19 +00001949
1950 /* CD ROM stuff (??) */
1951 case CDROMSUBCHNL:
1952 must_be_readable(tst, "ioctl(CDROMSUBCHNL (cdsc_format, char))",
1953 (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format),
1954 sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
1955 must_be_writable(tst, "ioctl(CDROMSUBCHNL)", arg3,
1956 sizeof(struct cdrom_subchnl));
1957 KERNEL_DO_SYSCALL(tid,res);
1958 if (!VG_(is_kerror)(res) && res == 0)
1959 make_readable (arg3, sizeof(struct cdrom_subchnl));
1960 break;
1961 case CDROMREADTOCHDR:
1962 must_be_writable(tst, "ioctl(CDROMREADTOCHDR)", arg3,
1963 sizeof(struct cdrom_tochdr));
1964 KERNEL_DO_SYSCALL(tid,res);
1965 if (!VG_(is_kerror)(res) && res == 0)
1966 make_readable (arg3, sizeof(struct cdrom_tochdr));
1967 break;
1968 case CDROMREADTOCENTRY:
1969 must_be_readable(tst, "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
1970 (int) &(((struct cdrom_tocentry *) arg3)->cdte_format),
1971 sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
1972 must_be_readable(tst, "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
1973 (int) &(((struct cdrom_tocentry *) arg3)->cdte_track),
1974 sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
1975 must_be_writable(tst, "ioctl(CDROMREADTOCENTRY)", arg3,
1976 sizeof(struct cdrom_tocentry));
1977 KERNEL_DO_SYSCALL(tid,res);
1978 if (!VG_(is_kerror)(res) && res == 0)
1979 make_readable (arg3, sizeof(struct cdrom_tochdr));
1980 break;
1981 case CDROMPLAYMSF:
1982 must_be_readable(tst, "ioctl(CDROMPLAYMSF)", arg3,
1983 sizeof(struct cdrom_msf));
1984 KERNEL_DO_SYSCALL(tid,res);
1985 break;
sewardjde4a1d02002-03-22 01:27:54 +00001986 /* We don't have any specific information on it, so
1987 try to do something reasonable based on direction and
1988 size bits. The encoding scheme is described in
sewardja4da9372002-05-21 00:44:02 +00001989 /usr/include/asm/ioctl.h.
1990
1991 According to Simon Hausmann, _IOC_READ means the kernel
1992 writes a value to the ioctl value passed from the user
1993 space and the other way around with _IOC_WRITE. */
sewardjde4a1d02002-03-22 01:27:54 +00001994 default: {
1995 UInt dir = _IOC_DIR(arg2);
1996 UInt size = _IOC_SIZE(arg2);
1997 if (/* size == 0 || */ dir == _IOC_NONE) {
1998 VG_(message)(Vg_UserMsg,
1999 "Warning: noted but unhandled ioctl 0x%x"
2000 " with no size/direction hints",
2001 arg2);
2002 VG_(message)(Vg_UserMsg,
2003 " This could cause spurious value errors"
2004 " to appear.");
2005 VG_(message)(Vg_UserMsg,
2006 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on"
2007 " writing a proper wrapper." );
2008 } else {
sewardjde4a1d02002-03-22 01:27:54 +00002009 if ((dir & _IOC_WRITE) && size > 0)
sewardja4da9372002-05-21 00:44:02 +00002010 must_be_readable(tst, "ioctl(generic)", arg3, size);
2011 if ((dir & _IOC_READ) && size > 0)
sewardj8c824512002-04-14 04:16:48 +00002012 must_be_writable(tst, "ioctl(generic)", arg3, size);
sewardjde4a1d02002-03-22 01:27:54 +00002013 }
sewardj2e93c502002-04-12 11:12:52 +00002014 KERNEL_DO_SYSCALL(tid,res);
sewardja4da9372002-05-21 00:44:02 +00002015 if (size > 0 && (dir & _IOC_READ)
sewardjde4a1d02002-03-22 01:27:54 +00002016 && !VG_(is_kerror)(res) && res == 0)
2017 make_readable (arg3, size);
2018 break;
2019 }
2020 }
2021 break;
2022
2023 case __NR_kill: /* syscall 37 */
2024 /* int kill(pid_t pid, int sig); */
2025 if (VG_(clo_trace_syscalls))
2026 VG_(printf)("kill ( %d, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00002027 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002028 break;
2029
2030 case __NR_link: /* syscall 9 */
2031 /* int link(const char *oldpath, const char *newpath); */
2032 if (VG_(clo_trace_syscalls))
2033 VG_(printf)("link ( %p, %p)\n", arg1, arg2);
sewardj8c824512002-04-14 04:16:48 +00002034 must_be_readable_asciiz( tst, "link(oldpath)", arg1);
2035 must_be_readable_asciiz( tst, "link(newpath)", arg2);
sewardj2e93c502002-04-12 11:12:52 +00002036 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002037 break;
2038
2039 case __NR_lseek: /* syscall 19 */
2040 /* off_t lseek(int fildes, off_t offset, int whence); */
2041 if (VG_(clo_trace_syscalls))
2042 VG_(printf)("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00002043 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002044 break;
2045
2046 case __NR__llseek: /* syscall 140 */
2047 /* int _llseek(unsigned int fd, unsigned long offset_high,
2048 unsigned long offset_low,
2049 loff_t * result, unsigned int whence); */
2050 if (VG_(clo_trace_syscalls))
2051 VG_(printf)("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
2052 arg1,arg2,arg3,arg4,arg5);
sewardj8c824512002-04-14 04:16:48 +00002053 must_be_writable( tst, "llseek(result)", arg4, sizeof(loff_t));
sewardj2e93c502002-04-12 11:12:52 +00002054 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002055 if (!VG_(is_kerror)(res) && res == 0)
2056 make_readable( arg4, sizeof(loff_t) );
2057 break;
2058
2059 case __NR_lstat: /* syscall 107 */
2060 /* int lstat(const char *file_name, struct stat *buf); */
2061 if (VG_(clo_trace_syscalls))
2062 VG_(printf)("lstat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002063 must_be_readable_asciiz( tst, "lstat(file_name)", arg1 );
2064 must_be_writable( tst, "lstat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002065 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002066 if (!VG_(is_kerror)(res) && res == 0) {
2067 make_readable( arg2, sizeof(struct stat) );
2068 }
2069 break;
2070
2071# if defined(__NR_lstat64)
2072 case __NR_lstat64: /* syscall 196 */
2073 /* int lstat64(const char *file_name, struct stat64 *buf); */
2074 if (VG_(clo_trace_syscalls))
2075 VG_(printf)("lstat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002076 must_be_readable_asciiz( tst, "lstat64(file_name)", arg1 );
2077 must_be_writable( tst, "lstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002078 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002079 if (!VG_(is_kerror)(res) && res == 0) {
2080 make_readable( arg2, sizeof(struct stat64) );
2081 }
2082 break;
2083# endif
2084
2085 case __NR_mkdir: /* syscall 39 */
2086 /* int mkdir(const char *pathname, mode_t mode); */
2087 if (VG_(clo_trace_syscalls))
2088 VG_(printf)("mkdir ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002089 must_be_readable_asciiz( tst, "mkdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002090 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002091 break;
2092
2093# if defined(__NR_mmap2)
2094 case __NR_mmap2: /* syscall 192 */
2095 /* My impression is that this is exactly like __NR_mmap
2096 except that all 6 args are passed in regs, rather than in
2097 a memory-block. */
2098 /* void* mmap(void *start, size_t length, int prot,
2099 int flags, int fd, off_t offset);
2100 */
2101 {
sewardj2e93c502002-04-12 11:12:52 +00002102 UInt arg6 = tst->m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +00002103 if (VG_(clo_trace_syscalls))
2104 VG_(printf)("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
2105 arg1, arg2, arg3, arg4, arg5, arg6 );
sewardj2e93c502002-04-12 11:12:52 +00002106 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002107 /* !!! shouldn't we also be doing the symtab loading stuff as
2108 in __NR_mmap ? */
2109 if (!VG_(is_kerror)(res))
2110 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
2111 }
2112 break;
2113# endif
2114
2115 case __NR_mmap: /* syscall 90 */
2116 /* void* mmap(void *start, size_t length, int prot,
2117 int flags, int fd, off_t offset);
2118 */
2119 {
2120 Bool arg_block_readable
2121 = VG_(clo_instrument)
2122 ? VGM_(check_readable)(arg1, 6*sizeof(UInt), NULL)
2123 : True;
sewardj8c824512002-04-14 04:16:48 +00002124 must_be_readable( tst, "mmap(args)", arg1, 6*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002125 if (arg_block_readable) {
2126 UInt* arg_block = (UInt*)arg1;
2127 UInt arg6;
2128 arg1 = arg_block[0];
2129 arg2 = arg_block[1];
2130 arg3 = arg_block[2];
2131 arg4 = arg_block[3];
2132 arg5 = arg_block[4];
2133 arg6 = arg_block[5];
2134 if (VG_(clo_trace_syscalls))
2135 VG_(printf)("mmap ( %p, %d, %d, %d, %d, %d )\n",
2136 arg1, arg2, arg3, arg4, arg5, arg6 );
2137 }
sewardj2e93c502002-04-12 11:12:52 +00002138 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002139 if (arg_block_readable && !VG_(is_kerror)(res))
2140 approximate_mmap_permissions( (Addr)res, arg2, arg3 );
2141 if (arg_block_readable && !VG_(is_kerror)(res)
2142 && (arg3 & PROT_EXEC)) {
2143 /* The client mmap'ed a segment with executable
2144 permissions. Tell the symbol-table loader, so that it
2145 has an opportunity to pick up more symbols if this mmap
2146 was caused by the client loading a new .so via
2147 dlopen(). This is important for debugging KDE. */
2148 VG_(read_symbols)();
2149 }
2150 }
2151
2152 break;
2153
2154 case __NR_mprotect: /* syscall 125 */
2155 /* int mprotect(const void *addr, size_t len, int prot); */
2156 /* should addr .. addr+len-1 be checked before the call? */
2157 if (VG_(clo_trace_syscalls))
2158 VG_(printf)("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
sewardj2e93c502002-04-12 11:12:52 +00002159 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002160 if (!VG_(is_kerror)(res))
2161 approximate_mmap_permissions ( arg1, arg2, arg3 );
2162 break;
2163
2164 case __NR_munmap: /* syscall 91 */
2165 /* int munmap(void *start, size_t length); */
2166 /* should start .. start+length-1 be checked before the call? */
2167 if (VG_(clo_trace_syscalls))
2168 VG_(printf)("munmap ( %p, %d )\n", arg1,arg2);
sewardj2e93c502002-04-12 11:12:52 +00002169 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002170 if (!VG_(is_kerror)(res)) {
2171 /* Mash around start and length so that the area passed to
2172 make_noaccess() exactly covers an integral number of
2173 pages. If we don't do that, our idea of addressible
2174 memory diverges from that of the kernel's, which causes
2175 the leak detector to crash. */
sewardj18d75132002-05-16 11:06:21 +00002176 Bool munmap_exe;
sewardjde4a1d02002-03-22 01:27:54 +00002177 Addr start = arg1;
2178 Addr length = arg2;
2179 while ((start % VKI_BYTES_PER_PAGE) > 0) { start--; length++; }
2180 while (((start+length) % VKI_BYTES_PER_PAGE) > 0) { length++; }
2181 /*
2182 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
2183 arg1, arg2, start, length, (arg1!=start || arg2!=length)
2184 ? "CHANGE" : "");
2185 */
2186 make_noaccess( start, length );
2187 /* Tell our symbol table machinery about this, so that if
2188 this happens to be a .so being unloaded, the relevant
2189 symbols are removed too. */
sewardj18d75132002-05-16 11:06:21 +00002190 munmap_exe = VG_(symtab_notify_munmap) ( start, length );
2191 if (munmap_exe)
2192 VG_(invalidate_translations) ( start, length );
sewardjde4a1d02002-03-22 01:27:54 +00002193 }
2194 break;
2195
2196 case __NR_nanosleep: /* syscall 162 */
2197 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
2198 if (VG_(clo_trace_syscalls))
2199 VG_(printf)("nanosleep ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002200 must_be_readable ( tst, "nanosleep(req)", arg1,
sewardjde4a1d02002-03-22 01:27:54 +00002201 sizeof(struct timespec) );
2202 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002203 must_be_writable ( tst, "nanosleep(rem)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002204 sizeof(struct timespec) );
sewardj2e93c502002-04-12 11:12:52 +00002205 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002206 /* Somewhat bogus ... is only written by the kernel if
2207 res == -1 && errno == EINTR. */
2208 if (!VG_(is_kerror)(res) && arg2 != (UInt)NULL)
2209 make_readable ( arg2, sizeof(struct timespec) );
2210 break;
2211
2212 case __NR__newselect: /* syscall 142 */
2213 /* int select(int n,
2214 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
2215 struct timeval *timeout);
2216 */
2217 if (VG_(clo_trace_syscalls))
2218 VG_(printf)("newselect ( %d, %p, %p, %p, %p )\n",
2219 arg1,arg2,arg3,arg4,arg5);
2220 if (arg2 != 0)
sewardj8c824512002-04-14 04:16:48 +00002221 must_be_readable( tst, "newselect(readfds)",
sewardjde4a1d02002-03-22 01:27:54 +00002222 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
2223 if (arg3 != 0)
sewardj8c824512002-04-14 04:16:48 +00002224 must_be_readable( tst, "newselect(writefds)",
sewardjde4a1d02002-03-22 01:27:54 +00002225 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
2226 if (arg4 != 0)
sewardj8c824512002-04-14 04:16:48 +00002227 must_be_readable( tst, "newselect(exceptfds)",
sewardjde4a1d02002-03-22 01:27:54 +00002228 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
2229 if (arg5 != 0)
sewardj8c824512002-04-14 04:16:48 +00002230 must_be_readable( tst, "newselect(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002231 sizeof(struct timeval) );
sewardj2e93c502002-04-12 11:12:52 +00002232 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002233 break;
2234
2235 case __NR_open: /* syscall 5 */
2236 /* int open(const char *pathname, int flags); */
2237 if (VG_(clo_trace_syscalls))
2238 VG_(printf)("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002239 must_be_readable_asciiz( tst, "open(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002240 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002241 if (VG_(clo_trace_syscalls))
2242 VG_(printf)("%d\n",res);
2243 break;
2244
2245 case __NR_pipe: /* syscall 42 */
2246 /* int pipe(int filedes[2]); */
2247 if (VG_(clo_trace_syscalls))
2248 VG_(printf)("pipe ( %p ) ...\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002249 must_be_writable( tst, "pipe(filedes)", arg1, 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002250 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002251 if (!VG_(is_kerror)(res))
2252 make_readable ( arg1, 2*sizeof(int) );
2253 if (VG_(clo_trace_syscalls) && !VG_(is_kerror)(res))
sewardj2e93c502002-04-12 11:12:52 +00002254 VG_(printf)("SYSCALL[%d] pipe --> (rd %d, wr %d)\n",
2255 VG_(getpid)(),
sewardjde4a1d02002-03-22 01:27:54 +00002256 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
2257 break;
2258
2259 case __NR_poll: /* syscall 168 */
2260 /* struct pollfd {
2261 int fd; -- file descriptor
2262 short events; -- requested events
2263 short revents; -- returned events
2264 };
2265 int poll(struct pollfd *ufds, unsigned int nfds,
2266 int timeout)
2267 */
2268 if (VG_(clo_trace_syscalls))
sewardja4da9372002-05-21 00:44:02 +00002269 VG_(printf)("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
sewardjde4a1d02002-03-22 01:27:54 +00002270 /* In fact some parts of this struct should be readable too.
2271 This should be fixed properly. */
sewardj8c824512002-04-14 04:16:48 +00002272 must_be_writable( tst, "poll(ufds)",
2273 arg1, arg2 * sizeof(struct pollfd) );
sewardj2e93c502002-04-12 11:12:52 +00002274 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002275 if (!VG_(is_kerror)(res) && res > 0) {
2276 Int i;
2277 struct pollfd * arr = (struct pollfd *)arg1;
2278 for (i = 0; i < arg2; i++)
2279 make_readable( (Addr)(&arr[i].revents), sizeof(Short) );
2280 }
2281 break;
2282
sewardjde4a1d02002-03-22 01:27:54 +00002283 case __NR_readlink: /* syscall 85 */
2284 /* int readlink(const char *path, char *buf, size_t bufsiz); */
2285 if (VG_(clo_trace_syscalls))
2286 VG_(printf)("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002287 must_be_readable_asciiz( tst, "readlink(path)", arg1 );
2288 must_be_writable ( tst, "readlink(buf)", arg2,arg3 );
sewardj2e93c502002-04-12 11:12:52 +00002289 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002290 if (!VG_(is_kerror)(res) && res > 0) {
2291 make_readable ( arg2, res );
2292 }
2293 break;
2294
2295 case __NR_readv: { /* syscall 145 */
2296 /* int readv(int fd, const struct iovec * vector, size_t count); */
2297 UInt i;
2298 struct iovec * vec;
2299 if (VG_(clo_trace_syscalls))
2300 VG_(printf)("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002301 must_be_readable( tst, "readv(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002302 arg2, arg3 * sizeof(struct iovec) );
2303 /* ToDo: don't do any of the following if the vector is invalid */
2304 vec = (struct iovec *)arg2;
2305 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002306 must_be_writable( tst, "readv(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002307 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002308 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002309 if (!VG_(is_kerror)(res) && res > 0) {
2310 /* res holds the number of bytes read. */
2311 for (i = 0; i < arg3; i++) {
2312 Int nReadThisBuf = vec[i].iov_len;
2313 if (nReadThisBuf > res) nReadThisBuf = res;
2314 make_readable( (UInt)vec[i].iov_base, nReadThisBuf );
2315 res -= nReadThisBuf;
2316 if (res < 0) VG_(panic)("vg_wrap_syscall: readv: res < 0");
2317 }
2318 }
2319 break;
2320 }
2321
2322 case __NR_rename: /* syscall 38 */
2323 /* int rename(const char *oldpath, const char *newpath); */
2324 if (VG_(clo_trace_syscalls))
2325 VG_(printf)("rename ( %p, %p )\n", arg1, arg2 );
sewardj8c824512002-04-14 04:16:48 +00002326 must_be_readable_asciiz( tst, "rename(oldpath)", arg1 );
2327 must_be_readable_asciiz( tst, "rename(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002328 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002329 break;
2330
2331 case __NR_rmdir: /* syscall 40 */
2332 /* int rmdir(const char *pathname); */
2333 if (VG_(clo_trace_syscalls))
2334 VG_(printf)("rmdir ( %p )\n", arg1);
sewardj8c824512002-04-14 04:16:48 +00002335 must_be_readable_asciiz( tst, "rmdir(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002336 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002337 break;
2338
sewardja4d4e482002-05-03 21:18:11 +00002339 case __NR_sched_setparam: /* syscall 154 */
2340 /* int sched_setparam(pid_t pid, const struct sched_param *p); */
2341 if (VG_(clo_instrument))
2342 VG_(printf)("sched_setparam ( %d, %p )\n", arg1, arg2 );
2343 must_be_readable( tst, "sched_setparam(ptr)",
2344 arg2, sizeof(struct sched_param) );
2345 KERNEL_DO_SYSCALL(tid,res);
2346 if (!VG_(is_kerror)(res))
2347 make_readable( arg2, sizeof(struct sched_param) );
2348 break;
2349
2350 case __NR_sched_getparam: /* syscall 155 */
2351 /* int sched_getparam(pid_t pid, struct sched_param *p); */
2352 if (VG_(clo_instrument))
2353 VG_(printf)("sched_getparam ( %d, %p )\n", arg1, arg2 );
2354 must_be_writable( tst, "sched_getparam(ptr)",
2355 arg2, sizeof(struct sched_param) );
2356 KERNEL_DO_SYSCALL(tid,res);
2357 if (!VG_(is_kerror)(res))
2358 make_readable( arg2, sizeof(struct sched_param) );
2359 break;
2360
2361 case __NR_sched_yield: /* syscall 158 */
2362 /* int sched_yield(void); */
2363 if (VG_(clo_instrument))
2364 VG_(printf)("sched_yield ()\n" );
sewardj2e93c502002-04-12 11:12:52 +00002365 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002366 break;
2367
2368 case __NR_select: /* syscall 82 */
2369 /* struct sel_arg_struct {
2370 unsigned long n;
2371 fd_set *inp, *outp, *exp;
2372 struct timeval *tvp;
2373 };
2374 int old_select(struct sel_arg_struct *arg);
2375 */
2376 {
2377 Bool arg_block_readable
2378 = VG_(clo_instrument)
2379 ? VGM_(check_readable)(arg1, 5*sizeof(UInt), NULL)
2380 : True;
sewardj8c824512002-04-14 04:16:48 +00002381 must_be_readable ( tst, "select(args)", arg1, 5*sizeof(UInt) );
sewardjde4a1d02002-03-22 01:27:54 +00002382 if (arg_block_readable) {
2383 UInt* arg_struct = (UInt*)arg1;
2384 arg1 = arg_struct[0];
2385 arg2 = arg_struct[1];
2386 arg3 = arg_struct[2];
2387 arg4 = arg_struct[3];
2388 arg5 = arg_struct[4];
2389
2390 if (VG_(clo_trace_syscalls))
2391 VG_(printf)("select ( %d, %p, %p, %p, %p )\n",
2392 arg1,arg2,arg3,arg4,arg5);
2393 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002394 must_be_readable(tst, "select(readfds)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002395 arg1/8 /* __FD_SETSIZE/8 */ );
2396 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002397 must_be_readable(tst, "select(writefds)", arg3,
sewardjde4a1d02002-03-22 01:27:54 +00002398 arg1/8 /* __FD_SETSIZE/8 */ );
2399 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002400 must_be_readable(tst, "select(exceptfds)", arg4,
sewardjde4a1d02002-03-22 01:27:54 +00002401 arg1/8 /* __FD_SETSIZE/8 */ );
2402 if (arg5 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002403 must_be_readable(tst, "select(timeout)", arg5,
sewardjde4a1d02002-03-22 01:27:54 +00002404 sizeof(struct timeval) );
2405 }
2406 }
sewardj2e93c502002-04-12 11:12:52 +00002407 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002408 break;
2409
2410 case __NR_setitimer: /* syscall 104 */
2411 /* setitimer(int which, const struct itimerval *value,
2412 struct itimerval *ovalue); */
2413 if (VG_(clo_trace_syscalls))
2414 VG_(printf)("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002415 must_be_readable(tst, "setitimer(value)",
sewardjde4a1d02002-03-22 01:27:54 +00002416 arg2, sizeof(struct itimerval) );
2417 if (arg3 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002418 must_be_writable(tst, "setitimer(ovalue)",
sewardjde4a1d02002-03-22 01:27:54 +00002419 arg3, sizeof(struct itimerval));
sewardj2e93c502002-04-12 11:12:52 +00002420 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002421 if (!VG_(is_kerror)(res) && arg3 != (Addr)NULL) {
2422 make_readable(arg3, sizeof(struct itimerval));
2423 }
2424 break;
2425
2426# if defined(__NR_setfsgid32)
2427 case __NR_setfsgid32: /* syscall 216 */
2428 /* int setfsgid(uid_t fsgid); */
2429 if (VG_(clo_trace_syscalls))
2430 VG_(printf)("setfsgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002431 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002432 break;
2433# endif
2434
2435# if defined(__NR_setgid32)
2436 case __NR_setgid32: /* syscall 214 */
2437# endif
2438 case __NR_setgid: /* syscall 46 */
2439 /* int setgid(gid_t gid); */
2440 if (VG_(clo_trace_syscalls))
2441 VG_(printf)("setgid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002442 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002443 break;
2444
2445 case __NR_setsid: /* syscall 66 */
2446 /* pid_t setsid(void); */
2447 if (VG_(clo_trace_syscalls))
2448 VG_(printf)("setsid ()\n");
sewardj2e93c502002-04-12 11:12:52 +00002449 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002450 break;
2451
2452# if defined(__NR_setgroups32)
2453 case __NR_setgroups32: /* syscall 206 */
sewardj2f0de322002-03-24 10:17:25 +00002454# endif
2455 case __NR_setgroups: /* syscall 81 */
sewardjde4a1d02002-03-22 01:27:54 +00002456 /* int setgroups(size_t size, const gid_t *list); */
2457 if (VG_(clo_trace_syscalls))
2458 VG_(printf)("setgroups ( %d, %p )\n", arg1, arg2);
2459 if (arg1 > 0)
sewardj8c824512002-04-14 04:16:48 +00002460 must_be_readable ( tst, "setgroups(list)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002461 arg1 * sizeof(gid_t) );
sewardj2e93c502002-04-12 11:12:52 +00002462 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002463 break;
sewardjde4a1d02002-03-22 01:27:54 +00002464
2465 case __NR_setpgid: /* syscall 57 */
2466 /* int setpgid(pid_t pid, pid_t pgid); */
2467 if (VG_(clo_trace_syscalls))
2468 VG_(printf)("setpgid ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002469 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002470 break;
2471
2472# if defined(__NR_setregid32)
2473 case __NR_setregid32: /* syscall 204 */
2474 /* int setregid(gid_t rgid, gid_t egid); */
2475 if (VG_(clo_trace_syscalls))
2476 VG_(printf)("setregid32(?) ( %d, %d )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002477 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002478 break;
2479# endif
2480
2481# if defined(__NR_setresuid32)
2482 case __NR_setresuid32: /* syscall 208 */
2483 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
2484 if (VG_(clo_trace_syscalls))
2485 VG_(printf)("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
sewardj2e93c502002-04-12 11:12:52 +00002486 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002487 break;
2488# endif
2489
2490# if defined(__NR_setreuid32)
2491 case __NR_setreuid32: /* syscall 203 */
2492# endif
2493 case __NR_setreuid: /* syscall 70 */
2494 /* int setreuid(uid_t ruid, uid_t euid); */
2495 if (VG_(clo_trace_syscalls))
2496 VG_(printf)("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
sewardj2e93c502002-04-12 11:12:52 +00002497 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002498 break;
2499
2500 case __NR_setrlimit: /* syscall 75 */
2501 /* int setrlimit (int resource, const struct rlimit *rlim); */
2502 if (VG_(clo_trace_syscalls))
2503 VG_(printf)("setrlimit ( %d, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002504 must_be_readable( tst, "setrlimit(rlim)", arg2, sizeof(struct rlimit) );
sewardj2e93c502002-04-12 11:12:52 +00002505 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002506 break;
2507
2508# if defined(__NR_setuid32)
2509 case __NR_setuid32: /* syscall 213 */
2510# endif
2511 case __NR_setuid: /* syscall 23 */
2512 /* int setuid(uid_t uid); */
2513 if (VG_(clo_trace_syscalls))
2514 VG_(printf)("setuid ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002515 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002516 break;
2517
2518 case __NR_socketcall: /* syscall 102 */
2519 /* int socketcall(int call, unsigned long *args); */
2520 if (VG_(clo_trace_syscalls))
2521 VG_(printf)("socketcall ( %d, %p )\n",arg1,arg2);
2522 switch (arg1 /* request */) {
2523
2524 case SYS_SOCKETPAIR:
2525 /* int socketpair(int d, int type, int protocol, int sv[2]); */
sewardj8c824512002-04-14 04:16:48 +00002526 must_be_readable( tst, "socketcall.socketpair(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002527 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002528 must_be_writable( tst, "socketcall.socketpair(sv)",
sewardjde4a1d02002-03-22 01:27:54 +00002529 ((UInt*)arg2)[3], 2*sizeof(int) );
sewardj2e93c502002-04-12 11:12:52 +00002530 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002531 if (!VG_(is_kerror)(res))
2532 make_readable ( ((UInt*)arg2)[3], 2*sizeof(int) );
2533 break;
2534
2535 case SYS_SOCKET:
2536 /* int socket(int domain, int type, int protocol); */
sewardj8c824512002-04-14 04:16:48 +00002537 must_be_readable( tst, "socketcall.socket(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002538 arg2, 3*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002539 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002540 break;
2541
2542 case SYS_BIND:
2543 /* int bind(int sockfd, struct sockaddr *my_addr,
2544 int addrlen); */
sewardj8c824512002-04-14 04:16:48 +00002545 must_be_readable( tst, "socketcall.bind(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002546 arg2, 3*sizeof(Addr) );
sewardjc483e8f2002-05-03 21:01:35 +00002547 must_be_readable_sockaddr( tst, "socketcall.bind(my_addr.%s)",
2548 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
sewardj2e93c502002-04-12 11:12:52 +00002549 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002550 break;
sewardjc483e8f2002-05-03 21:01:35 +00002551
sewardjde4a1d02002-03-22 01:27:54 +00002552 case SYS_LISTEN:
2553 /* int listen(int s, int backlog); */
sewardj8c824512002-04-14 04:16:48 +00002554 must_be_readable( tst, "socketcall.listen(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002555 arg2, 2*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_ACCEPT: {
2560 /* int accept(int s, struct sockaddr *addr, int *p_addrlen); */
2561 Addr addr;
2562 Addr p_addrlen;
2563 UInt addrlen_in, addrlen_out;
sewardj8c824512002-04-14 04:16:48 +00002564 must_be_readable( tst, "socketcall.accept(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002565 arg2, 3*sizeof(Addr) );
2566 addr = ((UInt*)arg2)[1];
2567 p_addrlen = ((UInt*)arg2)[2];
2568 if (p_addrlen != (Addr)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002569 must_be_readable ( tst, "socketcall.accept(addrlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002570 p_addrlen, sizeof(int) );
2571 addrlen_in = safe_dereference( p_addrlen, 0 );
sewardj8c824512002-04-14 04:16:48 +00002572 must_be_writable ( tst, "socketcall.accept(addr)",
sewardjde4a1d02002-03-22 01:27:54 +00002573 addr, addrlen_in );
2574 }
sewardj2e93c502002-04-12 11:12:52 +00002575 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002576 if (!VG_(is_kerror)(res) && res >= 0 && p_addrlen != (Addr)NULL) {
2577 addrlen_out = safe_dereference( p_addrlen, 0 );
2578 if (addrlen_out > 0)
2579 make_readable( addr, addrlen_out );
2580 }
2581 break;
2582 }
2583
2584 case SYS_SENDTO:
2585 /* int sendto(int s, const void *msg, int len,
2586 unsigned int flags,
2587 const struct sockaddr *to, int tolen); */
sewardj8c824512002-04-14 04:16:48 +00002588 must_be_readable( tst, "socketcall.sendto(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002589 6*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002590 must_be_readable( tst, "socketcall.sendto(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002591 ((UInt*)arg2)[1], /* msg */
2592 ((UInt*)arg2)[2] /* len */ );
sewardjc483e8f2002-05-03 21:01:35 +00002593 must_be_readable_sockaddr( tst, "socketcall.sendto(to.%s)",
2594 (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
sewardj2e93c502002-04-12 11:12:52 +00002595 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002596 break;
2597
2598 case SYS_SEND:
2599 /* int send(int s, const void *msg, size_t len, int flags); */
sewardj8c824512002-04-14 04:16:48 +00002600 must_be_readable( tst, "socketcall.send(args)", arg2,
sewardjde4a1d02002-03-22 01:27:54 +00002601 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002602 must_be_readable( tst, "socketcall.send(msg)",
sewardjde4a1d02002-03-22 01:27:54 +00002603 ((UInt*)arg2)[1], /* msg */
2604 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002605 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002606 break;
2607
2608 case SYS_RECVFROM:
2609 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
2610 struct sockaddr *from, int *fromlen); */
sewardj8c824512002-04-14 04:16:48 +00002611 must_be_readable( tst, "socketcall.recvfrom(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002612 arg2, 6*sizeof(Addr) );
2613 if ( ((UInt*)arg2)[4] /* from */ != 0) {
sewardj8c824512002-04-14 04:16:48 +00002614 must_be_readable( tst, "socketcall.recvfrom(fromlen)",
sewardjde4a1d02002-03-22 01:27:54 +00002615 ((UInt*)arg2)[5] /* fromlen */,
2616 sizeof(int) );
sewardj8c824512002-04-14 04:16:48 +00002617 must_be_writable( tst, "socketcall.recvfrom(from)",
sewardjde4a1d02002-03-22 01:27:54 +00002618 ((UInt*)arg2)[4], /*from*/
2619 safe_dereference( (Addr)
2620 ((UInt*)arg2)[5], 0 ) );
2621 }
sewardj8c824512002-04-14 04:16:48 +00002622 must_be_writable( tst, "socketcall.recvfrom(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002623 ((UInt*)arg2)[1], /* buf */
2624 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002625 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002626 if (!VG_(is_kerror)(res) && res >= 0) {
2627 make_readable( ((UInt*)arg2)[1], /* buf */
2628 ((UInt*)arg2)[2] /* len */ );
2629 if ( ((UInt*)arg2)[4] /* from */ != 0) {
2630 make_readable(
2631 ((UInt*)arg2)[4], /*from*/
2632 safe_dereference( (Addr) ((UInt*)arg2)[5], 0 ) );
2633 }
2634 }
2635 /* phew! */
2636 break;
2637
2638 case SYS_RECV:
2639 /* int recv(int s, void *buf, int len, unsigned int flags); */
2640 /* man 2 recv says:
2641 The recv call is normally used only on a connected socket
2642 (see connect(2)) and is identical to recvfrom with a NULL
2643 from parameter.
2644 */
sewardj8c824512002-04-14 04:16:48 +00002645 must_be_readable( tst, "socketcall.recv(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002646 arg2, 4*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002647 must_be_writable( tst, "socketcall.recv(buf)",
sewardjde4a1d02002-03-22 01:27:54 +00002648 ((UInt*)arg2)[1], /* buf */
2649 ((UInt*)arg2)[2] /* len */ );
sewardj2e93c502002-04-12 11:12:52 +00002650 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002651 if (!VG_(is_kerror)(res) && res >= 0
2652 && ((UInt*)arg2)[1] != (UInt)NULL) {
2653 make_readable( ((UInt*)arg2)[1], /* buf */
2654 ((UInt*)arg2)[2] /* len */ );
2655 }
2656 break;
2657
sewardjc483e8f2002-05-03 21:01:35 +00002658 case SYS_CONNECT:
sewardjde4a1d02002-03-22 01:27:54 +00002659 /* int connect(int sockfd,
2660 struct sockaddr *serv_addr, int addrlen ); */
sewardj8c824512002-04-14 04:16:48 +00002661 must_be_readable( tst, "socketcall.connect(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002662 arg2, 3*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002663 must_be_readable( tst, "socketcall.connect(serv_addr.sa_family)",
sewardjde4a1d02002-03-22 01:27:54 +00002664 ((UInt*)arg2)[1], /* serv_addr */
2665 sizeof (sa_family_t));
sewardjc483e8f2002-05-03 21:01:35 +00002666 must_be_readable_sockaddr( tst,
2667 "socketcall.connect(serv_addr.%s)",
2668 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
sewardj2e93c502002-04-12 11:12:52 +00002669 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002670 break;
sewardjde4a1d02002-03-22 01:27:54 +00002671
2672 case SYS_SETSOCKOPT:
2673 /* int setsockopt(int s, int level, int optname,
2674 const void *optval, int optlen); */
sewardj8c824512002-04-14 04:16:48 +00002675 must_be_readable( tst, "socketcall.setsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002676 arg2, 5*sizeof(Addr) );
sewardj8c824512002-04-14 04:16:48 +00002677 must_be_readable( tst, "socketcall.setsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002678 ((UInt*)arg2)[3], /* optval */
2679 ((UInt*)arg2)[4] /* optlen */ );
sewardj2e93c502002-04-12 11:12:52 +00002680 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002681 break;
2682
2683 case SYS_GETSOCKOPT:
2684 /* int setsockopt(int s, int level, int optname,
2685 void *optval, socklen_t *optlen); */
sewardj8c824512002-04-14 04:16:48 +00002686 must_be_readable( tst, "socketcall.getsockopt(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002687 arg2, 5*sizeof(Addr) );
2688 {
2689 Addr optval_p = ((UInt*)arg2)[3];
2690 Addr optlen_p = ((UInt*)arg2)[4];
sewardj8c824512002-04-14 04:16:48 +00002691 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
sewardjde4a1d02002-03-22 01:27:54 +00002692 UInt optlen_after;
2693 UInt optlen = safe_dereference ( optlen_p, 0 );
2694 if (optlen > 0)
sewardj8c824512002-04-14 04:16:48 +00002695 must_be_writable( tst, "socketcall.getsockopt(optval)",
sewardjde4a1d02002-03-22 01:27:54 +00002696 optval_p, optlen );
sewardj2e93c502002-04-12 11:12:52 +00002697 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002698 optlen_after = safe_dereference ( optlen_p, 0 );
2699 if (!VG_(is_kerror)(res) && optlen > 0 && optlen_after > 0)
2700 make_readable( optval_p, optlen_after );
2701 }
2702 break;
2703
2704 case SYS_GETSOCKNAME:
2705 /* int getsockname(int s, struct sockaddr* name,
2706 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002707 must_be_readable( tst, "socketcall.getsockname(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002708 arg2, 3*sizeof(Addr) );
2709 {
2710 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2711 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002712 must_be_writable( tst, "socketcall.getsockname(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002713 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002714 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002715 if (!VG_(is_kerror)(res)) {
2716 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2717 if (namelen > 0
2718 && ((UInt*)arg2)[1] != (UInt)NULL)
2719 make_readable( ((UInt*)arg2)[1], namelen );
2720 }
2721 }
2722 break;
2723
2724 case SYS_GETPEERNAME:
2725 /* int getpeername(int s, struct sockaddr* name,
2726 int* namelen) */
sewardj8c824512002-04-14 04:16:48 +00002727 must_be_readable( tst, "socketcall.getpeername(args)",
sewardjde4a1d02002-03-22 01:27:54 +00002728 arg2, 3*sizeof(Addr) );
2729 {
2730 UInt namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2731 if (namelen > 0)
sewardj8c824512002-04-14 04:16:48 +00002732 must_be_writable( tst, "socketcall.getpeername(name)",
sewardjde4a1d02002-03-22 01:27:54 +00002733 ((UInt*)arg2)[1], namelen );
sewardj2e93c502002-04-12 11:12:52 +00002734 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002735 if (!VG_(is_kerror)(res)) {
2736 namelen = safe_dereference( (Addr) ((UInt*)arg2)[2], 0);
2737 if (namelen > 0
2738 && ((UInt*)arg2)[1] != (UInt)NULL)
2739 make_readable( ((UInt*)arg2)[1], namelen );
2740 }
2741 }
2742 break;
2743
2744 case SYS_SHUTDOWN:
2745 /* int shutdown(int s, int how); */
sewardj8c824512002-04-14 04:16:48 +00002746 must_be_readable( tst, "socketcall.shutdown(args)",
2747 arg2, 2*sizeof(Addr) );
sewardj2e93c502002-04-12 11:12:52 +00002748 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002749 break;
2750
2751 case SYS_SENDMSG:
2752 {
2753 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
2754
2755 /* this causes warnings, and I don't get why. glibc bug?
2756 * (after all it's glibc providing the arguments array)
2757 must_be_readable( "socketcall.sendmsg(args)",
2758 arg2, 3*sizeof(Addr) );
2759 */
2760
2761 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
sewardj8c824512002-04-14 04:16:48 +00002762 msghdr_foreachfield ( tst, msg, must_be_readable_sendmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002763
sewardj2e93c502002-04-12 11:12:52 +00002764 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002765 break;
2766 }
2767
2768 case SYS_RECVMSG:
2769 {
2770 /* int recvmsg(int s, 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.recvmsg(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_writable_recvmsg );
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
2783 if ( !VG_(is_kerror)( res ) )
sewardj8c824512002-04-14 04:16:48 +00002784 msghdr_foreachfield( tst, msg, make_readable_recvmsg );
sewardjde4a1d02002-03-22 01:27:54 +00002785
2786 break;
2787 }
2788
2789 default:
2790 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
2791 VG_(panic)("... bye!\n");
2792 break; /*NOTREACHED*/
2793 }
2794 break;
2795
2796 case __NR_stat: /* syscall 106 */
2797 /* int stat(const char *file_name, struct stat *buf); */
2798 if (VG_(clo_trace_syscalls))
2799 VG_(printf)("stat ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002800 must_be_readable_asciiz( tst, "stat(file_name)", arg1 );
2801 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct stat) );
sewardj2e93c502002-04-12 11:12:52 +00002802 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002803 if (!VG_(is_kerror)(res))
2804 make_readable( arg2, sizeof(struct stat) );
2805 break;
2806
2807 case __NR_statfs: /* syscall 99 */
2808 /* int statfs(const char *path, struct statfs *buf); */
2809 if (VG_(clo_trace_syscalls))
2810 VG_(printf)("statfs ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002811 must_be_readable_asciiz( tst, "statfs(path)", arg1 );
2812 must_be_writable( tst, "stat(buf)", arg2, sizeof(struct statfs) );
sewardj2e93c502002-04-12 11:12:52 +00002813 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002814 if (!VG_(is_kerror)(res))
2815 make_readable( arg2, sizeof(struct statfs) );
2816 break;
2817
2818 case __NR_symlink: /* syscall 83 */
2819 /* int symlink(const char *oldpath, const char *newpath); */
2820 if (VG_(clo_trace_syscalls))
2821 VG_(printf)("symlink ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002822 must_be_readable_asciiz( tst, "symlink(oldpath)", arg1 );
2823 must_be_readable_asciiz( tst, "symlink(newpath)", arg2 );
sewardj2e93c502002-04-12 11:12:52 +00002824 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002825 break;
2826
2827# if defined(__NR_stat64)
2828 case __NR_stat64: /* syscall 195 */
2829 /* int stat64(const char *file_name, struct stat64 *buf); */
2830 if (VG_(clo_trace_syscalls))
2831 VG_(printf)("stat64 ( %p, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002832 must_be_readable_asciiz( tst, "stat64(file_name)", arg1 );
2833 must_be_writable( tst, "stat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002834 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002835 if (!VG_(is_kerror)(res))
2836 make_readable( arg2, sizeof(struct stat64) );
2837 break;
2838# endif
2839
2840# if defined(__NR_fstat64)
2841 case __NR_fstat64: /* syscall 197 */
2842 /* int fstat64(int filedes, struct stat64 *buf); */
2843 if (VG_(clo_trace_syscalls))
2844 VG_(printf)("fstat64 ( %d, %p )\n",arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002845 must_be_writable( tst, "fstat64(buf)", arg2, sizeof(struct stat64) );
sewardj2e93c502002-04-12 11:12:52 +00002846 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002847 if (!VG_(is_kerror)(res))
2848 make_readable( arg2, sizeof(struct stat64) );
2849 break;
2850# endif
2851
2852 case __NR_sysinfo: /* syscall 116 */
2853 /* int sysinfo(struct sysinfo *info); */
2854 if (VG_(clo_trace_syscalls))
2855 VG_(printf)("sysinfo ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002856 must_be_writable( tst, "sysinfo(info)", arg1, sizeof(struct sysinfo) );
sewardj2e93c502002-04-12 11:12:52 +00002857 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002858 if (!VG_(is_kerror)(res))
2859 make_readable( arg1, sizeof(struct sysinfo) );
2860 break;
2861
2862 case __NR_time: /* syscall 13 */
2863 /* time_t time(time_t *t); */
2864 if (VG_(clo_trace_syscalls))
2865 VG_(printf)("time ( %p )\n",arg1);
2866 if (arg1 != (UInt)NULL) {
sewardj8c824512002-04-14 04:16:48 +00002867 must_be_writable( tst, "time", arg1, sizeof(time_t) );
sewardjde4a1d02002-03-22 01:27:54 +00002868 }
sewardj2e93c502002-04-12 11:12:52 +00002869 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002870 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2871 make_readable( arg1, sizeof(time_t) );
2872 }
2873 break;
2874
2875 case __NR_times: /* syscall 43 */
2876 /* clock_t times(struct tms *buf); */
2877 if (VG_(clo_trace_syscalls))
2878 VG_(printf)("times ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002879 must_be_writable( tst, "times(buf)", arg1, sizeof(struct tms) );
sewardj2e93c502002-04-12 11:12:52 +00002880 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002881 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2882 make_readable( arg1, sizeof(struct tms) );
2883 }
2884 break;
2885
2886 case __NR_truncate: /* syscall 92 */
2887 /* int truncate(const char *path, size_t length); */
2888 if (VG_(clo_trace_syscalls))
2889 VG_(printf)("truncate ( %p, %d )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002890 must_be_readable_asciiz( tst, "truncate(path)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002891 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002892 break;
2893
2894 case __NR_umask: /* syscall 60 */
2895 /* mode_t umask(mode_t mask); */
2896 if (VG_(clo_trace_syscalls))
2897 VG_(printf)("umask ( %d )\n", arg1);
sewardj2e93c502002-04-12 11:12:52 +00002898 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002899 break;
2900
2901 case __NR_unlink: /* syscall 10 */
2902 /* int unlink(const char *pathname) */
2903 if (VG_(clo_trace_syscalls))
2904 VG_(printf)("ulink ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002905 must_be_readable_asciiz( tst, "unlink(pathname)", arg1 );
sewardj2e93c502002-04-12 11:12:52 +00002906 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002907 break;
2908
2909 case __NR_uname: /* syscall 122 */
2910 /* int uname(struct utsname *buf); */
2911 if (VG_(clo_trace_syscalls))
2912 VG_(printf)("uname ( %p )\n",arg1);
sewardj8c824512002-04-14 04:16:48 +00002913 must_be_writable( tst, "uname(buf)", arg1, sizeof(struct utsname) );
sewardj2e93c502002-04-12 11:12:52 +00002914 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002915 if (!VG_(is_kerror)(res) && arg1 != (UInt)NULL) {
2916 make_readable( arg1, sizeof(struct utsname) );
2917 }
2918 break;
2919
2920 case __NR_utime: /* syscall 30 */
2921 /* int utime(const char *filename, struct utimbuf *buf); */
2922 if (VG_(clo_trace_syscalls))
2923 VG_(printf)("utime ( %p, %p )\n", arg1,arg2);
sewardj8c824512002-04-14 04:16:48 +00002924 must_be_readable_asciiz( tst, "utime(filename)", arg1 );
sewardjde4a1d02002-03-22 01:27:54 +00002925 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002926 must_be_readable( tst, "utime(buf)", arg2,
2927 sizeof(struct utimbuf) );
sewardj2e93c502002-04-12 11:12:52 +00002928 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002929 break;
2930
2931 case __NR_wait4: /* syscall 114 */
2932 /* pid_t wait4(pid_t pid, int *status, int options,
2933 struct rusage *rusage) */
2934 if (VG_(clo_trace_syscalls))
2935 VG_(printf)("wait4 ( %d, %p, %d, %p )\n",
2936 arg1,arg2,arg3,arg4);
2937 if (arg2 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002938 must_be_writable( tst, "wait4(status)", arg2, sizeof(int) );
sewardjde4a1d02002-03-22 01:27:54 +00002939 if (arg4 != (Addr)NULL)
sewardj8c824512002-04-14 04:16:48 +00002940 must_be_writable( tst, "wait4(rusage)", arg4,
2941 sizeof(struct rusage) );
sewardj2e93c502002-04-12 11:12:52 +00002942 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002943 if (!VG_(is_kerror)(res)) {
2944 if (arg2 != (Addr)NULL)
2945 make_readable( arg2, sizeof(int) );
2946 if (arg4 != (Addr)NULL)
2947 make_readable( arg4, sizeof(struct rusage) );
2948 }
2949 break;
2950
sewardjde4a1d02002-03-22 01:27:54 +00002951 case __NR_writev: { /* syscall 146 */
2952 /* int writev(int fd, const struct iovec * vector, size_t count); */
2953 UInt i;
2954 struct iovec * vec;
2955 if (VG_(clo_trace_syscalls))
2956 VG_(printf)("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
sewardj8c824512002-04-14 04:16:48 +00002957 must_be_readable( tst, "writev(vector)",
sewardjde4a1d02002-03-22 01:27:54 +00002958 arg2, arg3 * sizeof(struct iovec) );
2959 /* ToDo: don't do any of the following if the vector is invalid */
2960 vec = (struct iovec *)arg2;
2961 for (i = 0; i < arg3; i++)
sewardj8c824512002-04-14 04:16:48 +00002962 must_be_readable( tst, "writev(vector[...])",
sewardjde4a1d02002-03-22 01:27:54 +00002963 (UInt)vec[i].iov_base,vec[i].iov_len );
sewardj2e93c502002-04-12 11:12:52 +00002964 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002965 break;
2966 }
2967
2968 /*-------------------------- SIGNALS --------------------------*/
2969
2970 /* Normally set to 1, so that Valgrind's signal-simulation machinery
2971 is engaged. Sometimes useful to disable (set to 0), for
2972 debugging purposes, to make clients more deterministic. */
2973# define SIGNAL_SIMULATION 1
2974
2975 case __NR_rt_sigaction:
2976 case __NR_sigaction:
2977 /* int sigaction(int signum, struct k_sigaction *act,
2978 struct k_sigaction *oldact); */
2979 if (VG_(clo_trace_syscalls))
2980 VG_(printf)("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
2981 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002982 must_be_readable( tst, "sigaction(act)",
sewardjde4a1d02002-03-22 01:27:54 +00002983 arg2, sizeof(vki_ksigaction));
2984 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00002985 must_be_writable( tst, "sigaction(oldact)",
sewardjde4a1d02002-03-22 01:27:54 +00002986 arg3, sizeof(vki_ksigaction));
2987 /* We do this one ourselves! */
2988# if SIGNAL_SIMULATION
sewardj2e93c502002-04-12 11:12:52 +00002989 VG_(do__NR_sigaction)(tid);
2990 res = tst->m_eax;
sewardjde4a1d02002-03-22 01:27:54 +00002991# else
2992 /* debugging signals; when we don't handle them. */
sewardj2e93c502002-04-12 11:12:52 +00002993 KERNEL_DO_SYSCALL(tid,res);
sewardjde4a1d02002-03-22 01:27:54 +00002994# endif
2995 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
2996 make_readable( arg3, sizeof(vki_ksigaction));
2997 break;
2998
2999 case __NR_rt_sigprocmask:
3000 case __NR_sigprocmask:
3001 /* int sigprocmask(int how, k_sigset_t *set,
3002 k_sigset_t *oldset); */
3003 if (VG_(clo_trace_syscalls))
3004 VG_(printf)("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
3005 if (arg2 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003006 must_be_readable( tst, "sigprocmask(set)",
sewardjde4a1d02002-03-22 01:27:54 +00003007 arg2, sizeof(vki_ksigset_t));
3008 if (arg3 != (UInt)NULL)
sewardj8c824512002-04-14 04:16:48 +00003009 must_be_writable( tst, "sigprocmask(oldset)",
sewardjde4a1d02002-03-22 01:27:54 +00003010 arg3, sizeof(vki_ksigset_t));
sewardj018f7622002-05-15 21:13:39 +00003011# if SIGNAL_SIMULATION
3012 VG_(do__NR_sigprocmask) ( tid,
3013 arg1 /*how*/,
3014 (vki_ksigset_t*) arg2,
3015 (vki_ksigset_t*) arg3 );
3016 res = tst->m_eax;
3017# else
sewardj2e93c502002-04-12 11:12:52 +00003018 KERNEL_DO_SYSCALL(tid,res);
sewardj018f7622002-05-15 21:13:39 +00003019# endif
sewardjde4a1d02002-03-22 01:27:54 +00003020 if (!VG_(is_kerror)(res) && res == 0 && arg3 != (UInt)NULL)
3021 make_readable( arg3, sizeof(vki_ksigset_t));
sewardjde4a1d02002-03-22 01:27:54 +00003022 break;
3023
3024 default:
3025 VG_(message)
3026 (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);
3027 VG_(message)
3028 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
3029 VG_(message)
3030 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
3031 VG_(unimplemented)("no wrapper for the above system call");
3032 vg_assert(3+3 == 7);
3033 break; /*NOTREACHED*/
3034 }
3035
sewardjde4a1d02002-03-22 01:27:54 +00003036 /* { void zzzmemscan(void); zzzmemscan(); } */
3037
sewardj126a41f2002-05-07 23:45:03 +00003038 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardjde4a1d02002-03-22 01:27:54 +00003039 sane_before_call = False;
3040
3041 if (sane_before_call && (!sane_after_call)) {
sewardj2e93c502002-04-12 11:12:52 +00003042 VG_(message)(Vg_DebugMsg, "perform_assumed_nonblocking_syscall: ");
sewardjde4a1d02002-03-22 01:27:54 +00003043 VG_(message)(Vg_DebugMsg,
3044 "probable sanity check failure for syscall number %d\n",
3045 syscallno );
3046 VG_(panic)("aborting due to the above ... bye!");
3047 }
3048
3049 VGP_POPCC;
3050}
3051
3052
sewardj2e93c502002-04-12 11:12:52 +00003053
3054/* Perform pre- and post- actions for a blocking syscall, but do not
3055 do the syscall itself. If res is NULL, the pre-syscall actions are
3056 to be performed. If res is non-NULL, the post-syscall actions are
3057 to be performed, and *res is assumed to hold the result of the
3058 syscall. This slightly strange scheme makes it impossible to
3059 mistakenly use the value of *res in the pre-syscall actions.
3060
3061 This doesn't actually do the syscall itself, it is important to
3062 observe.
3063
3064 Because %eax is used both for the syscall number before the call
3065 and the result value afterwards, we can't reliably use it to get
3066 the syscall number. So the caller has to pass it explicitly.
3067*/
sewardj8c824512002-04-14 04:16:48 +00003068void VG_(check_known_blocking_syscall) ( ThreadId tid,
sewardj2e93c502002-04-12 11:12:52 +00003069 Int syscallno,
3070 Int* /*IN*/ res )
3071{
sewardj018f7622002-05-15 21:13:39 +00003072 ThreadState* tst;
3073 Bool sane_before_post, sane_after_post;
3074 UInt arg1, arg2, arg3;
3075
sewardj2e93c502002-04-12 11:12:52 +00003076 VGP_PUSHCC(VgpSyscall);
3077
sewardj018f7622002-05-15 21:13:39 +00003078 vg_assert(VG_(is_valid_tid)(tid));
3079 sane_before_post = True;
3080 sane_after_post = True;
3081 tst = & VG_(threads)[tid];
3082 arg1 = tst->m_ebx;
3083 arg2 = tst->m_ecx;
3084 arg3 = tst->m_edx;
3085 /*
3086 arg4 = tst->m_esi;
3087 arg5 = tst->m_edi;
3088 */
3089
sewardj2e93c502002-04-12 11:12:52 +00003090 if (res != NULL
sewardj126a41f2002-05-07 23:45:03 +00003091 && ! VG_(first_and_last_secondaries_look_plausible)())
sewardj2e93c502002-04-12 11:12:52 +00003092 sane_before_post = False;
3093
3094 switch (syscallno) {
3095
3096 case __NR_read: /* syscall 3 */
3097 /* size_t read(int fd, void *buf, size_t count); */
3098 if (res == NULL) {
3099 /* PRE */
3100 if (VG_(clo_trace_syscalls))
3101 VG_(printf)(
3102 "SYSCALL--PRE[%d,%d] read ( %d, %p, %d )\n",
3103 VG_(getpid)(), tid,
3104 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00003105 must_be_writable( tst, "read(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00003106 } else {
3107 /* POST */
3108 if (VG_(clo_trace_syscalls))
3109 VG_(printf)(
3110 "SYSCALL-POST[%d,%d] read ( %d, %p, %d ) --> %d\n",
3111 VG_(getpid)(), tid,
3112 arg1, arg2, arg3, *res);
3113 if (!VG_(is_kerror)(*res) && *res > 0) {
3114 make_readable( arg2, *res );
3115 }
3116 }
3117 break;
3118
3119 case __NR_write: /* syscall 4 */
3120 /* size_t write(int fd, const void *buf, size_t count); */
3121 if (res == NULL) {
3122 /* PRE */
3123 if (VG_(clo_trace_syscalls))
3124 VG_(printf)(
3125 "SYSCALL--PRE[%d,%d] write ( %d, %p, %d )\n",
3126 VG_(getpid)(), tid,
3127 arg1, arg2, arg3);
sewardj8c824512002-04-14 04:16:48 +00003128 must_be_readable( tst, "write(buf)", arg2, arg3 );
sewardj2e93c502002-04-12 11:12:52 +00003129 } else {
3130 /* POST */
3131 if (VG_(clo_trace_syscalls))
3132 VG_(printf)(
3133 "SYSCALL-POST[%d,%d] write ( %d, %p, %d ) --> %d\n",
3134 VG_(getpid)(), tid,
3135 arg1, arg2, arg3, *res);
3136 }
3137 break;
3138
3139 default:
3140 VG_(printf)("check_known_blocking_syscall: unexpected %d\n",
3141 syscallno);
3142 VG_(panic)("check_known_blocking_syscall");
3143 /*NOTREACHED*/
3144 break;
3145 }
3146
3147 if (res != NULL) { /* only check after syscall */
sewardj126a41f2002-05-07 23:45:03 +00003148 if (! VG_(first_and_last_secondaries_look_plausible)())
sewardj2e93c502002-04-12 11:12:52 +00003149 sane_after_post = False;
3150
3151 if (sane_before_post && (!sane_after_post)) {
3152 VG_(message)(Vg_DebugMsg, "perform_known_blocking_syscall: ");
3153 VG_(message)(Vg_DebugMsg,
3154 "probable sanity check failure for syscall number %d\n",
3155 syscallno );
3156 VG_(panic)("aborting due to the above ... bye!");
3157 }
3158 }
3159
3160 VGP_POPCC;
3161}
3162
3163
sewardjde4a1d02002-03-22 01:27:54 +00003164/*--------------------------------------------------------------------*/
3165/*--- end vg_syscall_mem.c ---*/
3166/*--------------------------------------------------------------------*/