Fix decoding of getgroups, getgroups32, setgroups, and setgroups32 syscalls
Convert parsers of these syscalls to the same scheme as were applied to
parsers of other uid/gid related syscalls.
That is, define two sets of parsers on architectures that support
(either directly or via multiarch) 16-bit and 32-bit gid getgroups
and setgroups syscalls simultaneously, and reuse essentially the same
code by parametrizing uid_t and names of parser functions.
* groups.c: Remove.
(sys_getgroups, sys_setgroups): Move ...
* uid.c: ... here and parametrize their names.
* Makefile.am (strace_SOURCES): Remove groups.c.
* linux/syscall.h (sys_getgroups32, sys_setgroups32): Remove.
[NEED_UID16_PARSERS] (sys_getgroups16, sys_setgroups16): New prototypes.
* linux/arm/syscallent.h: Rename sys_[gs]etgroups to sys_[gs]etgroups16,
rename sys_[gs]etgroups32 to sys_[gs]etgroups.
* linux/bfin/syscallent.h: Likewise.
* linux/i386/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/microblaze/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* tests/uid.c: Test for getgroups.
* tests/uid16.c: Likewise.
* tests/uid32.c: Test for getgroups32.
* tests/uid.awk: Test for getgroups/getgroups32 decoding.
* tests/uid.test: Trace getgroups/getgroups32 syscalls.
diff --git a/uid.c b/uid.c
index 376d059..1f8c365 100644
--- a/uid.c
+++ b/uid.c
@@ -7,15 +7,17 @@
# define SIZEIFY_(x,size) SIZEIFY__(x,size)
# define SIZEIFY__(x,size) x ## size
-# define sys_getuid SIZEIFY(sys_getuid)
-# define sys_setfsuid SIZEIFY(sys_setfsuid)
-# define sys_setuid SIZEIFY(sys_setuid)
-# define sys_getresuid SIZEIFY(sys_getresuid)
-# define sys_setreuid SIZEIFY(sys_setreuid)
-# define sys_setresuid SIZEIFY(sys_setresuid)
+# define printuid SIZEIFY(printuid)
# define sys_chown SIZEIFY(sys_chown)
# define sys_fchown SIZEIFY(sys_fchown)
-# define printuid SIZEIFY(printuid)
+# define sys_getgroups SIZEIFY(sys_getgroups)
+# define sys_getresuid SIZEIFY(sys_getresuid)
+# define sys_getuid SIZEIFY(sys_getuid)
+# define sys_setfsuid SIZEIFY(sys_setfsuid)
+# define sys_setgroups SIZEIFY(sys_setgroups)
+# define sys_setresuid SIZEIFY(sys_setresuid)
+# define sys_setreuid SIZEIFY(sys_setreuid)
+# define sys_setuid SIZEIFY(sys_setuid)
#endif /* STRACE_UID_SIZE */
#include "defs.h"
@@ -141,4 +143,117 @@
tprintf("%s%u", text, uid);
}
+int
+sys_setgroups(struct tcb *tcp)
+{
+ if (entering(tcp)) {
+ unsigned long len, size, start, cur, end, abbrev_end;
+ uid_t gid;
+ int failed = 0;
+
+ len = tcp->u_arg[0];
+ tprintf("%lu, ", len);
+ if (len == 0) {
+ tprints("[]");
+ return 0;
+ }
+ start = tcp->u_arg[1];
+ if (start == 0) {
+ tprints("NULL");
+ return 0;
+ }
+ size = len * sizeof(gid);
+ end = start + size;
+ if (!verbose(tcp) || size / sizeof(gid) != len || end < start) {
+ tprintf("%#lx", start);
+ return 0;
+ }
+ if (abbrev(tcp)) {
+ abbrev_end = start + max_strlen * sizeof(gid);
+ if (abbrev_end < start)
+ abbrev_end = end;
+ } else {
+ abbrev_end = end;
+ }
+ tprints("[");
+ for (cur = start; cur < end; cur += sizeof(gid)) {
+ if (cur > start)
+ tprints(", ");
+ if (cur >= abbrev_end) {
+ tprints("...");
+ break;
+ }
+ if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+ tprints("?");
+ failed = 1;
+ break;
+ }
+ tprintf("%u", (unsigned int) gid);
+ }
+ tprints("]");
+ if (failed)
+ tprintf(" %#lx", tcp->u_arg[1]);
+ }
+ return 0;
+}
+
+int
+sys_getgroups(struct tcb *tcp)
+{
+ unsigned long len;
+
+ if (entering(tcp)) {
+ len = tcp->u_arg[0];
+ tprintf("%lu, ", len);
+ } else {
+ unsigned long size, start, cur, end, abbrev_end;
+ uid_t gid;
+ int failed = 0;
+
+ start = tcp->u_arg[1];
+ if (start == 0) {
+ tprints("NULL");
+ return 0;
+ }
+ len = tcp->u_rval;
+ if (len == 0) {
+ tprints("[]");
+ return 0;
+ }
+ size = len * sizeof(gid);
+ end = start + size;
+ if (!verbose(tcp) || tcp->u_arg[0] == 0 ||
+ size / sizeof(gid) != len || end < start) {
+ tprintf("%#lx", start);
+ return 0;
+ }
+ if (abbrev(tcp)) {
+ abbrev_end = start + max_strlen * sizeof(gid);
+ if (abbrev_end < start)
+ abbrev_end = end;
+ } else {
+ abbrev_end = end;
+ }
+ tprints("[");
+ for (cur = start; cur < end; cur += sizeof(gid)) {
+ if (cur > start)
+ tprints(", ");
+ if (cur >= abbrev_end) {
+ tprints("...");
+ break;
+ }
+ if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+ tprints("?");
+ failed = 1;
+ break;
+ }
+ tprintf("%u", (unsigned int) gid);
+ }
+ tprints("]");
+ if (failed)
+ tprintf(" %#lx", tcp->u_arg[1]);
+ }
+ return 0;
+}
+
#endif /* STRACE_UID_SIZE */