Set saner MAX_ARGS (6 or 8) for X86_64 and I386
I noticed that tcp->u_args[MAX_ARGS] array is way larger than
I'd expect: for all arches except HPPA it has 32 (!) elements.
I looked at the code and so far I spotted only one abuser of
this fact: sys_sigreturn. On several arches, it saves sigset_t
into tcp->u_args[1...N] on entry and prints it on exit, a-la
memcpy(&tcp->u_arg[1], &sc.oldmask[0], sizeof(sigset_t))
The problem here is that in glibc sigset_t is insanely large:
128 bytes, and using sizeof(sigset_t) in memcpy will overrun
&tcp->u_args[1] even with MAX_ARGS == 32:
On 32 bits, sizeof(tcp->u_args) == 32*4 == 128 bytes!
We may already have a bug there!
This commit changes the code to save NSIG / 8 bytes only.
NSIG can't ever be > 256, and in practice is <= 129,
thus NSIG / 8 is <= 16 bytes == 4 32-bit words,
and even MAX_ARGS == 5 should be enough for saving signal masks.
* defs.h: Reduce MAX_ARGS for X86_64 and I386 from 32 to 8
for FreeBSD and to 6 for everyone else. Add comment about current
state of needed MAX_ARGS.
* signal.c: Add comment about size of sigset_t.
(sprintsigmask): Reduce static string buffer from 8k to 2k.
(sys_sigreturn): Fix sigset saving to save only NSIG / 8 bytes,
not sizeof(sigset_t) bytes.
* linux/mips/syscallent.h: Reduce nargs of printargs-type syscall to 7.
* linux/arm/syscallent.h: Reduce nargs of printargs-type syscall to 6.
* linux/i386/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
diff --git a/defs.h b/defs.h
index 02242af..64e4da0 100644
--- a/defs.h
+++ b/defs.h
@@ -48,7 +48,7 @@
# endif
#endif
-/* configuration section */
+/* Configuration section */
#ifndef MAX_QUALS
#if defined(LINUX) && defined(MIPS)
#define MAX_QUALS 7000 /* maximum number of syscalls, signals, etc. */
@@ -63,14 +63,35 @@
#ifndef DEFAULT_ACOLUMN
#define DEFAULT_ACOLUMN 40 /* default alignment column for results */
#endif
+
+/* Maximum number of args to a syscall.
+ *
+ * Make sure that all entries in all syscallent.h files
+ * have nargs <= MAX_ARGS!
+ * linux/<ARCH>/syscallent.h: ia64 has many syscalls with
+ * nargs = 8, mips has two with nargs = 7 (both are printargs),
+ * all others are <= 6.
+ * freebsd/i386/syscallent.h: one syscall with nargs = 8
+ * (sys_sendfile, looks legitimate)
+ * and one with nargs = 7 (sys_mmap, maybe it should have 6?).
+ * sunos4/syscallent.h: all are <= 6.
+ * svr4/syscallent.h: all are -1.
+ */
#ifndef MAX_ARGS
# ifdef HPPA
-# define MAX_ARGS 6 /* maximum number of args to a syscall */
+# define MAX_ARGS 6
+# elif defined X86_64 || defined I386
+# ifdef FREEBSD
+# define MAX_ARGS 8
+# else
+# define MAX_ARGS 6
+# endif
# else
/* Way too big. Switch your arch to saner size after you tested that it works */
-# define MAX_ARGS 32 /* maximum number of args to a syscall */
+# define MAX_ARGS 32
# endif
#endif
+
#ifndef DEFAULT_SORTBY
#define DEFAULT_SORTBY "time" /* default sorting method for call profiling */
#endif