@@ -13,6 +13,8 @@
#include <linux/wait.h>
#include <linux/audit.h>
#include <linux/sched/mm.h>
+#include <linux/statfs.h>
+#include <linux/exportfs.h>
#include "fanotify.h"
@@ -146,11 +148,55 @@ 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,
+ gfp_t gfp)
+{
+ struct fanotify_event_fid *fid = NULL;
+ int dwords, bytes = 0;
+ struct kstatfs stat;
+ int err, type;
+
+ dwords = 0;
+ err = -ENOENT;
+ type = exportfs_encode_fh(path->dentry, NULL, &dwords, 0);
+ if (!dwords)
+ goto out_err;
+
+ err = vfs_statfs(path, &stat);
+ if (err)
+ goto out_err;
+
+ /* Treat failure to allocate fid as failure to allocate event */
+ bytes = dwords << 2;
+ fid = kmalloc(FANOTIFY_FID_LEN(bytes), gfp);
+ if (!fid)
+ return NULL;
+
+ type = exportfs_encode_fh(path->dentry, (struct fid *)fid->f_handle,
+ &dwords, 0);
+ err = -EINVAL;
+ if (type == FILEID_INVALID || bytes != dwords << 2)
+ goto out_err;
+
+ fid->handle_bytes = bytes;
+ fid->handle_type = type;
+ fid->fsid = stat.f_fsid;
+
+ return fid;
+
+out_err:
+ pr_warn_ratelimited("fanotify: failed to encode fid of %pd2 (bytes=%d, err=%i)\n",
+ path->dentry, bytes, err);
+ kfree(fid);
+ return ERR_PTR(err);
+}
+
struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
struct inode *inode, u32 mask,
const struct path *path)
{
struct fanotify_event *event = NULL;
+ struct fanotify_event_fid *fid = NULL;
gfp_t gfp = GFP_KERNEL_ACCOUNT;
/*
@@ -164,6 +210,16 @@ 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 && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+ fid = fanotify_alloc_fid(path, gfp);
+ /* Treat failure to allocate fid as failure to allocate event */
+ if (!fid)
+ goto out;
+ /* Report the event without a file identifier on encode error */
+ if (IS_ERR(fid))
+ fid = NULL;
+ }
+
if (fanotify_is_perm_event(mask)) {
struct fanotify_perm_event *pevent;
@@ -184,8 +240,7 @@ init: __maybe_unused
else
event->pid = get_pid(task_tgid(current));
if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
- /* TODO: allocate buffer and encode file handle */
- fanotify_set_fid(event, NULL);
+ fanotify_set_fid(event, fid);
} else if (path) {
event->path = *path;
path_get(&event->path);
Allocate and encode event->info.fid for a group with FAN_REPORT_FID. Treat failure to allocate fid buffer as failure to allocate event. Treat failure to encode fid by printing a warning but queueing the event without the fid information. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/notify/fanotify/fanotify.c | 59 +++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-)