All of lore.kernel.org
 help / color / mirror / Atom feed
From: Song Liu <song@kernel.org>
To: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: Greg KH <gregkh@linuxfoundation.org>,
	Jiri Kosina <jikos@kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
	Yonghong Song <yhs@fb.com>,
	John Fastabend <john.fastabend@gmail.com>,
	KP Singh <kpsingh@kernel.org>, Shuah Khan <shuah@kernel.org>,
	Dave Marchevsky <davemarchevsky@fb.com>,
	Joe Stringer <joe@cilium.io>, Jonathan Corbet <corbet@lwn.net>,
	Tero Kristo <tero.kristo@linux.intel.com>,
	open list <linux-kernel@vger.kernel.org>,
	"open list:HID CORE LAYER" <linux-input@vger.kernel.org>,
	Networking <netdev@vger.kernel.org>, bpf <bpf@vger.kernel.org>,
	linux-kselftest@vger.kernel.org,
	Linux Doc Mailing List <linux-doc@vger.kernel.org>
Subject: Re: [PATCH bpf-next v3 05/17] HID: hook up with bpf
Date: Fri, 18 Mar 2022 14:04:53 -0700	[thread overview]
Message-ID: <CAPhsuW5+WQDKDa4ffsABSJ-pY7i9J0oMPweEP+dOrjA4HwnhrQ@mail.gmail.com> (raw)
In-Reply-To: <CAPhsuW47s2tUhe-XQHJonBM9P3Upv8CNKpW_Zewgc_3RYW9WMQ@mail.gmail.com>

On Fri, Mar 18, 2022 at 2:02 PM Song Liu <song@kernel.org> wrote:
>
> On Fri, Mar 18, 2022 at 9:17 AM Benjamin Tissoires
> <benjamin.tissoires@redhat.com> wrote:
> >
> > Now that BPF can be compatible with HID, add the capability into HID.
> > drivers/hid/hid-bpf.c takes care of the glue between bpf and HID, and
> > hid-core can then inject any incoming event from the device into a BPF
> > program to filter/analyze it.
>
> So we only need this part for DEVICE EVENT?

NVM, I found other types in the following patches.

>
> >
> > Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> >
> > ---
> >
> > changes in v3:
> > - squashed "only call hid_bpf_raw_event() if a ctx is available"
> >   and "bpf: compute only the required buffer size for the device"
> >   into this one
> > - ensure the ctx.size is properly bounded by allocated size
> > - s/link_attach/pre_link_attach/
> > - s/array_detached/array_detach/
> > - fix default switch case when doing nothing
> > - reworked hid_bpf_pre_link_attach() to avoid the switch
> >
> > changes in v2:
> > - split the series by bpf/libbpf/hid/selftests and samples
> > - addressed review comments from v1
> > ---
> >  drivers/hid/Makefile   |   1 +
> >  drivers/hid/hid-bpf.c  | 174 +++++++++++++++++++++++++++++++++++++++++
> >  drivers/hid/hid-core.c |  24 +++++-
> >  include/linux/hid.h    |  11 +++
> >  4 files changed, 207 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/hid/hid-bpf.c
> >
> > diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> > index 6d3e630e81af..08d2d7619937 100644
> > --- a/drivers/hid/Makefile
> > +++ b/drivers/hid/Makefile
> > @@ -4,6 +4,7 @@
> >  #
> >  hid-y                  := hid-core.o hid-input.o hid-quirks.o
> >  hid-$(CONFIG_DEBUG_FS)         += hid-debug.o
> > +hid-$(CONFIG_BPF)              += hid-bpf.o
> >
> >  obj-$(CONFIG_HID)              += hid.o
> >  obj-$(CONFIG_UHID)             += uhid.o
> > diff --git a/drivers/hid/hid-bpf.c b/drivers/hid/hid-bpf.c
> > new file mode 100644
> > index 000000000000..5060ebcb9979
> > --- /dev/null
> > +++ b/drivers/hid/hid-bpf.c
> > @@ -0,0 +1,174 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + *  BPF in HID support for Linux
> > + *
> > + *  Copyright (c) 2022 Benjamin Tissoires
> > + */
> > +
> > +#include <linux/filter.h>
> > +#include <linux/mutex.h>
> > +#include <linux/slab.h>
> > +
> > +#include <uapi/linux/bpf_hid.h>
> > +#include <linux/hid.h>
> > +
> > +static int __hid_bpf_match_sysfs(struct device *dev, const void *data)
> > +{
> > +       struct kernfs_node *kn = dev->kobj.sd;
> > +       struct kernfs_node *uevent_kn;
> > +
> > +       uevent_kn = kernfs_find_and_get_ns(kn, "uevent", NULL);
> > +
> > +       return uevent_kn == data;
> > +}
> > +
> > +static struct hid_device *hid_bpf_fd_to_hdev(int fd)
> > +{
> > +       struct device *dev;
> > +       struct hid_device *hdev;
> > +       struct fd f = fdget(fd);
> > +       struct inode *inode;
> > +       struct kernfs_node *node;
> > +
> > +       if (!f.file) {
> > +               hdev = ERR_PTR(-EBADF);
> > +               goto out;
> > +       }
> > +
> > +       inode = file_inode(f.file);
> > +       node = inode->i_private;
> > +
> > +       dev = bus_find_device(&hid_bus_type, NULL, node, __hid_bpf_match_sysfs);
> > +
> > +       if (dev)
> > +               hdev = to_hid_device(dev);
> > +       else
> > +               hdev = ERR_PTR(-EINVAL);
> > +
> > + out:
> > +       fdput(f);
> > +       return hdev;
> > +}
> > +
> > +static int hid_bpf_pre_link_attach(struct hid_device *hdev, enum bpf_hid_attach_type type)
> > +{
> > +       int err = 0;
> > +       unsigned int i, j, max_report_len = 0;
> > +       unsigned int alloc_size = 0;
> > +
> > +       if (type != BPF_HID_ATTACH_DEVICE_EVENT)
> > +               return 0;
> > +
> > +       /* hdev->bpf.device_data is already allocated, abort */
> > +       if (hdev->bpf.device_data)
> > +               return 0;
> > +
> > +       /* compute the maximum report length for this device */
> > +       for (i = 0; i < HID_REPORT_TYPES; i++) {
> > +               struct hid_report_enum *report_enum = hdev->report_enum + i;
> > +
> > +               for (j = 0; j < HID_MAX_IDS; j++) {
> > +                       struct hid_report *report = report_enum->report_id_hash[j];
> > +
> > +                       if (report)
> > +                               max_report_len = max(max_report_len, hid_report_len(report));
> > +               }
> > +       }
> > +
> > +       /*
> > +        * Give us a little bit of extra space and some predictability in the
> > +        * buffer length we create. This way, we can tell users that they can
> > +        * work on chunks of 64 bytes of memory without having the bpf verifier
> > +        * scream at them.
> > +        */
> > +       alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
> > +
> > +       hdev->bpf.device_data = kzalloc(alloc_size, GFP_KERNEL);
> > +       if (!hdev->bpf.device_data)
> > +               err = -ENOMEM;
> > +       else
> > +               hdev->bpf.allocated_data = alloc_size;
> > +
> > +       return err;
> > +}
> > +
> > +static void hid_bpf_array_detach(struct hid_device *hdev, enum bpf_hid_attach_type type)
> > +{
> > +       switch (type) {
> > +       case BPF_HID_ATTACH_DEVICE_EVENT:
> > +               kfree(hdev->bpf.device_data);
> > +               hdev->bpf.device_data = NULL;
> > +               break;
> > +       default:
> > +               /* do nothing */
> > +               break;
> > +       }
> > +}
> > +
> > +static int hid_bpf_run_progs(struct hid_device *hdev, struct hid_bpf_ctx_kern *ctx)
> > +{
> > +       enum bpf_hid_attach_type type;
> > +
> > +       if (!ctx)
> > +               return -EINVAL;
> > +
> > +       switch (ctx->type) {
> > +       case HID_BPF_DEVICE_EVENT:
> > +               type = BPF_HID_ATTACH_DEVICE_EVENT;
> > +               break;
> > +       default:
> > +               return -EINVAL;
> > +       }
> > +
> > +       if (!hdev->bpf.run_array[type])
> > +               return 0;
> > +
> > +       return BPF_PROG_RUN_ARRAY(hdev->bpf.run_array[type], ctx, bpf_prog_run);
> > +}
> > +
> > +u8 *hid_bpf_raw_event(struct hid_device *hdev, u8 *data, int *size)
> > +{
> > +       int ret;
> > +       struct hid_bpf_ctx_kern ctx = {
> > +               .type = HID_BPF_DEVICE_EVENT,
> > +               .hdev = hdev,
> > +               .size = *size,
> > +               .data = hdev->bpf.device_data,
> > +               .allocated_size = hdev->bpf.allocated_data,
> > +       };
> > +
> > +       if (bpf_hid_link_empty(&hdev->bpf, BPF_HID_ATTACH_DEVICE_EVENT))
> > +               return data;
> > +
> > +       memset(ctx.data, 0, hdev->bpf.allocated_data);
> > +       memcpy(ctx.data, data, *size);
> > +
> > +       ret = hid_bpf_run_progs(hdev, &ctx);
> > +       if (ret)
> > +               return ERR_PTR(-EIO);
> > +
> > +       if (!ctx.size || ctx.size > ctx.allocated_size)
> > +               return ERR_PTR(-EINVAL);
> > +
> > +       *size = ctx.size;
> > +
> > +       return ctx.data;
> > +}
> > +
> > +int __init hid_bpf_module_init(void)
> > +{
> > +       struct bpf_hid_hooks hooks = {
> > +               .hdev_from_fd = hid_bpf_fd_to_hdev,
> > +               .pre_link_attach = hid_bpf_pre_link_attach,
> > +               .array_detach = hid_bpf_array_detach,
> > +       };
> > +
> > +       bpf_hid_set_hooks(&hooks);
> > +
> > +       return 0;
> > +}
> > +
> > +void __exit hid_bpf_module_exit(void)
> > +{
> > +       bpf_hid_set_hooks(NULL);
> > +}
> > diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> > index f1aed5bbd000..937fab7eb9c6 100644
> > --- a/drivers/hid/hid-core.c
> > +++ b/drivers/hid/hid-core.c
> > @@ -1748,13 +1748,24 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
> >         struct hid_driver *hdrv;
> >         unsigned int a;
> >         u32 rsize, csize = size;
> > -       u8 *cdata = data;
> > +       u8 *cdata;
> >         int ret = 0;
> >
> > +       /* we pre-test if device_data is available here to cut the calls at the earliest */
> > +       if (hid->bpf.device_data) {
> > +               data = hid_bpf_raw_event(hid, data, &size);
> > +               if (IS_ERR(data)) {
> > +                       ret = PTR_ERR(data);
> > +                       goto out;
> > +               }
> > +       }
> > +
> >         report = hid_get_report(report_enum, data);
> >         if (!report)
> >                 goto out;
> >
> > +       cdata = data;
> > +
> >         if (report_enum->numbered) {
> >                 cdata++;
> >                 csize--;
> > @@ -2528,10 +2539,12 @@ int hid_add_device(struct hid_device *hdev)
> >
> >         hid_debug_register(hdev, dev_name(&hdev->dev));
> >         ret = device_add(&hdev->dev);
> > -       if (!ret)
> > +       if (!ret) {
> >                 hdev->status |= HID_STAT_ADDED;
> > -       else
> > +       } else {
> >                 hid_debug_unregister(hdev);
> > +               bpf_hid_exit(hdev);
> > +       }
> >
> >         return ret;
> >  }
> > @@ -2567,6 +2580,7 @@ struct hid_device *hid_allocate_device(void)
> >         spin_lock_init(&hdev->debug_list_lock);
> >         sema_init(&hdev->driver_input_lock, 1);
> >         mutex_init(&hdev->ll_open_lock);
> > +       bpf_hid_init(hdev);
> >
> >         return hdev;
> >  }
> > @@ -2574,6 +2588,7 @@ EXPORT_SYMBOL_GPL(hid_allocate_device);
> >
> >  static void hid_remove_device(struct hid_device *hdev)
> >  {
> > +       bpf_hid_exit(hdev);
> >         if (hdev->status & HID_STAT_ADDED) {
> >                 device_del(&hdev->dev);
> >                 hid_debug_unregister(hdev);
> > @@ -2700,6 +2715,8 @@ static int __init hid_init(void)
> >
> >         hid_debug_init();
> >
> > +       hid_bpf_module_init();
> > +
> >         return 0;
> >  err_bus:
> >         bus_unregister(&hid_bus_type);
> > @@ -2709,6 +2726,7 @@ static int __init hid_init(void)
> >
> >  static void __exit hid_exit(void)
> >  {
> > +       hid_bpf_module_exit();
> >         hid_debug_exit();
> >         hidraw_exit();
> >         bus_unregister(&hid_bus_type);
> > diff --git a/include/linux/hid.h b/include/linux/hid.h
> > index 56f6f4ad45a7..8fd79011f461 100644
> > --- a/include/linux/hid.h
> > +++ b/include/linux/hid.h
> > @@ -27,6 +27,7 @@
> >  #include <linux/mutex.h>
> >  #include <linux/power_supply.h>
> >  #include <uapi/linux/hid.h>
> > +#include <uapi/linux/bpf_hid.h>
> >
> >  /*
> >   * We parse each description item into this structure. Short items data
> > @@ -1210,4 +1211,14 @@ do {                                                                     \
> >  #define hid_dbg_once(hid, fmt, ...)                    \
> >         dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__)
> >
> > +#ifdef CONFIG_BPF
> > +u8 *hid_bpf_raw_event(struct hid_device *hdev, u8 *rd, int *size);
> > +int hid_bpf_module_init(void);
> > +void hid_bpf_module_exit(void);
> > +#else
> > +static inline u8 *hid_bpf_raw_event(struct hid_device *hdev, u8 *rd, int *size) { return rd; }
> > +static inline int hid_bpf_module_init(void) { return 0; }
> > +static inline void hid_bpf_module_exit(void) {}
> > +#endif
> > +
> >  #endif
> > --
> > 2.35.1
> >

  reply	other threads:[~2022-03-18 21:05 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-18 16:15 [PATCH bpf-next v3 00/17] Introduce eBPF support for HID devices Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 01/17] bpf: add new is_sys_admin_prog_type() helper Benjamin Tissoires
2022-03-18 18:07   ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 02/17] bpf: introduce hid program type Benjamin Tissoires
2022-03-18 20:48   ` Song Liu
2022-03-21 16:07     ` Benjamin Tissoires
2022-03-21 21:51       ` Song Liu
2022-03-22 11:06         ` Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 03/17] bpf/verifier: prevent non GPL programs to be loaded against HID Benjamin Tissoires
2022-03-18 20:51   ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 04/17] libbpf: add HID program type and API Benjamin Tissoires
2022-03-18 20:53   ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 05/17] HID: hook up with bpf Benjamin Tissoires
2022-03-18 21:02   ` Song Liu
2022-03-18 21:04     ` Song Liu [this message]
2022-03-18 16:15 ` [PATCH bpf-next v3 06/17] HID: allow to change the report descriptor from an eBPF program Benjamin Tissoires
2022-03-18 21:10   ` Song Liu
2022-03-21 16:20     ` Benjamin Tissoires
2022-03-21 22:03       ` Song Liu
2022-03-22 22:51   ` Alexei Starovoitov
2022-03-23 16:08     ` Benjamin Tissoires
2022-03-25 17:00       ` Andrii Nakryiko
2022-03-28  6:56         ` Benjamin Tissoires
2022-03-28 21:35           ` Andrii Nakryiko
2022-03-29 13:53             ` Benjamin Tissoires
2022-04-01 13:21               ` Benjamin Tissoires
2022-03-30 21:27       ` Alexei Starovoitov
2022-03-18 16:15 ` [PATCH bpf-next v3 07/17] selftests/bpf: add tests for the HID-bpf initial implementation Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 08/17] selftests/bpf: add report descriptor fixup tests Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 09/17] selftests/bpf: Add a test for BPF_F_INSERT_HEAD Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 10/17] selftests/bpf: add test for user call of HID bpf programs Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 11/17] samples/bpf: add new hid_mouse example Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 12/17] bpf/hid: add more HID helpers Benjamin Tissoires
2022-03-18 21:19   ` Song Liu
2022-03-21 16:24     ` Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 13/17] HID: bpf: implement hid_bpf_get|set_bits Benjamin Tissoires
2022-03-18 21:20   ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 14/17] HID: add implementation of bpf_hid_raw_request Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 15/17] selftests/bpf: add tests for hid_{get|set}_bits helpers Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 16/17] selftests/bpf: add tests for bpf_hid_hw_request Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 17/17] Documentation: add HID-BPF docs Benjamin Tissoires
2022-03-18 18:05   ` Song Liu
2022-03-29 13:04 ` [PATCH bpf-next v3 00/17] Introduce eBPF support for HID devices Tero Kristo
2022-04-01  9:37   ` Benjamin Tissoires

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAPhsuW5+WQDKDa4ffsABSJ-pY7i9J0oMPweEP+dOrjA4HwnhrQ@mail.gmail.com \
    --to=song@kernel.org \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=benjamin.tissoires@redhat.com \
    --cc=bpf@vger.kernel.org \
    --cc=corbet@lwn.net \
    --cc=daniel@iogearbox.net \
    --cc=davemarchevsky@fb.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jikos@kernel.org \
    --cc=joe@cilium.io \
    --cc=john.fastabend@gmail.com \
    --cc=kafai@fb.com \
    --cc=kpsingh@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=shuah@kernel.org \
    --cc=songliubraving@fb.com \
    --cc=tero.kristo@linux.intel.com \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.