Enhance capget and capset syscalls decoding
* system.c (cap_version): New xlat structure.
(print_cap_header, print_cap_data): New functions.
(sys_capget, sys_capset): Use them.
diff --git a/system.c b/system.c
index 4fdfa6f..cf66b13 100644
--- a/system.c
+++ b/system.c
@@ -494,45 +494,75 @@
{ 0, NULL },
};
+#ifndef _LINUX_CAPABILITY_VERSION_1
+# define _LINUX_CAPABILITY_VERSION_1 0x19980330
+#endif
+#ifndef _LINUX_CAPABILITY_VERSION_2
+# define _LINUX_CAPABILITY_VERSION_2 0x20071026
+#endif
+#ifndef _LINUX_CAPABILITY_VERSION_3
+# define _LINUX_CAPABILITY_VERSION_3 0x20080522
+#endif
+
+static const struct xlat cap_version[] = {
+ { _LINUX_CAPABILITY_VERSION_1, "_LINUX_CAPABILITY_VERSION_1" },
+ { _LINUX_CAPABILITY_VERSION_2, "_LINUX_CAPABILITY_VERSION_3" },
+ { _LINUX_CAPABILITY_VERSION_3, "_LINUX_CAPABILITY_VERSION_3" },
+ { 0, NULL }
+};
+
+static void
+print_cap_header(struct tcb *tcp, unsigned long addr)
+{
+ union { cap_user_header_t p; long *a; char *c; } arg;
+ long a[sizeof(*arg.p) / sizeof(long) + 1];
+ arg.a = a;
+
+ if (!addr)
+ tprints("NULL");
+ else if (!verbose(tcp) ||
+ umoven(tcp, addr, sizeof(*arg.p), arg.c) < 0)
+ tprintf("%#lx", addr);
+ else {
+ tprints("{");
+ printxval(cap_version, arg.p->version,
+ "_LINUX_CAPABILITY_VERSION_???");
+ tprintf(", %d}", arg.p->pid);
+ }
+}
+
+static void
+print_cap_data(struct tcb *tcp, unsigned long addr)
+{
+ union { cap_user_data_t p; long *a; char *c; } arg;
+ long a[sizeof(*arg.p) / sizeof(long) + 1];
+ arg.a = a;
+
+ if (!addr)
+ tprints("NULL");
+ else if (!verbose(tcp) ||
+ (exiting(tcp) && syserror(tcp)) ||
+ umoven(tcp, addr, sizeof(*arg.p), arg.c) < 0)
+ tprintf("%#lx", addr);
+ else {
+ tprints("{");
+ printflags(capabilities, arg.p->effective, "CAP_???");
+ tprints(", ");
+ printflags(capabilities, arg.p->permitted, "CAP_???");
+ tprints(", ");
+ printflags(capabilities, arg.p->inheritable, "CAP_???");
+ tprints("}");
+ }
+}
+
int
sys_capget(struct tcb *tcp)
{
- /* cap_user_ types are _pointers_ to (small) structs. */
- /* Structs themselves have no names defined. */
- /* Have to use ugly hack to place them on stack. */
- union { cap_user_header_t p; long *a; char *c; } arg0;
- union { cap_user_data_t p; long *a; char *c; } arg1;
- long a0[sizeof(*arg0.p) / sizeof(long) + 1];
- long a1[sizeof(*arg1.p) / sizeof(long) + 1];
- arg0.a = a0;
- arg1.a = a1;
-
- if (!entering(tcp)) {
- if (!tcp->u_arg[0])
- tprints("NULL");
- else if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[0]);
- else if (umoven(tcp, tcp->u_arg[0], sizeof(*arg0.p), arg0.c) < 0)
- tprints("???");
- else {
- tprintf("%#x, %d", arg0.p->version, arg0.p->pid);
- }
+ if (entering(tcp)) {
+ print_cap_header(tcp, tcp->u_arg[0]);
tprints(", ");
- if (!tcp->u_arg[1])
- tprints("NULL");
- else if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[1]);
- else if (umoven(tcp, tcp->u_arg[1], sizeof(*arg1.p), arg1.c) < 0)
- tprints("???");
- else {
- tprints("{");
- printflags(capabilities, arg1.p->effective, "CAP_???");
- tprints(", ");
- printflags(capabilities, arg1.p->permitted, "CAP_???");
- tprints(", ");
- printflags(capabilities, arg1.p->inheritable, "CAP_???");
- tprints("}");
- }
+ } else {
+ print_cap_data(tcp, tcp->u_arg[1]);
}
return 0;
}
@@ -540,39 +570,10 @@
int
sys_capset(struct tcb *tcp)
{
- union { cap_user_header_t p; long *a; char *c; } arg0;
- union { cap_user_data_t p; long *a; char *c; } arg1;
- long a0[sizeof(*arg0.p) / sizeof(long) + 1];
- long a1[sizeof(*arg1.p) / sizeof(long) + 1];
- arg0.a = a0;
- arg1.a = a1;
-
if (entering(tcp)) {
- if (!tcp->u_arg[0])
- tprints("NULL");
- else if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[0]);
- else if (umoven(tcp, tcp->u_arg[0], sizeof(*arg0.p), arg0.c) < 0)
- tprints("???");
- else {
- tprintf("%#x, %d", arg0.p->version, arg0.p->pid);
- }
+ print_cap_header(tcp, tcp->u_arg[0]);
tprints(", ");
- if (!tcp->u_arg[1])
- tprints("NULL");
- else if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[1]);
- else if (umoven(tcp, tcp->u_arg[1], sizeof(*arg1.p), arg1.c) < 0)
- tprints("???");
- else {
- tprints("{");
- printflags(capabilities, arg1.p->effective, "CAP_???");
- tprints(", ");
- printflags(capabilities, arg1.p->permitted, "CAP_???");
- tprints(", ");
- printflags(capabilities, arg1.p->inheritable, "CAP_???");
- tprints("}");
- }
+ print_cap_data(tcp, tcp->u_arg[1]);
}
return 0;
}