Implement fanotify_init and fanotify_mark decoding
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 5 Feb 2014 04:13:18 +0000 (04:13 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 5 Feb 2014 04:55:21 +0000 (04:55 +0000)
* fanotify.c: New file.
* linux/fanotify.h: Likewise.
* Makefile.am (strace_SOURCES): Add fanotify.c.
(EXTRA_DIST): Add linux/fanotify.h.
* defs.h (print_dirfd): New prototype.
* file.c (print_dirfd): Export.
* linux/dummy.h (sys_fanotify_init, sys_fanotify_mark): Remove.
* linux/syscall.h (sys_fanotify_init, sys_fanotify_mark): New
prototypes.
* pathtrace.c (pathtrace_match): Handle sys_fanotify_init and
sys_fanotify_mark.

Makefile.am
defs.h
fanotify.c [new file with mode: 0644]
file.c
linux/dummy.h
linux/fanotify.h [new file with mode: 0644]
linux/syscall.h
pathtrace.c

index 2ba30f6f5a8a82fed92a98b9a21c0e719154ba52..e9e4d2126674e91852af2000898a03ec79cb397b 100644 (file)
@@ -20,6 +20,7 @@ strace_SOURCES =      \
        block.c         \
        count.c         \
        desc.c          \
+       fanotify.c      \
        file.c          \
        io.c            \
        ioctl.c         \
@@ -94,6 +95,7 @@ EXTRA_DIST =                          \
        linux/bfin/syscallent.h         \
        linux/dummy.h                   \
        linux/errnoent.h                \
+       linux/fanotify.h                \
        linux/hppa/errnoent.h           \
        linux/hppa/ioctlent.h.in        \
        linux/hppa/signalent.h          \
diff --git a/defs.h b/defs.h
index b0a91447c8f4e3670fb3dc0e4f63655701b47698..f457d30bfa095de68428b7bb5b5a7646cc88aa7f 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -678,6 +678,7 @@ extern void printsiginfo(siginfo_t *, int);
 extern void printsiginfo_at(struct tcb *tcp, long addr);
 #endif
 extern void printfd(struct tcb *, int);
+extern void print_dirfd(struct tcb *, int);
 extern void printsock(struct tcb *, long, int);
 extern void print_sock_optmgmt(struct tcb *, long, int);
 extern void printrusage(struct tcb *, long);
diff --git a/fanotify.c b/fanotify.c
new file mode 100644 (file)
index 0000000..c8a7e37
--- /dev/null
@@ -0,0 +1,86 @@
+#include "defs.h"
+#include <linux/fanotify.h>
+
+static const struct xlat fan_classes[] = {
+       XLAT(FAN_CLASS_NOTIF),
+       XLAT(FAN_CLASS_CONTENT),
+       XLAT(FAN_CLASS_PRE_CONTENT),
+       XLAT_END
+};
+
+static const struct xlat fan_init_flags[] = {
+       XLAT(FAN_CLOEXEC),
+       XLAT(FAN_NONBLOCK),
+       XLAT(FAN_UNLIMITED_QUEUE),
+       XLAT(FAN_UNLIMITED_MARKS),
+       XLAT_END
+};
+
+int
+sys_fanotify_init(struct tcb *tcp)
+{
+       unsigned flags;
+
+       if (exiting(tcp))
+               return 0;
+
+       flags = tcp->u_arg[0];
+       printxval(fan_classes, flags & FAN_ALL_CLASS_BITS, "FAN_CLASS_???");
+       flags &= ~FAN_ALL_CLASS_BITS;
+       if (flags) {
+               tprints("|");
+               printflags(fan_init_flags, flags, "FAN_???");
+       }
+       tprints(", ");
+       tprint_open_modes((unsigned) tcp->u_arg[1]);
+
+       return 0;
+}
+
+static const struct xlat fan_mark_flags[] = {
+       XLAT(FAN_MARK_ADD),
+       XLAT(FAN_MARK_REMOVE),
+       XLAT(FAN_MARK_DONT_FOLLOW),
+       XLAT(FAN_MARK_ONLYDIR),
+       XLAT(FAN_MARK_MOUNT),
+       XLAT(FAN_MARK_IGNORED_MASK),
+       XLAT(FAN_MARK_IGNORED_SURV_MODIFY),
+       XLAT(FAN_MARK_FLUSH),
+       XLAT_END
+};
+
+static const struct xlat fan_event_flags[] = {
+       XLAT(FAN_ACCESS),
+       XLAT(FAN_MODIFY),
+       XLAT(FAN_CLOSE),
+       XLAT(FAN_CLOSE_WRITE),
+       XLAT(FAN_CLOSE_NOWRITE),
+       XLAT(FAN_OPEN),
+       XLAT(FAN_Q_OVERFLOW),
+       XLAT(FAN_OPEN_PERM),
+       XLAT(FAN_ACCESS_PERM),
+       XLAT(FAN_ONDIR),
+       XLAT(FAN_EVENT_ON_CHILD),
+       XLAT_END
+};
+
+int
+sys_fanotify_mark(struct tcb *tcp)
+{
+       if (exiting(tcp))
+               return 0;
+
+       printfd(tcp, tcp->u_arg[0]);
+       tprints(", ");
+       printflags(fan_mark_flags, (unsigned) tcp->u_arg[1], "FAN_MARK_???");
+       tprints(", ");
+       printflags(fan_event_flags, tcp->u_arg[2], "FAN_???");
+       tprints(", ");
+       if ((int) tcp->u_arg[3] == FAN_NOFD)
+               tprints("FAN_NOFD, ");
+       else
+               print_dirfd(tcp, tcp->u_arg[3]);
+       printpath(tcp, tcp->u_arg[4]);
+
+       return 0;
+}
diff --git a/file.c b/file.c
index 475949535281d721c2db6d5e6415b47d60fedd30..cfaa1af3865006ccbf2989237859483438f8968c 100644 (file)
--- a/file.c
+++ b/file.c
@@ -332,7 +332,7 @@ const struct xlat open_mode_flags[] = {
 /* The fd is an "int", so when decoding x86 on x86_64, we need to force sign
  * extension to get the right value.  We do this by declaring fd as int here.
  */
-static void
+void
 print_dirfd(struct tcb *tcp, int fd)
 {
        if (fd == AT_FDCWD)
index 6af5ec7b0f9a6a7739381ab5938d39297a9bdc53..979ed376df95ee24d3d3a97c2653ac1bc71ad49e 100644 (file)
@@ -33,8 +33,6 @@
 
 /* still unfinished */
 #define        sys_add_key             printargs
-#define        sys_fanotify_init       printargs
-#define        sys_fanotify_mark       printargs
 #define        sys_finit_module        printargs
 #define        sys_ioperm              printargs
 #define        sys_iopl                printargs
diff --git a/linux/fanotify.h b/linux/fanotify.h
new file mode 100644 (file)
index 0000000..030508d
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef _UAPI_LINUX_FANOTIFY_H
+#define _UAPI_LINUX_FANOTIFY_H
+
+#include <linux/types.h>
+
+/* the following events that user-space can register for */
+#define FAN_ACCESS             0x00000001      /* File was accessed */
+#define FAN_MODIFY             0x00000002      /* File was modified */
+#define FAN_CLOSE_WRITE                0x00000008      /* Writtable file closed */
+#define FAN_CLOSE_NOWRITE      0x00000010      /* Unwrittable file closed */
+#define FAN_OPEN               0x00000020      /* File was opened */
+
+#define FAN_Q_OVERFLOW         0x00004000      /* Event queued overflowed */
+
+#define FAN_OPEN_PERM          0x00010000      /* File open in perm check */
+#define FAN_ACCESS_PERM                0x00020000      /* File accessed in perm check */
+
+#define FAN_ONDIR              0x40000000      /* event occurred against dir */
+
+#define FAN_EVENT_ON_CHILD     0x08000000      /* interested in child events */
+
+/* helper events */
+#define FAN_CLOSE              (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
+
+/* flags used for fanotify_init() */
+#define FAN_CLOEXEC            0x00000001
+#define FAN_NONBLOCK           0x00000002
+
+/* These are NOT bitwise flags.  Both bits are used togther.  */
+#define FAN_CLASS_NOTIF                0x00000000
+#define FAN_CLASS_CONTENT      0x00000004
+#define FAN_CLASS_PRE_CONTENT  0x00000008
+#define FAN_ALL_CLASS_BITS     (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \
+                                FAN_CLASS_PRE_CONTENT)
+
+#define FAN_UNLIMITED_QUEUE    0x00000010
+#define FAN_UNLIMITED_MARKS    0x00000020
+
+#define FAN_ALL_INIT_FLAGS     (FAN_CLOEXEC | FAN_NONBLOCK | \
+                                FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
+                                FAN_UNLIMITED_MARKS)
+
+/* flags used for fanotify_modify_mark() */
+#define FAN_MARK_ADD           0x00000001
+#define FAN_MARK_REMOVE                0x00000002
+#define FAN_MARK_DONT_FOLLOW   0x00000004
+#define FAN_MARK_ONLYDIR       0x00000008
+#define FAN_MARK_MOUNT         0x00000010
+#define FAN_MARK_IGNORED_MASK  0x00000020
+#define FAN_MARK_IGNORED_SURV_MODIFY   0x00000040
+#define FAN_MARK_FLUSH         0x00000080
+
+#define FAN_ALL_MARK_FLAGS     (FAN_MARK_ADD |\
+                                FAN_MARK_REMOVE |\
+                                FAN_MARK_DONT_FOLLOW |\
+                                FAN_MARK_ONLYDIR |\
+                                FAN_MARK_MOUNT |\
+                                FAN_MARK_IGNORED_MASK |\
+                                FAN_MARK_IGNORED_SURV_MODIFY |\
+                                FAN_MARK_FLUSH)
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility.  Apps will get only the
+ * events that they originally wanted.  Be sure to add new events here!
+ */
+#define FAN_ALL_EVENTS (FAN_ACCESS |\
+                       FAN_MODIFY |\
+                       FAN_CLOSE |\
+                       FAN_OPEN)
+
+/*
+ * All events which require a permission response from userspace
+ */
+#define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\
+                            FAN_ACCESS_PERM)
+
+#define FAN_ALL_OUTGOING_EVENTS        (FAN_ALL_EVENTS |\
+                                FAN_ALL_PERM_EVENTS |\
+                                FAN_Q_OVERFLOW)
+
+#define FANOTIFY_METADATA_VERSION      3
+
+struct fanotify_event_metadata {
+       __u32 event_len;
+       __u8 vers;
+       __u8 reserved;
+       __u16 metadata_len;
+       __aligned_u64 mask;
+       __s32 fd;
+       __s32 pid;
+};
+
+struct fanotify_response {
+       __s32 fd;
+       __u32 response;
+};
+
+/* Legit userspace responses to a _PERM event */
+#define FAN_ALLOW      0x01
+#define FAN_DENY       0x02
+/* No fd set in event */
+#define FAN_NOFD       -1
+
+/* Helper functions to deal with fanotify_event_metadata buffers */
+#define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
+
+#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \
+                                  (struct fanotify_event_metadata*)(((char *)(meta)) + \
+                                  (meta)->event_len))
+
+#define FAN_EVENT_OK(meta, len)        ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \
+                               (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
+                               (long)(meta)->event_len <= (long)(len))
+
+#endif /* _UAPI_LINUX_FANOTIFY_H */
index 502e8eb5a861dbf550517c66ddc46d5c5aa0708e..d2ba126c05b7bd5d1324dec8bb8f09f298b3ceb6 100644 (file)
@@ -66,6 +66,8 @@ int sys_faccessat();
 int sys_fadvise64();
 int sys_fadvise64_64();
 int sys_fallocate();
+int sys_fanotify_init();
+int sys_fanotify_mark();
 int sys_fchmod();
 int sys_fchmodat();
 int sys_fchown();
index f6c3b80f72e3fcf3c97253d36276c30be58a40a5..9fb99c42ff240d067180d2a6406edbee53a62d06 100644 (file)
@@ -251,6 +251,12 @@ pathtrace_match(struct tcb *tcp)
                return fdmatch(tcp, tcp->u_arg[2]);
        }
 
+       if (s->sys_func == sys_fanotify_mark) {
+               /* x, x, x, fd, path */
+               return fdmatch(tcp, tcp->u_arg[3]) ||
+                       upathmatch(tcp, tcp->u_arg[4]);
+       }
+
        if (s->sys_func == sys_select ||
            s->sys_func == sys_oldselect ||
            s->sys_func == sys_pselect6)
@@ -341,7 +347,7 @@ pathtrace_match(struct tcb *tcp)
            s->sys_func == sys_epoll_create ||
            s->sys_func == sys_socket ||
            s->sys_func == sys_socketpair ||
-           strcmp(s->sys_name, "fanotify_init") == 0)
+           s->sys_func == sys_fanotify_init)
        {
                /*
                 * These have TRACE_FILE or TRACE_DESCRIPTOR or TRACE_NETWORK set,