Fix fanotify_mark decoding on 32-bit architectures
The fanotify_mark syscall takes a 64-bit mask, and on 32-bit
architectures it is split up into two syscall arguments.
* configure.ac (AC_CHECK_FUNCS): Add fanotify_mark.
(AC_CHECK_HEADERS): Add sys/fanotify.h.
* defs.h (getllval): New prototype.
* util.c (getllval): New function based on printllval.
(printllval): Use getllval.
* fanotify.c (sys_fanotify_mark): Use getllval to properly decode
64-bit mask and two syscall arguments followed by it.
* tests/fanotify_mark.c: New file.
* tests/fanotify_mark.test: New test.
* tests/Makefile.am (check_PROGRAMS): Add fanotify_mark.
(TESTS): Add fanotify_mark.test.
* tests/.gitignore: Add fanotify_mark.
diff --git a/util.c b/util.c
index 570888c..c7ad34f 100644
--- a/util.c
+++ b/util.c
@@ -242,39 +242,39 @@
}
/*
- * Print 64bit argument at position arg_no and return the index of the next
- * argument.
+ * Fetch 64bit argument at position arg_no and
+ * return the index of the next argument.
*/
int
-printllval(struct tcb *tcp, const char *format, int arg_no)
+getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
{
#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
# if SUPPORTED_PERSONALITIES > 1
if (current_wordsize > 4) {
# endif
- tprintf(format, tcp->u_arg[arg_no]);
+ *val = tcp->u_arg[arg_no];
arg_no++;
# if SUPPORTED_PERSONALITIES > 1
} else {
# if defined(AARCH64) || defined(POWERPC64)
/* Align arg_no to the next even number. */
arg_no = (arg_no + 1) & 0xe;
-# endif
- tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
+# endif /* AARCH64 || POWERPC64 */
+ *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
arg_no += 2;
}
-# endif /* SUPPORTED_PERSONALITIES */
+# endif /* SUPPORTED_PERSONALITIES > 1 */
#elif SIZEOF_LONG > 4
# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
#elif defined LINUX_MIPSN32
- tprintf(format, tcp->ext_arg[arg_no]);
+ *val = tcp->ext_arg[arg_no];
arg_no++;
#elif defined X32
if (current_personality == 0) {
- tprintf(format, tcp->ext_arg[arg_no]);
+ *val = tcp->ext_arg[arg_no];
arg_no++;
} else {
- tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
+ *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
arg_no += 2;
}
#else
@@ -285,7 +285,7 @@
/* Align arg_no to the next even number. */
arg_no = (arg_no + 1) & 0xe;
# endif
- tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
+ *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
arg_no += 2;
#endif
@@ -293,6 +293,20 @@
}
/*
+ * Print 64bit argument at position arg_no and
+ * return the index of the next argument.
+ */
+int
+printllval(struct tcb *tcp, const char *format, int arg_no)
+{
+ unsigned long long val = 0;
+
+ arg_no = getllval(tcp, &val, arg_no);
+ tprintf(format, val);
+ return arg_no;
+}
+
+/*
* Interpret `xlat' as an array of flags
* print the entries whose bits are on in `flags'
* return # of flags printed.