[PATCH] fanotify: register event pid for pidfd reporting
From: AnonymeMeow
Date: Sat May 30 2026 - 06:51:17 EST
pidfd_prepare() may still fail if userspace reads the event after the
task has been reaped and the pid has not been registered with pidfs.
Register the event pid with pidfs when creating the fanotify event if
pidfd reporting was requested, so pidfd_prepare() can later create a
pidfd for the reaped task.
[JK: Reworked error handling ]
Signed-off-by: AnonymeMeow <anonymemeow@xxxxxxxxx>
Link: https://patch.msgid.link/20260530105117.45792-1-anonymemeow@xxxxxxxxx
Signed-off-by: Jan Kara <jack@xxxxxxx>
---
fs/notify/fanotify/fanotify.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 8ed77901db57..de013dd132d7 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -14,6 +14,7 @@
#include <linux/sched/mm.h>
#include <linux/statfs.h>
#include <linux/stringhash.h>
+#include <linux/pidfs.h>
#include "fanotify.h"
@@ -760,7 +761,7 @@ static struct fanotify_event *fanotify_alloc_event(
bool name_event = false;
unsigned int hash = 0;
bool ondir = mask & FAN_ONDIR;
- struct pid *pid;
+ struct pid *pid = NULL;
if ((fid_mode & FAN_REPORT_DIR_FID) && dirid) {
/*
@@ -839,6 +840,16 @@ static struct fanotify_event *fanotify_alloc_event(
/* Whoever is interested in the event, pays for the allocation. */
old_memcg = set_active_memcg(group->memcg);
+ if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
+ pid = get_pid(task_pid(current));
+ else
+ pid = get_pid(task_tgid(current));
+
+ /* Prepare task for creating pidfd for it even if it exits */
+ if (FAN_GROUP_FLAG(group, FAN_REPORT_PIDFD))
+ if (pidfs_register_pid(pid))
+ goto out;
+
if (fanotify_is_perm_event(mask)) {
event = fanotify_alloc_perm_event(data, data_type, gfp);
} else if (fanotify_is_error_event(mask)) {
@@ -860,17 +871,14 @@ static struct fanotify_event *fanotify_alloc_event(
if (!event)
goto out;
- if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
- pid = get_pid(task_pid(current));
- else
- pid = get_pid(task_tgid(current));
-
/* Mix event info, FAN_ONDIR flag and pid into event merge key */
hash ^= hash_long((unsigned long)pid | ondir, FANOTIFY_EVENT_HASH_BITS);
fanotify_init_event(event, hash, mask);
event->pid = pid;
-
+ pid = NULL;
out:
+ if (pid)
+ put_pid(pid);
set_active_memcg(old_memcg);
return event;
}
--
2.51.0
--5w6nv5meznsemm7q--