All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lena Djokic <Lena.Djokic@rt-rk.com>
To: qemu-devel@nongnu.org, riku.voipio@iki.fi
Subject: [Qemu-devel] [PATCH v2 1/7] linux-user: Add fanotify implementation
Date: Thu, 24 Nov 2016 17:08:52 +0100	[thread overview]
Message-ID: <1480003738-8754-2-git-send-email-Lena.Djokic@rt-rk.com> (raw)
In-Reply-To: <1480003738-8754-1-git-send-email-Lena.Djokic@rt-rk.com>

This commit adds implementation of fanotify_init and fanotify_mark.
Second argument for fanotify_init needs conversion because of flags
which can be FAN_NONBLOCK and FAN_CLOEXEC which rely on O_NONBLOCK
and O_CLOEXEC and those can have different values on different platforms.
For fanotify_mark argument layout is different for 32-bit and 64-bit
platforms and this implementation have support for that situation.
Also, support for writing and reading of file descriptor opened by
fanotify_init is added.
Configure file contains checks for excistence of fanotify support on
given build system.

Signed-off-by: Lena Djokic <Lena.Djokic@rt-rk.com>
---
 configure            |  20 ++++++++
 linux-user/syscall.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 142 insertions(+), 4 deletions(-)

diff --git a/configure b/configure
index fd6f898..56e6c98 100755
--- a/configure
+++ b/configure
@@ -3537,6 +3537,23 @@ if compile_prog "" "" ; then
   inotify1=yes
 fi
 
+# check if fanotify group of system calls is supported
+fanotify=no
+cat > $TMPC << EOF
+#include <sys/fanotify.h>
+
+int
+main(void)
+{
+    fanotify_init(0,0);
+    fanotify_mark(0,0,0,0,0);
+    return 0;
+}
+EOF
+if compile_prog "" "" ; then
+  fanotify=yes
+fi
+
 # check if utimensat and futimens are supported
 utimens=no
 cat > $TMPC << EOF
@@ -5335,6 +5352,9 @@ fi
 if test "$inotify1" = "yes" ; then
   echo "CONFIG_INOTIFY1=y" >> $config_host_mak
 fi
+if test "$fanotify" = "yes" ; then
+  echo "CONFIG_FANOTIFY=y" >> $config_host_mak
+fi
 if test "$byteswap_h" = "yes" ; then
   echo "CONFIG_BYTESWAP_H=y" >> $config_host_mak
 fi
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7b77503..f5d9a26 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -76,6 +76,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #ifdef CONFIG_SENDFILE
 #include <sys/sendfile.h>
 #endif
+#ifdef CONFIG_FANOTIFY
+#include <sys/fanotify.h>
+#endif
 
 #define termios host_termios
 #define winsize host_winsize
@@ -499,9 +502,13 @@ enum {
     QEMU___IFLA_INET6_MAX
 };
 
+typedef abi_long (*TargetFdReadFunc)(void *, size_t);
+typedef abi_long (*TargetFdWriteFunc)(void *, size_t);
 typedef abi_long (*TargetFdDataFunc)(void *, size_t);
 typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t);
 typedef struct TargetFdTrans {
+    TargetFdReadFunc read_op;
+    TargetFdWriteFunc write_op;
     TargetFdDataFunc host_to_target_data;
     TargetFdDataFunc target_to_host_data;
     TargetFdAddrFunc target_to_host_addr;
@@ -511,6 +518,22 @@ static TargetFdTrans **target_fd_trans;
 
 static unsigned int target_fd_max;
 
+static TargetFdReadFunc fd_trans_read_op(int fd)
+{
+    if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+        return target_fd_trans[fd]->read_op;
+    }
+    return NULL;
+}
+
+static TargetFdWriteFunc fd_trans_write_op(int fd)
+{
+    if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
+        return target_fd_trans[fd]->write_op;
+    }
+    return NULL;
+}
+
 static TargetFdDataFunc fd_trans_target_to_host_data(int fd)
 {
     if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
@@ -7527,6 +7550,47 @@ static target_timer_t get_timer_id(abi_long arg)
     return timerid;
 }
 
+#if defined(CONFIG_FANOTIFY)
+static inline abi_long fanotify_fd_read_op(void *buf, size_t len)
+{
+    struct fanotify_event_metadata *fem;
+    int num;
+
+    /* Read buffer for fanotify file descriptor contains one or more
+     * of fanotify_event_metadata structures.
+     */
+    fem = (struct fanotify_event_metadata *)buf;
+    num = len / sizeof(struct fanotify_event_metadata);
+    for (int i = 0; i < num; i++) {
+        (fem + i)->event_len = tswap32((fem + i)->event_len);
+        /* Fields (fem+i)->vers and (fem+i)->reserved are single byte,
+         * so swapping is not needed for them.
+         */
+        (fem + i)->metadata_len = tswap16((fem + i)->metadata_len);
+        (fem + i)->mask = tswap64((fem + i)->mask);
+        (fem + i)->fd = tswap32((fem + i)->fd);
+        (fem + i)->pid = tswap32((fem + i)->pid);
+    }
+
+    return len;
+}
+
+static inline abi_long fanotify_fd_write_op(void *buf, size_t len)
+{
+    struct fanotify_response *fr = (struct fanotify_response *)buf;
+
+    fr->fd = tswap32(fr->fd);
+    fr->response = tswap32(fr->response);
+
+    return len;
+}
+
+static TargetFdTrans fanotify_trans = {
+    .read_op = fanotify_fd_read_op,
+    .write_op = fanotify_fd_write_op,
+};
+#endif
+
 /* do_syscall() should always have a single exit point at the end so
    that actions, such as logging of syscall results, can be performed.
    All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -7613,16 +7677,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
                 goto efault;
             ret = get_errno(safe_read(arg1, p, arg3));
-            if (ret >= 0 &&
-                fd_trans_host_to_target_data(arg1)) {
-                ret = fd_trans_host_to_target_data(arg1)(p, ret);
-            }
+            if (ret >= 0) {
+                if (fd_trans_read_op(arg1)) {
+                    ret = fd_trans_read_op(arg1)(p, ret);
+                }
+                if (fd_trans_host_to_target_data(arg1)) {
+                    ret = fd_trans_host_to_target_data(arg1)(p, ret);
+                }
+             }
             unlock_user(p, arg2, ret);
         }
         break;
     case TARGET_NR_write:
         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
             goto efault;
+        if (fd_trans_write_op(arg1)) {
+            ret = fd_trans_write_op(arg1)(p, arg3);
+            if (is_error(ret)) {
+                unlock_user(p, arg2, 0);
+                break;
+            }
+        }
         ret = get_errno(safe_write(arg1, p, arg3));
         unlock_user(p, arg2, 0);
         break;
@@ -11567,6 +11642,49 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
 
+#if defined(TARGET_NR_fanotify_init) && defined(CONFIG_FANOTIFY)
+    case TARGET_NR_fanotify_init:
+        {
+            ret = get_errno(fanotify_init(arg1, target_to_host_bitmask(arg2,
+                                                fcntl_flags_tbl)));
+            if (ret >= 0) {
+                fd_trans_register(ret, &fanotify_trans);
+            }
+        }
+        break;
+#endif
+#if defined(TARGET_NR_fanotify_mark) && defined(CONFIG_FANOTIFY)
+    case TARGET_NR_fanotify_mark:
+        {
+            p = NULL;
+#if (TARGET_ABI_BITS == 32)
+            if (arg6) {
+                p = lock_user_string(arg6);
+                if (!p) {
+                    goto efault;
+                }
+            }
+            ret = get_errno(fanotify_mark(arg1, arg2,
+                                target_offset64(arg3, arg4), arg5 , p));
+            if (arg6) {
+                unlock_user(p, arg6, 0);
+            }
+#else
+            if (arg5) {
+                p = lock_user_string(arg5);
+                if (!p) {
+                    goto efault;
+                }
+            }
+            ret = get_errno(fanotify_mark(arg1, arg2, arg3, arg4 , p));
+            if (arg5) {
+                unlock_user(p, arg5, 0);
+            }
+#endif
+        }
+        break;
+#endif
+
 #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
     case TARGET_NR_mq_open:
         {
-- 
2.7.4

  reply	other threads:[~2016-11-24 16:09 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-24 16:08 [Qemu-devel] [PATCH v2 0/7] Improvements of qemu linux-user Lena Djokic
2016-11-24 16:08 ` Lena Djokic [this message]
2016-12-16 16:43   ` [Qemu-devel] [PATCH v2 1/7] linux-user: Add fanotify implementation Peter Maydell
2016-11-24 16:08 ` [Qemu-devel] [PATCH v2 2/7] linux-user: Fix inotify_init1 support Lena Djokic
2016-12-16 14:53   ` Peter Maydell
2017-01-05 12:13   ` Riku Voipio
2016-11-24 16:08 ` [Qemu-devel] [PATCH v2 3/7] linux-user: Fix flock definition for mips64 Lena Djokic
2016-12-16 14:51   ` Peter Maydell
2016-11-24 16:08 ` [Qemu-devel] [PATCH v2 4/7] linux-user: Fix fcnt Lena Djokic
2016-12-16 14:45   ` Peter Maydell
2016-11-24 16:08 ` [Qemu-devel] [PATCH v2 5/7] linux-user: Fix readahead Lena Djokic
2016-12-16 14:27   ` Peter Maydell
2017-01-05 12:14   ` Riku Voipio
2016-11-24 16:08 ` [Qemu-devel] [PATCH v2 6/7] linux-user: Fix syslog Lena Djokic
2016-12-16 14:38   ` Peter Maydell
2016-11-24 16:08 ` [Qemu-devel] [PATCH v2 7/7] linux-user: Fix mq_open Lena Djokic
2016-12-16 14:39   ` Peter Maydell
2017-01-05 12:14   ` Riku Voipio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1480003738-8754-2-git-send-email-Lena.Djokic@rt-rk.com \
    --to=lena.djokic@rt-rk.com \
    --cc=qemu-devel@nongnu.org \
    --cc=riku.voipio@iki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.