[RFC/PATCH v2 bpf-next fanotify 1/7] fanotify: Introduce fanotify fastpath handler

Amir Goldstein amir73il at gmail.com
Fri Nov 15 08:51:02 UTC 2024


On Thu, Nov 14, 2024 at 9:44 AM Song Liu <song at kernel.org> wrote:
>
> fanotify fastpath handler enables handling fanotify events within the
> kernel, and thus saves a trip to the user space. fanotify fastpath handler
> can be useful in many use cases. For example, if a user is only interested
> in events for some files in side a directory, a fastpath handler can be
> used to filter out irrelevant events.
>
> fanotify fastpath handler is attached to fsnotify_group. At most one
> fastpath handler can be attached to a fsnotify_group. The attach/detach
> of fastpath handlers are controlled by two new ioctls on the fanotify fds:
> FAN_IOC_ADD_FP and FAN_IOC_DEL_FP.
>
> fanotify fastpath handler is packaged in a kernel module. In the future,
> it is also possible to package fastpath handler in a BPF program. Since
> loading modules requires CAP_SYS_ADMIN, _loading_ fanotify fastpath
> handler in kernel modules is limited to CAP_SYS_ADMIN. However,
> non-SYS_CAP_ADMIN users can _attach_ fastpath handler loaded by sys admin
> to their fanotify fds. To make fanotify fastpath handler more useful
> for non-CAP_SYS_ADMIN users, a fastpath handler can take arguments at
> attach time.
>
> sysfs entry /sys/kernel/fanotify_fastpath is added to help users know
> which fastpath handlers are available. At the moment, files are added for
> each fastpath handler: flags, desc, and init_args.
>
> Signed-off-by: Song Liu <song at kernel.org>
> ---
>  fs/notify/fanotify/Kconfig             |  13 ++
>  fs/notify/fanotify/Makefile            |   1 +
>  fs/notify/fanotify/fanotify.c          |  29 +++
>  fs/notify/fanotify/fanotify_fastpath.c | 282 +++++++++++++++++++++++++
>  fs/notify/fanotify/fanotify_user.c     |   7 +
>  include/linux/fanotify.h               | 131 ++++++++++++
>  include/linux/fsnotify_backend.h       |   4 +
>  include/uapi/linux/fanotify.h          |  25 +++
>  8 files changed, 492 insertions(+)
>  create mode 100644 fs/notify/fanotify/fanotify_fastpath.c
>
> diff --git a/fs/notify/fanotify/Kconfig b/fs/notify/fanotify/Kconfig
> index 0e36aaf379b7..74677d3699a3 100644
> --- a/fs/notify/fanotify/Kconfig
> +++ b/fs/notify/fanotify/Kconfig
> @@ -24,3 +24,16 @@ config FANOTIFY_ACCESS_PERMISSIONS
>            hierarchical storage management systems.
>
>            If unsure, say N.
> +
> +config FANOTIFY_FASTPATH
> +       bool "fanotify fastpath handler"
> +       depends on FANOTIFY
> +       default y
> +       help
> +          Say Y here if you want to use fanotify in kernel fastpath handler.
> +          The fastpath handler can be implemented in a kernel module or a
> +          BPF program. The fastpath handler can speed up fanotify in many
> +          use cases. For example, when the listener is only interested in
> +          a subset of events.
> +
> +          If unsure, say Y.
> \ No newline at end of file
> diff --git a/fs/notify/fanotify/Makefile b/fs/notify/fanotify/Makefile
> index 25ef222915e5..543cb7aa08fc 100644
> --- a/fs/notify/fanotify/Makefile
> +++ b/fs/notify/fanotify/Makefile
> @@ -1,2 +1,3 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_FANOTIFY)         += fanotify.o fanotify_user.o
> +obj-$(CONFIG_FANOTIFY_FASTPATH)        += fanotify_fastpath.o
> diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
> index 224bccaab4cc..b395b628a58b 100644
> --- a/fs/notify/fanotify/fanotify.c
> +++ b/fs/notify/fanotify/fanotify.c
> @@ -18,6 +18,8 @@
>
>  #include "fanotify.h"
>
> +extern struct srcu_struct fsnotify_mark_srcu;
> +
>  static bool fanotify_path_equal(const struct path *p1, const struct path *p2)
>  {
>         return p1->mnt == p2->mnt && p1->dentry == p2->dentry;
> @@ -888,6 +890,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
>         struct fsnotify_event *fsn_event;
>         __kernel_fsid_t fsid = {};
>         u32 match_mask = 0;
> +       struct fanotify_fastpath_hook *fp_hook __maybe_unused;
>
>         BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
>         BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
> @@ -933,6 +936,27 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
>         if (FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS))
>                 fsid = fanotify_get_fsid(iter_info);
>
> +#ifdef CONFIG_FANOTIFY_FASTPATH
> +       fp_hook = srcu_dereference(group->fanotify_data.fp_hook, &fsnotify_mark_srcu);
> +       if (fp_hook) {
> +               struct fanotify_fastpath_event fp_event = {
> +                       .mask = mask,
> +                       .data = data,
> +                       .data_type = data_type,
> +                       .dir = dir,
> +                       .file_name = file_name,
> +                       .fsid = &fsid,
> +                       .match_mask = match_mask,
> +               };
> +
> +               ret = fp_hook->ops->fp_handler(group, fp_hook, &fp_event);
> +               if (ret == FAN_FP_RET_SKIP_EVENT) {
> +                       ret = 0;
> +                       goto finish;
> +               }
> +       }
> +#endif
> +

To me it makes sense that the fastpath module could also return a negative
(deny) result for permission events.

Is there a specific reason that you did not handle this or just didn't think
of this option?

Thanks,
Amir.



More information about the Linux-security-module-archive mailing list