Hi Matthew! On Thu 10-06-21 10:21:50, Matthew Bobrowski wrote: > Introduce a new flag FAN_REPORT_PIDFD for fanotify_init(2) which > allows userspace applications to control whether a pidfd info record > containing a pidfd is to be returned with each event. > > If FAN_REPORT_PIDFD is enabled for a notification group, an additional > struct fanotify_event_info_pidfd object will be supplied alongside the > generic struct fanotify_event_metadata within a single event. This > functionality is analogous to that of FAN_REPORT_FID in terms of how > the event structure is supplied to the userspace application. Usage of > FAN_REPORT_PIDFD with FAN_REPORT_FID/FAN_REPORT_DFID_NAME is > permitted, and in this case a struct fanotify_event_info_pidfd object > will follow any struct fanotify_event_info_fid object. > > Currently, the usage of FAN_REPORT_TID is not permitted along with > FAN_REPORT_PIDFD as the pidfd API only supports the creation of pidfds > for thread-group leaders. Additionally, the FAN_REPORT_PIDFD is > limited to privileged processes only i.e. listeners that are running > with the CAP_SYS_ADMIN capability. Attempting to supply either of > these initialisation flags with FAN_REPORT_PIDFD will result with > EINVAL being returned to the caller. > > In the event of a pidfd creation error, there are two types of error > values that can be reported back to the listener. There is > FAN_NOPIDFD, which will be reported in cases where the process > responsible for generating the event has terminated prior to fanotify > being able to create pidfd for event->pid via pidfd_create(). The > there is FAN_EPIDFD, which will be reported if a more generic pidfd > creation error occurred when calling pidfd_create(). > > Signed-off-by: Matthew Bobrowski <repnop@xxxxxxxxxx> A few comments in addition to what Amir wrote: > @@ -524,6 +561,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, > } > metadata.fd = fd; > > + /* > + * Currently, reporting a pidfd to an unprivileged listener is not > + * supported. The FANOTIFY_UNPRIV flag is to be kept here so that a > + * pidfd is not accidentally leaked to an unprivileged listener. > + */ > + if (pidfd_mode && !FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) { Hum, you've added FAN_REPORT_PIDFD to FANOTIFY_ADMIN_INIT_FLAGS so this condition should be always true? I don't think we need to be that much defensive and would just drop the check here. > + /* > + * The PIDTYPE_TGID check for an event->pid is performed > + * preemptively in attempt to catch those rare instances > + * where the process responsible for generating the event has > + * terminated prior to calling into pidfd_create() and > + * acquiring a valid pidfd. Report FAN_NOPIDFD to the listener > + * in those cases. > + */ > + if (metadata.pid == 0 || > + !pid_has_task(event->pid, PIDTYPE_TGID)) { > + pidfd = FAN_NOPIDFD; > + } else { > + pidfd = pidfd_create(event->pid, 0); > + if (pidfd < 0) > + /* > + * All other pidfd creation errors are reported > + * as FAN_EPIDFD to the listener. > + */ > + pidfd = FAN_EPIDFD; > + } > + } > + > ret = -EFAULT; > /* > * Sanity check copy size in case get_one_event() and ... > @@ -558,6 +632,10 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, > put_unused_fd(fd); > fput(f); > } > + > + if (pidfd < 0) > + put_unused_fd(pidfd); > + put_unused_fd() is not enough to destroy the pidfd you have. That will just mark 'pidfd' as free in the fd table. You rather need to call close_fd() here to fully close open file. Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR