]> granicus.if.org Git - strace/blob - system.c
Include <sys/uio.h> unconditionally
[strace] / system.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "defs.h"
32
33 #define _LINUX_SOCKET_H
34 #define _LINUX_FS_H
35
36 #define MS_RDONLY        1      /* Mount read-only */
37 #define MS_NOSUID        2      /* Ignore suid and sgid bits */
38 #define MS_NODEV         4      /* Disallow access to device special files */
39 #define MS_NOEXEC        8      /* Disallow program execution */
40 #define MS_SYNCHRONOUS  16      /* Writes are synced at once */
41 #define MS_REMOUNT      32      /* Alter flags of a mounted FS */
42 #define MS_MANDLOCK     64      /* Allow mandatory locks on an FS */
43 #define MS_DIRSYNC      128     /* Directory modifications are synchronous */
44 #define MS_NOATIME      1024    /* Do not update access times. */
45 #define MS_NODIRATIME   2048    /* Do not update directory access times */
46 #define MS_BIND         4096
47 #define MS_MOVE         8192
48 #define MS_REC          16384
49 #define MS_SILENT       32768
50 #define MS_POSIXACL     (1<<16) /* VFS does not apply the umask */
51 #define MS_UNBINDABLE   (1<<17) /* change to unbindable */
52 #define MS_PRIVATE      (1<<18) /* change to private */
53 #define MS_SLAVE        (1<<19) /* change to slave */
54 #define MS_SHARED       (1<<20) /* change to shared */
55 #define MS_RELATIME     (1<<21)
56 #define MS_KERNMOUNT    (1<<22)
57 #define MS_I_VERSION    (1<<23)
58 #define MS_STRICTATIME  (1<<24)
59 #define MS_NOSEC        (1<<28)
60 #define MS_BORN         (1<<29)
61 #define MS_ACTIVE       (1<<30)
62 #define MS_NOUSER       (1<<31)
63 #define MS_MGC_VAL      0xc0ed0000      /* Magic flag number */
64 #define MS_MGC_MSK      0xffff0000      /* Magic flag mask */
65
66 #include <sys/socket.h>
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
69 #ifdef HAVE_LINUX_CAPABILITY_H
70 # include <linux/capability.h>
71 #endif
72 #ifdef HAVE_ASM_CACHECTL_H
73 # include <asm/cachectl.h>
74 #endif
75 #ifdef HAVE_LINUX_USTNAME_H
76 # include <linux/utsname.h>
77 #endif
78 #ifdef HAVE_ASM_SYSMIPS_H
79 # include <asm/sysmips.h>
80 #endif
81 #include <linux/sysctl.h>
82 #include <linux/personality.h>
83
84 #include "xlat/mount_flags.h"
85
86 int
87 sys_mount(struct tcb *tcp)
88 {
89         if (entering(tcp)) {
90                 int ignore_type = 0, ignore_data = 0;
91                 unsigned long flags = tcp->u_arg[3];
92
93                 /* Discard magic */
94                 if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
95                         flags &= ~MS_MGC_MSK;
96
97                 if (flags & MS_REMOUNT)
98                         ignore_type = 1;
99                 else if (flags & (MS_BIND | MS_MOVE))
100                         ignore_type = ignore_data = 1;
101
102                 printpath(tcp, tcp->u_arg[0]);
103                 tprints(", ");
104
105                 printpath(tcp, tcp->u_arg[1]);
106                 tprints(", ");
107
108                 if (ignore_type && tcp->u_arg[2])
109                         tprintf("%#lx", tcp->u_arg[2]);
110                 else
111                         printstr(tcp, tcp->u_arg[2], -1);
112                 tprints(", ");
113
114                 printflags(mount_flags, tcp->u_arg[3], "MS_???");
115                 tprints(", ");
116
117                 if (ignore_data && tcp->u_arg[4])
118                         tprintf("%#lx", tcp->u_arg[4]);
119                 else
120                         printstr(tcp, tcp->u_arg[4], -1);
121         }
122         return 0;
123 }
124
125 #define MNT_FORCE       0x00000001      /* Attempt to forcibily umount */
126 #define MNT_DETACH      0x00000002      /* Just detach from the tree */
127 #define MNT_EXPIRE      0x00000004      /* Mark for expiry */
128
129 #include "xlat/umount_flags.h"
130
131 int
132 sys_umount2(struct tcb *tcp)
133 {
134         if (entering(tcp)) {
135                 printstr(tcp, tcp->u_arg[0], -1);
136                 tprints(", ");
137                 printflags(umount_flags, tcp->u_arg[1], "MNT_???");
138         }
139         return 0;
140 }
141
142 /* These are not macros, but enums.  We just copy the values by hand
143    from Linux 2.6.9 here.  */
144 #include "xlat/personality_options.h"
145
146 int
147 sys_personality(struct tcb *tcp)
148 {
149         if (entering(tcp))
150                 printxval(personality_options, tcp->u_arg[0], "PER_???");
151         return 0;
152 }
153
154 enum {
155         SYSLOG_ACTION_CLOSE = 0,
156         SYSLOG_ACTION_OPEN,
157         SYSLOG_ACTION_READ,
158         SYSLOG_ACTION_READ_ALL,
159         SYSLOG_ACTION_READ_CLEAR,
160         SYSLOG_ACTION_CLEAR,
161         SYSLOG_ACTION_CONSOLE_OFF,
162         SYSLOG_ACTION_CONSOLE_ON,
163         SYSLOG_ACTION_CONSOLE_LEVEL,
164         SYSLOG_ACTION_SIZE_UNREAD,
165         SYSLOG_ACTION_SIZE_BUFFER
166 };
167
168 #include "xlat/syslog_action_type.h"
169
170 int
171 sys_syslog(struct tcb *tcp)
172 {
173         int type = tcp->u_arg[0];
174
175         if (entering(tcp)) {
176                 /* type */
177                 printxval(syslog_action_type, type, "SYSLOG_ACTION_???");
178                 tprints(", ");
179         }
180
181         switch (type) {
182                 case SYSLOG_ACTION_READ:
183                 case SYSLOG_ACTION_READ_ALL:
184                 case SYSLOG_ACTION_READ_CLEAR:
185                         if (entering(tcp))
186                                 return 0;
187                         break;
188                 default:
189                         if (entering(tcp)) {
190                                 tprintf("%#lx, %lu",
191                                         tcp->u_arg[1], tcp->u_arg[2]);
192                         }
193                         return 0;
194         }
195
196         /* bufp */
197         if (syserror(tcp))
198                 tprintf("%#lx", tcp->u_arg[1]);
199         else
200                 printstr(tcp, tcp->u_arg[1], tcp->u_rval);
201         /* len */
202         tprintf(", %d", (int) tcp->u_arg[2]);
203
204         return 0;
205 }
206
207 #ifdef M68K
208 #include "xlat/cacheflush_scope.h"
209
210 static const struct xlat cacheflush_flags[] = {
211 #ifdef FLUSH_CACHE_BOTH
212         XLAT(FLUSH_CACHE_BOTH),
213 #endif
214 #ifdef FLUSH_CACHE_DATA
215         XLAT(FLUSH_CACHE_DATA),
216 #endif
217 #ifdef FLUSH_CACHE_INSN
218         XLAT(FLUSH_CACHE_INSN),
219 #endif
220         XLAT_END
221 };
222
223 int
224 sys_cacheflush(struct tcb *tcp)
225 {
226         if (entering(tcp)) {
227                 /* addr */
228                 tprintf("%#lx, ", tcp->u_arg[0]);
229                 /* scope */
230                 printxval(cacheflush_scope, tcp->u_arg[1], "FLUSH_SCOPE_???");
231                 tprints(", ");
232                 /* flags */
233                 printflags(cacheflush_flags, tcp->u_arg[2], "FLUSH_CACHE_???");
234                 /* len */
235                 tprintf(", %lu", tcp->u_arg[3]);
236         }
237         return 0;
238 }
239 #endif /* M68K */
240
241 #ifdef BFIN
242
243 #include <bfin_sram.h>
244
245 #include "xlat/sram_alloc_flags.h"
246
247 int
248 sys_sram_alloc(struct tcb *tcp)
249 {
250         if (entering(tcp)) {
251                 /* size */
252                 tprintf("%lu, ", tcp->u_arg[0]);
253                 /* flags */
254                 printflags(sram_alloc_flags, tcp->u_arg[1], "???_SRAM");
255         }
256         return 1;
257 }
258
259 #include <asm/cachectl.h>
260
261 static const struct xlat cacheflush_flags[] = {
262         XLAT(ICACHE),
263         XLAT(DCACHE),
264         XLAT(BCACHE),
265         XLAT_END
266 };
267
268 int
269 sys_cacheflush(struct tcb *tcp)
270 {
271         if (entering(tcp)) {
272                 /* start addr */
273                 tprintf("%#lx, ", tcp->u_arg[0]);
274                 /* length */
275                 tprintf("%ld, ", tcp->u_arg[1]);
276                 /* flags */
277                 printxval(cacheflush_flags, tcp->u_arg[1], "?CACHE");
278         }
279         return 0;
280 }
281
282 #endif
283
284 #ifdef SH
285 static const struct xlat cacheflush_flags[] = {
286 #ifdef CACHEFLUSH_D_INVAL
287         XLAT(CACHEFLUSH_D_INVAL),
288 #endif
289 #ifdef CACHEFLUSH_D_WB
290         XLAT(CACHEFLUSH_D_WB),
291 #endif
292 #ifdef CACHEFLUSH_D_PURGE
293         XLAT(CACHEFLUSH_D_PURGE),
294 #endif
295 #ifdef CACHEFLUSH_I
296         XLAT(CACHEFLUSH_I),
297 #endif
298         XLAT_END
299 };
300
301 int
302 sys_cacheflush(struct tcb *tcp)
303 {
304         if (entering(tcp)) {
305                 /* addr */
306                 tprintf("%#lx, ", tcp->u_arg[0]);
307                 /* len */
308                 tprintf("%lu, ", tcp->u_arg[1]);
309                 /* flags */
310                 printflags(cacheflush_flags, tcp->u_arg[2], "CACHEFLUSH_???");
311         }
312         return 0;
313 }
314 #endif /* SH */
315
316 #ifdef SYS_capget
317
318 #include "xlat/capabilities.h"
319
320 #ifndef _LINUX_CAPABILITY_VERSION_1
321 # define _LINUX_CAPABILITY_VERSION_1 0x19980330
322 #endif
323 #ifndef _LINUX_CAPABILITY_VERSION_2
324 # define _LINUX_CAPABILITY_VERSION_2 0x20071026
325 #endif
326 #ifndef _LINUX_CAPABILITY_VERSION_3
327 # define _LINUX_CAPABILITY_VERSION_3 0x20080522
328 #endif
329
330 #include "xlat/cap_version.h"
331
332 static void
333 print_cap_header(struct tcb *tcp, unsigned long addr)
334 {
335         union { cap_user_header_t p; long *a; char *c; } arg;
336         long a[sizeof(*arg.p) / sizeof(long) + 1];
337         arg.a = a;
338
339         if (!addr)
340                 tprints("NULL");
341         else if (!verbose(tcp) ||
342                  umoven(tcp, addr, sizeof(*arg.p), arg.c) < 0)
343                 tprintf("%#lx", addr);
344         else {
345                 tprints("{");
346                 printxval(cap_version, arg.p->version,
347                           "_LINUX_CAPABILITY_VERSION_???");
348                 tprintf(", %d}", arg.p->pid);
349         }
350 }
351
352 static void
353 print_cap_data(struct tcb *tcp, unsigned long addr)
354 {
355         union { cap_user_data_t p; long *a; char *c; } arg;
356         long a[sizeof(*arg.p) / sizeof(long) + 1];
357         arg.a = a;
358
359         if (!addr)
360                 tprints("NULL");
361         else if (!verbose(tcp) ||
362                  (exiting(tcp) && syserror(tcp)) ||
363                  umoven(tcp, addr, sizeof(*arg.p), arg.c) < 0)
364                 tprintf("%#lx", addr);
365         else {
366                 tprints("{");
367                 printflags(capabilities, arg.p->effective, "CAP_???");
368                 tprints(", ");
369                 printflags(capabilities, arg.p->permitted, "CAP_???");
370                 tprints(", ");
371                 printflags(capabilities, arg.p->inheritable, "CAP_???");
372                 tprints("}");
373         }
374 }
375
376 int
377 sys_capget(struct tcb *tcp)
378 {
379         if (entering(tcp)) {
380                 print_cap_header(tcp, tcp->u_arg[0]);
381                 tprints(", ");
382         } else {
383                 print_cap_data(tcp, tcp->u_arg[1]);
384         }
385         return 0;
386 }
387
388 int
389 sys_capset(struct tcb *tcp)
390 {
391         if (entering(tcp)) {
392                 print_cap_header(tcp, tcp->u_arg[0]);
393                 tprints(", ");
394                 print_cap_data(tcp, tcp->u_arg[1]);
395         }
396         return 0;
397 }
398
399 #else
400
401 int sys_capget(struct tcb *tcp)
402 {
403         return printargs(tcp);
404 }
405
406 int sys_capset(struct tcb *tcp)
407 {
408         return printargs(tcp);
409 }
410
411 #endif
412
413 #include "xlat/sysctl_root.h"
414 #include "xlat/sysctl_kern.h"
415 #include "xlat/sysctl_vm.h"
416 #include "xlat/sysctl_net.h"
417 #include "xlat/sysctl_net_core.h"
418 #include "xlat/sysctl_net_unix.h"
419 #include "xlat/sysctl_net_ipv4.h"
420 #include "xlat/sysctl_net_ipv4_route.h"
421 #include "xlat/sysctl_net_ipv4_conf.h"
422 #include "xlat/sysctl_net_ipv6.h"
423 #include "xlat/sysctl_net_ipv6_route.h"
424
425 int
426 sys_sysctl(struct tcb *tcp)
427 {
428         struct __sysctl_args info;
429         int *name;
430         unsigned long size;
431
432         if (umove(tcp, tcp->u_arg[0], &info) < 0)
433                 return printargs(tcp);
434
435         size = sizeof(int) * (unsigned long) info.nlen;
436         name = (size / sizeof(int) != (unsigned long) info.nlen) ? NULL : malloc(size);
437         if (name == NULL ||
438             umoven(tcp, (unsigned long) info.name, size, (char *) name) < 0) {
439                 free(name);
440                 if (entering(tcp))
441                         tprintf("{%p, %d, %p, %p, %p, %lu}",
442                                 info.name, info.nlen, info.oldval,
443                                 info.oldlenp, info.newval, (unsigned long)info.newlen);
444                 return 0;
445         }
446
447         if (entering(tcp)) {
448                 unsigned int cnt = 0, max_cnt;
449
450                 tprints("{{");
451
452                 if (info.nlen == 0)
453                         goto out;
454                 printxval(sysctl_root, name[0], "CTL_???");
455                 ++cnt;
456
457                 if (info.nlen == 1)
458                         goto out;
459                 switch (name[0]) {
460                 case CTL_KERN:
461                         tprints(", ");
462                         printxval(sysctl_kern, name[1], "KERN_???");
463                         ++cnt;
464                         break;
465                 case CTL_VM:
466                         tprints(", ");
467                         printxval(sysctl_vm, name[1], "VM_???");
468                         ++cnt;
469                         break;
470                 case CTL_NET:
471                         tprints(", ");
472                         printxval(sysctl_net, name[1], "NET_???");
473                         ++cnt;
474
475                         if (info.nlen == 2)
476                                 goto out;
477                         switch (name[1]) {
478                         case NET_CORE:
479                                 tprints(", ");
480                                 printxval(sysctl_net_core, name[2],
481                                           "NET_CORE_???");
482                                 break;
483                         case NET_UNIX:
484                                 tprints(", ");
485                                 printxval(sysctl_net_unix, name[2],
486                                           "NET_UNIX_???");
487                                 break;
488                         case NET_IPV4:
489                                 tprints(", ");
490                                 printxval(sysctl_net_ipv4, name[2],
491                                           "NET_IPV4_???");
492
493                                 if (info.nlen == 3)
494                                         goto out;
495                                 switch (name[2]) {
496                                 case NET_IPV4_ROUTE:
497                                         tprints(", ");
498                                         printxval(sysctl_net_ipv4_route,
499                                                   name[3],
500                                                   "NET_IPV4_ROUTE_???");
501                                         break;
502                                 case NET_IPV4_CONF:
503                                         tprints(", ");
504                                         printxval(sysctl_net_ipv4_conf,
505                                                   name[3],
506                                                   "NET_IPV4_CONF_???");
507                                         break;
508                                 default:
509                                         goto out;
510                                 }
511                                 break;
512                         case NET_IPV6:
513                                 tprints(", ");
514                                 printxval(sysctl_net_ipv6, name[2],
515                                           "NET_IPV6_???");
516
517                                 if (info.nlen == 3)
518                                         goto out;
519                                 switch (name[2]) {
520                                 case NET_IPV6_ROUTE:
521                                         tprints(", ");
522                                         printxval(sysctl_net_ipv6_route,
523                                                   name[3],
524                                                   "NET_IPV6_ROUTE_???");
525                                         break;
526                                 default:
527                                         goto out;
528                                 }
529                                 break;
530                         default:
531                                 goto out;
532                         }
533                         break;
534                 default:
535                         goto out;
536                 }
537         out:
538                 max_cnt = info.nlen;
539                 if (abbrev(tcp) && max_cnt > max_strlen)
540                         max_cnt = max_strlen;
541                 while (cnt < max_cnt)
542                         tprintf(", %x", name[cnt++]);
543                 if (cnt < (unsigned) info.nlen)
544                         tprints(", ...");
545                 tprintf("}, %d, ", info.nlen);
546         } else {
547                 size_t oldlen = 0;
548                 if (info.oldval == NULL) {
549                         tprints("NULL");
550                 } else if (umove(tcp, (long)info.oldlenp, &oldlen) >= 0
551                            && info.nlen >= 2
552                            && ((name[0] == CTL_KERN
553                                 && (name[1] == KERN_OSRELEASE
554                                     || name[1] == KERN_OSTYPE
555 #ifdef KERN_JAVA_INTERPRETER
556                                     || name[1] == KERN_JAVA_INTERPRETER
557 #endif
558 #ifdef KERN_JAVA_APPLETVIEWER
559                                     || name[1] == KERN_JAVA_APPLETVIEWER
560 #endif
561                                         )))) {
562                         printpath(tcp, (size_t)info.oldval);
563                 } else {
564                         tprintf("%p", info.oldval);
565                 }
566                 tprintf(", %lu, ", (unsigned long)oldlen);
567                 if (info.newval == NULL)
568                         tprints("NULL");
569                 else if (syserror(tcp))
570                         tprintf("%p", info.newval);
571                 else
572                         printpath(tcp, (size_t)info.newval);
573                 tprintf(", %lu", (unsigned long)info.newlen);
574         }
575
576         free(name);
577         return 0;
578 }
579
580 #ifdef MIPS
581
582 #ifndef __NEW_UTS_LEN
583 #define __NEW_UTS_LEN 64
584 #endif
585
586 #include "xlat/sysmips_operations.h"
587
588 int sys_sysmips(struct tcb *tcp)
589 {
590         if (entering(tcp)) {
591                 printxval(sysmips_operations, tcp->u_arg[0], "???");
592                 if (!verbose(tcp)) {
593                         tprintf("%ld, %ld, %ld", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
594                 } else if (tcp->u_arg[0] == SETNAME) {
595                         char nodename[__NEW_UTS_LEN + 1];
596                         if (umovestr(tcp, tcp->u_arg[1], (__NEW_UTS_LEN + 1), nodename) < 0)
597                                 tprintf(", %#lx", tcp->u_arg[1]);
598                         else
599                                 tprintf(", \"%.*s\"", (int)(__NEW_UTS_LEN + 1), nodename);
600                 } else if (tcp->u_arg[0] == MIPS_ATOMIC_SET) {
601                         tprintf(", %#lx, 0x%lx", tcp->u_arg[1], tcp->u_arg[2]);
602                 } else if (tcp->u_arg[0] == MIPS_FIXADE) {
603                         tprintf(", 0x%lx", tcp->u_arg[1]);
604                 } else {
605                         tprintf("%ld, %ld, %ld", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
606                 }
607         }
608
609         return 0;
610 }
611
612 #endif /* MIPS */
613
614 #ifdef OR1K
615 #define OR1K_ATOMIC_SWAP        1
616 #define OR1K_ATOMIC_CMPXCHG     2
617 #define OR1K_ATOMIC_XCHG        3
618 #define OR1K_ATOMIC_ADD         4
619 #define OR1K_ATOMIC_DECPOS      5
620 #define OR1K_ATOMIC_AND         6
621 #define OR1K_ATOMIC_OR          7
622 #define OR1K_ATOMIC_UMAX        8
623 #define OR1K_ATOMIC_UMIN        9
624
625 #include "xlat/atomic_ops.h"
626
627 int sys_or1k_atomic(struct tcb *tcp)
628 {
629         if (entering(tcp)) {
630                 printxval(atomic_ops, tcp->u_arg[0], "???");
631                 switch(tcp->u_arg[0]) {
632                 case OR1K_ATOMIC_SWAP:
633                         tprintf(", 0x%lx, 0x%lx", tcp->u_arg[1], tcp->u_arg[2]);
634                         break;
635                 case OR1K_ATOMIC_CMPXCHG:
636                         tprintf(", 0x%lx, %#lx, %#lx", tcp->u_arg[1], tcp->u_arg[2],
637                                 tcp->u_arg[3]);
638                         break;
639
640                 case OR1K_ATOMIC_XCHG:
641                 case OR1K_ATOMIC_ADD:
642                 case OR1K_ATOMIC_AND:
643                 case OR1K_ATOMIC_OR:
644                 case OR1K_ATOMIC_UMAX:
645                 case OR1K_ATOMIC_UMIN:
646                         tprintf(", 0x%lx, %#lx", tcp->u_arg[1], tcp->u_arg[2]);
647                         break;
648
649                 case OR1K_ATOMIC_DECPOS:
650                         tprintf(", 0x%lx", tcp->u_arg[1]);
651                         break;
652
653                 default:
654                         break;
655                 }
656         }
657
658         return RVAL_HEX;
659 }
660
661 #endif /* OR1K */