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#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
425int
426sys_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) != 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		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 < 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
588int 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
627int 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 */
662