linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Paris <eparis@redhat.com>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	netdev@vger.kernel.org
Cc: davem@davemloft.net, viro@zeniv.linux.org.uk,
	alan@linux.intel.com, hch@infradead.org
Subject: [PATCH 6/8] fanotify: userspace socket
Date: Fri, 11 Sep 2009 01:26:35 -0400	[thread overview]
Message-ID: <20090911052634.32359.72086.stgit@paris.rdu.redhat.com> (raw)
In-Reply-To: <20090911052558.32359.18075.stgit@paris.rdu.redhat.com>

This patch implements an userspace interface for the fanotify notification
system.  An fanotify socket is created in userspace and is 'bound' to an
address.  That bind call actually creates the new fanotify listener much like
inotify_init() creates an inotify instance.

Requests for notification of events on certain fs objects is done using a
setsockopt() call.  (not implemented in this patch)  This setsockopt() call is
largely analogous to inotify_add_watch()

Events are retrieved from the kernel calling read on the bound socket.
This interface is designed to be forward looking as the kernel/userspace
interaction can be changed simply by implementing a new getsockopt option.

Macros are provided much like the netlink macros in order to allow of the
messages from the kernel to userspace to change in length in the future while
maintaining backwards compatibility.

This patch only implements the socket registration and the bind call.  The
getsockopt() calls and data read call are implemented in later patches.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/fanotify/Makefile      |    2 -
 fs/notify/fanotify/af_fanotify.c |  152 ++++++++++++++++++++++++++++++++++++++
 fs/notify/fanotify/af_fanotify.h |   21 +++++
 fs/notify/fanotify/fanotify.h    |    2 +
 include/linux/fanotify.h         |   19 +++++
 5 files changed, 195 insertions(+), 1 deletions(-)
 create mode 100644 fs/notify/fanotify/af_fanotify.c
 create mode 100644 fs/notify/fanotify/af_fanotify.h

diff --git a/fs/notify/fanotify/Makefile b/fs/notify/fanotify/Makefile
index e7d39c0..1196005 100644
--- a/fs/notify/fanotify/Makefile
+++ b/fs/notify/fanotify/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_FANOTIFY)		+= fanotify.o
+obj-$(CONFIG_FANOTIFY)		+= fanotify.o af_fanotify.o
diff --git a/fs/notify/fanotify/af_fanotify.c b/fs/notify/fanotify/af_fanotify.c
new file mode 100644
index 0000000..d7bf658
--- /dev/null
+++ b/fs/notify/fanotify/af_fanotify.c
@@ -0,0 +1,152 @@
+#include <linux/errno.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/fsnotify_backend.h>
+#include <linux/init.h>
+#include <linux/kernel.h> /* UINT_MAX */
+#include <linux/mount.h> /* mntget() */
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/types.h>
+
+#include <net/net_namespace.h>
+#include <net/sock.h>
+
+#include "fanotify.h"
+#include "af_fanotify.h"
+
+static const struct proto_ops fanotify_proto_ops;
+
+static struct proto fanotify_proto = {
+	.name     = "FANOTIFY",
+	.owner    = THIS_MODULE,
+	.obj_size = sizeof(struct fanotify_sock),
+};
+
+static int fan_sock_create(struct net *net, struct socket *sock, int protocol)
+{
+	struct sock *sk;
+	struct fanotify_sock *fan_sock;
+
+	/* FIXME maybe a new LSM hook? */
+	if (!capable(CAP_NET_RAW))
+		return -EPERM;
+
+	if (protocol != 0)
+		return -ESOCKTNOSUPPORT;
+
+	if (sock->type != SOCK_RAW)
+		return -ESOCKTNOSUPPORT;
+
+	sock->state = SS_UNCONNECTED;
+
+	sk = sk_alloc(net, PF_FANOTIFY, GFP_KERNEL, &fanotify_proto);
+	if (sk == NULL)
+		return -ENOBUFS;
+
+	sock->ops = &fanotify_proto_ops;
+
+	sock_init_data(sock, sk);
+
+	sk->sk_family = PF_FANOTIFY;
+	sk_refcnt_debug_inc(sk);
+
+	fan_sock = fan_sk(sk);
+	fan_sock->group = NULL;
+
+	return 0;
+}
+
+static int fan_release(struct socket *sock)
+{
+	struct sock *sk;
+	struct fanotify_sock *fan_sock;
+
+	sk = sock->sk;
+	if (!sk)
+		return 0;
+
+	fan_sock = fan_sk(sk);
+
+	if (sock->state == SS_CONNECTED) {
+		sock->state = SS_UNCONNECTED;
+		fsnotify_put_group(fan_sock->group);
+	}
+
+	fan_sock->group = NULL;
+
+	sock_orphan(sk);
+	sock->sk = NULL;
+
+	sk_refcnt_debug_release(sk);
+
+	sock_put(sk);
+
+	return 0;
+}
+
+static int fan_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+{
+	struct fanotify_addr *fan_addr = (struct fanotify_addr *)addr;
+	struct fanotify_sock *fan_sock;
+
+	if (addr_len != sizeof(struct fanotify_addr))
+		return -EINVAL;
+
+	if (sock->state != SS_UNCONNECTED)
+		return -EINVAL;
+
+	if (!fanotify_is_mask_valid(fan_addr->mask))
+		return -EINVAL;
+
+	fan_sock = fan_sk(sock->sk);
+	fan_sock->group = fsnotify_obtain_group(fan_addr->mask, &fanotify_ops);
+
+	if (IS_ERR(fan_sock->group))
+		return PTR_ERR(fan_sock->group);
+
+	fan_sock->group->max_events = 16383;
+
+	sock->state = SS_CONNECTED;
+
+	return 0;
+}
+
+static const struct net_proto_family fanotify_family_ops = {
+	.family		=	PF_FANOTIFY,
+	.create		=	fan_sock_create,
+	.owner		=	THIS_MODULE,
+};
+
+static const struct proto_ops fanotify_proto_ops = {
+	.family =	PF_FANOTIFY,
+	.owner =	THIS_MODULE,
+	.release =	fan_release,
+	.bind =		fan_bind,
+	.connect =	sock_no_connect,
+	.socketpair =	sock_no_socketpair,
+	.accept =	sock_no_accept,
+	.getname =	sock_no_getname,
+	.poll =		sock_no_poll,
+	.ioctl =	sock_no_ioctl,
+	.listen =	sock_no_listen,
+	.shutdown =	sock_no_shutdown,
+	.setsockopt =	sock_no_setsockopt,
+	.getsockopt =	sock_no_getsockopt,
+	.sendmsg =	sock_no_sendmsg,
+	.recvmsg =	sock_no_recvmsg,
+	.mmap =		sock_no_mmap,
+	.sendpage =	sock_no_sendpage,
+};
+
+static int __init fanotify_init(void)
+{
+	if (proto_register(&fanotify_proto, 0))
+		panic("unable to register fanotify protocol with network stack\n");
+
+	sock_register(&fanotify_family_ops);
+
+	return 0;
+}
+device_initcall(fanotify_init);
diff --git a/fs/notify/fanotify/af_fanotify.h b/fs/notify/fanotify/af_fanotify.h
new file mode 100644
index 0000000..fff0e66
--- /dev/null
+++ b/fs/notify/fanotify/af_fanotify.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_AF_FANOTIFY_H
+#define _LINUX_AF_FANOTIFY_H
+
+#include <linux/fanotify.h>
+#include <net/sock.h>
+
+struct fanotify_sock {
+	struct sock		sock;
+	struct fsnotify_group	*group;
+};
+
+static inline struct fanotify_sock *fan_sk(struct sock *sock)
+{
+	struct fanotify_sock *fan_sock;
+
+	fan_sock = container_of(sock, struct fanotify_sock, sock);
+
+	return fan_sock;
+}
+
+#endif /* _LINUX_AF_NET_H */
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index a8785c1..6c7bf06 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -4,6 +4,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+extern const struct fsnotify_ops fanotify_ops;
+
 static inline bool fanotify_is_mask_valid(__u32 mask)
 {
 	if (mask & ~(FAN_ALL_INCOMING_EVENTS))
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index b560f86..4c1c6cd 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_FANOTIFY_H
 #define _LINUX_FANOTIFY_H
 
+#include <linux/socket.h>
 #include <linux/types.h>
 
 /* the following events that user-space can register for */
@@ -34,6 +35,24 @@
  */
 #define FAN_ALL_INCOMING_EVENTS	(FAN_ALL_EVENTS |\
 				 FAN_EVENT_ON_CHILD)
+#ifndef SOL_FANOTIFY
+#define SOL_FANOTIFY	278
+#endif
+
+#ifndef AF_FANOTIFY
+#define AF_FANOTIFY	37
+#define PF_FANOTIFY	AF_FANOTIFY
+#endif
+
+struct fanotify_addr {
+	sa_family_t family;
+	__u32 priority;	/* unused */
+	__u32 mask_hi;	/* unused */
+	__u32 mask;	/* unused */
+	__u32 f_flags;	/* unused */
+	__u32 unused[16];
+}  __attribute__((packed));
+
 #ifdef __KERNEL__
 
 #endif /* __KERNEL__ */

  parent reply	other threads:[~2009-09-11  5:26 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-11  5:25 [PATCH 1/8] networking/fanotify: declare fanotify socket numbers Eric Paris
2009-09-11  5:26 ` [PATCH 2/8] vfs: introduce FMODE_NONOTIFY Eric Paris
2009-09-11  5:26 ` [PATCH 3/8] fanotify: fscking all notification system Eric Paris
2009-09-11  5:26 ` [PATCH 4/8] fanotify:drop notification if they exist in the outgoing queue Eric Paris
2009-09-11  5:26 ` [PATCH 5/8] fanotify: merge notification events with different masks Eric Paris
2009-09-11  5:26 ` Eric Paris [this message]
2009-09-11  5:26 ` [PATCH 7/8] fanotify: userspace can add and remove fsnotify inode marks Eric Paris
2009-09-11  5:26 ` [PATCH 8/8] fanotify: send events to userspace over socket reads Eric Paris
2009-09-11 14:08   ` Daniel Walker
2009-09-11 14:15     ` Eric Paris
2009-09-11 14:22       ` Daniel Walker
2009-09-11 14:32       ` Daniel Walker
2009-09-11 14:32 ` [PATCH 1/8] networking/fanotify: declare fanotify socket numbers Andreas Gruenbacher
2009-09-11 16:04   ` Eric Paris
2009-09-11 18:46 ` David Miller
2009-09-11 19:33   ` Eric Paris
2009-09-11 20:46     ` Jamie Lokier
2009-09-11 21:13       ` Eric Paris
2009-09-11 21:27         ` Jamie Lokier
2009-09-11 21:51           ` Eric Paris
2009-09-12  9:41             ` Evgeniy Polyakov
2009-09-14  0:17               ` Jamie Lokier
2009-09-14 14:07                 ` Evgeniy Polyakov
2009-09-14 19:08                   ` fanotify as syscalls Eric Paris
2009-09-15 20:16                     ` Evgeniy Polyakov
2009-09-15 21:54                       ` Eric Paris
2009-09-15 23:49                         ` Linus Torvalds
2009-09-16  1:26                           ` Eric Paris
2009-09-16  7:52                             ` Jamie Lokier
2009-09-16  9:48                               ` Eric Paris
2009-09-16 12:17                                 ` Jamie Lokier
2009-09-17 20:07                                   ` Andreas Gruenbacher
2009-09-18 20:52                                     ` Eric Paris
2009-09-18 22:00                                       ` Andreas Gruenbacher
2009-09-19  3:04                                         ` Eric Paris
2009-09-21 20:04                                           ` Andreas Gruenbacher
2009-09-21 20:28                                             ` Jamie Lokier
2009-09-21 21:27                                               ` Andreas Gruenbacher
2009-09-21 22:00                                                 ` Jamie Lokier
2009-09-21 23:09                                                   ` Andreas Gruenbacher
2009-09-21 23:56                                                     ` Jamie Lokier
2009-09-21 22:18                                               ` Davide Libenzi
2009-09-21 23:12                                                 ` Jamie Lokier
2009-09-22 14:51                                                   ` Davide Libenzi
2009-09-22 15:31                                                     ` Andreas Gruenbacher
2009-09-22 16:04                                                       ` Davide Libenzi
2009-09-23  8:39                                                         ` Tvrtko Ursulin
2009-09-23 11:20                                                           ` hch
2009-09-23 15:35                                                             ` Davide Libenzi
2009-09-23 21:58                                                               ` hch
2009-09-23 11:32                                                           ` Arjan van de Ven
2009-09-23 15:42                                                             ` Tvrtko Ursulin
2009-09-23 15:51                                                             ` Eric Paris
2009-09-23 21:56                                                               ` hch
2009-09-23 15:26                                                           ` Davide Libenzi
2009-09-23 15:45                                                             ` Tvrtko Ursulin
2009-09-23 17:31                                                               ` Davide Libenzi
2009-09-22 16:11                                                       ` Eric Paris
2009-09-22 16:27                                                         ` Jamie Lokier
2009-09-22 23:43                                                           ` Davide Libenzi
2009-09-22 21:06                                             ` Eric Paris
2009-09-22 21:38                                               ` Andreas Gruenbacher
2009-09-16 10:41                               ` Alan Cox
2009-09-16 11:41                                 ` Jamie Lokier
2009-09-16 12:01                                   ` Alan Cox
2009-09-16 12:56                                     ` Jamie Lokier
2009-09-16 15:53                                       ` Eric Paris
2009-09-16 21:49                                         ` Jamie Lokier
2009-09-16 22:33                                           ` Eric Paris
2009-09-16 11:30                         ` Arnd Bergmann
2009-09-16 12:05                         ` Evgeniy Polyakov
2009-09-16 12:27                           ` Jamie Lokier
2009-09-17 16:40                             ` Linus Torvalds
2009-09-17 17:35                               ` Arjan van de Ven
2009-09-17 18:53                               ` Eric Paris
2009-09-22  0:15                               ` Eric W. Biederman
2009-09-22  0:22                                 ` Randy Dunlap
2009-09-11 21:21     ` [PATCH 1/8] networking/fanotify: declare fanotify socket numbers jamal
2009-09-11 21:42       ` Jamie Lokier
2009-09-11 22:52         ` jamal
2009-09-14  0:03           ` Jamie Lokier
2009-09-14  1:26             ` Eric Paris
2009-09-14 13:15             ` jamal
2009-09-12  9:47         ` Evgeniy Polyakov

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=20090911052634.32359.72086.stgit@paris.rdu.redhat.com \
    --to=eparis@redhat.com \
    --cc=alan@linux.intel.com \
    --cc=davem@davemloft.net \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).