summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2023-03-27 21:22:53 +0300
committerChristian Brauner <brauner@kernel.org>2023-04-03 12:16:57 +0300
commiteee3a0e93924f2aab8ebaa7f2e26fd0f3b33f9e7 (patch)
tree5a4692d7b26c242aa85b806fc66897e23426bab4
parentca7707f5430ad6b1c9cb7cee0a7f67d69328bb2d (diff)
downloadlinux-eee3a0e93924f2aab8ebaa7f2e26fd0f3b33f9e7.tar.xz
fanotify: use pidfd_prepare()
We generally try to avoid installing a file descriptor into the caller's file descriptor table just to close it again via close_fd() in case an error occurs. Instead we reserve a file descriptor but don't install it into the caller's file descriptor table yet. If we fail for other, unrelated reasons we can just close the reserved file descriptor and if we make it past all meaningful error paths we just install it. Fanotify gets this right already for one fd type but not for pidfds. Use the new pidfd_prepare() helper to reserve a pidfd and a pidfd file and switch to the more common fd allocation and installation pattern. Acked-by: Jan Kara <jack@suse.cz> Message-Id: <20230327-pidfd-file-api-v1-3-5c0e9a3158e4@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
-rw-r--r--fs/notify/fanotify/fanotify_user.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 8f430bfad487..22fb1cf7e1fc 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -663,7 +663,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
struct fanotify_info *info = fanotify_event_info(event);
unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
- struct file *f = NULL;
+ struct file *f = NULL, *pidfd_file = NULL;
int ret, pidfd = FAN_NOPIDFD, fd = FAN_NOFD;
pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -718,7 +718,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
!pid_has_task(event->pid, PIDTYPE_TGID)) {
pidfd = FAN_NOPIDFD;
} else {
- pidfd = pidfd_create(event->pid, 0);
+ pidfd = pidfd_prepare(event->pid, 0, &pidfd_file);
if (pidfd < 0)
pidfd = FAN_EPIDFD;
}
@@ -751,6 +751,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
if (f)
fd_install(fd, f);
+ if (pidfd_file)
+ fd_install(pidfd, pidfd_file);
+
return metadata.event_len;
out_close_fd:
@@ -759,8 +762,10 @@ out_close_fd:
fput(f);
}
- if (pidfd >= 0)
- close_fd(pidfd);
+ if (pidfd >= 0) {
+ put_unused_fd(pidfd);
+ fput(pidfd_file);
+ }
return ret;
}