#include <linux/memcontrol.h>
#include <linux/statfs.h>
#include <linux/exportfs.h>
+#include <linux/pidfd.h>
#include <asm/ioctls.h>
metadata.fd = fd >= 0 ? fd : FAN_NOFD;
if (pidfd_mode) {
- /*
- * Complain if the FAN_REPORT_PIDFD and FAN_REPORT_TID mutual
- * exclusion is ever lifted. At the time of incoporating pidfd
- * support within fanotify, the pidfd API only supported the
- * creation of pidfds for thread-group leaders.
- */
- WARN_ON_ONCE(FAN_GROUP_FLAG(group, FAN_REPORT_TID));
+ unsigned int tid_mode = FAN_GROUP_FLAG(group, FAN_REPORT_TID);
+ enum pid_type pidtype = tid_mode ? PIDTYPE_PID : PIDTYPE_TGID;
+ unsigned int pidfd_flags = tid_mode ? PIDFD_THREAD : 0;
/*
- * The PIDTYPE_TGID check for an event->pid is performed
+ * The pid_has_task() check for an event->pid is performed
* preemptively in an attempt to catch out cases where the event
- * listener reads events after the event generating process has
+ * listener reads events after the event generating task has
* already terminated. Depending on flag FAN_REPORT_FD_ERROR,
* report either -ESRCH or FAN_NOPIDFD to the event listener in
* those cases with all other pidfd creation errors reported as
* the error code itself or as FAN_EPIDFD.
*/
- if (metadata.pid && pid_has_task(event->pid, PIDTYPE_TGID))
- pidfd = pidfd_prepare(event->pid, 0, &pidfd_file);
+ if (metadata.pid && pid_has_task(event->pid, pidtype))
+ pidfd = pidfd_prepare(event->pid, pidfd_flags, &pidfd_file);
if (!FAN_GROUP_FLAG(group, FAN_REPORT_FD_ERROR) && pidfd < 0)
pidfd = pidfd == -ESRCH ? FAN_NOPIDFD : FAN_EPIDFD;
#endif
return -EINVAL;
- /*
- * A pidfd can only be returned for a thread-group leader; thus
- * FAN_REPORT_PIDFD and FAN_REPORT_TID need to remain mutually
- * exclusive.
- */
- if ((flags & FAN_REPORT_PIDFD) && (flags & FAN_REPORT_TID))
- return -EINVAL;
-
/* Don't allow mixing mnt events with inode events for now */
if (flags & FAN_REPORT_MNT) {
if (class != FAN_CLASS_NOTIF)