linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Jan Kara <jack@suse.cz>
Cc: Matthew Bobrowski <mbobrowski@mbobrowski.org>,
	linux-fsdevel@vger.kernel.org
Subject: [PATCH v3 11/13] fanotify: support events with data type FSNOTIFY_EVENT_INODE
Date: Sun, 25 Nov 2018 15:43:50 +0200	[thread overview]
Message-ID: <20181125134352.21499-12-amir73il@gmail.com> (raw)
In-Reply-To: <20181125134352.21499-1-amir73il@gmail.com>

When event data type is FSNOTIFY_EVENT_INODE, we don't have a refernece
to the mount, so we will not be able to open a file descriptor when user
reads the event. However, if the listener has enabled reporting file
identifier with the FAN_REPORT_FID init flag, we allow repoting those
events and we use an indentifier inode to encode fid.

The inode to use as indetifier when reporting fid depedns on the event.
For dirent modification events, we report the modified directory inode
and we report the "victim" inode otherwise.
For example:
FS_ATTRIB reports the child inode even if reported on a watched parent.
FS_CREATE reports the modified dir inode and not the created inode.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c      | 62 ++++++++++++++++++++----------
 fs/notify/fanotify/fanotify.h      |  2 +-
 fs/notify/fanotify/fanotify_user.c |  3 +-
 3 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index ef567d07f5a6..3e8b3abe4952 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -114,14 +114,11 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 	pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
 		 __func__, iter_info->report_mask, event_mask, data, data_type);
 
-	/* If we don't have enough info to send an event to userspace say no */
-	if (data_type != FSNOTIFY_EVENT_PATH)
-		return 0;
-
-	/* Sorry, fanotify only gives a damn about files and dirs */
-	if (!d_is_reg(path->dentry) &&
-	    !d_can_lookup(path->dentry))
-		return 0;
+	if (data_type == FSNOTIFY_EVENT_PATH) {
+		/* Path type events are only relevant for files and dirs */
+		if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
+			return 0;
+	}
 
 	fsnotify_foreach_obj_type(type) {
 		if (!fsnotify_iter_should_report_type(iter_info, type))
@@ -155,7 +152,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 		~marks_ignored_mask;
 }
 
-static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path,
+static struct fanotify_event_fid *fanotify_alloc_fid(struct inode *inode,
 						     gfp_t gfp)
 {
 	struct fanotify_event_fid *fid = NULL;
@@ -164,7 +161,7 @@ static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path,
 
 	dwords = 0;
 	err = -ENOENT;
-	type = exportfs_encode_fh(path->dentry, NULL, &dwords,  0);
+	type = exportfs_encode_inode_fh(inode, NULL, &dwords,  NULL);
 	if (!dwords)
 		goto out_err;
 
@@ -174,8 +171,8 @@ static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path,
 	if (!fid)
 		return NULL;
 
-	type = exportfs_encode_fh(path->dentry, (struct fid *)fid->f_handle,
-				  &dwords,  0);
+	type = exportfs_encode_inode_fh(inode, (struct fid *)fid->f_handle,
+					&dwords,  NULL);
 	err = -EINVAL;
 	if (type == FILEID_INVALID || bytes != dwords << 2)
 		goto out_err;
@@ -186,20 +183,42 @@ static struct fanotify_event_fid *fanotify_alloc_fid(const struct path *path,
 	return fid;
 
 out_err:
-	pr_warn_ratelimited("fanotify: failed to encode fid of %pd2 (bytes=%d, err=%i)\n",
-			    path->dentry, bytes, err);
+	pr_warn_ratelimited("fanotify: failed to encode fid (ino=%lu, type=%d, bytes=%d, err=%i)\n",
+			    inode->i_ino, type, bytes, err);
 	kfree(fid);
 	return ERR_PTR(err);
 }
 
+/*
+ * The inode to use as indetifier when reporting fid depedns on the event.
+ * Report the modified directory inode on dirent modification events.
+ * Report the "victim" inode otherwise.
+ * For example:
+ * FS_ATTRIB reports the child inode even if reported on a watched parent.
+ * FS_CREATE reports the modified dir inode and not the created inode.
+ */
+static struct inode *fanotify_report_id(struct inode *to_tell, u32 event_mask,
+					const void *data, int data_type)
+{
+	if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
+		return to_tell;
+	else if (data_type == FSNOTIFY_EVENT_INODE)
+		return (struct inode *)data;
+	else if (data_type == FSNOTIFY_EVENT_PATH)
+		return d_inode(((struct path *)data)->dentry);
+	else
+		return NULL;
+}
+
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 					    struct inode *inode, u32 mask,
-					    const struct path *path,
+					    const void *data, int data_type,
 					    __kernel_fsid_t *fsid)
 {
 	struct fanotify_event *event = NULL;
 	struct fanotify_event_fid *fid = NULL;
 	gfp_t gfp = GFP_KERNEL_ACCOUNT;
+	struct inode *id = fanotify_report_id(inode, mask, data, data_type);
 
 	/*
 	 * For queues with unlimited length lost events are not expected and
@@ -212,8 +231,8 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 	/* Whoever is interested in the event, pays for the allocation. */
 	memalloc_use_memcg(group->memcg);
 
-	if (path && fsid && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
-		fid = fanotify_alloc_fid(path, gfp);
+	if (id && fsid && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+		fid = fanotify_alloc_fid(id, gfp);
 		/* Treat failure to allocate fid as failure to allocate event */
 		if (!fid)
 			goto out;
@@ -245,8 +264,8 @@ init: __maybe_unused
 		event->pid = get_pid(task_tgid(current));
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
 		fanotify_set_fid(event, fid);
-	} else if (path) {
-		event->path = *path;
+	} else if (data_type == FSNOTIFY_EVENT_PATH) {
+		event->path = *((struct path *)data);
 		path_get(&event->path);
 	} else {
 		event->path.mnt = NULL;
@@ -283,10 +302,13 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 
 	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 12);
 
+	/* Events without path data require FAN_REPORT_FID */
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
 		__fsid.val[0] = 0;
 		__fsid.val[1] = 0;
 		fsid = &__fsid;
+	} else if (data_type != FSNOTIFY_EVENT_PATH) {
+		return 0;
 	}
 
 	mask = fanotify_group_event_mask(iter_info, mask, data, data_type,
@@ -306,7 +328,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 			return 0;
 	}
 
-	event = fanotify_alloc_event(group, inode, mask, data, fsid);
+	event = fanotify_alloc_event(group, inode, mask, data, data_type, fsid);
 	ret = -ENOMEM;
 	if (unlikely(!event)) {
 		/*
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index b9938626b2a3..3c21c9a1278d 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -100,5 +100,5 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 					    struct inode *inode, u32 mask,
-					    const struct path *path,
+					    const void *data, int data_type,
 					    __kernel_fsid_t *fsid);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 92afb297fdea..9479bd418c31 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -799,7 +799,8 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	atomic_inc(&user->fanotify_listeners);
 	group->memcg = get_mem_cgroup_from_mm(current->mm);
 
-	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, NULL);
+	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL,
+				      FSNOTIFY_EVENT_NONE, NULL);
 	if (unlikely(!oevent)) {
 		fd = -ENOMEM;
 		goto out_destroy_group;
-- 
2.17.1

  parent reply	other threads:[~2018-11-26  0:35 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-25 13:43 [PATCH v3 00/13] fanotify: add support for more event types Amir Goldstein
2018-11-25 13:43 ` [PATCH v3 01/13] fsnotify: annotate directory entry modification events Amir Goldstein
2018-11-28 12:59   ` Jan Kara
2018-11-28 14:39     ` Amir Goldstein
2018-11-28 14:43       ` Jan Kara
2018-11-28 15:01         ` Amir Goldstein
2018-11-25 13:43 ` [PATCH v3 02/13] fsnotify: send all event types to super block marks Amir Goldstein
2018-11-28 14:26   ` Jan Kara
2018-11-25 13:43 ` [PATCH v3 03/13] fanotify: rename struct fanotify_{,perm_}event_info Amir Goldstein
2018-11-28 14:29   ` Jan Kara
2018-11-25 13:43 ` [PATCH v3 04/13] fanotify: define the structures to report a unique file identifier Amir Goldstein
2018-11-28 15:27   ` Jan Kara
2018-11-28 16:24     ` Amir Goldstein
2018-11-28 17:43       ` Jan Kara
2018-11-28 18:34         ` Amir Goldstein
2018-11-29  7:51           ` Jan Kara
2018-11-29  8:16             ` Amir Goldstein
2018-11-29 10:16               ` Jan Kara
2018-11-29 11:10                 ` Amir Goldstein
2018-11-30 15:32                 ` Amir Goldstein
2018-12-01 16:43                   ` Amir Goldstein
2018-11-25 13:43 ` [PATCH v3 05/13] fanotify: classify events that hold a " Amir Goldstein
2018-11-28 15:33   ` Jan Kara
2018-11-28 15:44     ` Jan Kara
2018-11-28 15:52       ` Amir Goldstein
2018-11-25 13:43 ` [PATCH v3 06/13] fanotify: encode file identifier for FAN_REPORT_FID Amir Goldstein
2018-11-25 13:43 ` [PATCH v3 07/13] fanotify: copy event fid info to user Amir Goldstein
2018-11-29  9:00   ` Jan Kara
     [not found]     ` <CAOQ4uxjcb=UqQiw0XcpDfetK28bM4tOYdvgxPwhkjgE2mxpt=g@mail.gmail.com>
2018-11-29  9:49       ` Jan Kara
2018-11-25 13:43 ` [PATCH v3 08/13] fanotify: enable FAN_REPORT_FID init flag Amir Goldstein
2018-11-29  9:46   ` Jan Kara
2018-11-29 10:52     ` Jan Kara
2018-11-29 11:03     ` Amir Goldstein
2018-11-29 13:08       ` Jan Kara
2018-11-25 13:43 ` [PATCH v3 09/13] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
2018-11-29 10:48   ` Jan Kara
2018-11-29 11:42     ` Amir Goldstein
2018-11-29 13:11       ` Jan Kara
2018-11-25 13:43 ` [PATCH v3 10/13] fanotify: check FS_ISDIR flag instead of d_is_dir() Amir Goldstein
2018-11-25 13:43 ` Amir Goldstein [this message]
2018-11-25 13:43 ` [PATCH v3 12/13] fanotify: add support for create/attrib/move/delete events Amir Goldstein
2018-11-25 13:43 ` [PATCH v3 13/13] fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID Amir Goldstein

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=20181125134352.21499-12-amir73il@gmail.com \
    --to=amir73il@gmail.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=mbobrowski@mbobrowski.org \
    /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).