system.c revision d35bdcad13caac3e167735e1f0fc50355b2f9523
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 86int 87sys_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 131int 132sys_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 146int 147sys_personality(struct tcb *tcp) 148{ 149 if (entering(tcp)) 150 printxval(personality_options, tcp->u_arg[0], "PER_???"); 151 return 0; 152} 153 154enum { 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 170int 171sys_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 210static 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 223int 224sys_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 247int 248sys_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 261static const struct xlat cacheflush_flags[] = { 262 XLAT(ICACHE), 263 XLAT(DCACHE), 264 XLAT(BCACHE), 265 XLAT_END 266}; 267 268int 269sys_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 285static 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 301int 302sys_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 332static void 333print_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 352static void 353print_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 376int 377sys_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 388int 389sys_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 401int sys_capget(struct tcb *tcp) 402{ 403 return printargs(tcp); 404} 405 406int sys_capset(struct tcb *tcp) 407{ 408 return printargs(tcp); 409} 410 411#endif 412 413/* Linux 2.6.18+ headers removed CTL_PROC enum. */ 414# define CTL_PROC 4 415# define CTL_CPU 10 /* older headers lack */ 416#include "xlat/sysctl_root.h" 417#include "xlat/sysctl_kern.h" 418#include "xlat/sysctl_vm.h" 419#include "xlat/sysctl_net.h" 420#include "xlat/sysctl_net_core.h" 421#include "xlat/sysctl_net_unix.h" 422#include "xlat/sysctl_net_ipv4.h" 423#include "xlat/sysctl_net_ipv4_route.h" 424#include "xlat/sysctl_net_ipv4_conf.h" 425#include "xlat/sysctl_net_ipv6.h" 426#include "xlat/sysctl_net_ipv6_route.h" 427 428int 429sys_sysctl(struct tcb *tcp) 430{ 431 struct __sysctl_args info; 432 int *name; 433 unsigned long size; 434 435 if (umove(tcp, tcp->u_arg[0], &info) < 0) 436 return printargs(tcp); 437 438 size = sizeof(int) * (unsigned long) info.nlen; 439 name = (size / sizeof(int) != info.nlen) ? NULL : malloc(size); 440 if (name == NULL || 441 umoven(tcp, (unsigned long) info.name, size, (char *) name) < 0) { 442 free(name); 443 if (entering(tcp)) 444 tprintf("{%p, %d, %p, %p, %p, %lu}", 445 info.name, info.nlen, info.oldval, 446 info.oldlenp, info.newval, (unsigned long)info.newlen); 447 return 0; 448 } 449 450 if (entering(tcp)) { 451 int cnt = 0, max_cnt; 452 453 tprints("{{"); 454 455 if (info.nlen == 0) 456 goto out; 457 printxval(sysctl_root, name[0], "CTL_???"); 458 ++cnt; 459 460 if (info.nlen == 1) 461 goto out; 462 switch (name[0]) { 463 case CTL_KERN: 464 tprints(", "); 465 printxval(sysctl_kern, name[1], "KERN_???"); 466 ++cnt; 467 break; 468 case CTL_VM: 469 tprints(", "); 470 printxval(sysctl_vm, name[1], "VM_???"); 471 ++cnt; 472 break; 473 case CTL_NET: 474 tprints(", "); 475 printxval(sysctl_net, name[1], "NET_???"); 476 ++cnt; 477 478 if (info.nlen == 2) 479 goto out; 480 switch (name[1]) { 481 case NET_CORE: 482 tprints(", "); 483 printxval(sysctl_net_core, name[2], 484 "NET_CORE_???"); 485 break; 486 case NET_UNIX: 487 tprints(", "); 488 printxval(sysctl_net_unix, name[2], 489 "NET_UNIX_???"); 490 break; 491 case NET_IPV4: 492 tprints(", "); 493 printxval(sysctl_net_ipv4, name[2], 494 "NET_IPV4_???"); 495 496 if (info.nlen == 3) 497 goto out; 498 switch (name[2]) { 499 case NET_IPV4_ROUTE: 500 tprints(", "); 501 printxval(sysctl_net_ipv4_route, 502 name[3], 503 "NET_IPV4_ROUTE_???"); 504 break; 505 case NET_IPV4_CONF: 506 tprints(", "); 507 printxval(sysctl_net_ipv4_conf, 508 name[3], 509 "NET_IPV4_CONF_???"); 510 break; 511 default: 512 goto out; 513 } 514 break; 515 case NET_IPV6: 516 tprints(", "); 517 printxval(sysctl_net_ipv6, name[2], 518 "NET_IPV6_???"); 519 520 if (info.nlen == 3) 521 goto out; 522 switch (name[2]) { 523 case NET_IPV6_ROUTE: 524 tprints(", "); 525 printxval(sysctl_net_ipv6_route, 526 name[3], 527 "NET_IPV6_ROUTE_???"); 528 break; 529 default: 530 goto out; 531 } 532 break; 533 default: 534 goto out; 535 } 536 break; 537 default: 538 goto out; 539 } 540 out: 541 max_cnt = info.nlen; 542 if (abbrev(tcp) && max_cnt > max_strlen) 543 max_cnt = max_strlen; 544 while (cnt < max_cnt) 545 tprintf(", %x", name[cnt++]); 546 if (cnt < info.nlen) 547 tprints(", ..."); 548 tprintf("}, %d, ", info.nlen); 549 } else { 550 size_t oldlen = 0; 551 if (info.oldval == NULL) { 552 tprints("NULL"); 553 } else if (umove(tcp, (long)info.oldlenp, &oldlen) >= 0 554 && info.nlen >= 2 555 && ((name[0] == CTL_KERN 556 && (name[1] == KERN_OSRELEASE 557 || name[1] == KERN_OSTYPE 558#ifdef KERN_JAVA_INTERPRETER 559 || name[1] == KERN_JAVA_INTERPRETER 560#endif 561#ifdef KERN_JAVA_APPLETVIEWER 562 || name[1] == KERN_JAVA_APPLETVIEWER 563#endif 564 )))) { 565 printpath(tcp, (size_t)info.oldval); 566 } else { 567 tprintf("%p", info.oldval); 568 } 569 tprintf(", %lu, ", (unsigned long)oldlen); 570 if (info.newval == NULL) 571 tprints("NULL"); 572 else if (syserror(tcp)) 573 tprintf("%p", info.newval); 574 else 575 printpath(tcp, (size_t)info.newval); 576 tprintf(", %lu", (unsigned long)info.newlen); 577 } 578 579 free(name); 580 return 0; 581} 582 583#ifdef MIPS 584 585#ifndef __NEW_UTS_LEN 586#define __NEW_UTS_LEN 64 587#endif 588 589#include "xlat/sysmips_operations.h" 590 591int sys_sysmips(struct tcb *tcp) 592{ 593 if (entering(tcp)) { 594 printxval(sysmips_operations, tcp->u_arg[0], "???"); 595 if (!verbose(tcp)) { 596 tprintf("%ld, %ld, %ld", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]); 597 } else if (tcp->u_arg[0] == SETNAME) { 598 char nodename[__NEW_UTS_LEN + 1]; 599 if (umovestr(tcp, tcp->u_arg[1], (__NEW_UTS_LEN + 1), nodename) < 0) 600 tprintf(", %#lx", tcp->u_arg[1]); 601 else 602 tprintf(", \"%.*s\"", (int)(__NEW_UTS_LEN + 1), nodename); 603 } else if (tcp->u_arg[0] == MIPS_ATOMIC_SET) { 604 tprintf(", %#lx, 0x%lx", tcp->u_arg[1], tcp->u_arg[2]); 605 } else if (tcp->u_arg[0] == MIPS_FIXADE) { 606 tprintf(", 0x%lx", tcp->u_arg[1]); 607 } else { 608 tprintf("%ld, %ld, %ld", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]); 609 } 610 } 611 612 return 0; 613} 614 615#endif /* MIPS */ 616 617#ifdef OR1K 618#define OR1K_ATOMIC_SWAP 1 619#define OR1K_ATOMIC_CMPXCHG 2 620#define OR1K_ATOMIC_XCHG 3 621#define OR1K_ATOMIC_ADD 4 622#define OR1K_ATOMIC_DECPOS 5 623#define OR1K_ATOMIC_AND 6 624#define OR1K_ATOMIC_OR 7 625#define OR1K_ATOMIC_UMAX 8 626#define OR1K_ATOMIC_UMIN 9 627 628#include "xlat/atomic_ops.h" 629 630int sys_or1k_atomic(struct tcb *tcp) 631{ 632 if (entering(tcp)) { 633 printxval(atomic_ops, tcp->u_arg[0], "???"); 634 switch(tcp->u_arg[0]) { 635 case OR1K_ATOMIC_SWAP: 636 tprintf(", 0x%lx, 0x%lx", tcp->u_arg[1], tcp->u_arg[2]); 637 break; 638 case OR1K_ATOMIC_CMPXCHG: 639 tprintf(", 0x%lx, %#lx, %#lx", tcp->u_arg[1], tcp->u_arg[2], 640 tcp->u_arg[3]); 641 break; 642 643 case OR1K_ATOMIC_XCHG: 644 case OR1K_ATOMIC_ADD: 645 case OR1K_ATOMIC_AND: 646 case OR1K_ATOMIC_OR: 647 case OR1K_ATOMIC_UMAX: 648 case OR1K_ATOMIC_UMIN: 649 tprintf(", 0x%lx, %#lx", tcp->u_arg[1], tcp->u_arg[2]); 650 break; 651 652 case OR1K_ATOMIC_DECPOS: 653 tprintf(", 0x%lx", tcp->u_arg[1]); 654 break; 655 656 default: 657 break; 658 } 659 } 660 661 return RVAL_HEX; 662} 663 664#endif /* OR1K */ 665