@@ -80,6 +80,7 @@ struct type {
// KIND_ARRAY
struct {
struct type *type;
+ u8 length_off;
} array;
// KIND_STRUCT
@@ -110,4 +111,15 @@ struct syscall_spec {
struct argument args[ABI_MAX_ARGS];
};
+struct syscall_values {
+ union {
+ u8 u8;
+ u16 u16;
+ u32 u32;
+ u64 u64;
+ void *ptr;
+ char *str;
+ };
+};
+
#endif
@@ -7,10 +7,11 @@
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>
+#include <linux/vmalloc.h>
-typedef void (*cb_t)(void *ctx, struct type *t, int flags, const void __user *p, int post);
+typedef void (*cb_t)(void *ctx, struct type *t, int flags, const void __user *p, struct syscall_values *val, int post);
-static size_t handle_type(cb_t cb, void *ctx, struct type *t, int flags, const void __user *p);
+static size_t handle_type(cb_t cb, void *ctx, struct type *t, int flags, const void __user *p, struct syscall_values *val);
static u64 read_val(struct type *t, int flags, const void __user *p)
{
@@ -60,27 +61,34 @@ static u64 read_val(struct type *t, int flags, const void __user *p)
}
}
-static size_t handle_type(cb_t cb, void *ctx, struct type *t, int flags, const void __user *p)
+static size_t handle_type(cb_t cb, void *ctx, struct type *t, int flags, const void __user *p, struct syscall_values *val)
{
size_t off;
- cb(ctx, t, flags, p, 0);
+ cb(ctx, t, flags, p, val, 0);
switch (t->kind) {
case KIND_SCALAR: {
off = t->scalar.size;
+ val->u64 = read_val(t, flags, p);
break;
}
case KIND_PTR: {
const void __user* p1;
p1 = (const void __user*)read_val(t, flags, p);
- handle_type(cb, ctx, t->ptr.type, 0, p1);
+ handle_type(cb, ctx, t->ptr.type, 0, p1, val);
off = sizeof(void *);
break;
}
case KIND_ARRAY: {
- // TODO: don't know the size...
- // off = handle_array(cb, ctx, t, p);
+ // length_off == 0 => string
+ if (t->array.length_off == 0) {
+ u8 len = strnlen_user(p, 0x10000);
+ val->ptr = vmalloc(len);
+ if (WARN_ON(!val->ptr))
+ break;
+ strncpy_from_user(val->ptr, p, len);
+ } else {} // todo
break;
}
case KIND_STRUCT: {
@@ -95,8 +103,8 @@ static size_t handle_type(cb_t cb, void *ctx, struct type *t, int flags, const v
if (!f)
break;
if (i)
- cb(ctx, NULL, 0, NULL, 0);
- off += handle_type(cb, ctx, f, arg->flags, p + off);
+ cb(ctx, NULL, 0, NULL, val, 0);
+ off += handle_type(cb, ctx, f, arg->flags, p + off, val);
}
break;
}
@@ -109,13 +117,13 @@ static size_t handle_type(cb_t cb, void *ctx, struct type *t, int flags, const v
struct type *t1;
for (t1 = t; t1->kind == KIND_RESOURCE; t1 = t1->res.type) {}
- off = handle_type(cb, ctx, t1, flags, p);
+ off = handle_type(cb, ctx, t1, flags, p, val);
break;
}
default:
BUG();
}
- cb(ctx, t, flags, p, 1);
+ cb(ctx, t, flags, p, val, 1);
return off;
}
@@ -125,6 +133,7 @@ static void handle_syscall(cb_t cb, void *ctx, struct syscall_spec *s, va_list *
struct argument *arg;
struct type *f;
long v;
+ struct syscall_values vals[ABI_MAX_ARGS] = { 0 };
for (i = 0; i < ABI_MAX_ARGS; i++) {
arg = &s->args[i];
@@ -132,9 +141,9 @@ static void handle_syscall(cb_t cb, void *ctx, struct syscall_spec *s, va_list *
if (!f)
break;
if (i)
- cb(ctx, NULL, 0, NULL, 0);
+ cb(ctx, NULL, 0, NULL, &vals[i], 0);
v = va_arg(*ap, long);
- handle_type(cb, ctx, f, arg->flags, &v);
+ handle_type(cb, ctx, f, arg->flags, &v, &vals[i]);
}
}
@@ -148,7 +157,7 @@ static void check_retval(struct syscall_spec *s, long retval)
if (s->errno[i] == -retval)
return;
}
- __WARN_printf("syscall %s returned unexpected error %ld",
+ WARN("syscall %s returned unexpected error %ld",
s->name, retval);
}
@@ -169,7 +178,7 @@ void check_pre_printf(struct check_pre_ctx *ctx, const char *fmt, ...)
va_end(args);
}
-void check_pre_cb(void *ctx, struct type *t, int flags, const void __user *p, int post)
+void check_pre_cb(void *ctx, struct type *t, int flags, const void __user *p, struct syscall_values *val, int post)
{
if (!t) {
check_pre_printf(ctx, ", ");
@@ -188,7 +197,7 @@ void check_pre_cb(void *ctx, struct type *t, int flags, const void __user *p, in
check_pre_printf(ctx, "&%p=", (void*)read_val(t, flags, p));
break;
case KIND_ARRAY:
- check_pre_printf(ctx, post ? "]" : "[");
+ check_pre_printf(ctx, post ? " %s ]" : "[", val->ptr);
break;
case KIND_STRUCT:
check_pre_printf(ctx, post ? "}" : "{");
@@ -287,9 +296,16 @@ static struct type type_iptr = {
.scalar.size = sizeof(void *),
};
+static struct type type_string_i8 = {
+ .kind = KIND_ARRAY,
+ .array.type = &type_i8,
+ .array.length_off = 0,
+};
+
static struct type type_array_i8 = {
.kind = KIND_ARRAY,
.array.type = &type_i8,
+ .array.length_off = 1,
};
static struct type type_ptr_array_i8 = {
@@ -300,7 +316,7 @@ static struct type type_ptr_array_i8 = {
static struct type type_pathname = {
.kind = KIND_RESOURCE,
.res.res = RES_PATHNAME,
- .res.type = &type_array_i8,
+ .res.type = &type_string_i8,
};
static struct type type_ptr_pathname = {
@@ -752,5 +768,15 @@ struct syscall_spec syscall_spec_sync_file_range2 = { .name = "sync_file_range2"
struct syscall_spec syscall_spec_statfs64 = { .name = "statfs64" };
struct syscall_spec syscall_spec_fstatfs64 = { .name = "fstatfs64" };
struct syscall_spec syscall_spec_bdflush = { .name = "bdflush" };
+struct syscall_spec syscall_spec_sigaction = { .name = "sigaction" };
+struct syscall_spec syscall_spec_old_mmap = { .name = "old_mmap" };
+struct syscall_spec syscall_spec_truncate64 = { .name = "truncate64" };
+struct syscall_spec syscall_spec_ftruncate64 = { .name = "ftruncate64" };
+struct syscall_spec syscall_spec_stat64 = { .name = "stat64" };
+struct syscall_spec syscall_spec_lstat64 = { .name = "lstat64" };
+struct syscall_spec syscall_spec_fstat64 = { .name = "fstat64" };
+struct syscall_spec syscall_spec_fstatat64 = { .name = "fstatat64" };
+struct syscall_spec syscall_spec_fcntl64 = { .name = "fcntl64" };
+struct syscall_spec syscall_spec_old_select = { .name = "old_select" };
#undef $