From patchwork Fri Mar 4 17:28:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769582 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 135D9C4332F for ; Fri, 4 Mar 2022 17:30:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240362AbiCDRbZ (ORCPT ); Fri, 4 Mar 2022 12:31:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233773AbiCDRbY (ORCPT ); Fri, 4 Mar 2022 12:31:24 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 611B61BE0D5 for ; Fri, 4 Mar 2022 09:30:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415032; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7ZanlT+mtaAIwjGwU2toplmlGf6ZuTIRandFY4G7p54=; b=c1SZLPU31VM5AKrP8ik8/b3KBNWVNtIbc9+aYcdpluQy6XQN0nYWpmBItgkY2sljPlHd/d sD+kTYPFmY8BG7fUqtu/Zyjq4X3B9vZqY613nNa8FOUk1I5nj3WcJO9D6XzSmytofCl6OQ uhJuM/Od/Zlb6qB2S2UC4ecNuPlpMuA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-654-yu9FeJp1MuappFvdmDwWdQ-1; Fri, 04 Mar 2022 12:30:30 -0500 X-MC-Unique: yu9FeJp1MuappFvdmDwWdQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0F9781854E37; Fri, 4 Mar 2022 17:30:18 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9CC6286599; Fri, 4 Mar 2022 17:29:21 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires , Sean Young Subject: [PATCH bpf-next v2 01/28] bpf: add new is_sys_admin_prog_type() helper Date: Fri, 4 Mar 2022 18:28:25 +0100 Message-Id: <20220304172852.274126-2-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net LIRC_MODE2 does not really need net_admin capability, but only sys_admin. Extract a new helper for it, it will be also used for the HID bpf implementation. Cc: Sean Young Signed-off-by: Benjamin Tissoires Acked-by: Sean Young --- new in v2 --- kernel/bpf/syscall.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index db402ebc5570..cc570891322b 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2165,7 +2165,6 @@ static bool is_net_admin_prog_type(enum bpf_prog_type prog_type) case BPF_PROG_TYPE_LWT_SEG6LOCAL: case BPF_PROG_TYPE_SK_SKB: case BPF_PROG_TYPE_SK_MSG: - case BPF_PROG_TYPE_LIRC_MODE2: case BPF_PROG_TYPE_FLOW_DISSECTOR: case BPF_PROG_TYPE_CGROUP_DEVICE: case BPF_PROG_TYPE_CGROUP_SOCK: @@ -2202,6 +2201,17 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type) } } +static bool is_sys_admin_prog_type(enum bpf_prog_type prog_type) +{ + switch (prog_type) { + case BPF_PROG_TYPE_LIRC_MODE2: + case BPF_PROG_TYPE_EXT: /* extends any prog */ + return true; + default: + return false; + } +} + /* last field in 'union bpf_attr' used by this command */ #define BPF_PROG_LOAD_LAST_FIELD core_relo_rec_size @@ -2252,6 +2262,8 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr) return -EPERM; if (is_perfmon_prog_type(type) && !perfmon_capable()) return -EPERM; + if (is_sys_admin_prog_type(type) && !capable(CAP_SYS_ADMIN)) + return -EPERM; /* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog * or btf, we need to check which one it is From patchwork Fri Mar 4 17:28:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769583 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57F31C43217 for ; Fri, 4 Mar 2022 17:31:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241050AbiCDRbv (ORCPT ); Fri, 4 Mar 2022 12:31:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240988AbiCDRbu (ORCPT ); Fri, 4 Mar 2022 12:31:50 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B472F1CD9CE for ; Fri, 4 Mar 2022 09:31:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415059; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=j/520MpHx+NcYX343307RJA9RFktzbyQejGGURQtlT0=; b=hyyVeK7auB117/toqoLr9yDqtm4zzBTIjo87icHrvg6vNC6bmyd5HztaKob9KIOsTVz8o/ KzgHu/kgBu9rc/iC+KBAYssBHwDDgczXykbBTWmg9t5PiF0f5xLo1goVfCsukWToKG7moS s1KeR3rYQvPHOkfCFk5xndA4gLcp7dQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-88-1Fr99WliNlKpG84-n5BQBA-1; Fri, 04 Mar 2022 12:30:56 -0500 X-MC-Unique: 1Fr99WliNlKpG84-n5BQBA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7C73E1006AA5; Fri, 4 Mar 2022 17:30:53 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 68EB786599; Fri, 4 Mar 2022 17:30:18 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 02/28] bpf: introduce hid program type Date: Fri, 4 Mar 2022 18:28:26 +0100 Message-Id: <20220304172852.274126-3-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net HID is a protocol that could benefit from using BPF too. This patch implements a net-like use of BPF capability for HID. Any incoming report coming from the device can be injected into a series of BPF programs that can modify it or even discard it by setting the size in the context to 0. The kernel/bpf implementation is based on net-namespace.c, with only the bpf_link part kept, there is no real points in keeping the bpf_prog_{attach|detach} API. The implementation here is only focusing on the bpf changes. The HID changes that hooks onto this are coming in a separate patch. Given that HID can be compiled in as a module, and the functions that kernel/bpf/hid.c needs to call in hid.ko are exported in struct hid_hooks. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples - unsigned long -> __u16 in uapi/linux/bpf_hid.h - change the bpf_ctx to be of variable size, with a min of 1024 bytes - make this 1 kB available directly from bpf program, the rest will need a helper - add some more doc comments in uapi --- include/linux/bpf-hid.h | 108 ++++++++ include/linux/bpf_types.h | 4 + include/linux/hid.h | 5 + include/uapi/linux/bpf.h | 7 + include/uapi/linux/bpf_hid.h | 39 +++ kernel/bpf/Makefile | 3 + kernel/bpf/hid.c | 437 +++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 8 + tools/include/uapi/linux/bpf.h | 7 + 9 files changed, 618 insertions(+) create mode 100644 include/linux/bpf-hid.h create mode 100644 include/uapi/linux/bpf_hid.h create mode 100644 kernel/bpf/hid.c diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h new file mode 100644 index 000000000000..3cda78051b5f --- /dev/null +++ b/include/linux/bpf-hid.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _BPF_HID_H +#define _BPF_HID_H + +#include +#include +#include +#include +#include + +struct bpf_prog; +struct bpf_prog_array; +struct hid_device; + +enum bpf_hid_attach_type { + BPF_HID_ATTACH_INVALID = -1, + BPF_HID_ATTACH_DEVICE_EVENT = 0, + MAX_BPF_HID_ATTACH_TYPE +}; + +struct bpf_hid { + struct hid_bpf_ctx *ctx; + + /* Array of programs to run compiled from links */ + struct bpf_prog_array __rcu *run_array[MAX_BPF_HID_ATTACH_TYPE]; + struct list_head links[MAX_BPF_HID_ATTACH_TYPE]; +}; + +static inline enum bpf_hid_attach_type +to_bpf_hid_attach_type(enum bpf_attach_type attach_type) +{ + switch (attach_type) { + case BPF_HID_DEVICE_EVENT: + return BPF_HID_ATTACH_DEVICE_EVENT; + default: + return BPF_HID_ATTACH_INVALID; + } +} + +static inline struct hid_bpf_ctx *bpf_hid_allocate_ctx(struct hid_device *hdev, + size_t data_size) +{ + struct hid_bpf_ctx *ctx; + + /* ensure data_size is between min and max */ + data_size = clamp_val(data_size, + HID_BPF_MIN_BUFFER_SIZE, + HID_BPF_MAX_BUFFER_SIZE); + + ctx = kzalloc(sizeof(*ctx) + data_size, GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->hdev = hdev; + ctx->allocated_size = data_size; + + return ctx; +} + +union bpf_attr; +struct bpf_prog; + +#if IS_ENABLED(CONFIG_HID) +int bpf_hid_prog_query(const union bpf_attr *attr, + union bpf_attr __user *uattr); +int bpf_hid_link_create(const union bpf_attr *attr, + struct bpf_prog *prog); +#else +static inline int bpf_hid_prog_query(const union bpf_attr *attr, + union bpf_attr __user *uattr) +{ + return -EOPNOTSUPP; +} + +static inline int bpf_hid_link_create(const union bpf_attr *attr, + struct bpf_prog *prog) +{ + return -EOPNOTSUPP; +} +#endif + +static inline bool bpf_hid_link_empty(struct bpf_hid *bpf, + enum bpf_hid_attach_type type) +{ + return list_empty(&bpf->links[type]); +} + +struct bpf_hid_hooks { + struct hid_device *(*hdev_from_fd)(int fd); + int (*link_attach)(struct hid_device *hdev, enum bpf_hid_attach_type type); + void (*array_detached)(struct hid_device *hdev, enum bpf_hid_attach_type type); +}; + +#ifdef CONFIG_BPF +int bpf_hid_init(struct hid_device *hdev); +void bpf_hid_exit(struct hid_device *hdev); +void bpf_hid_set_hooks(struct bpf_hid_hooks *hooks); +#else +static inline int bpf_hid_init(struct hid_device *hdev) +{ + return 0; +} + +static inline void bpf_hid_exit(struct hid_device *hdev) {} +static inline void bpf_hid_set_hooks(struct bpf_hid_hooks *hooks) {} +#endif + +#endif /* _BPF_HID_H */ diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h index 48a91c51c015..1509862aacc4 100644 --- a/include/linux/bpf_types.h +++ b/include/linux/bpf_types.h @@ -76,6 +76,10 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_EXT, bpf_extension, BPF_PROG_TYPE(BPF_PROG_TYPE_LSM, lsm, void *, void *) #endif /* CONFIG_BPF_LSM */ +#if IS_ENABLED(CONFIG_HID) +BPF_PROG_TYPE(BPF_PROG_TYPE_HID, hid, + __u32, u32) +#endif #endif BPF_PROG_TYPE(BPF_PROG_TYPE_SYSCALL, bpf_syscall, void *, void *) diff --git a/include/linux/hid.h b/include/linux/hid.h index 7487b0586fe6..56f6f4ad45a7 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -639,6 +640,10 @@ struct hid_device { /* device report descriptor */ struct list_head debug_list; spinlock_t debug_list_lock; wait_queue_head_t debug_wait; + +#ifdef CONFIG_BPF + struct bpf_hid bpf; +#endif }; #define to_hid_device(pdev) \ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index afe3d0d7f5f2..5978b92cacd3 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -952,6 +952,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_LSM, BPF_PROG_TYPE_SK_LOOKUP, BPF_PROG_TYPE_SYSCALL, /* a program that can execute syscalls */ + BPF_PROG_TYPE_HID, }; enum bpf_attach_type { @@ -997,6 +998,7 @@ enum bpf_attach_type { BPF_SK_REUSEPORT_SELECT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, BPF_PERF_EVENT, + BPF_HID_DEVICE_EVENT, __MAX_BPF_ATTACH_TYPE }; @@ -1011,6 +1013,7 @@ enum bpf_link_type { BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, BPF_LINK_TYPE_PERF_EVENT = 7, + BPF_LINK_TYPE_HID = 8, MAX_BPF_LINK_TYPE, }; @@ -5870,6 +5873,10 @@ struct bpf_link_info { struct { __u32 ifindex; } xdp; + struct { + __s32 hidraw_ino; + __u32 attach_type; + } hid; }; } __attribute__((aligned(8))); diff --git a/include/uapi/linux/bpf_hid.h b/include/uapi/linux/bpf_hid.h new file mode 100644 index 000000000000..975ca5bd526f --- /dev/null +++ b/include/uapi/linux/bpf_hid.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */ + +/* + * HID BPF public headers + * + * Copyright (c) 2021 Benjamin Tissoires + */ + +#ifndef _UAPI__LINUX_BPF_HID_H__ +#define _UAPI__LINUX_BPF_HID_H__ + +#include + +/* + * The first 1024 bytes are available directly in the bpf programs. + * To access the rest of the data (if allocated_size is bigger + * than 1024, you need to use bpf_hid_ helpers. + */ +#define HID_BPF_MIN_BUFFER_SIZE 1024 +#define HID_BPF_MAX_BUFFER_SIZE 16384 /* in sync with HID_MAX_BUFFER_SIZE */ + +struct hid_device; + +enum hid_bpf_event { + HID_BPF_UNDEF = 0, + HID_BPF_DEVICE_EVENT, /* when attach type is BPF_HID_DEVICE_EVENT */ +}; + +struct hid_bpf_ctx { + enum hid_bpf_event type; /* read-only */ + __u16 allocated_size; /* the allocated size of data below (RO) */ + struct hid_device *hdev; /* read-only */ + + __u16 size; /* used size in data (RW) */ + __u8 data[]; /* data buffer (RW) */ +}; + +#endif /* _UAPI__LINUX_BPF_HID_H__ */ + diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index c1a9be6a4b9f..8d5619d3d7e5 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -35,6 +35,9 @@ ifeq ($(CONFIG_BPF_JIT),y) obj-$(CONFIG_BPF_SYSCALL) += bpf_struct_ops.o obj-${CONFIG_BPF_LSM} += bpf_lsm.o endif +ifneq ($(CONFIG_HID),) +obj-$(CONFIG_BPF_SYSCALL) += hid.o +endif obj-$(CONFIG_BPF_PRELOAD) += preload/ obj-$(CONFIG_BPF_SYSCALL) += relo_core.o diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c new file mode 100644 index 000000000000..db7f75a0a812 --- /dev/null +++ b/kernel/bpf/hid.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * based on kernel/bpf/net-namespace.c + */ + +#include +#include +#include +#include +#include + +/* + * Functions to manage BPF programs attached to hid + */ + +struct bpf_hid_link { + struct bpf_link link; + enum bpf_attach_type type; + enum bpf_hid_attach_type hid_type; + + /* Must be accessed with bpf_hid_mutex held. */ + struct hid_device *hdev; + struct list_head node; /* node in list of links attached to hid */ +}; + +/* Protects updates to bpf_hid */ +DEFINE_MUTEX(bpf_hid_mutex); + +static struct bpf_hid_hooks hid_hooks = {0}; + +void bpf_hid_set_hooks(struct bpf_hid_hooks *hooks) +{ + if (hooks) + hid_hooks = *hooks; + else + memset(&hid_hooks, 0, sizeof(hid_hooks)); +} +EXPORT_SYMBOL_GPL(bpf_hid_set_hooks); + +static const struct bpf_func_proto * +hid_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) +{ + switch (func_id) { + default: + return bpf_base_func_proto(func_id); + } +} + +static bool hid_is_valid_access(int off, int size, + enum bpf_access_type access_type, + const struct bpf_prog *prog, + struct bpf_insn_access_aux *info) +{ + /* everything not in ctx is prohibited */ + if (off < 0 || off + size > sizeof(struct hid_bpf_ctx) + HID_BPF_MIN_BUFFER_SIZE) + return false; + + switch (off) { + /* type, allocated_size, hdev are read-only */ + case bpf_ctx_range_till(struct hid_bpf_ctx, type, hdev): + return access_type == BPF_READ; + } + + /* everything else is read/write */ + return true; +} + +const struct bpf_verifier_ops hid_verifier_ops = { + .get_func_proto = hid_func_proto, + .is_valid_access = hid_is_valid_access +}; + +/* Must be called with bpf_hid_mutex held. */ +static void bpf_hid_run_array_detach(struct hid_device *hdev, + enum bpf_hid_attach_type type) +{ + struct bpf_prog_array *run_array; + + run_array = rcu_replace_pointer(hdev->bpf.run_array[type], NULL, + lockdep_is_held(&bpf_hid_mutex)); + bpf_prog_array_free(run_array); + + if (hid_hooks.array_detached) + hid_hooks.array_detached(hdev, type); +} + +static int link_index(struct hid_device *hdev, enum bpf_hid_attach_type type, + struct bpf_hid_link *link) +{ + struct bpf_hid_link *pos; + int i = 0; + + list_for_each_entry(pos, &hdev->bpf.links[type], node) { + if (pos == link) + return i; + i++; + } + return -ENOENT; +} + +static int link_count(struct hid_device *hdev, enum bpf_hid_attach_type type) +{ + struct list_head *pos; + int i = 0; + + list_for_each(pos, &hdev->bpf.links[type]) + i++; + return i; +} + +static void fill_prog_array(struct hid_device *hdev, enum bpf_hid_attach_type type, + struct bpf_prog_array *prog_array) +{ + struct bpf_hid_link *pos; + unsigned int i = 0; + + list_for_each_entry(pos, &hdev->bpf.links[type], node) { + prog_array->items[i].prog = pos->link.prog; + i++; + } +} + +static void bpf_hid_link_release(struct bpf_link *link) +{ + struct bpf_hid_link *hid_link = + container_of(link, struct bpf_hid_link, link); + enum bpf_hid_attach_type type = hid_link->hid_type; + struct bpf_prog_array *old_array, *new_array; + struct hid_device *hdev; + int cnt, idx; + + mutex_lock(&bpf_hid_mutex); + + hdev = hid_link->hdev; + if (!hdev) + goto out_unlock; + + /* Remember link position in case of safe delete */ + idx = link_index(hdev, type, hid_link); + list_del(&hid_link->node); + + cnt = link_count(hdev, type); + if (!cnt) { + bpf_hid_run_array_detach(hdev, type); + goto out_unlock; + } + + old_array = rcu_dereference_protected(hdev->bpf.run_array[type], + lockdep_is_held(&bpf_hid_mutex)); + new_array = bpf_prog_array_alloc(cnt, GFP_KERNEL); + if (!new_array) { + WARN_ON(bpf_prog_array_delete_safe_at(old_array, idx)); + goto out_unlock; + } + fill_prog_array(hdev, type, new_array); + rcu_assign_pointer(hdev->bpf.run_array[type], new_array); + bpf_prog_array_free(old_array); + +out_unlock: + hid_link->hdev = NULL; + mutex_unlock(&bpf_hid_mutex); +} + +static int bpf_hid_link_detach(struct bpf_link *link) +{ + bpf_hid_link_release(link); + return 0; +} + +static void bpf_hid_link_dealloc(struct bpf_link *link) +{ + struct bpf_hid_link *hid_link = + container_of(link, struct bpf_hid_link, link); + + kfree(hid_link); +} + +static int bpf_hid_link_update_prog(struct bpf_link *link, + struct bpf_prog *new_prog, + struct bpf_prog *old_prog) +{ + struct bpf_hid_link *hid_link = + container_of(link, struct bpf_hid_link, link); + enum bpf_hid_attach_type type = hid_link->hid_type; + struct bpf_prog_array *run_array; + struct hid_device *hdev; + int idx, ret; + + if (old_prog && old_prog != link->prog) + return -EPERM; + if (new_prog->type != link->prog->type) + return -EINVAL; + + mutex_lock(&bpf_hid_mutex); + + hdev = hid_link->hdev; + if (!hdev) { + /* hid dying */ + ret = -ENOLINK; + goto out_unlock; + } + + run_array = rcu_dereference_protected(hdev->bpf.run_array[type], + lockdep_is_held(&bpf_hid_mutex)); + idx = link_index(hdev, type, hid_link); + ret = bpf_prog_array_update_at(run_array, idx, new_prog); + if (ret) + goto out_unlock; + + old_prog = xchg(&link->prog, new_prog); + bpf_prog_put(old_prog); + +out_unlock: + mutex_unlock(&bpf_hid_mutex); + return ret; +} + +static int bpf_hid_link_fill_info(const struct bpf_link *link, + struct bpf_link_info *info) +{ + const struct bpf_hid_link *hid_link = + container_of(link, struct bpf_hid_link, link); + int hidraw_ino = -1; + struct hid_device *hdev; + struct hidraw *hidraw; + + mutex_lock(&bpf_hid_mutex); + hdev = hid_link->hdev; + if (hdev && hdev->hidraw) { + hidraw = hdev->hidraw; + hidraw_ino = hidraw->minor; + } + mutex_unlock(&bpf_hid_mutex); + + info->hid.hidraw_ino = hidraw_ino; + info->hid.attach_type = hid_link->type; + return 0; +} + +static void bpf_hid_link_show_fdinfo(const struct bpf_link *link, + struct seq_file *seq) +{ + struct bpf_link_info info = {}; + + bpf_hid_link_fill_info(link, &info); + seq_printf(seq, + "hidraw_ino:\t%u\n" + "attach_type:\t%u\n", + info.hid.hidraw_ino, + info.hid.attach_type); +} + +static const struct bpf_link_ops bpf_hid_link_ops = { + .release = bpf_hid_link_release, + .dealloc = bpf_hid_link_dealloc, + .detach = bpf_hid_link_detach, + .update_prog = bpf_hid_link_update_prog, + .fill_link_info = bpf_hid_link_fill_info, + .show_fdinfo = bpf_hid_link_show_fdinfo, +}; + +/* Must be called with bpf_hid_mutex held. */ +static int __bpf_hid_prog_query(const union bpf_attr *attr, + union bpf_attr __user *uattr, + struct hid_device *hdev, + enum bpf_hid_attach_type type) +{ + __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids); + struct bpf_prog_array *run_array; + u32 prog_cnt = 0, flags = 0; + + run_array = rcu_dereference_protected(hdev->bpf.run_array[type], + lockdep_is_held(&bpf_hid_mutex)); + if (run_array) + prog_cnt = bpf_prog_array_length(run_array); + + if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) + return -EFAULT; + if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt))) + return -EFAULT; + if (!attr->query.prog_cnt || !prog_ids || !prog_cnt) + return 0; + + return bpf_prog_array_copy_to_user(run_array, prog_ids, + attr->query.prog_cnt); +} + +int bpf_hid_prog_query(const union bpf_attr *attr, + union bpf_attr __user *uattr) +{ + enum bpf_hid_attach_type type; + struct hid_device *hdev; + int ret; + + if (attr->query.query_flags || !hid_hooks.hdev_from_fd) + return -EINVAL; + + type = to_bpf_hid_attach_type(attr->query.attach_type); + if (type < 0) + return -EINVAL; + + hdev = hid_hooks.hdev_from_fd(attr->query.target_fd); + if (IS_ERR(hdev)) + return PTR_ERR(hdev); + + mutex_lock(&bpf_hid_mutex); + ret = __bpf_hid_prog_query(attr, uattr, hdev, type); + mutex_unlock(&bpf_hid_mutex); + + return ret; +} + +static int bpf_hid_max_progs(enum bpf_hid_attach_type type) +{ + switch (type) { + case BPF_HID_ATTACH_DEVICE_EVENT: + return 64; + default: + return 0; + } +} + +static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link, + enum bpf_hid_attach_type type) +{ + struct bpf_hid_link *hid_link = + container_of(link, struct bpf_hid_link, link); + struct bpf_prog_array *run_array; + int cnt, err = 0; + + mutex_lock(&bpf_hid_mutex); + + cnt = link_count(hdev, type); + if (cnt >= bpf_hid_max_progs(type)) { + err = -E2BIG; + goto out_unlock; + } + + if (hid_hooks.link_attach) { + err = hid_hooks.link_attach(hdev, type); + if (err) + goto out_unlock; + } + + run_array = bpf_prog_array_alloc(cnt + 1, GFP_KERNEL); + if (!run_array) { + err = -ENOMEM; + goto out_unlock; + } + + list_add_tail(&hid_link->node, &hdev->bpf.links[type]); + + fill_prog_array(hdev, type, run_array); + run_array = rcu_replace_pointer(hdev->bpf.run_array[type], run_array, + lockdep_is_held(&bpf_hid_mutex)); + bpf_prog_array_free(run_array); + +out_unlock: + mutex_unlock(&bpf_hid_mutex); + return err; +} + +int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog) +{ + enum bpf_hid_attach_type hid_type; + struct bpf_link_primer link_primer; + struct bpf_hid_link *hid_link; + enum bpf_attach_type type; + struct hid_device *hdev; + int err; + + if (attr->link_create.flags || !hid_hooks.hdev_from_fd) + return -EINVAL; + + type = attr->link_create.attach_type; + hid_type = to_bpf_hid_attach_type(type); + if (hid_type < 0) + return -EINVAL; + + hdev = hid_hooks.hdev_from_fd(attr->link_create.target_fd); + if (IS_ERR(hdev)) + return PTR_ERR(hdev); + + hid_link = kzalloc(sizeof(*hid_link), GFP_USER); + if (!hid_link) + return -ENOMEM; + + bpf_link_init(&hid_link->link, BPF_LINK_TYPE_HID, + &bpf_hid_link_ops, prog); + hid_link->hdev = hdev; + hid_link->type = type; + hid_link->hid_type = hid_type; + + err = bpf_link_prime(&hid_link->link, &link_primer); + if (err) { + kfree(hid_link); + return err; + } + + err = bpf_hid_link_attach(hdev, &hid_link->link, hid_type); + if (err) { + bpf_link_cleanup(&link_primer); + return err; + } + + return bpf_link_settle(&link_primer); +} + +const struct bpf_prog_ops hid_prog_ops = { +}; + +int bpf_hid_init(struct hid_device *hdev) +{ + int type; + + for (type = 0; type < MAX_BPF_HID_ATTACH_TYPE; type++) + INIT_LIST_HEAD(&hdev->bpf.links[type]); + + return 0; +} +EXPORT_SYMBOL_GPL(bpf_hid_init); + +void bpf_hid_exit(struct hid_device *hdev) +{ + enum bpf_hid_attach_type type; + struct bpf_hid_link *hid_link; + + mutex_lock(&bpf_hid_mutex); + for (type = 0; type < MAX_BPF_HID_ATTACH_TYPE; type++) { + bpf_hid_run_array_detach(hdev, type); + list_for_each_entry(hid_link, &hdev->bpf.links[type], node) { + hid_link->hdev = NULL; /* auto-detach link */ + } + } + mutex_unlock(&bpf_hid_mutex); +} +EXPORT_SYMBOL_GPL(bpf_hid_exit); diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index cc570891322b..a94e78ec3211 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3,6 +3,7 @@ */ #include #include +#include #include #include #include @@ -2205,6 +2206,7 @@ static bool is_sys_admin_prog_type(enum bpf_prog_type prog_type) { switch (prog_type) { case BPF_PROG_TYPE_LIRC_MODE2: + case BPF_PROG_TYPE_HID: case BPF_PROG_TYPE_EXT: /* extends any prog */ return true; default: @@ -3200,6 +3202,8 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type) return BPF_PROG_TYPE_SK_LOOKUP; case BPF_XDP: return BPF_PROG_TYPE_XDP; + case BPF_HID_DEVICE_EVENT: + return BPF_PROG_TYPE_HID; default: return BPF_PROG_TYPE_UNSPEC; } @@ -3343,6 +3347,8 @@ static int bpf_prog_query(const union bpf_attr *attr, case BPF_SK_MSG_VERDICT: case BPF_SK_SKB_VERDICT: return sock_map_bpf_prog_query(attr, uattr); + case BPF_HID_DEVICE_EVENT: + return bpf_hid_prog_query(attr, uattr); default: return -EINVAL; } @@ -4337,6 +4343,8 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) ret = bpf_perf_link_attach(attr, prog); break; #endif + case BPF_PROG_TYPE_HID: + return bpf_hid_link_create(attr, prog); default: ret = -EINVAL; } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index afe3d0d7f5f2..5978b92cacd3 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -952,6 +952,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_LSM, BPF_PROG_TYPE_SK_LOOKUP, BPF_PROG_TYPE_SYSCALL, /* a program that can execute syscalls */ + BPF_PROG_TYPE_HID, }; enum bpf_attach_type { @@ -997,6 +998,7 @@ enum bpf_attach_type { BPF_SK_REUSEPORT_SELECT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, BPF_PERF_EVENT, + BPF_HID_DEVICE_EVENT, __MAX_BPF_ATTACH_TYPE }; @@ -1011,6 +1013,7 @@ enum bpf_link_type { BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, BPF_LINK_TYPE_PERF_EVENT = 7, + BPF_LINK_TYPE_HID = 8, MAX_BPF_LINK_TYPE, }; @@ -5870,6 +5873,10 @@ struct bpf_link_info { struct { __u32 ifindex; } xdp; + struct { + __s32 hidraw_ino; + __u32 attach_type; + } hid; }; } __attribute__((aligned(8))); From patchwork Fri Mar 4 17:28:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769585 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABD0EC4167E for ; Fri, 4 Mar 2022 17:31:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241118AbiCDRcH (ORCPT ); Fri, 4 Mar 2022 12:32:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41708 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241134AbiCDRcB (ORCPT ); Fri, 4 Mar 2022 12:32:01 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 97FF71CE98B for ; Fri, 4 Mar 2022 09:31:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415068; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1ZQuxqUPl7vDCQpUuTYcwfRw9C5mZXz4jQogneyXZWU=; b=g3b4mepJf1irF2cgoEBcFfFrc6PH7O0QbNv1E0FHsBIYT/JzHxPo0TQCr0idHLZtJrutdj zzb5EwraETHAAqNcumYSW5t4oTO92QuXrFAZ2SH29I1JyKIjFjJ+c+PY/Ti6DS9CX80hPk rbyDO6187fUxB1UfZias2qL1ZPx12MU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-614-o3Q7OgITME-QB5bLizegwA-1; Fri, 04 Mar 2022 12:31:05 -0500 X-MC-Unique: o3Q7OgITME-QB5bLizegwA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A50C518766D0; Fri, 4 Mar 2022 17:31:02 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id CD5CE86595; Fri, 4 Mar 2022 17:30:53 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 03/28] HID: hook up with bpf Date: Fri, 4 Mar 2022 18:28:27 +0100 Message-Id: <20220304172852.274126-4-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net 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. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- 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 | 157 +++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-core.c | 21 +++++- include/linux/hid.h | 11 +++ 4 files changed, 187 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..8120e598de9f --- /dev/null +++ b/drivers/hid/hid-bpf.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * BPF in HID support for Linux + * + * Copyright (c) 2022 Benjamin Tissoires + */ + +#include +#include +#include + +#include +#include + +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_link_attach(struct hid_device *hdev, enum bpf_hid_attach_type type) +{ + int err = 0; + + switch (type) { + case BPF_HID_ATTACH_DEVICE_EVENT: + if (!hdev->bpf.ctx) { + hdev->bpf.ctx = bpf_hid_allocate_ctx(hdev, HID_BPF_MAX_BUFFER_SIZE); + if (IS_ERR(hdev->bpf.ctx)) { + err = PTR_ERR(hdev->bpf.ctx); + hdev->bpf.ctx = NULL; + } + } + break; + default: + /* do nothing */ + } + + return err; +} + +static void hid_bpf_array_detached(struct hid_device *hdev, enum bpf_hid_attach_type type) +{ + switch (type) { + case BPF_HID_ATTACH_DEVICE_EVENT: + kfree(hdev->bpf.ctx); + hdev->bpf.ctx = NULL; + break; + default: + /* do nothing */ + } +} + +static int hid_bpf_run_progs(struct hid_device *hdev, enum bpf_hid_attach_type type, + struct hid_bpf_ctx *ctx, u8 *data, int size) +{ + enum hid_bpf_event event = HID_BPF_UNDEF; + + if (type < 0 || !ctx) + return -EINVAL; + + if (size > ctx->allocated_size) + return -E2BIG; + + switch (type) { + case BPF_HID_ATTACH_DEVICE_EVENT: + event = HID_BPF_DEVICE_EVENT; + break; + default: + return -EINVAL; + } + + if (!hdev->bpf.run_array[type]) + return 0; + + memset(ctx->data, 0, ctx->allocated_size); + ctx->type = event; + + if (size && data) { + memcpy(ctx->data, data, size); + ctx->size = size; + } else { + ctx->size = 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; + + if (bpf_hid_link_empty(&hdev->bpf, BPF_HID_ATTACH_DEVICE_EVENT)) + return data; + + ret = hid_bpf_run_progs(hdev, BPF_HID_ATTACH_DEVICE_EVENT, + hdev->bpf.ctx, data, *size); + if (ret) + return ERR_PTR(ret); + + if (!hdev->bpf.ctx->size) + return ERR_PTR(-EINVAL); + + *size = hdev->bpf.ctx->size; + + return hdev->bpf.ctx->data; +} + +int __init hid_bpf_module_init(void) +{ + struct bpf_hid_hooks hooks = { + .hdev_from_fd = hid_bpf_fd_to_hdev, + .link_attach = hid_bpf_link_attach, + .array_detached = hid_bpf_array_detached, + }; + + 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..a80bffe6ce4a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1748,13 +1748,21 @@ 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; + 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 +2536,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 +2577,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 +2585,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 +2712,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 +2723,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 #include #include +#include /* * 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 From patchwork Fri Mar 4 17:28:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769584 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21C2BC4167B for ; Fri, 4 Mar 2022 17:31:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241109AbiCDRcG (ORCPT ); Fri, 4 Mar 2022 12:32:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41838 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241118AbiCDRcF (ORCPT ); Fri, 4 Mar 2022 12:32:05 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E5C751CDDE9 for ; Fri, 4 Mar 2022 09:31:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rCz0m9X2qfcLrQ17iU+zBSGZpBuvHijRaj3zwrGqBqI=; b=R1wogSeK3RLjOzTDgj1d2WYXU710zGxVIcbBPBwHFr+S2u9cXNMHv7dzt68py9C5EE/w7W eixNojmpInHD9dG/K2hiQymwrpIuhTzSYK1uveEkxcS4Ti3ScFY+pZtC2sOwyxs+6heyW+ qQcWH9+zcGoXVCjeHDl3ZuZaZz3cfE4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-377-ArT2qtWiMi2Tv-xsW-M3kQ-1; Fri, 04 Mar 2022 12:31:09 -0500 X-MC-Unique: ArT2qtWiMi2Tv-xsW-M3kQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EF76518766D0; Fri, 4 Mar 2022 17:31:06 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0126B86595; Fri, 4 Mar 2022 17:31:02 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 04/28] libbpf: add HID program type and API Date: Fri, 4 Mar 2022 18:28:28 +0100 Message-Id: <20220304172852.274126-5-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net HID-bpf program type are needing a new SEC. To bind a hid-bpf program, we can rely on bpf_program__attach_fd() so export a new function to the API. Signed-off-by: Benjamin Tissoires Acked-by: Song Liu --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/lib/bpf/libbpf.c | 7 +++++++ tools/lib/bpf/libbpf.h | 2 ++ tools/lib/bpf/libbpf.map | 1 + 3 files changed, 10 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 81bf01d67671..356bbd3ad2c7 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -8680,6 +8680,7 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("cgroup/setsockopt", CGROUP_SOCKOPT, BPF_CGROUP_SETSOCKOPT, SEC_ATTACHABLE | SEC_SLOPPY_PFX), SEC_DEF("struct_ops+", STRUCT_OPS, 0, SEC_NONE), SEC_DEF("sk_lookup", SK_LOOKUP, BPF_SK_LOOKUP, SEC_ATTACHABLE | SEC_SLOPPY_PFX), + SEC_DEF("hid/device_event", HID, BPF_HID_DEVICE_EVENT, SEC_ATTACHABLE_OPT | SEC_SLOPPY_PFX), }; #define MAX_TYPE_NAME_SIZE 32 @@ -10659,6 +10660,12 @@ static struct bpf_link *attach_iter(const struct bpf_program *prog, long cookie) return bpf_program__attach_iter(prog, NULL); } +struct bpf_link * +bpf_program__attach_hid(const struct bpf_program *prog, int hid_fd) +{ + return bpf_program__attach_fd(prog, hid_fd, 0, "hid"); +} + struct bpf_link *bpf_program__attach(const struct bpf_program *prog) { if (!prog->sec_def || !prog->sec_def->attach_fn) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index c8d8daad212e..f677ac0a9ede 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -529,6 +529,8 @@ struct bpf_iter_attach_opts { LIBBPF_API struct bpf_link * bpf_program__attach_iter(const struct bpf_program *prog, const struct bpf_iter_attach_opts *opts); +LIBBPF_API struct bpf_link * +bpf_program__attach_hid(const struct bpf_program *prog, int hid_fd); /* * Libbpf allows callers to adjust BPF programs before being loaded diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 47e70c9058d9..fdc6fa743953 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -424,6 +424,7 @@ LIBBPF_0.6.0 { LIBBPF_0.7.0 { global: bpf_btf_load; + bpf_program__attach_hid; bpf_program__expected_attach_type; bpf_program__log_buf; bpf_program__log_level; From patchwork Fri Mar 4 17:28:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769586 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95859C433EF for ; Fri, 4 Mar 2022 17:31:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241196AbiCDRcX (ORCPT ); Fri, 4 Mar 2022 12:32:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42262 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241142AbiCDRcS (ORCPT ); Fri, 4 Mar 2022 12:32:18 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B11951CE986 for ; Fri, 4 Mar 2022 09:31:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=I7r/0u1wKcqwzT9dQZnDB5pb1zco56GPsVeprvV5Efs=; b=QUT6l6x5pavni2nHGNl44sHEVNpid//KdsmqzYuLLh/OQ2FwXRn3ZgpiuGEZpDJ1wkOV45 19dmg8NqwODmiQ0NAA+5NNXPq0s1XtDqMU6j24nZsjqJWLdykIkwYNubkmA4vj/hv65Gn1 TimvZAP4dlPQX3669ceU0DnHrSQJUqw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-658-6IzWbtDMMw2t5rOlvY6QRw-1; Fri, 04 Mar 2022 12:31:15 -0500 X-MC-Unique: 6IzWbtDMMw2t5rOlvY6QRw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9B974801AFE; Fri, 4 Mar 2022 17:31:11 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3D8C986595; Fri, 4 Mar 2022 17:31:07 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 05/28] selftests/bpf: add tests for the HID-bpf initial implementation Date: Fri, 4 Mar 2022 18:28:29 +0100 Message-Id: <20220304172852.274126-6-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net The test is pretty basic: - create a virtual uhid device that no userspace will like (to not mess up the running system) - attach a BPF prog to it - open the matching hidraw node - inject one event and check: * that the BPF program can do something on the event stream * can modify the event stream Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/testing/selftests/bpf/prog_tests/hid.c | 335 +++++++++++++++++++ tools/testing/selftests/bpf/progs/hid.c | 20 ++ 2 files changed, 355 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/hid.c create mode 100644 tools/testing/selftests/bpf/progs/hid.c diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c new file mode 100644 index 000000000000..ee495d5a8bd5 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022 Red Hat */ +#include +#include +#include "hid.skel.h" + +#include +#include +#include +#include +#include +#include + +static unsigned char rdesc[] = { + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x09, 0x21, /* Usage (Vendor Usage 0x21) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x09, 0x01, /* Usage (Vendor Usage 0x01) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x85, 0x01, /* REPORT_ID (1) */ + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* Output (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x06, /* USAGE_MINIMUM (6) */ + 0x29, 0x08, /* USAGE_MAXIMUM (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0xb1, 0x02, /* Feature (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + + 0xc0, /* END_COLLECTION */ + 0xc0, /* END_COLLECTION */ +}; + +static int uhid_write(int fd, const struct uhid_event *ev) +{ + ssize_t ret; + + ret = write(fd, ev, sizeof(*ev)); + if (ret < 0) { + fprintf(stderr, "Cannot write to uhid: %m\n"); + return -errno; + } else if (ret != sizeof(*ev)) { + fprintf(stderr, "Wrong size written to uhid: %zd != %zu\n", + ret, sizeof(ev)); + return -EFAULT; + } else { + return 0; + } +} + +static int create(int fd, int rand_nb) +{ + struct uhid_event ev; + char buf[25]; + + sprintf(buf, "test-uhid-device-%d", rand_nb); + + memset(&ev, 0, sizeof(ev)); + ev.type = UHID_CREATE; + strcpy((char *)ev.u.create.name, buf); + ev.u.create.rd_data = rdesc; + ev.u.create.rd_size = sizeof(rdesc); + ev.u.create.bus = BUS_USB; + ev.u.create.vendor = 0x0001; + ev.u.create.product = 0x0a37; + ev.u.create.version = 0; + ev.u.create.country = 0; + + sprintf(buf, "%d", rand_nb); + strcpy((char *)ev.u.create.phys, buf); + + return uhid_write(fd, &ev); +} + +static void destroy(int fd) +{ + struct uhid_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.type = UHID_DESTROY; + + uhid_write(fd, &ev); +} + +static int send_event(int fd, u8 *buf, size_t size) +{ + struct uhid_event ev; + + if (size > sizeof(ev.u.input.data)) + return -E2BIG; + + memset(&ev, 0, sizeof(ev)); + ev.type = UHID_INPUT2; + ev.u.input2.size = size; + + memcpy(ev.u.input2.data, buf, size); + + return uhid_write(fd, &ev); +} + +static int setup_uhid(int rand_nb) +{ + int fd; + const char *path = "/dev/uhid"; + int ret; + + fd = open(path, O_RDWR | O_CLOEXEC); + if (!ASSERT_GE(fd, 0, "open uhid-cdev")) + return -EPERM; + + ret = create(fd, rand_nb); + if (!ASSERT_OK(ret, "create uhid device")) { + close(fd); + return -EPERM; + } + + return fd; +} + +static int get_sysfs_fd(int rand_nb) +{ + const char *workdir = "/sys/devices/virtual/misc/uhid"; + const char *target = "0003:0001:0A37.*"; + char uevent[1024]; + char temp[512]; + char phys[512]; + DIR *d; + struct dirent *dir; + int fd, nread; + int found = -1; + + /* it would be nice to be able to use nftw, but the no_alu32 target doesn't support it */ + + sprintf(phys, "PHYS=%d", rand_nb); + + d = opendir(workdir); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (fnmatch(target, dir->d_name, 0)) + continue; + + /* we found the correct VID/PID, now check for phys */ + sprintf(uevent, "%s/%s/uevent", workdir, dir->d_name); + fd = open(uevent, O_RDONLY | O_NONBLOCK); + if (fd < 0) + continue; + + nread = read(fd, temp, ARRAY_SIZE(temp)); + if (nread > 0 && (strstr(temp, phys)) != NULL) { + found = fd; + break; + } + + close(fd); + fd = 0; + } + closedir(d); + } + + return found; +} + +static int get_hidraw(struct bpf_link *link) +{ + struct bpf_link_info info = {0}; + int prog_id, i; + + /* retry 5 times in case the system is loaded */ + for (i = 5; i > 0; i--) { + usleep(10); + prog_id = link_info_prog_id(link, &info); + if (!prog_id) + continue; + if (info.hid.hidraw_ino >= 0) + break; + } + + if (!prog_id) + return -1; + + return info.hid.hidraw_ino; +} + +/* + * Attach hid_first_event to the given uhid device, + * retrieve and open the matching hidraw node, + * inject one event in the uhid device, + * check that the program sees it and can change the data + */ +static int test_hid_raw_event(struct hid *hid_skel, int uhid_fd, int sysfs_fd) +{ + int err, hidraw_ino, hidraw_fd = -1; + char hidraw_path[64] = {0}; + u8 buf[10] = {0}; + int ret = -1; + + /* check that the program is correctly loaded */ + ASSERT_EQ(hid_skel->data->callback_check, 52, "callback_check1"); + ASSERT_EQ(hid_skel->data->callback2_check, 52, "callback2_check1"); + + /* attach the first program */ + hid_skel->links.hid_first_event = + bpf_program__attach_hid(hid_skel->progs.hid_first_event, sysfs_fd); + if (!ASSERT_OK_PTR(hid_skel->links.hid_first_event, + "attach_hid(hid_first_event)")) + return PTR_ERR(hid_skel->links.hid_first_event); + + hidraw_ino = get_hidraw(hid_skel->links.hid_first_event); + if (!ASSERT_GE(hidraw_ino, 0, "get_hidraw")) + goto cleanup; + + /* open hidraw node to check the other side of the pipe */ + sprintf(hidraw_path, "/dev/hidraw%d", hidraw_ino); + hidraw_fd = open(hidraw_path, O_RDWR | O_NONBLOCK); + + if (!ASSERT_GE(hidraw_fd, 0, "open_hidraw")) + goto cleanup; + + /* inject one event */ + buf[0] = 1; + buf[1] = 42; + send_event(uhid_fd, buf, 6); + + /* check that hid_first_event() was executed */ + ASSERT_EQ(hid_skel->data->callback_check, 42, "callback_check1"); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(hidraw_fd, buf, sizeof(buf)); + if (!ASSERT_EQ(err, 6, "read_hidraw")) + goto cleanup; + + if (!ASSERT_EQ(buf[2], 47, "hid_first_event")) + goto cleanup; + + /* inject another event */ + buf[0] = 1; + buf[1] = 47; + send_event(uhid_fd, buf, 6); + + /* check that hid_first_event() was executed */ + ASSERT_EQ(hid_skel->data->callback_check, 47, "callback_check1"); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(hidraw_fd, buf, sizeof(buf)); + if (!ASSERT_EQ(err, 6, "read_hidraw")) + goto cleanup; + + if (!ASSERT_EQ(buf[2], 52, "hid_first_event")) + goto cleanup; + + ret = 0; + +cleanup: + if (hidraw_fd >= 0) + close(hidraw_fd); + + hid__detach(hid_skel); + + return ret; +} + +void serial_test_hid_bpf(void) +{ + struct hid *hid_skel = NULL; + int err, uhid_fd, sysfs_fd; + time_t t; + int rand_nb; + + /* initialize random number generator */ + srand((unsigned int)time(&t)); + + rand_nb = rand() % 1024; + + uhid_fd = setup_uhid(rand_nb); + if (!ASSERT_GE(uhid_fd, 0, "setup uhid")) + return; + + /* give a little bit of time for the device to appear */ + /* TODO: check on uhid events */ + usleep(1000); + + /* locate the uevent file of the created device */ + sysfs_fd = get_sysfs_fd(rand_nb); + if (!ASSERT_GE(sysfs_fd, 0, "locate sysfs uhid device")) + goto cleanup; + + hid_skel = hid__open_and_load(); + if (!ASSERT_OK_PTR(hid_skel, "hid_skel_load")) + goto cleanup; + + /* start the tests! */ + err = test_hid_raw_event(hid_skel, uhid_fd, sysfs_fd); + ASSERT_OK(err, "hid"); + +cleanup: + hid__destroy(hid_skel); + destroy(uhid_fd); +} diff --git a/tools/testing/selftests/bpf/progs/hid.c b/tools/testing/selftests/bpf/progs/hid.c new file mode 100644 index 000000000000..2201dd3b105d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/hid.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022 Red hat */ +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +__u64 callback_check = 52; +__u64 callback2_check = 52; + +SEC("hid/device_event") +int hid_first_event(struct hid_bpf_ctx *ctx) +{ + callback_check = ctx->data[1]; + + ctx->data[2] = ctx->data[1] + 5; + + return 0; +} From patchwork Fri Mar 4 17:28:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769587 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC024C433FE for ; Fri, 4 Mar 2022 17:31:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241160AbiCDRca (ORCPT ); Fri, 4 Mar 2022 12:32:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42346 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241171AbiCDRcU (ORCPT ); Fri, 4 Mar 2022 12:32:20 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 01CC81CFA03 for ; Fri, 4 Mar 2022 09:31:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415082; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yRMFUZZ3JBAMX0c9TwljMlvXIqWPVDlRh3QSDyZIcHU=; b=OQ0V4K8xM70qACuKAy2mxBxmG/XCXVIalpsy0635FRbzv40b18gaXgJpsw6/Q/8OrbcIya KVXqhiO1BF15NICXPT6i/HHwYQq/aNdywaSH/c+ppTGDW6iiObC1JRI5hcSu+0KZNkF+Tp pN0gR1+vJhlu8KjvbgQEne+2vxOH0KQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-611-B3pqBQAdPpO5qT85sCSGaA-1; Fri, 04 Mar 2022 12:31:18 -0500 X-MC-Unique: B3pqBQAdPpO5qT85sCSGaA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CB1941091DA1; Fri, 4 Mar 2022 17:31:15 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id EEB4E86595; Fri, 4 Mar 2022 17:31:11 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 06/28] samples/bpf: add new hid_mouse example Date: Fri, 4 Mar 2022 18:28:30 +0100 Message-Id: <20220304172852.274126-7-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Everything should be available in the selftest part of the tree, but providing an example without uhid and hidraw will be more easy to follow for users. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- samples/bpf/.gitignore | 1 + samples/bpf/Makefile | 4 ++ samples/bpf/hid_mouse_kern.c | 66 ++++++++++++++++++ samples/bpf/hid_mouse_user.c | 129 +++++++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 samples/bpf/hid_mouse_kern.c create mode 100644 samples/bpf/hid_mouse_user.c diff --git a/samples/bpf/.gitignore b/samples/bpf/.gitignore index 0e7bfdbff80a..65440bd618b2 100644 --- a/samples/bpf/.gitignore +++ b/samples/bpf/.gitignore @@ -2,6 +2,7 @@ cpustat fds_example hbm +hid_mouse ibumad lathist lwt_len_hist diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 38638845db9d..84ef458487df 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -60,6 +60,8 @@ tprogs-y += xdp_redirect_map tprogs-y += xdp_redirect tprogs-y += xdp_monitor +tprogs-y += hid_mouse + # Libbpf dependencies LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf LIBBPF_OUTPUT = $(abspath $(BPF_SAMPLES_PATH))/libbpf @@ -124,6 +126,7 @@ xdp_redirect_cpu-objs := xdp_redirect_cpu_user.o $(XDP_SAMPLE) xdp_redirect_map-objs := xdp_redirect_map_user.o $(XDP_SAMPLE) xdp_redirect-objs := xdp_redirect_user.o $(XDP_SAMPLE) xdp_monitor-objs := xdp_monitor_user.o $(XDP_SAMPLE) +hid_mouse-objs := hid_mouse_user.o # Tell kbuild to always build the programs always-y := $(tprogs-y) @@ -181,6 +184,7 @@ always-y += ibumad_kern.o always-y += hbm_out_kern.o always-y += hbm_edt_kern.o always-y += xdpsock_kern.o +always-y += hid_mouse_kern.o ifeq ($(ARCH), arm) # Strip all except -D__LINUX_ARM_ARCH__ option needed to handle linux diff --git a/samples/bpf/hid_mouse_kern.c b/samples/bpf/hid_mouse_kern.c new file mode 100644 index 000000000000..c24a12e06b40 --- /dev/null +++ b/samples/bpf/hid_mouse_kern.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2021 Benjamin Tissoires + */ +#include +#include +#include +#include + +SEC("hid/device_event") +int hid_y_event(struct hid_bpf_ctx *ctx) +{ + s16 y; + + bpf_printk("event: %02x size: %d", ctx->type, ctx->size); + bpf_printk("incoming event: %02x %02x %02x", + ctx->data[0], + ctx->data[1], + ctx->data[2]); + bpf_printk(" %02x %02x %02x", + ctx->data[3], + ctx->data[4], + ctx->data[5]); + bpf_printk(" %02x %02x %02x", + ctx->data[6], + ctx->data[7], + ctx->data[8]); + + y = ctx->data[3] | (ctx->data[4] << 8); + + y = -y; + + ctx->data[3] = y & 0xFF; + ctx->data[4] = (y >> 8) & 0xFF; + + bpf_printk("modified event: %02x %02x %02x", + ctx->data[0], + ctx->data[1], + ctx->data[2]); + bpf_printk(" %02x %02x %02x", + ctx->data[3], + ctx->data[4], + ctx->data[5]); + bpf_printk(" %02x %02x %02x", + ctx->data[6], + ctx->data[7], + ctx->data[8]); + + return 0; +} + +SEC("hid/device_event") +int hid_x_event(struct hid_bpf_ctx *ctx) +{ + s16 x; + + x = ctx->data[1] | (ctx->data[2] << 8); + + x = -x; + + ctx->data[1] = x & 0xFF; + ctx->data[2] = (x >> 8) & 0xFF; + return 0; +} + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/hid_mouse_user.c b/samples/bpf/hid_mouse_user.c new file mode 100644 index 000000000000..d4f37caca2fa --- /dev/null +++ b/samples/bpf/hid_mouse_user.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2021 Benjamin Tissoires + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bpf_util.h" +#include +#include + +static char *sysfs_path; +static int sysfs_fd; +static int prog_count; + +struct prog { + int fd; + struct bpf_link *link; + enum bpf_attach_type type; +}; + +static struct prog progs[10]; + +static void int_exit(int sig) +{ + for (prog_count--; prog_count >= 0; prog_count--) + bpf_link__destroy(progs[prog_count].link); + + close(sysfs_fd); + exit(0); +} + +static void usage(const char *prog) +{ + fprintf(stderr, + "%s: %s /sys/bus/hid/devices/0BUS:0VID:0PID:00ID/uevent\n\n", + __func__, prog); +} + +int main(int argc, char **argv) +{ + struct bpf_prog_info info = {}; + __u32 info_len = sizeof(info); + const char *optstr = ""; + struct bpf_object *obj; + struct bpf_program *prog; + int opt; + char filename[256]; + int err; + + while ((opt = getopt(argc, argv, optstr)) != -1) { + switch (opt) { + default: + usage(basename(argv[0])); + return 1; + } + } + + if (optind == argc) { + usage(basename(argv[0])); + return 1; + } + + sysfs_path = argv[optind]; + if (!sysfs_path) { + perror("sysfs"); + return 1; + } + + snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + obj = bpf_object__open_file(filename, NULL); + err = libbpf_get_error(obj); + if (err) { + fprintf(stderr, "ERROR: opening BPF object file failed\n"); + obj = NULL; + err = 1; + goto cleanup; + } + + /* load BPF program */ + err = bpf_object__load(obj); + if (err) { + fprintf(stderr, "ERROR: loading BPF object file failed\n"); + goto cleanup; + } + + sysfs_fd = open(sysfs_path, O_RDONLY); + + bpf_object__for_each_program(prog, obj) { + progs[prog_count].fd = bpf_program__fd(prog); + progs[prog_count].type = bpf_program__get_expected_attach_type(prog); + progs[prog_count].link = bpf_program__attach_hid(prog, sysfs_fd); + if (libbpf_get_error(progs[prog_count].link)) { + fprintf(stderr, "bpf_prog_attach: err=%m\n"); + progs[prog_count].fd = 0; + progs[prog_count].link = NULL; + goto cleanup; + } + prog_count++; + } + + signal(SIGINT, int_exit); + signal(SIGTERM, int_exit); + + err = bpf_obj_get_info_by_fd(progs[0].fd, &info, &info_len); + if (err) { + printf("can't get prog info - %s\n", strerror(errno)); + goto cleanup; + } + + while (1) + ; + + cleanup: + for (prog_count--; prog_count >= 0; prog_count--) + bpf_link__destroy(progs[prog_count].link); + + bpf_object__close(obj); + return err; +} From patchwork Fri Mar 4 17:28:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769592 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2505C433FE for ; Fri, 4 Mar 2022 17:32:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241114AbiCDRdM (ORCPT ); Fri, 4 Mar 2022 12:33:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232124AbiCDRck (ORCPT ); Fri, 4 Mar 2022 12:32:40 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 947521D084E for ; Fri, 4 Mar 2022 09:31:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415108; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=63XOkucXPoA9BHtkIxmyyJJF1thlmZZsP4rRoHSnHtU=; b=YAUWPZQ/5TceItxSJPloCNljtvMwFRwvQeJLIxrdc1N/U6vUIQwZqcE156EVXKaVMkxFoS ABqL6XNmibqEqlrJRVnBboS4bsJ87STUabtFcyQtQ6oqeMV3U+MGYL6rucWokDfKkAvh0r jomePCRjC8w4LQVnpNnIVkjLPvAUs98= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-665-kbUcF6rtML6PKyFbOs9qiw-1; Fri, 04 Mar 2022 12:31:43 -0500 X-MC-Unique: kbUcF6rtML6PKyFbOs9qiw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 25CE618766D2; Fri, 4 Mar 2022 17:31:40 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2F6C286595; Fri, 4 Mar 2022 17:31:15 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 07/28] bpf/hid: add a new attach type to change the report descriptor Date: Fri, 4 Mar 2022 18:28:31 +0100 Message-Id: <20220304172852.274126-8-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net The report descriptor is the dictionary of the HID protocol specific to the given device. Changing it is a common habit in the HID world, and making that feature accessible from eBPF allows to fix devices without having to install a new kernel. However, the report descriptor is supposed to be static on a device. To be able to change it, we need to reconnect the device at the HID level. So whenever the report descriptor program type is attached or detached, we call on a hook on HID to notify it that there is something to be done. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples - unsigned long -> __u16 in uapi/linux/bpf_hid.h --- include/linux/bpf-hid.h | 4 ++++ include/uapi/linux/bpf.h | 1 + include/uapi/linux/bpf_hid.h | 1 + kernel/bpf/hid.c | 5 +++++ kernel/bpf/syscall.c | 2 ++ tools/include/uapi/linux/bpf.h | 1 + 6 files changed, 14 insertions(+) diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h index 3cda78051b5f..0c5000b28b20 100644 --- a/include/linux/bpf-hid.h +++ b/include/linux/bpf-hid.h @@ -15,6 +15,7 @@ struct hid_device; enum bpf_hid_attach_type { BPF_HID_ATTACH_INVALID = -1, BPF_HID_ATTACH_DEVICE_EVENT = 0, + BPF_HID_ATTACH_RDESC_FIXUP, MAX_BPF_HID_ATTACH_TYPE }; @@ -32,6 +33,8 @@ to_bpf_hid_attach_type(enum bpf_attach_type attach_type) switch (attach_type) { case BPF_HID_DEVICE_EVENT: return BPF_HID_ATTACH_DEVICE_EVENT; + case BPF_HID_RDESC_FIXUP: + return BPF_HID_ATTACH_RDESC_FIXUP; default: return BPF_HID_ATTACH_INVALID; } @@ -88,6 +91,7 @@ static inline bool bpf_hid_link_empty(struct bpf_hid *bpf, struct bpf_hid_hooks { struct hid_device *(*hdev_from_fd)(int fd); int (*link_attach)(struct hid_device *hdev, enum bpf_hid_attach_type type); + void (*link_attached)(struct hid_device *hdev, enum bpf_hid_attach_type type); void (*array_detached)(struct hid_device *hdev, enum bpf_hid_attach_type type); }; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 5978b92cacd3..a7a8d9cfcf24 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -999,6 +999,7 @@ enum bpf_attach_type { BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, BPF_PERF_EVENT, BPF_HID_DEVICE_EVENT, + BPF_HID_RDESC_FIXUP, __MAX_BPF_ATTACH_TYPE }; diff --git a/include/uapi/linux/bpf_hid.h b/include/uapi/linux/bpf_hid.h index 975ca5bd526f..634f17c0b1cb 100644 --- a/include/uapi/linux/bpf_hid.h +++ b/include/uapi/linux/bpf_hid.h @@ -24,6 +24,7 @@ struct hid_device; enum hid_bpf_event { HID_BPF_UNDEF = 0, HID_BPF_DEVICE_EVENT, /* when attach type is BPF_HID_DEVICE_EVENT */ + HID_BPF_RDESC_FIXUP, /* ................... BPF_HID_RDESC_FIXUP */ }; struct hid_bpf_ctx { diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index db7f75a0a812..37500313e270 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -315,6 +315,8 @@ static int bpf_hid_max_progs(enum bpf_hid_attach_type type) switch (type) { case BPF_HID_ATTACH_DEVICE_EVENT: return 64; + case BPF_HID_ATTACH_RDESC_FIXUP: + return 1; default: return 0; } @@ -355,6 +357,9 @@ static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link, lockdep_is_held(&bpf_hid_mutex)); bpf_prog_array_free(run_array); + if (hid_hooks.link_attached) + hid_hooks.link_attached(hdev, type); + out_unlock: mutex_unlock(&bpf_hid_mutex); return err; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index a94e78ec3211..7428a1a512c6 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3203,6 +3203,7 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type) case BPF_XDP: return BPF_PROG_TYPE_XDP; case BPF_HID_DEVICE_EVENT: + case BPF_HID_RDESC_FIXUP: return BPF_PROG_TYPE_HID; default: return BPF_PROG_TYPE_UNSPEC; @@ -3348,6 +3349,7 @@ static int bpf_prog_query(const union bpf_attr *attr, case BPF_SK_SKB_VERDICT: return sock_map_bpf_prog_query(attr, uattr); case BPF_HID_DEVICE_EVENT: + case BPF_HID_RDESC_FIXUP: return bpf_hid_prog_query(attr, uattr); default: return -EINVAL; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 5978b92cacd3..a7a8d9cfcf24 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -999,6 +999,7 @@ enum bpf_attach_type { BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, BPF_PERF_EVENT, BPF_HID_DEVICE_EVENT, + BPF_HID_RDESC_FIXUP, __MAX_BPF_ATTACH_TYPE }; From patchwork Fri Mar 4 17:28:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769588 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16D51C4321E for ; Fri, 4 Mar 2022 17:31:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241190AbiCDRcp (ORCPT ); Fri, 4 Mar 2022 12:32:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42332 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241175AbiCDRcm (ORCPT ); Fri, 4 Mar 2022 12:32:42 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 61ED31D06FE for ; Fri, 4 Mar 2022 09:31:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415110; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OE0r/OKc2053ESgSK8t3z8KfogKogU32PwBJEY1LnEc=; b=VYRdRWujDG2993NligVFxyp9Rgz3/g+F/kHz+xT8LMIFZ0vhHldZ2Rl/pgvEhdq5msCO79 VwxFCHVvCtzF9W01d3MkBsCowXLFu8amRk0Urtjq5BOSCWFcscbSHZwm7ZV1YoI85tfOKb L0+TBskQNB2eSgUTC07B0v7Nl3jaw6s= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-488-mJypGw2FOR24BpQcynWSUg-1; Fri, 04 Mar 2022 12:31:47 -0500 X-MC-Unique: mJypGw2FOR24BpQcynWSUg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 760178031E1; Fri, 4 Mar 2022 17:31:44 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7628E86595; Fri, 4 Mar 2022 17:31:40 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 08/28] HID: allow to change the report descriptor from an eBPF program Date: Fri, 4 Mar 2022 18:28:32 +0100 Message-Id: <20220304172852.274126-9-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Make use of BPF_HID_ATTACH_RDESC_FIXUP so we can trigger an rdesc fixup in the bpf world. Whenever the program gets attached/detached, the device is reconnected meaning that userspace will see it disappearing and reappearing with the new report descriptor. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- drivers/hid/hid-bpf.c | 60 ++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-core.c | 3 ++- include/linux/hid.h | 6 +++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-bpf.c b/drivers/hid/hid-bpf.c index 8120e598de9f..510e24f4307c 100644 --- a/drivers/hid/hid-bpf.c +++ b/drivers/hid/hid-bpf.c @@ -50,6 +50,14 @@ static struct hid_device *hid_bpf_fd_to_hdev(int fd) return hdev; } +static int hid_reconnect(struct hid_device *hdev) +{ + if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) + return device_reprobe(&hdev->dev); + + return 0; +} + static int hid_bpf_link_attach(struct hid_device *hdev, enum bpf_hid_attach_type type) { int err = 0; @@ -71,6 +79,17 @@ static int hid_bpf_link_attach(struct hid_device *hdev, enum bpf_hid_attach_type return err; } +static void hid_bpf_link_attached(struct hid_device *hdev, enum bpf_hid_attach_type type) +{ + switch (type) { + case BPF_HID_ATTACH_RDESC_FIXUP: + hid_reconnect(hdev); + break; + default: + /* do nothing */ + } +} + static void hid_bpf_array_detached(struct hid_device *hdev, enum bpf_hid_attach_type type) { switch (type) { @@ -78,6 +97,9 @@ static void hid_bpf_array_detached(struct hid_device *hdev, enum bpf_hid_attach_ kfree(hdev->bpf.ctx); hdev->bpf.ctx = NULL; break; + case BPF_HID_ATTACH_RDESC_FIXUP: + hid_reconnect(hdev); + break; default: /* do nothing */ } @@ -98,6 +120,9 @@ static int hid_bpf_run_progs(struct hid_device *hdev, enum bpf_hid_attach_type t case BPF_HID_ATTACH_DEVICE_EVENT: event = HID_BPF_DEVICE_EVENT; break; + case BPF_HID_ATTACH_RDESC_FIXUP: + event = HID_BPF_RDESC_FIXUP; + break; default: return -EINVAL; } @@ -138,11 +163,46 @@ u8 *hid_bpf_raw_event(struct hid_device *hdev, u8 *data, int *size) return hdev->bpf.ctx->data; } +u8 *hid_bpf_report_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size) +{ + struct hid_bpf_ctx *ctx = NULL; + int ret; + + if (bpf_hid_link_empty(&hdev->bpf, BPF_HID_ATTACH_RDESC_FIXUP)) + goto ignore_bpf; + + ctx = bpf_hid_allocate_ctx(hdev, HID_MAX_DESCRIPTOR_SIZE); + if (IS_ERR(ctx)) + goto ignore_bpf; + + ret = hid_bpf_run_progs(hdev, BPF_HID_ATTACH_RDESC_FIXUP, ctx, rdesc, *size); + if (ret) + goto ignore_bpf; + + *size = ctx->size; + + if (!*size) { + rdesc = NULL; + goto unlock; + } + + rdesc = kmemdup(ctx->data, *size, GFP_KERNEL); + + unlock: + kfree(ctx); + return rdesc; + + ignore_bpf: + kfree(ctx); + return kmemdup(rdesc, *size, GFP_KERNEL); +} + int __init hid_bpf_module_init(void) { struct bpf_hid_hooks hooks = { .hdev_from_fd = hid_bpf_fd_to_hdev, .link_attach = hid_bpf_link_attach, + .link_attached = hid_bpf_link_attached, .array_detached = hid_bpf_array_detached, }; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index a80bffe6ce4a..0eb8189faaee 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1213,7 +1213,8 @@ int hid_open_report(struct hid_device *device) return -ENODEV; size = device->dev_rsize; - buf = kmemdup(start, size, GFP_KERNEL); + /* hid_bpf_report_fixup() ensures we work on a copy of rdesc */ + buf = hid_bpf_report_fixup(device, start, &size); if (buf == NULL) return -ENOMEM; diff --git a/include/linux/hid.h b/include/linux/hid.h index 8fd79011f461..66d949d10b78 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1213,10 +1213,16 @@ do { \ #ifdef CONFIG_BPF u8 *hid_bpf_raw_event(struct hid_device *hdev, u8 *rd, int *size); +u8 *hid_bpf_report_fixup(struct hid_device *hdev, u8 *rdesc, unsigned 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 u8 *hid_bpf_report_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *size) +{ + return kmemdup(rdesc, *size, GFP_KERNEL); +} static inline int hid_bpf_module_init(void) { return 0; } static inline void hid_bpf_module_exit(void) {} #endif From patchwork Fri Mar 4 17:28:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769590 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E1EDC4332F for ; Fri, 4 Mar 2022 17:32:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241170AbiCDRdJ (ORCPT ); Fri, 4 Mar 2022 12:33:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241256AbiCDRc4 (ORCPT ); Fri, 4 Mar 2022 12:32:56 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 374A11CE9AA for ; Fri, 4 Mar 2022 09:32:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415127; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AHXclG4UU3SsFO1lmPzG4KrgiciUiPhbXYLOOW1McYw=; b=LrghOQXNUOR0r0kuatoGrfArTEqrYDbRFzbT30v73POJbiNl7MumXnywvf8JMPLuxtTjVQ APKp52hkHExi+L9CTgivORTFZxOt/4n1gOdw2+VNgzVhg3XA6aiE7f5nRDNWikj0KyhhHi FLuiC3oQ6vcYGI9corXHnWfetncRevs= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-438-dEgrSUCrOImgtxojmRx8Bg-1; Fri, 04 Mar 2022 12:32:04 -0500 X-MC-Unique: dEgrSUCrOImgtxojmRx8Bg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C19BA1091DA1; Fri, 4 Mar 2022 17:32:01 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id C5B2886595; Fri, 4 Mar 2022 17:31:44 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 09/28] libbpf: add new attach type BPF_HID_RDESC_FIXUP Date: Fri, 4 Mar 2022 18:28:33 +0100 Message-Id: <20220304172852.274126-10-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Adds the SEC definiton for report descriptor fixups. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/lib/bpf/libbpf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 356bbd3ad2c7..192ef3901251 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -8681,6 +8681,7 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("struct_ops+", STRUCT_OPS, 0, SEC_NONE), SEC_DEF("sk_lookup", SK_LOOKUP, BPF_SK_LOOKUP, SEC_ATTACHABLE | SEC_SLOPPY_PFX), SEC_DEF("hid/device_event", HID, BPF_HID_DEVICE_EVENT, SEC_ATTACHABLE_OPT | SEC_SLOPPY_PFX), + SEC_DEF("hid/rdesc_fixup", HID, BPF_HID_RDESC_FIXUP, SEC_ATTACHABLE_OPT | SEC_SLOPPY_PFX), }; #define MAX_TYPE_NAME_SIZE 32 From patchwork Fri Mar 4 17:28:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769589 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1AC4EC43219 for ; Fri, 4 Mar 2022 17:32:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238474AbiCDRdI (ORCPT ); Fri, 4 Mar 2022 12:33:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241313AbiCDRdC (ORCPT ); Fri, 4 Mar 2022 12:33:02 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 87CEB1CD9D0 for ; Fri, 4 Mar 2022 09:32:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415133; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=keWwWK0FSYCv+KDSFFo0E62Z2+V4Q5lYFQr59m0uXhY=; b=NXcZpkoFsS5LU6ZllD3S0e4qtRl9immt/7MD/MFWJZ5pPprn1sPr8ZoMURji0C9qXD7ebx qVBafEntXdESOeWIwqKWpuqTlcWm8KlkCz+0nlBrYML6yzFH67N+hnBj+g7g8MWfoHNPCf EdVcduY/kpKTKn9DGJt0ZGUXl6bSpY8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-58-UzYFijzsP3uGYt2lwCK8bg-1; Fri, 04 Mar 2022 12:32:08 -0500 X-MC-Unique: UzYFijzsP3uGYt2lwCK8bg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id ED8B51091DA0; Fri, 4 Mar 2022 17:32:05 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1DED686595; Fri, 4 Mar 2022 17:32:01 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 10/28] selftests/bpf: add report descriptor fixup tests Date: Fri, 4 Mar 2022 18:28:34 +0100 Message-Id: <20220304172852.274126-11-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Simple report descriptor override in HID: replace part of the report descriptor from a static definition in the bpf kernel program. Note that this test should be run last because we disconnect/reconnect the device, meaning that it changes the overall uhid device. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/testing/selftests/bpf/prog_tests/hid.c | 69 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/hid.c | 48 ++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c index ee495d5a8bd5..91543b8078ca 100644 --- a/tools/testing/selftests/bpf/prog_tests/hid.c +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -9,6 +9,7 @@ #include #include #include +#include #include static unsigned char rdesc[] = { @@ -296,6 +297,71 @@ static int test_hid_raw_event(struct hid *hid_skel, int uhid_fd, int sysfs_fd) return ret; } +/* + * Attach hid_rdesc_fixup to the given uhid device, + * retrieve and open the matching hidraw node, + * check that the hidraw report descriptor has been updated. + */ +static int test_rdesc_fixup(struct hid *hid_skel, int uhid_fd, int sysfs_fd) +{ + struct hidraw_report_descriptor rpt_desc = {0}; + int err, desc_size, hidraw_ino, hidraw_fd = -1; + char hidraw_path[64] = {0}; + int ret = -1; + + /* attach the program */ + hid_skel->links.hid_rdesc_fixup = + bpf_program__attach_hid(hid_skel->progs.hid_rdesc_fixup, sysfs_fd); + if (!ASSERT_OK_PTR(hid_skel->links.hid_rdesc_fixup, + "attach_hid(hid_rdesc_fixup)")) + return PTR_ERR(hid_skel->links.hid_rdesc_fixup); + + /* give a little bit of time for the device to appear */ + /* TODO: check on uhid events */ + usleep(1000); + + hidraw_ino = get_hidraw(hid_skel->links.hid_rdesc_fixup); + if (!ASSERT_GE(hidraw_ino, 0, "get_hidraw")) + goto cleanup; + + /* open hidraw node to check the other side of the pipe */ + sprintf(hidraw_path, "/dev/hidraw%d", hidraw_ino); + hidraw_fd = open(hidraw_path, O_RDWR | O_NONBLOCK); + + if (!ASSERT_GE(hidraw_fd, 0, "open_hidraw")) + goto cleanup; + + /* check that hid_rdesc_fixup() was executed */ + ASSERT_EQ(hid_skel->data->callback2_check, 0x21, "callback_check2"); + + /* read the exposed report descriptor from hidraw */ + err = ioctl(hidraw_fd, HIDIOCGRDESCSIZE, &desc_size); + if (!ASSERT_GE(err, 0, "HIDIOCGRDESCSIZE")) + goto cleanup; + + /* ensure the new size of the rdesc is bigger than the old one */ + if (!ASSERT_GT(desc_size, sizeof(rdesc), "new_rdesc_size")) + goto cleanup; + + rpt_desc.size = desc_size; + err = ioctl(hidraw_fd, HIDIOCGRDESC, &rpt_desc); + if (!ASSERT_GE(err, 0, "HIDIOCGRDESC")) + goto cleanup; + + if (!ASSERT_EQ(rpt_desc.value[4], 0x42, "hid_rdesc_fixup")) + goto cleanup; + + ret = 0; + +cleanup: + if (hidraw_fd >= 0) + close(hidraw_fd); + + hid__detach(hid_skel); + + return ret; +} + void serial_test_hid_bpf(void) { struct hid *hid_skel = NULL; @@ -329,6 +395,9 @@ void serial_test_hid_bpf(void) err = test_hid_raw_event(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid"); + err = test_rdesc_fixup(hid_skel, uhid_fd, sysfs_fd); + ASSERT_OK(err, "hid_rdesc_fixup"); + cleanup: hid__destroy(hid_skel); destroy(uhid_fd); diff --git a/tools/testing/selftests/bpf/progs/hid.c b/tools/testing/selftests/bpf/progs/hid.c index 2201dd3b105d..2270448d0d3f 100644 --- a/tools/testing/selftests/bpf/progs/hid.c +++ b/tools/testing/selftests/bpf/progs/hid.c @@ -18,3 +18,51 @@ int hid_first_event(struct hid_bpf_ctx *ctx) return 0; } + +static __u8 rdesc[] = { + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x32, /* USAGE (Z) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* Output (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x06, /* USAGE_MINIMUM (6) */ + 0x29, 0x08, /* USAGE_MAXIMUM (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0xb1, 0x02, /* Feature (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + + 0xc0, /* END_COLLECTION */ + 0xc0, /* END_COLLECTION */ +}; + +SEC("hid/rdesc_fixup") +int hid_rdesc_fixup(struct hid_bpf_ctx *ctx) +{ + callback2_check = ctx->data[4]; + + /* insert rdesc at offset 52 */ + __builtin_memcpy(&ctx->data[52], rdesc, sizeof(rdesc)); + ctx->size = sizeof(rdesc) + 52; + + ctx->data[4] = 0x42; + + return 0; +} From patchwork Fri Mar 4 17:28:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769591 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1396C433F5 for ; Fri, 4 Mar 2022 17:32:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241211AbiCDRdL (ORCPT ); Fri, 4 Mar 2022 12:33:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241340AbiCDRdG (ORCPT ); Fri, 4 Mar 2022 12:33:06 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 982301CD9D0 for ; Fri, 4 Mar 2022 09:32:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415137; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jXjAemh+tgaeshWdU0Zw5DqV+Jw6OpdtZV+yJ3YWHiI=; b=Pq7oeTiZim9L821up8Bt3uocFT/eU/E65NZHoJlL0nObHmj2VUQZXsbPFfcZgyUx/LcgAx P29tuo0YljEnqu1VlOzAfUjrJlSBuMzSGqEWodX0j2feEF39NlXpAnECSittVQQdOjOJSb LvBlR0i2K7aFq4xiz/1bMB3vszFO/PM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-204-hTrIEclbMQmRMq9TQ7IA5A-1; Fri, 04 Mar 2022 12:32:12 -0500 X-MC-Unique: hTrIEclbMQmRMq9TQ7IA5A-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 59BC51091DA0; Fri, 4 Mar 2022 17:32:10 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 49C2486595; Fri, 4 Mar 2022 17:32:06 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 11/28] samples/bpf: add a report descriptor fixup Date: Fri, 4 Mar 2022 18:28:35 +0100 Message-Id: <20220304172852.274126-12-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net the program inverts the definition of X and Y at a given place in the report descriptor of my mouse. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- samples/bpf/hid_mouse_kern.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/samples/bpf/hid_mouse_kern.c b/samples/bpf/hid_mouse_kern.c index c24a12e06b40..958820caaf5d 100644 --- a/samples/bpf/hid_mouse_kern.c +++ b/samples/bpf/hid_mouse_kern.c @@ -62,5 +62,30 @@ int hid_x_event(struct hid_bpf_ctx *ctx) return 0; } +SEC("hid/rdesc_fixup") +int hid_rdesc_fixup(struct hid_bpf_ctx *ctx) +{ + if (ctx->type != HID_BPF_RDESC_FIXUP) + return 0; + + bpf_printk("rdesc: %02x %02x %02x", + ctx->data[0], + ctx->data[1], + ctx->data[2]); + bpf_printk(" %02x %02x %02x", + ctx->data[3], + ctx->data[4], + ctx->data[5]); + bpf_printk(" %02x %02x %02x ...", + ctx->data[6], + ctx->data[7], + ctx->data[8]); + + ctx->data[39] = 0x31; + ctx->data[41] = 0x30; + + return 0; +} + char _license[] SEC("license") = "GPL"; u32 _version SEC("version") = LINUX_VERSION_CODE; From patchwork Fri Mar 4 17:28:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769593 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D1C9C433F5 for ; Fri, 4 Mar 2022 17:33:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241249AbiCDRdv (ORCPT ); Fri, 4 Mar 2022 12:33:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46044 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241198AbiCDRdr (ORCPT ); Fri, 4 Mar 2022 12:33:47 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A91301B785 for ; Fri, 4 Mar 2022 09:32:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415161; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jxX8RNUdMtQkr8agXKyQdLygFyl1w1wHLWAQzrI5Jww=; b=EBbGMnAbYdDaqhREQNZFD/dwJVWKGoEqux53IwUGg94ln9ZkWzABDKyoNPgBlMb0Q4Dh5B wiGDlGpBgMEz/7m7J+9cG32JO3gbqQCkkhkWB4KFwOe2wA3aDyzqMaGybBxshiWkFklt6r Aa3+iQKX2R/ONY6kKWJMR1PoeQJutlE= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-604-rlFpjqNtNyGRyAZNWq3Ftw-1; Fri, 04 Mar 2022 12:32:38 -0500 X-MC-Unique: rlFpjqNtNyGRyAZNWq3Ftw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D0971824FA8; Fri, 4 Mar 2022 17:32:35 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id AA1FE86595; Fri, 4 Mar 2022 17:32:10 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 12/28] bpf/hid: add hid_{get|set}_data helpers Date: Fri, 4 Mar 2022 18:28:36 +0100 Message-Id: <20220304172852.274126-13-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net When we process an incoming HID report, it is common to have to account for fields that are not aligned in the report. HID is using 2 helpers hid_field_extract() and implement() to pick up any data at any offset within the report. Export those 2 helpers in BPF programs so users can also rely on them. The second net worth advantage of those helpers is that now we can fetch data anywhere in the report without knowing at compile time the location of it. The boundary checks are done in hid-bpf.c, to prevent a memory leak. Signed-off-by: Benjamin Tissoires Reviewed-by: Greg Kroah-Hartman --- changes in v2: - split the patch with libbpf and HID left outside. --- include/linux/bpf-hid.h | 4 +++ include/uapi/linux/bpf.h | 32 ++++++++++++++++++++ kernel/bpf/hid.c | 53 ++++++++++++++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 32 ++++++++++++++++++++ 4 files changed, 121 insertions(+) diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h index 0c5000b28b20..69bb28523ceb 100644 --- a/include/linux/bpf-hid.h +++ b/include/linux/bpf-hid.h @@ -93,6 +93,10 @@ struct bpf_hid_hooks { int (*link_attach)(struct hid_device *hdev, enum bpf_hid_attach_type type); void (*link_attached)(struct hid_device *hdev, enum bpf_hid_attach_type type); void (*array_detached)(struct hid_device *hdev, enum bpf_hid_attach_type type); + int (*hid_get_data)(struct hid_device *hdev, u8 *buf, size_t buf_size, + u64 offset, u32 n, u8 *data, u64 data_size); + int (*hid_set_data)(struct hid_device *hdev, u8 *buf, size_t buf_size, + u64 offset, u32 n, u8 *data, u64 data_size); }; #ifdef CONFIG_BPF diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a7a8d9cfcf24..4845a20e6f96 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5090,6 +5090,36 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. On error * *dst* buffer is zeroed out. + * + * int bpf_hid_get_data(void *ctx, u64 offset, u32 n, u8 *data, u64 size) + * Description + * Get the data of size n (in bits) at the given offset (bits) in the + * ctx->event.data field and store it into data. + * + * if n is less or equal than 32, we can address with bit precision, + * the value in the buffer. However, data must be a pointer to a u32 + * and size must be 4. + * + * if n is greater than 32, offset and n must be a multiple of 8 + * and the result is working with a memcpy internally. + * Return + * The length of data copied into data. On error, a negative value + * is returned. + * + * int bpf_hid_set_data(void *ctx, u64 offset, u32 n, u8 *data, u64 size) + * Description + * Set the data of size n (in bits) at the given offset (bits) in the + * ctx->event.data field. + * + * if n is less or equal than 32, we can address with bit precision, + * the value in the buffer. However, data must be a pointer to a u32 + * and size must be 4. + * + * if n is greater than 32, offset and n must be a multiple of 8 + * and the result is working with a memcpy internally. + * Return + * The length of data copied into ctx->event.data. On error, a negative + * value is returned. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5284,6 +5314,8 @@ union bpf_attr { FN(xdp_load_bytes), \ FN(xdp_store_bytes), \ FN(copy_from_user_task), \ + FN(hid_get_data), \ + FN(hid_set_data), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index 37500313e270..640e55ba66ec 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -37,10 +37,63 @@ void bpf_hid_set_hooks(struct bpf_hid_hooks *hooks) } EXPORT_SYMBOL_GPL(bpf_hid_set_hooks); +BPF_CALL_5(bpf_hid_get_data, void*, ctx, u64, offset, u32, n, void*, data, u64, size) +{ + struct hid_bpf_ctx *bpf_ctx = ctx; + + if (!hid_hooks.hid_get_data) + return -EOPNOTSUPP; + + return hid_hooks.hid_get_data(bpf_ctx->hdev, + bpf_ctx->data, bpf_ctx->allocated_size, + offset, n, + data, size); +} + +static const struct bpf_func_proto bpf_hid_get_data_proto = { + .func = bpf_hid_get_data, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_MEM, + .arg5_type = ARG_CONST_SIZE_OR_ZERO, +}; + +BPF_CALL_5(bpf_hid_set_data, void*, ctx, u64, offset, u32, n, void*, data, u64, size) +{ + struct hid_bpf_ctx *bpf_ctx = ctx; + + if (!hid_hooks.hid_set_data) + return -EOPNOTSUPP; + + hid_hooks.hid_set_data(bpf_ctx->hdev, + bpf_ctx->data, bpf_ctx->allocated_size, + offset, n, + data, size); + return 0; +} + +static const struct bpf_func_proto bpf_hid_set_data_proto = { + .func = bpf_hid_set_data, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_MEM, + .arg5_type = ARG_CONST_SIZE_OR_ZERO, +}; + static const struct bpf_func_proto * hid_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { switch (func_id) { + case BPF_FUNC_hid_get_data: + return &bpf_hid_get_data_proto; + case BPF_FUNC_hid_set_data: + return &bpf_hid_set_data_proto; default: return bpf_base_func_proto(func_id); } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index a7a8d9cfcf24..4845a20e6f96 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5090,6 +5090,36 @@ union bpf_attr { * Return * 0 on success, or a negative error in case of failure. On error * *dst* buffer is zeroed out. + * + * int bpf_hid_get_data(void *ctx, u64 offset, u32 n, u8 *data, u64 size) + * Description + * Get the data of size n (in bits) at the given offset (bits) in the + * ctx->event.data field and store it into data. + * + * if n is less or equal than 32, we can address with bit precision, + * the value in the buffer. However, data must be a pointer to a u32 + * and size must be 4. + * + * if n is greater than 32, offset and n must be a multiple of 8 + * and the result is working with a memcpy internally. + * Return + * The length of data copied into data. On error, a negative value + * is returned. + * + * int bpf_hid_set_data(void *ctx, u64 offset, u32 n, u8 *data, u64 size) + * Description + * Set the data of size n (in bits) at the given offset (bits) in the + * ctx->event.data field. + * + * if n is less or equal than 32, we can address with bit precision, + * the value in the buffer. However, data must be a pointer to a u32 + * and size must be 4. + * + * if n is greater than 32, offset and n must be a multiple of 8 + * and the result is working with a memcpy internally. + * Return + * The length of data copied into ctx->event.data. On error, a negative + * value is returned. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5284,6 +5314,8 @@ union bpf_attr { FN(xdp_load_bytes), \ FN(xdp_store_bytes), \ FN(copy_from_user_task), \ + FN(hid_get_data), \ + FN(hid_set_data), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper From patchwork Fri Mar 4 17:28:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769594 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1080C433F5 for ; Fri, 4 Mar 2022 17:33:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241191AbiCDRdx (ORCPT ); Fri, 4 Mar 2022 12:33:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241037AbiCDRdt (ORCPT ); Fri, 4 Mar 2022 12:33:49 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B931720F53 for ; Fri, 4 Mar 2022 09:32:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415167; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WeTIWQC6fVAlk6Saj5kWD691Ja7Vds/ypH8GpPfWruc=; b=Qq/QFcehw+WHXNYiQumYzGr3D5khM3jfGfLoWlRK1tK0xxniP3m10I3avXArNII93j0Ktq g2wP7no/elJ3Y1IPwvF6B21DojuLHRgWSV1r916ND/hqgAxRVoOMn2ZtV1+Xp49ulF4hME /MsNssYTZZbQTDsslvOndVUjMiT32OU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-394-0nhDjJoCOhe0PWVuPWThqg-1; Fri, 04 Mar 2022 12:32:42 -0500 X-MC-Unique: 0nhDjJoCOhe0PWVuPWThqg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5BF2B8066F3; Fri, 4 Mar 2022 17:32:40 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2F2038659E; Fri, 4 Mar 2022 17:32:36 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 13/28] HID: bpf: implement hid_bpf_get|set_data Date: Fri, 4 Mar 2022 18:28:37 +0100 Message-Id: <20220304172852.274126-14-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net We have 2 cases of usage here: - either n <= 32: we are addressing individual bits at the given offset - either n > 32: we are using a memcpy to transmit the data to the caller, meaning that we need to be byte-aligned. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples - allow for n > 32, by relying on memcpy --- drivers/hid/hid-bpf.c | 68 ++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-core.c | 4 +-- include/linux/hid.h | 2 ++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-bpf.c b/drivers/hid/hid-bpf.c index 510e24f4307c..8ae247fba5bc 100644 --- a/drivers/hid/hid-bpf.c +++ b/drivers/hid/hid-bpf.c @@ -105,6 +105,72 @@ static void hid_bpf_array_detached(struct hid_device *hdev, enum bpf_hid_attach_ } } +int hid_bpf_get_data(struct hid_device *hdev, u8 *buf, size_t buf_size, u64 offset, u32 n, + u8 *data, u64 data_size) +{ + u32 *value = (u32 *)data; + + if (((offset + n) >> 3) >= buf_size) + return -E2BIG; + + if (n <= 32) { + /* data must be a pointer to a u32 */ + if (data_size != 4) + return -EINVAL; + + *value = hid_field_extract(hdev, buf, offset, n); + return 4; + } + + /* if n > 32, use memcpy, but ensure we are dealing with full bytes */ + if ((n | offset) & 0x7) + return -EINVAL; + + /* work on bytes now */ + offset = offset >> 3; + n = n >> 3; + + if (n > data_size) + return -EINVAL; + + memcpy(data, buf + offset, n); + + return n; +} + +int hid_bpf_set_data(struct hid_device *hdev, u8 *buf, size_t buf_size, u64 offset, u32 n, + u8 *data, u64 data_size) +{ + u32 *value = (u32 *)data; + + if (((offset + n) >> 3) >= buf_size) + return -E2BIG; + + if (n <= 32) { + /* data must be a pointer to a u32 */ + if (data_size != 4) + return -EINVAL; + + implement(hdev, buf, offset, n, *value); + return 4; + } + + /* if n > 32, use memcpy, but ensure we are dealing with full bytes */ + if ((n | offset) & 0x7) + return -EINVAL; + + /* work on bytes now */ + offset = offset >> 3; + n = n >> 3; + + if (n > data_size) + return -EINVAL; + + memcpy(buf + offset, data, n); + + return n; +} + static int hid_bpf_run_progs(struct hid_device *hdev, enum bpf_hid_attach_type type, struct hid_bpf_ctx *ctx, u8 *data, int size) { @@ -204,6 +270,8 @@ int __init hid_bpf_module_init(void) .link_attach = hid_bpf_link_attach, .link_attached = hid_bpf_link_attached, .array_detached = hid_bpf_array_detached, + .hid_get_data = hid_bpf_get_data, + .hid_set_data = hid_bpf_set_data, }; bpf_hid_set_hooks(&hooks); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0eb8189faaee..d3f4499ee4cd 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1416,8 +1416,8 @@ static void __implement(u8 *report, unsigned offset, int n, u32 value) } } -static void implement(const struct hid_device *hid, u8 *report, - unsigned offset, unsigned n, u32 value) +void implement(const struct hid_device *hid, u8 *report, unsigned int offset, unsigned int n, + u32 value) { if (unlikely(n > 32)) { hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", diff --git a/include/linux/hid.h b/include/linux/hid.h index 66d949d10b78..7454e844324c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -944,6 +944,8 @@ bool hid_compare_device_paths(struct hid_device *hdev_a, s32 hid_snto32(__u32 value, unsigned n); __u32 hid_field_extract(const struct hid_device *hid, __u8 *report, unsigned offset, unsigned n); +void implement(const struct hid_device *hid, u8 *report, unsigned int offset, unsigned int n, + u32 value); #ifdef CONFIG_PM int hid_driver_suspend(struct hid_device *hdev, pm_message_t state); From patchwork Fri Mar 4 17:28:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769595 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32E5EC43219 for ; Fri, 4 Mar 2022 17:33:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241236AbiCDRd6 (ORCPT ); Fri, 4 Mar 2022 12:33:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241234AbiCDRdt (ORCPT ); Fri, 4 Mar 2022 12:33:49 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2493333E14 for ; Fri, 4 Mar 2022 09:32:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415170; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ux6twZOFT9lb2qTfIZn2kGfR1Z5YetNZFcKf5G8re3c=; b=V2o/Y64/Z/iu0s3iSvY0JMrwHhYddrC0uWnh5xQ9rOwASV4E2gao6le1yZbMS9rBga1Lwu 9PvTqvldTILhaGgLuYHO79pLTrx1KtX+SMqriJnVucNtjKzohSzZvr7fUoH1P0241unKtt 6ty3wvSaIIo+8cebZUwT/Gt7yCZ9EmA= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-452-PycJhc6zM8GUH9sRgyf9ng-1; Fri, 04 Mar 2022 12:32:47 -0500 X-MC-Unique: PycJhc6zM8GUH9sRgyf9ng-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8702B824FA7; Fri, 4 Mar 2022 17:32:44 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id ABB6786595; Fri, 4 Mar 2022 17:32:40 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 14/28] selftests/bpf: add tests for hid_{get|set}_data helpers Date: Fri, 4 Mar 2022 18:28:38 +0100 Message-Id: <20220304172852.274126-15-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Simple test added here, with one use of each helper. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the patch with libbpf left outside. --- tools/testing/selftests/bpf/prog_tests/hid.c | 65 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/hid.c | 45 ++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c index 91543b8078ca..74426523dd6f 100644 --- a/tools/testing/selftests/bpf/prog_tests/hid.c +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -297,6 +297,68 @@ static int test_hid_raw_event(struct hid *hid_skel, int uhid_fd, int sysfs_fd) return ret; } +/* + * Attach hid_set_get_data to the given uhid device, + * retrieve and open the matching hidraw node, + * inject one event in the uhid device, + * check that the program makes correct use of bpf_hid_{set|get}_data. + */ +static int test_hid_set_get_data(struct hid *hid_skel, int uhid_fd, int sysfs_fd) +{ + int err, hidraw_ino, hidraw_fd = -1; + char hidraw_path[64] = {0}; + u8 buf[10] = {0}; + int ret = -1; + + /* attach hid_set_get_data program */ + hid_skel->links.hid_set_get_data = + bpf_program__attach_hid(hid_skel->progs.hid_set_get_data, sysfs_fd); + if (!ASSERT_OK_PTR(hid_skel->links.hid_set_get_data, + "attach_hid(hid_set_get_data)")) + return PTR_ERR(hid_skel->links.hid_set_get_data); + + hidraw_ino = get_hidraw(hid_skel->links.hid_set_get_data); + if (!ASSERT_GE(hidraw_ino, 0, "get_hidraw")) + goto cleanup; + + /* open hidraw node to check the other side of the pipe */ + sprintf(hidraw_path, "/dev/hidraw%d", hidraw_ino); + hidraw_fd = open(hidraw_path, O_RDWR | O_NONBLOCK); + + if (!ASSERT_GE(hidraw_fd, 0, "open_hidraw")) + goto cleanup; + + /* inject one event */ + buf[0] = 1; + buf[1] = 42; + send_event(uhid_fd, buf, 6); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(hidraw_fd, buf, sizeof(buf)); + if (!ASSERT_EQ(err, 6, "read_hidraw")) + goto cleanup; + + if (!ASSERT_EQ(buf[2], (42 >> 2), "hid_set_get_data")) + goto cleanup; + + if (!ASSERT_EQ(buf[3], 1, "hid_set_get_data")) + goto cleanup; + + if (!ASSERT_EQ(buf[4], 42, "hid_set_get_data")) + goto cleanup; + + ret = 0; + +cleanup: + if (hidraw_fd >= 0) + close(hidraw_fd); + + hid__detach(hid_skel); + + return ret; +} + /* * Attach hid_rdesc_fixup to the given uhid device, * retrieve and open the matching hidraw node, @@ -395,6 +457,9 @@ void serial_test_hid_bpf(void) err = test_hid_raw_event(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid"); + err = test_hid_set_get_data(hid_skel, uhid_fd, sysfs_fd); + ASSERT_OK(err, "hid_set_get_data"); + err = test_rdesc_fixup(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_rdesc_fixup"); diff --git a/tools/testing/selftests/bpf/progs/hid.c b/tools/testing/selftests/bpf/progs/hid.c index 2270448d0d3f..de6668471940 100644 --- a/tools/testing/selftests/bpf/progs/hid.c +++ b/tools/testing/selftests/bpf/progs/hid.c @@ -66,3 +66,48 @@ int hid_rdesc_fixup(struct hid_bpf_ctx *ctx) return 0; } + +SEC("hid/device_event") +int hid_set_get_data(struct hid_bpf_ctx *ctx) +{ + int ret; + __u8 *buf; + + buf = bpf_ringbuf_reserve(&ringbuf, 8, 0); + if (!buf) + return -12; /* -ENOMEM */ + + /* first try read/write with n > 32 */ + ret = bpf_hid_get_data(ctx, 0, 64, buf, 8); + if (ret < 0) + goto discard; + + /* reinject it */ + ret = bpf_hid_set_data(ctx, 24, 64, buf, 8); + if (ret < 0) + goto discard; + + /* extract data at bit offset 10 of size 4 (half a byte) */ + ret = bpf_hid_get_data(ctx, 10, 4, buf, 8); /* expected to fail */ + if (ret > 0) { + ret = -1; + goto discard; + } + + ret = bpf_hid_get_data(ctx, 10, 4, buf, 4); + if (ret < 0) + goto discard; + + /* reinject it */ + ret = bpf_hid_set_data(ctx, 16, 4, buf, 4); + if (ret < 0) + goto discard; + + ret = 0; + + discard: + + bpf_ringbuf_discard(buf, 0); + + return ret; +} From patchwork Fri Mar 4 17:28:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769596 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 27F27C4321E for ; Fri, 4 Mar 2022 17:33:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241230AbiCDReb (ORCPT ); Fri, 4 Mar 2022 12:34:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46600 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241319AbiCDReN (ORCPT ); Fri, 4 Mar 2022 12:34:13 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8F37A5521C for ; Fri, 4 Mar 2022 09:33:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415190; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=olWbYkTvC+e+vMVbk45dm+kEMM67iGwcmeNrgiVuKYI=; b=iWzO/iFKvP+PE/rWALG4v0W2Vkcy8i212KiraB9LqFkZVoJtDEOrlMLv9PIBBjcq5KFG8y AsCPNs3Kjwc0dAItPvOmaXsPP/Mmv7pEHUb4qq91bpa13OE+KODoL2eAI7SVR2xbWleslO SAalXhHbjFPtUV7fAZI45acXMdXUKF0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-198-G47TMMIbM7CXeohmMcgQ0w-1; Fri, 04 Mar 2022 12:33:07 -0500 X-MC-Unique: G47TMMIbM7CXeohmMcgQ0w-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DCAF66C50A; Fri, 4 Mar 2022 17:33:04 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id D69C28659E; Fri, 4 Mar 2022 17:32:44 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 15/28] bpf/hid: add new BPF type to trigger commands from userspace Date: Fri, 4 Mar 2022 18:28:39 +0100 Message-Id: <20220304172852.274126-16-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Given that we can not call bpf_hid_raw_request() from within an IRQ, userspace needs to have a way to communicate with the device when it needs. Implement a new type that the caller can run at will without being in an IRQ context. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples - unsigned long -> __u16 in uapi/linux/bpf_hid.h - int -> __32 in uapi/linux/bpf_hid.h --- include/linux/bpf-hid.h | 3 + include/uapi/linux/bpf.h | 1 + include/uapi/linux/bpf_hid.h | 10 +++ kernel/bpf/hid.c | 116 +++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 2 + tools/include/uapi/linux/bpf.h | 1 + 6 files changed, 133 insertions(+) diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h index 69bb28523ceb..4cf2e99109fe 100644 --- a/include/linux/bpf-hid.h +++ b/include/linux/bpf-hid.h @@ -16,6 +16,7 @@ enum bpf_hid_attach_type { BPF_HID_ATTACH_INVALID = -1, BPF_HID_ATTACH_DEVICE_EVENT = 0, BPF_HID_ATTACH_RDESC_FIXUP, + BPF_HID_ATTACH_USER_EVENT, MAX_BPF_HID_ATTACH_TYPE }; @@ -35,6 +36,8 @@ to_bpf_hid_attach_type(enum bpf_attach_type attach_type) return BPF_HID_ATTACH_DEVICE_EVENT; case BPF_HID_RDESC_FIXUP: return BPF_HID_ATTACH_RDESC_FIXUP; + case BPF_HID_USER_EVENT: + return BPF_HID_ATTACH_USER_EVENT; default: return BPF_HID_ATTACH_INVALID; } diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 4845a20e6f96..b3063384d380 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1000,6 +1000,7 @@ enum bpf_attach_type { BPF_PERF_EVENT, BPF_HID_DEVICE_EVENT, BPF_HID_RDESC_FIXUP, + BPF_HID_USER_EVENT, __MAX_BPF_ATTACH_TYPE }; diff --git a/include/uapi/linux/bpf_hid.h b/include/uapi/linux/bpf_hid.h index 634f17c0b1cb..14a3c0405345 100644 --- a/include/uapi/linux/bpf_hid.h +++ b/include/uapi/linux/bpf_hid.h @@ -25,6 +25,12 @@ enum hid_bpf_event { HID_BPF_UNDEF = 0, HID_BPF_DEVICE_EVENT, /* when attach type is BPF_HID_DEVICE_EVENT */ HID_BPF_RDESC_FIXUP, /* ................... BPF_HID_RDESC_FIXUP */ + HID_BPF_USER_EVENT, /* ................... BPF_HID_USER_EVENT */ +}; + +/* type is HID_BPF_USER_EVENT */ +struct hid_bpf_ctx_user_event { + __s32 retval; }; struct hid_bpf_ctx { @@ -32,6 +38,10 @@ struct hid_bpf_ctx { __u16 allocated_size; /* the allocated size of data below (RO) */ struct hid_device *hdev; /* read-only */ + union { + struct hid_bpf_ctx_user_event user; /* read-write */ + } u; + __u16 size; /* used size in data (RW) */ __u8 data[]; /* data buffer (RW) */ }; diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index 640e55ba66ec..de003dbd7d01 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -370,6 +370,8 @@ static int bpf_hid_max_progs(enum bpf_hid_attach_type type) return 64; case BPF_HID_ATTACH_RDESC_FIXUP: return 1; + case BPF_HID_ATTACH_USER_EVENT: + return 64; default: return 0; } @@ -464,7 +466,121 @@ int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog) return bpf_link_settle(&link_primer); } +static int hid_bpf_prog_test_run(struct bpf_prog *prog, + const union bpf_attr *attr, + union bpf_attr __user *uattr) +{ + struct hid_device *hdev = NULL; + struct bpf_prog_array *progs; + struct hid_bpf_ctx *ctx = NULL; + bool valid_prog = false; + int i; + int target_fd, ret; + void __user *data_out = u64_to_user_ptr(attr->test.data_out); + void __user *data_in = u64_to_user_ptr(attr->test.data_in); + u32 user_size_in = attr->test.data_size_in; + u32 user_size_out = attr->test.data_size_out; + + if (!hid_hooks.hdev_from_fd) + return -EOPNOTSUPP; + + if (attr->test.ctx_size_in != sizeof(int)) + return -EINVAL; + + if (user_size_in > HID_BPF_MAX_BUFFER_SIZE) + return -E2BIG; + + if (copy_from_user(&target_fd, (void *)attr->test.ctx_in, attr->test.ctx_size_in)) + return -EFAULT; + + hdev = hid_hooks.hdev_from_fd(target_fd); + if (IS_ERR(hdev)) + return PTR_ERR(hdev); + + ret = mutex_lock_interruptible(&bpf_hid_mutex); + if (ret) + return ret; + + /* check if the given program is of correct type and registered */ + progs = rcu_dereference_protected(hdev->bpf.run_array[BPF_HID_ATTACH_USER_EVENT], + lockdep_is_held(&bpf_hid_mutex)); + if (!progs) { + ret = -EFAULT; + goto unlock; + } + + for (i = 0; i < bpf_prog_array_length(progs); i++) { + if (progs->items[i].prog == prog) { + valid_prog = true; + break; + } + } + + if (!valid_prog) { + ret = -EINVAL; + goto unlock; + } + + ctx = bpf_hid_allocate_ctx(hdev, max(user_size_in, user_size_out)); + if (IS_ERR(ctx)) { + ret = PTR_ERR(ctx); + goto unlock; + } + + ctx->type = HID_BPF_USER_EVENT; + + /* copy data_in from userspace */ + if (user_size_in) { + if (user_size_in > ctx->allocated_size) { + /* should never happen, given that size is < HID_BPF_MAX_BUFFER_SIZE */ + ret = -E2BIG; + goto unlock; + } + + if (copy_from_user(ctx->data, data_in, user_size_in)) { + ret = -EFAULT; + goto unlock; + } + + ctx->size = user_size_in; + } + + migrate_disable(); + + ret = bpf_prog_run(prog, ctx); + + migrate_enable(); + + if (user_size_out && data_out) { + user_size_out = min3(user_size_out, (u32)ctx->size, (u32)ctx->allocated_size); + + if (copy_to_user(data_out, ctx->data, user_size_out)) { + ret = -EFAULT; + goto unlock; + } + + if (copy_to_user(&uattr->test.data_size_out, + &user_size_out, + sizeof(user_size_out))) { + ret = -EFAULT; + goto unlock; + } + } + + if (copy_to_user(&uattr->test.retval, &ctx->u.user.retval, sizeof(ctx->u.user.retval))) { + ret = -EFAULT; + goto unlock; + } + +unlock: + kfree(ctx); + + mutex_unlock(&bpf_hid_mutex); + return ret; +} + const struct bpf_prog_ops hid_prog_ops = { + .test_run = hid_bpf_prog_test_run, }; int bpf_hid_init(struct hid_device *hdev) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 7428a1a512c6..74d13ec826df 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3204,6 +3204,7 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type) return BPF_PROG_TYPE_XDP; case BPF_HID_DEVICE_EVENT: case BPF_HID_RDESC_FIXUP: + case BPF_HID_USER_EVENT: return BPF_PROG_TYPE_HID; default: return BPF_PROG_TYPE_UNSPEC; @@ -3350,6 +3351,7 @@ static int bpf_prog_query(const union bpf_attr *attr, return sock_map_bpf_prog_query(attr, uattr); case BPF_HID_DEVICE_EVENT: case BPF_HID_RDESC_FIXUP: + case BPF_HID_USER_EVENT: return bpf_hid_prog_query(attr, uattr); default: return -EINVAL; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 4845a20e6f96..b3063384d380 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1000,6 +1000,7 @@ enum bpf_attach_type { BPF_PERF_EVENT, BPF_HID_DEVICE_EVENT, BPF_HID_RDESC_FIXUP, + BPF_HID_USER_EVENT, __MAX_BPF_ATTACH_TYPE }; From patchwork Fri Mar 4 17:28:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769617 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C1B1C4332F for ; Fri, 4 Mar 2022 17:34:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241263AbiCDRew (ORCPT ); Fri, 4 Mar 2022 12:34:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241285AbiCDRe2 (ORCPT ); Fri, 4 Mar 2022 12:34:28 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D7A89BBE3A for ; Fri, 4 Mar 2022 09:33:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415213; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dC7k1be6lN3cUaIIjd9MGG1pPTUoElV+YfwqD2h91kQ=; b=QPgF3lulLv5QToUlBIyIIWL5CsP8oL7iiAdFv7LnGl/h/meYrmsPU+sObe1Dmle7IFHAfC Aact2fz7RFPlO9YNYV2NxPkKoqnQfKAwhUJURi1SovlPv9xy+EV59h7OxN2X1wIJeDAbde t+N0G0xRS1MH602Cay4Zh16nmgBDtpc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-201-sv4bWhGgNK-1YtHveq57fA-1; Fri, 04 Mar 2022 12:33:30 -0500 X-MC-Unique: sv4bWhGgNK-1YtHveq57fA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 83A2D8031E1; Fri, 4 Mar 2022 17:33:27 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3876686595; Fri, 4 Mar 2022 17:33:05 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 16/28] libbpf: add new attach type BPF_HID_USER_EVENT Date: Fri, 4 Mar 2022 18:28:40 +0100 Message-Id: <20220304172852.274126-17-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Adds the SEC definiton for the user callbacks of HID bpf. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/lib/bpf/libbpf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 192ef3901251..d1e305f760bb 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -8682,6 +8682,7 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("sk_lookup", SK_LOOKUP, BPF_SK_LOOKUP, SEC_ATTACHABLE | SEC_SLOPPY_PFX), SEC_DEF("hid/device_event", HID, BPF_HID_DEVICE_EVENT, SEC_ATTACHABLE_OPT | SEC_SLOPPY_PFX), SEC_DEF("hid/rdesc_fixup", HID, BPF_HID_RDESC_FIXUP, SEC_ATTACHABLE_OPT | SEC_SLOPPY_PFX), + SEC_DEF("hid/user_event", HID, BPF_HID_USER_EVENT, SEC_ATTACHABLE_OPT | SEC_SLOPPY_PFX), }; #define MAX_TYPE_NAME_SIZE 32 From patchwork Fri Mar 4 17:28:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769618 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 62175C433EF for ; Fri, 4 Mar 2022 17:34:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234731AbiCDRe4 (ORCPT ); Fri, 4 Mar 2022 12:34:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48164 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241311AbiCDRec (ORCPT ); Fri, 4 Mar 2022 12:34:32 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 5D8D8E38B3 for ; Fri, 4 Mar 2022 09:33:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415217; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ipdlvVgLqb/o8JixuAcNZBiqSMV+zn+7l3KEEPsCPfk=; b=QD+8kYJ8f1Bzxc0QjB5cVekFo2R1NXnQGElg5rZQBQ5CC4oTNC8dXN735YUZ0xIh+yOhNc bFY/f5hFFlFfw4E2bdXG3h42dm2TfZ28tg8hSWHLWwkTMdOCYOAydFc1RE28Qjr+Z7jr1n qTL5Hm4nRekiZDh4uv9i4ZPj3CnyUBs= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-251-1_tlnEw-PxaPkP19iknvew-1; Fri, 04 Mar 2022 12:33:34 -0500 X-MC-Unique: 1_tlnEw-PxaPkP19iknvew-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B7CDB18766D0; Fri, 4 Mar 2022 17:33:31 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id D402686595; Fri, 4 Mar 2022 17:33:27 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 17/28] selftests/bpf: add test for user call of HID bpf programs Date: Fri, 4 Mar 2022 18:28:41 +0100 Message-Id: <20220304172852.274126-18-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Add a simple test to see if we can trigger a bpf program of type "hid/user_event". Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/testing/selftests/bpf/prog_tests/hid.c | 56 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/hid.c | 10 ++++ 2 files changed, 66 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c index 74426523dd6f..eb4c0d0a4666 100644 --- a/tools/testing/selftests/bpf/prog_tests/hid.c +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -359,6 +359,59 @@ static int test_hid_set_get_data(struct hid *hid_skel, int uhid_fd, int sysfs_fd return ret; } +/* + * Attach hid_user to the given uhid device, + * call the bpf program from userspace + * check that the program is called and does the expected. + */ +static int test_hid_user_call(struct hid *hid_skel, int uhid_fd, int sysfs_fd) +{ + int err, prog_fd; + u8 buf[10] = {0}; + int ret = -1; + + LIBBPF_OPTS(bpf_test_run_opts, run_attrs, + .repeat = 1, + .ctx_in = &sysfs_fd, + .ctx_size_in = sizeof(sysfs_fd), + .data_in = buf, + .data_size_in = sizeof(buf), + .data_out = buf, + .data_size_out = sizeof(buf), + ); + + /* attach hid_user program */ + hid_skel->links.hid_user = bpf_program__attach_hid(hid_skel->progs.hid_user, sysfs_fd); + if (!ASSERT_OK_PTR(hid_skel->links.hid_user, + "attach_hid(hid_user)")) + return PTR_ERR(hid_skel->links.hid_user); + + buf[0] = 39; + + prog_fd = bpf_program__fd(hid_skel->progs.hid_user); + + err = bpf_prog_test_run_opts(prog_fd, &run_attrs); + if (!ASSERT_EQ(err, 0, "bpf_prog_test_run_xattr")) + goto cleanup; + + if (!ASSERT_EQ(run_attrs.retval, 72, "bpf_prog_test_run_opts")) + goto cleanup; + + if (!ASSERT_EQ(buf[1], 42, "hid_user_check_in")) + goto cleanup; + + if (!ASSERT_EQ(buf[2], 4, "hid_user_check_static_out")) + goto cleanup; + + ret = 0; + +cleanup: + + hid__detach(hid_skel); + + return ret; +} + /* * Attach hid_rdesc_fixup to the given uhid device, * retrieve and open the matching hidraw node, @@ -460,6 +513,9 @@ void serial_test_hid_bpf(void) err = test_hid_set_get_data(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_set_get_data"); + err = test_hid_user_call(hid_skel, uhid_fd, sysfs_fd); + ASSERT_OK(err, "hid_user"); + err = test_rdesc_fixup(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_rdesc_fixup"); diff --git a/tools/testing/selftests/bpf/progs/hid.c b/tools/testing/selftests/bpf/progs/hid.c index de6668471940..fabfaf0f2526 100644 --- a/tools/testing/selftests/bpf/progs/hid.c +++ b/tools/testing/selftests/bpf/progs/hid.c @@ -111,3 +111,13 @@ int hid_set_get_data(struct hid_bpf_ctx *ctx) return ret; } + +SEC("hid/user_event") +int hid_user(struct hid_bpf_ctx *ctx) +{ + ctx->data[1] = ctx->data[0] + 3; + ctx->data[2] = 4; + ctx->u.user.retval = 72; + + return 0; +} From patchwork Fri Mar 4 17:28:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769619 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD80EC4332F for ; Fri, 4 Mar 2022 17:34:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241360AbiCDRfQ (ORCPT ); Fri, 4 Mar 2022 12:35:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241255AbiCDRei (ORCPT ); Fri, 4 Mar 2022 12:34:38 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id CCA7715723D for ; Fri, 4 Mar 2022 09:33:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415221; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pDa8V+PwdBzLVKm2f7jt5tKntZYRCDbywdKX+LuGF8o=; b=QcyDkkhKlBiD53auiMeSdQT3C+S7oHiozXtxAa46eGkv3EfJ7UpSRIoFPR7B68veilbDUt Ob9E9okCqsfLkbpprpeOzXYO4rF6+dgK4FcFXzc5QZPt5fXEG2/r1amMIZNoM8sp9ubUPo 6zz7wMy30Uf5DzEVrFWfBIWHFH62Og8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-381-MRXFdnLJOSycTbX4FoI6Hg-1; Fri, 04 Mar 2022 12:33:38 -0500 X-MC-Unique: MRXFdnLJOSycTbX4FoI6Hg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0162E1006AA7; Fri, 4 Mar 2022 17:33:36 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1722186595; Fri, 4 Mar 2022 17:33:31 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 18/28] selftests/bpf: hid: rely on uhid event to know if a test device is ready Date: Fri, 4 Mar 2022 18:28:42 +0100 Message-Id: <20220304172852.274126-19-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net We need this for 2 reasons: - first we remove the ugly sleeps - then when we try to communicate with the device, we need to have another thread that handles that communication and simulate a real device Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/testing/selftests/bpf/prog_tests/hid.c | 126 ++++++++++++++++++- 1 file changed, 120 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c index eb4c0d0a4666..cc01601c1168 100644 --- a/tools/testing/selftests/bpf/prog_tests/hid.c +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -67,6 +67,12 @@ static unsigned char rdesc[] = { 0xc0, /* END_COLLECTION */ }; +static pthread_mutex_t uhid_started_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t uhid_started = PTHREAD_COND_INITIALIZER; + +/* no need to protect uhid_stopped, only one thread accesses it */ +static bool uhid_stopped; + static int uhid_write(int fd, const struct uhid_event *ev) { ssize_t ret; @@ -118,6 +124,104 @@ static void destroy(int fd) uhid_write(fd, &ev); } +static int event(int fd) +{ + struct uhid_event ev; + ssize_t ret; + + memset(&ev, 0, sizeof(ev)); + ret = read(fd, &ev, sizeof(ev)); + if (ret == 0) { + fprintf(stderr, "Read HUP on uhid-cdev\n"); + return -EFAULT; + } else if (ret < 0) { + fprintf(stderr, "Cannot read uhid-cdev: %m\n"); + return -errno; + } else if (ret != sizeof(ev)) { + fprintf(stderr, "Invalid size read from uhid-dev: %zd != %zu\n", + ret, sizeof(ev)); + return -EFAULT; + } + + switch (ev.type) { + case UHID_START: + pthread_mutex_lock(&uhid_started_mtx); + pthread_cond_signal(&uhid_started); + pthread_mutex_unlock(&uhid_started_mtx); + + fprintf(stderr, "UHID_START from uhid-dev\n"); + break; + case UHID_STOP: + uhid_stopped = true; + + fprintf(stderr, "UHID_STOP from uhid-dev\n"); + break; + case UHID_OPEN: + fprintf(stderr, "UHID_OPEN from uhid-dev\n"); + break; + case UHID_CLOSE: + fprintf(stderr, "UHID_CLOSE from uhid-dev\n"); + break; + case UHID_OUTPUT: + fprintf(stderr, "UHID_OUTPUT from uhid-dev\n"); + break; + case UHID_GET_REPORT: + fprintf(stderr, "UHID_GET_REPORT from uhid-dev\n"); + break; + case UHID_SET_REPORT: + fprintf(stderr, "UHID_SET_REPORT from uhid-dev\n"); + break; + default: + fprintf(stderr, "Invalid event from uhid-dev: %u\n", ev.type); + } + + return 0; +} + +static void *read_uhid_events_thread(void *arg) +{ + int fd = *(int *)arg; + struct pollfd pfds[1]; + int ret = 0; + + pfds[0].fd = fd; + pfds[0].events = POLLIN; + + uhid_stopped = false; + + while (!uhid_stopped) { + ret = poll(pfds, 1, 100); + if (ret < 0) { + fprintf(stderr, "Cannot poll for fds: %m\n"); + break; + } + if (pfds[0].revents & POLLIN) { + ret = event(fd); + if (ret) + break; + } + } + + return (void *)(long)ret; +} + +static int uhid_start_listener(pthread_t *tid, int uhid_fd) +{ + int fd = uhid_fd; + + pthread_mutex_lock(&uhid_started_mtx); + if (CHECK_FAIL(pthread_create(tid, NULL, read_uhid_events_thread, + (void *)&fd))) { + pthread_mutex_unlock(&uhid_started_mtx); + close(fd); + return -EIO; + } + pthread_cond_wait(&uhid_started, &uhid_started_mtx); + pthread_mutex_unlock(&uhid_started_mtx); + + return 0; +} + static int send_event(int fd, u8 *buf, size_t size) { struct uhid_event ev; @@ -422,7 +526,9 @@ static int test_rdesc_fixup(struct hid *hid_skel, int uhid_fd, int sysfs_fd) struct hidraw_report_descriptor rpt_desc = {0}; int err, desc_size, hidraw_ino, hidraw_fd = -1; char hidraw_path[64] = {0}; + void *uhid_err; int ret = -1; + pthread_t tid; /* attach the program */ hid_skel->links.hid_rdesc_fixup = @@ -431,9 +537,8 @@ static int test_rdesc_fixup(struct hid *hid_skel, int uhid_fd, int sysfs_fd) "attach_hid(hid_rdesc_fixup)")) return PTR_ERR(hid_skel->links.hid_rdesc_fixup); - /* give a little bit of time for the device to appear */ - /* TODO: check on uhid events */ - usleep(1000); + err = uhid_start_listener(&tid, uhid_fd); + ASSERT_OK(err, "uhid_start_listener"); hidraw_ino = get_hidraw(hid_skel->links.hid_rdesc_fixup); if (!ASSERT_GE(hidraw_ino, 0, "get_hidraw")) @@ -474,6 +579,10 @@ static int test_rdesc_fixup(struct hid *hid_skel, int uhid_fd, int sysfs_fd) hid__detach(hid_skel); + pthread_join(tid, &uhid_err); + err = (int)(long)uhid_err; + CHECK_FAIL(err); + return ret; } @@ -481,7 +590,9 @@ void serial_test_hid_bpf(void) { struct hid *hid_skel = NULL; int err, uhid_fd, sysfs_fd; + void *uhid_err; time_t t; + pthread_t tid; int rand_nb; /* initialize random number generator */ @@ -493,9 +604,8 @@ void serial_test_hid_bpf(void) if (!ASSERT_GE(uhid_fd, 0, "setup uhid")) return; - /* give a little bit of time for the device to appear */ - /* TODO: check on uhid events */ - usleep(1000); + err = uhid_start_listener(&tid, uhid_fd); + ASSERT_OK(err, "uhid_start_listener"); /* locate the uevent file of the created device */ sysfs_fd = get_sysfs_fd(rand_nb); @@ -522,4 +632,8 @@ void serial_test_hid_bpf(void) cleanup: hid__destroy(hid_skel); destroy(uhid_fd); + + pthread_join(tid, &uhid_err); + err = (int)(long)uhid_err; + CHECK_FAIL(err); } From patchwork Fri Mar 4 17:28:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769642 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2394C433EF for ; Fri, 4 Mar 2022 17:35:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241349AbiCDRft (ORCPT ); Fri, 4 Mar 2022 12:35:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48922 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241393AbiCDRfR (ORCPT ); Fri, 4 Mar 2022 12:35:17 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 41D941D21F8 for ; Fri, 4 Mar 2022 09:34:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6gple0WPBUTESb5NzCZwiTEsdsSCzabkmqhh6wKvZG0=; b=PJrJnQ61yVIMxErFmFEmm7l8Gv8PDcjjM431BTcOylyYcjpkf9lYAT31qdRz/6PzslLmX3 jQOilvWraA9vDmEGr3IeB2qFH/fjzFUt9TGw9evjXqwTBF+RQZ59EE5idpQtA6m6ebANg6 /FJ/15v1RfEO5Jt+ytIoASgO/JmQJeo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-643-s2olJurQOcWQo2M85ZZEbQ-1; Fri, 04 Mar 2022 12:34:05 -0500 X-MC-Unique: s2olJurQOcWQo2M85ZZEbQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BE03E18766D0; Fri, 4 Mar 2022 17:34:02 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 50CC686596; Fri, 4 Mar 2022 17:33:36 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 19/28] bpf/hid: add bpf_hid_raw_request helper function Date: Fri, 4 Mar 2022 18:28:43 +0100 Message-Id: <20220304172852.274126-20-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net When we are in a user_event context, we can talk to the device to fetch or set features/outputs/inputs reports. Add a bpf helper to do so. This helper is thus only available to user_events, because calling this function while in IRQ context (any other BPF type) is forbidden. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- include/linux/bpf-hid.h | 2 ++ include/uapi/linux/bpf.h | 8 ++++++++ kernel/bpf/hid.c | 26 ++++++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 8 ++++++++ 4 files changed, 44 insertions(+) diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h index 4cf2e99109fe..bd548f6a4a26 100644 --- a/include/linux/bpf-hid.h +++ b/include/linux/bpf-hid.h @@ -100,6 +100,8 @@ struct bpf_hid_hooks { u64 offset, u32 n, u8 *data, u64 data_size); int (*hid_set_data)(struct hid_device *hdev, u8 *buf, size_t buf_size, u64 offset, u32 n, u8 *data, u64 data_size); + int (*hid_raw_request)(struct hid_device *hdev, u8 *buf, size_t size, + u8 rtype, u8 reqtype); }; #ifdef CONFIG_BPF diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index b3063384d380..417cf1c31579 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5121,6 +5121,13 @@ union bpf_attr { * Return * The length of data copied into ctx->event.data. On error, a negative * value is returned. + * + * int bpf_hid_raw_request(void *ctx, void *buf, u64 size, u8 rtype, u8 reqtype) + * Description + * communicate with the HID device + * Return + * 0 on success. + * negative value on error. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5317,6 +5324,7 @@ union bpf_attr { FN(copy_from_user_task), \ FN(hid_get_data), \ FN(hid_set_data), \ + FN(hid_raw_request), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index de003dbd7d01..653d10c0f4e6 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -86,6 +86,28 @@ static const struct bpf_func_proto bpf_hid_set_data_proto = { .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; +BPF_CALL_5(bpf_hid_raw_request, void*, ctx, void*, buf, u64, size, + u8, rtype, u8, reqtype) +{ + struct hid_bpf_ctx *bpf_ctx = ctx; + + if (!hid_hooks.hid_raw_request) + return -EOPNOTSUPP; + + return hid_hooks.hid_raw_request(bpf_ctx->hdev, buf, size, rtype, reqtype); +} + +static const struct bpf_func_proto bpf_hid_raw_request_proto = { + .func = bpf_hid_raw_request, + .gpl_only = true, /* hid_raw_request is EXPORT_SYMBOL_GPL */ + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_CONST_SIZE_OR_ZERO, + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, +}; + static const struct bpf_func_proto * hid_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { @@ -94,6 +116,10 @@ hid_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_hid_get_data_proto; case BPF_FUNC_hid_set_data: return &bpf_hid_set_data_proto; + case BPF_FUNC_hid_raw_request: + if (prog->expected_attach_type != BPF_HID_DEVICE_EVENT) + return &bpf_hid_raw_request_proto; + return NULL; default: return bpf_base_func_proto(func_id); } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index b3063384d380..417cf1c31579 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5121,6 +5121,13 @@ union bpf_attr { * Return * The length of data copied into ctx->event.data. On error, a negative * value is returned. + * + * int bpf_hid_raw_request(void *ctx, void *buf, u64 size, u8 rtype, u8 reqtype) + * Description + * communicate with the HID device + * Return + * 0 on success. + * negative value on error. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5317,6 +5324,7 @@ union bpf_attr { FN(copy_from_user_task), \ FN(hid_get_data), \ FN(hid_set_data), \ + FN(hid_raw_request), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper From patchwork Fri Mar 4 17:28:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769644 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A24FBC433FE for ; Fri, 4 Mar 2022 17:35:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235857AbiCDRfy (ORCPT ); Fri, 4 Mar 2022 12:35:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46010 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239039AbiCDRfm (ORCPT ); Fri, 4 Mar 2022 12:35:42 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 79B75C4285 for ; Fri, 4 Mar 2022 09:34:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415252; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4uaRcXJGT7eJtc1mwhxALaaVlywKZULlCyjWv5ugIh0=; b=OY2m3QKHXDPIg/B3DzPniCv+YLvqKuj+MEztUnOaESSH4vliScrRKiwrerBhKyPKtkLNW4 wOUze/SsCXZVTwC4e86Qq6SmmvUcE3aJXlfl3H/0kCRdtz0obLDZUEpSL+ml8iqUew7wog NBxnurscjYaFALF01Jb4Kkf7JqTT3U0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-623-0XfFFxquOmClpCb5GaO1Kw-1; Fri, 04 Mar 2022 12:34:09 -0500 X-MC-Unique: 0XfFFxquOmClpCb5GaO1Kw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id ED6331091DA0; Fri, 4 Mar 2022 17:34:06 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1DBA6865A4; Fri, 4 Mar 2022 17:34:02 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 20/28] HID: add implementation of bpf_hid_raw_request Date: Fri, 4 Mar 2022 18:28:44 +0100 Message-Id: <20220304172852.274126-21-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Hook up BPF to hid_hw_raw_request. Not much to report here except that we need to export hid_get_report from hid-core so it gets available in hid-bpf.c Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- drivers/hid/hid-bpf.c | 63 ++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-core.c | 3 +- include/linux/hid.h | 1 + 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-bpf.c b/drivers/hid/hid-bpf.c index 8ae247fba5bc..b8c0060f3180 100644 --- a/drivers/hid/hid-bpf.c +++ b/drivers/hid/hid-bpf.c @@ -171,6 +171,68 @@ int hid_bpf_set_data(struct hid_device *hdev, u8 *buf, size_t buf_size, u64 offs return n; } +int hid_bpf_raw_request(struct hid_device *hdev, u8 *buf, size_t size, + u8 rtype, u8 reqtype) +{ + struct hid_report *report; + struct hid_report_enum *report_enum; + u8 *dma_data; + u32 report_len; + int ret; + + /* check arguments */ + switch (rtype) { + case HID_INPUT_REPORT: + case HID_OUTPUT_REPORT: + case HID_FEATURE_REPORT: + break; + default: + return -EINVAL; + } + + switch (reqtype) { + case HID_REQ_GET_REPORT: + case HID_REQ_GET_IDLE: + case HID_REQ_GET_PROTOCOL: + case HID_REQ_SET_REPORT: + case HID_REQ_SET_IDLE: + case HID_REQ_SET_PROTOCOL: + break; + default: + return -EINVAL; + } + + if (size < 1) + return -EINVAL; + + report_enum = hdev->report_enum + rtype; + report = hid_get_report(report_enum, buf); + if (!report) + return -EINVAL; + + report_len = hid_report_len(report); + + if (size > report_len) + size = report_len; + + dma_data = kmemdup(buf, size, GFP_KERNEL); + if (!dma_data) + return -ENOMEM; + + ret = hid_hw_raw_request(hdev, + dma_data[0], + dma_data, + size, + rtype, + reqtype); + + if (ret > 0) + memcpy(buf, dma_data, ret); + + kfree(dma_data); + return ret; +} + static int hid_bpf_run_progs(struct hid_device *hdev, enum bpf_hid_attach_type type, struct hid_bpf_ctx *ctx, u8 *data, int size) { @@ -272,6 +334,7 @@ int __init hid_bpf_module_init(void) .array_detached = hid_bpf_array_detached, .hid_get_data = hid_bpf_get_data, .hid_set_data = hid_bpf_set_data, + .hid_raw_request = hid_bpf_raw_request, }; bpf_hid_set_hooks(&hooks); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d3f4499ee4cd..d0e015986e17 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1686,8 +1686,7 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) } EXPORT_SYMBOL_GPL(hid_set_field); -static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, - const u8 *data) +struct hid_report *hid_get_report(struct hid_report_enum *report_enum, const u8 *data) { struct hid_report *report; unsigned int n = 0; /* Normally report number is 0 */ diff --git a/include/linux/hid.h b/include/linux/hid.h index 7454e844324c..b2698df31e5b 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -946,6 +946,7 @@ __u32 hid_field_extract(const struct hid_device *hid, __u8 *report, unsigned offset, unsigned n); void implement(const struct hid_device *hid, u8 *report, unsigned int offset, unsigned int n, u32 value); +struct hid_report *hid_get_report(struct hid_report_enum *report_enum, const u8 *data); #ifdef CONFIG_PM int hid_driver_suspend(struct hid_device *hdev, pm_message_t state); From patchwork Fri Mar 4 17:28:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769643 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6780FC433FE for ; Fri, 4 Mar 2022 17:35:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239338AbiCDRfw (ORCPT ); Fri, 4 Mar 2022 12:35:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46158 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240995AbiCDRfn (ORCPT ); Fri, 4 Mar 2022 12:35:43 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 30C68E3383 for ; Fri, 4 Mar 2022 09:34:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415257; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WrwFvawmGNYLjBbdBaVrUJ4+1AcvrT1rP+FxAAGD/3Y=; b=RqGrJILTPB5xOkYnnbsuQSwx3muM0wgFm3HPOeERatqRoQvoKstUN36WKG3VTTFRb76UCL BQguTZ1KOKSzSkanAuoXoIHRLYD2GQwgOcHk5NFw3AttsQFvLHwsQPrq36EpyA1RogYfs1 AMqsEDd50xUgghnRqrmA/3Tq5LD5qDo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-408-piTcRwObNu6k0pucFk9asw-1; Fri, 04 Mar 2022 12:34:13 -0500 X-MC-Unique: piTcRwObNu6k0pucFk9asw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 47AB3824FA6; Fri, 4 Mar 2022 17:34:11 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 45500865A7; Fri, 4 Mar 2022 17:34:07 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 21/28] selftests/bpf: add tests for bpf_hid_hw_request Date: Fri, 4 Mar 2022 18:28:45 +0100 Message-Id: <20220304172852.274126-22-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Add tests for the newly implemented function. We test here only the GET_REPORT part because the other calls are pure HID protocol and won't infer the result of the test of the bpf hook. Signed-off-by: Benjamin Tissoires --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples --- tools/testing/selftests/bpf/prog_tests/hid.c | 71 +++++++++++++++++++- tools/testing/selftests/bpf/progs/hid.c | 57 ++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c index cc01601c1168..a2bab6a799a1 100644 --- a/tools/testing/selftests/bpf/prog_tests/hid.c +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -67,6 +67,8 @@ static unsigned char rdesc[] = { 0xc0, /* END_COLLECTION */ }; +static u8 feature_data[] = { 1, 2 }; + static pthread_mutex_t uhid_started_mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t uhid_started = PTHREAD_COND_INITIALIZER; @@ -126,7 +128,7 @@ static void destroy(int fd) static int event(int fd) { - struct uhid_event ev; + struct uhid_event ev, answer; ssize_t ret; memset(&ev, 0, sizeof(ev)); @@ -143,6 +145,8 @@ static int event(int fd) return -EFAULT; } + memset(&answer, 0, sizeof(answer)); + switch (ev.type) { case UHID_START: pthread_mutex_lock(&uhid_started_mtx); @@ -167,6 +171,15 @@ static int event(int fd) break; case UHID_GET_REPORT: fprintf(stderr, "UHID_GET_REPORT from uhid-dev\n"); + + answer.type = UHID_GET_REPORT_REPLY; + answer.u.get_report_reply.id = ev.u.get_report.id; + answer.u.get_report_reply.err = ev.u.get_report.rnum == 1 ? 0 : -EIO; + answer.u.get_report_reply.size = sizeof(feature_data); + memcpy(answer.u.get_report_reply.data, feature_data, sizeof(feature_data)); + + uhid_write(fd, &answer); + break; case UHID_SET_REPORT: fprintf(stderr, "UHID_SET_REPORT from uhid-dev\n"); @@ -516,6 +529,59 @@ static int test_hid_user_call(struct hid *hid_skel, int uhid_fd, int sysfs_fd) return ret; } +/* + * Attach hid_user_raw_request to the given uhid device, + * call the bpf program from userspace + * check that the program is called and does the expected. + */ +static int test_hid_user_raw_request_call(struct hid *hid_skel, int uhid_fd, int sysfs_fd) +{ + int err, prog_fd; + u8 buf[10] = {0}; + int ret = -1; + + LIBBPF_OPTS(bpf_test_run_opts, run_attrs, + .repeat = 1, + .ctx_in = &sysfs_fd, + .ctx_size_in = sizeof(sysfs_fd), + .data_in = buf, + .data_size_in = sizeof(buf), + .data_out = buf, + .data_size_out = sizeof(buf), + ); + + /* attach hid_user_raw_request program */ + hid_skel->links.hid_user_raw_request = + bpf_program__attach_hid(hid_skel->progs.hid_user_raw_request, sysfs_fd); + if (!ASSERT_OK_PTR(hid_skel->links.hid_user_raw_request, + "attach_hid(hid_user_raw_request)")) + return PTR_ERR(hid_skel->links.hid_user_raw_request); + + buf[0] = 2; /* HID_FEATURE_REPORT */ + buf[1] = 1; /* HID_REQ_GET_REPORT */ + buf[2] = 1; /* report ID */ + + prog_fd = bpf_program__fd(hid_skel->progs.hid_user_raw_request); + + err = bpf_prog_test_run_opts(prog_fd, &run_attrs); + if (!ASSERT_EQ(err, 0, "bpf_prog_test_run_xattr")) + goto cleanup; + + if (!ASSERT_EQ(run_attrs.retval, 2, "bpf_prog_test_run_xattr_retval")) + goto cleanup; + + if (!ASSERT_EQ(buf[3], 2, "hid_user_raw_request_check_in")) + goto cleanup; + + ret = 0; + +cleanup: + + hid__detach(hid_skel); + + return ret; +} + /* * Attach hid_rdesc_fixup to the given uhid device, * retrieve and open the matching hidraw node, @@ -626,6 +692,9 @@ void serial_test_hid_bpf(void) err = test_hid_user_call(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_user"); + err = test_hid_user_raw_request_call(hid_skel, uhid_fd, sysfs_fd); + ASSERT_OK(err, "hid_user_raw_request"); + err = test_rdesc_fixup(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_rdesc_fixup"); diff --git a/tools/testing/selftests/bpf/progs/hid.c b/tools/testing/selftests/bpf/progs/hid.c index fabfaf0f2526..ea011ff9e752 100644 --- a/tools/testing/selftests/bpf/progs/hid.c +++ b/tools/testing/selftests/bpf/progs/hid.c @@ -9,6 +9,11 @@ char _license[] SEC("license") = "GPL"; __u64 callback_check = 52; __u64 callback2_check = 52; +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 4096 * 64); +} ringbuf SEC(".maps"); + SEC("hid/device_event") int hid_first_event(struct hid_bpf_ctx *ctx) { @@ -121,3 +126,55 @@ int hid_user(struct hid_bpf_ctx *ctx) return 0; } + +SEC("hid/user_event") +int hid_user_raw_request(struct hid_bpf_ctx *ctx) +{ + const unsigned int buflen = 256; + const unsigned int _buflen = buflen * sizeof(__u8); + __u8 *buf; + int ret; + __u32 size; + __u8 rtype, reqtype; + + buf = bpf_ringbuf_reserve(&ringbuf, _buflen, 0); + if (!buf) + return -12; /* -ENOMEM */ + + __builtin_memcpy(buf, ctx->data, _buflen); + + /* + * build up a custom API for our needs: + * offset 0, size 1: report type + * offset 1, size 1: request type + * offset 2+: data + */ + rtype = buf[0]; + reqtype = buf[1]; + size = ctx->size - 2; + + if (size < _buflen - 2) { + ret = bpf_hid_raw_request(ctx, + &buf[2], + size, + rtype, + reqtype); + if (ret < 0) + goto discard; + } else { + ret = -7; /* -E2BIG */ + goto discard; + } + + __builtin_memcpy(&ctx->data[2], &buf[2], _buflen - 2); + + ctx->size = ret + 2; + ctx->u.user.retval = ret; + + ret = 0; + + discard: + bpf_ringbuf_discard(buf, 0); + + return ret; +} From patchwork Fri Mar 4 17:28:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769647 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5259C433EF for ; Fri, 4 Mar 2022 17:35:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240432AbiCDRgd (ORCPT ); Fri, 4 Mar 2022 12:36:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47250 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241373AbiCDRfv (ORCPT ); Fri, 4 Mar 2022 12:35:51 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 13CC21D085E for ; Fri, 4 Mar 2022 09:34:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hyjhRPbC8PoyGPK2vPUfa6keKBWHXHhBVk1iPd78sYA=; b=LX1oO7JnuAxTbQf7aKL+MChL5E/cgTMlyiVCaBSrQAe309tUYjzLUVwRvIopSWsVyecunC XE4TiJkgi+INgqffNczfIf4ZZ9GFn7KfdsavU8uPrxwAN0po6i7gU5DPequQ7XHLGECHLn K38dO5TqJlkaKQwbp1W3TSAzbLxfvdM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-640-SBCJqgcINg6uDPA-vRyA7w-1; Fri, 04 Mar 2022 12:34:29 -0500 X-MC-Unique: SBCJqgcINg6uDPA-vRyA7w-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 004E11006AAA; Fri, 4 Mar 2022 17:34:26 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9BCB286596; Fri, 4 Mar 2022 17:34:11 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 22/28] bpf/verifier: prevent non GPL programs to be loaded against HID Date: Fri, 4 Mar 2022 18:28:46 +0100 Message-Id: <20220304172852.274126-23-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net This is just to hammer the obvious because I suspect you can not already load a bpf HID program which is not GPL because all of the useful functions are GPL only. Anyway, this ensures that users are not tempted to bypass this requirement and will allow us to ship tested BPF programs in the kernel without having to aorry about the license. Signed-off-by: Benjamin Tissoires --- new in v2: - Note: I placed this statement in check_attach_btf_id() to be local to other similar checks (regarding LSM), however, I have no idea if this is the correct place. Please shout at me if it isn't. --- include/linux/bpf-hid.h | 8 ++++++++ kernel/bpf/hid.c | 12 ++++++++++++ kernel/bpf/verifier.c | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h index bd548f6a4a26..3da1d0ecb9be 100644 --- a/include/linux/bpf-hid.h +++ b/include/linux/bpf-hid.h @@ -2,6 +2,7 @@ #ifndef _BPF_HID_H #define _BPF_HID_H +#include #include #include #include @@ -71,6 +72,8 @@ int bpf_hid_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr); int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog); +int bpf_hid_verify_prog(struct bpf_verifier_log *vlog, + const struct bpf_prog *prog); #else static inline int bpf_hid_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) @@ -83,6 +86,11 @@ static inline int bpf_hid_link_create(const union bpf_attr *attr, { return -EOPNOTSUPP; } +static inline int bpf_hid_verify_prog(struct bpf_verifier_log *vlog, + const struct bpf_prog *prog) +{ + return -EOPNOTSUPP; +} #endif static inline bool bpf_hid_link_empty(struct bpf_hid *bpf, diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index 653d10c0f4e6..b3dc1cd37a3e 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -37,6 +37,18 @@ void bpf_hid_set_hooks(struct bpf_hid_hooks *hooks) } EXPORT_SYMBOL_GPL(bpf_hid_set_hooks); +int bpf_hid_verify_prog(struct bpf_verifier_log *vlog, + const struct bpf_prog *prog) +{ + if (!prog->gpl_compatible) { + bpf_log(vlog, + "HID programs must have a GPL compatible license\n"); + return -EINVAL; + } + + return 0; +} + BPF_CALL_5(bpf_hid_get_data, void*, ctx, u64, offset, u32, n, void*, data, u64, size) { struct hid_bpf_ctx *bpf_ctx = ctx; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a57db4b2803c..afec8fa1d674 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -14235,6 +14236,12 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) return check_struct_ops_btf_id(env); + if (prog->type == BPF_PROG_TYPE_HID) { + ret = bpf_hid_verify_prog(&env->log, prog); + if (ret < 0) + return ret; + } + if (prog->type != BPF_PROG_TYPE_TRACING && prog->type != BPF_PROG_TYPE_LSM && prog->type != BPF_PROG_TYPE_EXT) From patchwork Fri Mar 4 17:28:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769645 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B7FA2C433FE for ; Fri, 4 Mar 2022 17:35:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241398AbiCDRgZ (ORCPT ); Fri, 4 Mar 2022 12:36:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46024 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241250AbiCDRgR (ORCPT ); Fri, 4 Mar 2022 12:36:17 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E11F11D1780 for ; Fri, 4 Mar 2022 09:34:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415275; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6D49UDKOrGqHPDx4/UWVPGxY1Jg6fRi4v4NPaaelVcs=; b=REs4LvZQVmXvZ4E5QTyuszPIGSWDWZJYO9c/RMVmiIYpsOCcVtsCrqlEHB7iIe1UWXwF3s eD4MKYaI/DlrPjqQjzILv8+8EkybTxjHwU5+3GrD7CtFxtOMagnXAutswlIHmnAQaRx6Lm jP2lyw42GT1tteFREkGMomKslBRrFI4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-635-4zNjMA1AP86pw5KyP-IlSg-1; Fri, 04 Mar 2022 12:34:32 -0500 X-MC-Unique: 4zNjMA1AP86pw5KyP-IlSg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5AC7C5EF; Fri, 4 Mar 2022 17:34:30 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 50EE986595; Fri, 4 Mar 2022 17:34:26 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 23/28] HID: bpf: compute only the required buffer size for the device Date: Fri, 4 Mar 2022 18:28:47 +0100 Message-Id: <20220304172852.274126-24-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net There is no point in using 16 kB of memory if the device needs less for all of its reports (uwhich is usually the case). Signed-off-by: Benjamin Tissoires --- new in v2 --- drivers/hid/hid-bpf.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-bpf.c b/drivers/hid/hid-bpf.c index b8c0060f3180..d56fbad990ed 100644 --- a/drivers/hid/hid-bpf.c +++ b/drivers/hid/hid-bpf.c @@ -61,11 +61,24 @@ static int hid_reconnect(struct hid_device *hdev) static int hid_bpf_link_attach(struct hid_device *hdev, enum bpf_hid_attach_type type) { int err = 0; + unsigned int i, j, max_report_len = 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)); + } + } switch (type) { case BPF_HID_ATTACH_DEVICE_EVENT: if (!hdev->bpf.ctx) { - hdev->bpf.ctx = bpf_hid_allocate_ctx(hdev, HID_BPF_MAX_BUFFER_SIZE); + hdev->bpf.ctx = bpf_hid_allocate_ctx(hdev, max_report_len); if (IS_ERR(hdev->bpf.ctx)) { err = PTR_ERR(hdev->bpf.ctx); hdev->bpf.ctx = NULL; From patchwork Fri Mar 4 17:28:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769646 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DC8EC433FE for ; Fri, 4 Mar 2022 17:35:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241317AbiCDRg3 (ORCPT ); Fri, 4 Mar 2022 12:36:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241386AbiCDRgT (ORCPT ); Fri, 4 Mar 2022 12:36:19 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0257A1D3AC6 for ; Fri, 4 Mar 2022 09:34:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415280; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T7C9fiyEzdqJww9q8MHw/Ezwfh03XjAvosyY3fabJCA=; b=M+dmyIQzmX9GiSB/vjtqwani+gFsLf6ib8UR68aMfDsGxOH2/QXHmFsDj2oUYW66zhQRQw DwO19EsZ/Yqi6slCz9dDwDawq8yS/1kWV4YbC35LerkyW2qsju0iHeSahYu8b0d5uW3sxf DaNrKgQhTMq7THBTNG2kPNga9JtXiFc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-424-vDZVZTx9PuGg1UxPErrkZQ-1; Fri, 04 Mar 2022 12:34:37 -0500 X-MC-Unique: vDZVZTx9PuGg1UxPErrkZQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 98CE75EF; Fri, 4 Mar 2022 17:34:34 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id AAE9186595; Fri, 4 Mar 2022 17:34:30 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 24/28] HID: bpf: only call hid_bpf_raw_event() if a ctx is available Date: Fri, 4 Mar 2022 18:28:48 +0100 Message-Id: <20220304172852.274126-25-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net the context is allocated the first time a program of type DEVICE_EVENT is attached to the device. To not add too much jumps in the code for the general device handling, call hid_bpf_raw_event() only if we know that a program has been attached once during the life of the device. Signed-off-by: Benjamin Tissoires --- new in v2 --- drivers/hid/hid-core.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d0e015986e17..2b49f6064a40 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1751,10 +1751,13 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, u8 *cdata; int ret = 0; - data = hid_bpf_raw_event(hid, data, &size); - if (IS_ERR(data)) { - ret = PTR_ERR(data); - goto out; + /* we pre-test if ctx is available here to cut the calls at the earliest */ + if (hid->bpf.ctx) { + 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); From patchwork Fri Mar 4 17:28:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769648 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9BE33C433EF for ; Fri, 4 Mar 2022 17:35:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241331AbiCDRgl (ORCPT ); Fri, 4 Mar 2022 12:36:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46306 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241341AbiCDRgY (ORCPT ); Fri, 4 Mar 2022 12:36:24 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0150A1D3DB0 for ; Fri, 4 Mar 2022 09:34:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415287; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G/shJm1MeQ7S0DudVE/fEwfDM0MCEACLr6XHTMqvVM4=; b=VkXjanbAdVzsCIfdUK4xdjZU5/vIe0OAzr+P+2YeInQRR5PvbFXYPgsScHKu1iXuZbJoGF byJDBassDkOM5NVT65KP2EYzDv/HzcCV57UKvKaxbYITN/b9K5LN8itw26cyYVjMYywkiB i/uKt2uGEPxMM3AFS/bi2KFVKO+KVWw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-451-GhrcENtyOjS9MMXFgSLOeQ-1; Fri, 04 Mar 2022 12:34:41 -0500 X-MC-Unique: GhrcENtyOjS9MMXFgSLOeQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E877E824FA8; Fri, 4 Mar 2022 17:34:38 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id EA81886595; Fri, 4 Mar 2022 17:34:34 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 25/28] bpf/hid: Add a flag to add the program at the beginning of the list Date: Fri, 4 Mar 2022 18:28:49 +0100 Message-Id: <20220304172852.274126-26-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net When tracing the incoming events, if a bpf program is already loaded, the next bpf program will see the potentially changed data. Add a flag to BPF_LINK_CREATE that allows to chose the position of the inserted program: at the beginning or at the end. This way, we can have a tracing program that compare the raw event from the device and the transformed stream from all the other bpf programs. Signed-off-by: Benjamin Tissoires --- new in v2 --- include/uapi/linux/bpf.h | 10 ++++++++++ kernel/bpf/hid.c | 11 +++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 417cf1c31579..23ebe5e96d69 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1123,6 +1123,16 @@ enum bpf_link_type { */ #define BPF_F_XDP_HAS_FRAGS (1U << 5) +/* HID flag used in BPF_LINK_CREATE command + * + * NONE(default): The bpf program will be added at the tail of the list + * of existing bpf program for this type. + * + * BPF_F_INSERT_HEAD: The bpf program will be added at the beginning + * of the list of existing bpf program for this type.. + */ +#define BPF_F_INSERT_HEAD (1U << 0) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * the following extensions: * diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index b3dc1cd37a3e..141eb4169079 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -416,7 +416,7 @@ static int bpf_hid_max_progs(enum bpf_hid_attach_type type) } static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link, - enum bpf_hid_attach_type type) + enum bpf_hid_attach_type type, u32 flags) { struct bpf_hid_link *hid_link = container_of(link, struct bpf_hid_link, link); @@ -443,7 +443,10 @@ static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link, goto out_unlock; } - list_add_tail(&hid_link->node, &hdev->bpf.links[type]); + if (flags & BPF_F_INSERT_HEAD) + list_add(&hid_link->node, &hdev->bpf.links[type]); + else + list_add_tail(&hid_link->node, &hdev->bpf.links[type]); fill_prog_array(hdev, type, run_array); run_array = rcu_replace_pointer(hdev->bpf.run_array[type], run_array, @@ -467,7 +470,7 @@ int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog) struct hid_device *hdev; int err; - if (attr->link_create.flags || !hid_hooks.hdev_from_fd) + if ((attr->link_create.flags & ~BPF_F_INSERT_HEAD) || !hid_hooks.hdev_from_fd) return -EINVAL; type = attr->link_create.attach_type; @@ -495,7 +498,7 @@ int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog) return err; } - err = bpf_hid_link_attach(hdev, &hid_link->link, hid_type); + err = bpf_hid_link_attach(hdev, &hid_link->link, hid_type, attr->link_create.flags); if (err) { bpf_link_cleanup(&link_primer); return err; From patchwork Fri Mar 4 17:28:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769649 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 88B22C43217 for ; Fri, 4 Mar 2022 17:36:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241421AbiCDRgv (ORCPT ); Fri, 4 Mar 2022 12:36:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241268AbiCDRg0 (ORCPT ); Fri, 4 Mar 2022 12:36:26 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EFDBE4F9E2 for ; Fri, 4 Mar 2022 09:35:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415304; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=P4dsF2EhkFauEdp0HjjqmUlAUUQayYI3BzeDrS6IW5o=; b=UboHNQDsGgU0dhebtdjsi4+lIEYgzrisMwsPJR8NWLqeja/WHnpaWEV7yYkt2/WXe1xANY yPD2VP1+07Vvqsf81aZhBGKy5GRNxut8IU20G0xZMJb+kJw5DS22UAmdUzuakBG/w2CkQn V5zFJIlgZbkixldCMH6ucx/I+Q31/Oc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-425-XrAQH9HIPDG3yTSLSPEL1A-1; Fri, 04 Mar 2022 12:35:01 -0500 X-MC-Unique: XrAQH9HIPDG3yTSLSPEL1A-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7CD1E805EE5; Fri, 4 Mar 2022 17:34:58 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 45EE386595; Fri, 4 Mar 2022 17:34:39 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 26/28] libbpf: add handling for BPF_F_INSERT_HEAD in HID programs Date: Fri, 4 Mar 2022 18:28:50 +0100 Message-Id: <20220304172852.274126-27-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Export the newly created flag to libbpf. Signed-off-by: Benjamin Tissoires --- new in v2 --- tools/include/uapi/linux/bpf.h | 10 ++++++++++ tools/lib/bpf/libbpf.c | 17 +++++++++-------- tools/lib/bpf/libbpf.h | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 417cf1c31579..23ebe5e96d69 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1123,6 +1123,16 @@ enum bpf_link_type { */ #define BPF_F_XDP_HAS_FRAGS (1U << 5) +/* HID flag used in BPF_LINK_CREATE command + * + * NONE(default): The bpf program will be added at the tail of the list + * of existing bpf program for this type. + * + * BPF_F_INSERT_HEAD: The bpf program will be added at the beginning + * of the list of existing bpf program for this type.. + */ +#define BPF_F_INSERT_HEAD (1U << 0) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * the following extensions: * diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index d1e305f760bb..6f0cb6717207 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -10533,10 +10533,11 @@ static struct bpf_link *attach_lsm(const struct bpf_program *prog, long cookie) static struct bpf_link * bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id, - const char *target_name) + const char *target_name, __u32 flags) { DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts, - .target_btf_id = btf_id); + .target_btf_id = btf_id, + .flags = flags); enum bpf_attach_type attach_type; char errmsg[STRERR_BUFSIZE]; struct bpf_link *link; @@ -10570,19 +10571,19 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id struct bpf_link * bpf_program__attach_cgroup(const struct bpf_program *prog, int cgroup_fd) { - return bpf_program__attach_fd(prog, cgroup_fd, 0, "cgroup"); + return bpf_program__attach_fd(prog, cgroup_fd, 0, "cgroup", 0); } struct bpf_link * bpf_program__attach_netns(const struct bpf_program *prog, int netns_fd) { - return bpf_program__attach_fd(prog, netns_fd, 0, "netns"); + return bpf_program__attach_fd(prog, netns_fd, 0, "netns", 0); } struct bpf_link *bpf_program__attach_xdp(const struct bpf_program *prog, int ifindex) { /* target_fd/target_ifindex use the same field in LINK_CREATE */ - return bpf_program__attach_fd(prog, ifindex, 0, "xdp"); + return bpf_program__attach_fd(prog, ifindex, 0, "xdp", 0); } struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog, @@ -10608,7 +10609,7 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog, if (btf_id < 0) return libbpf_err_ptr(btf_id); - return bpf_program__attach_fd(prog, target_fd, btf_id, "freplace"); + return bpf_program__attach_fd(prog, target_fd, btf_id, "freplace", 0); } else { /* no target, so use raw_tracepoint_open for compatibility * with old kernels @@ -10663,9 +10664,9 @@ static struct bpf_link *attach_iter(const struct bpf_program *prog, long cookie) } struct bpf_link * -bpf_program__attach_hid(const struct bpf_program *prog, int hid_fd) +bpf_program__attach_hid(const struct bpf_program *prog, int hid_fd, __u32 flags) { - return bpf_program__attach_fd(prog, hid_fd, 0, "hid"); + return bpf_program__attach_fd(prog, hid_fd, 0, "hid", flags); } struct bpf_link *bpf_program__attach(const struct bpf_program *prog) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index f677ac0a9ede..65be3e2ec62d 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -530,7 +530,7 @@ LIBBPF_API struct bpf_link * bpf_program__attach_iter(const struct bpf_program *prog, const struct bpf_iter_attach_opts *opts); LIBBPF_API struct bpf_link * -bpf_program__attach_hid(const struct bpf_program *prog, int hid_fd); +bpf_program__attach_hid(const struct bpf_program *prog, int hid_fd, __u32 flags); /* * Libbpf allows callers to adjust BPF programs before being loaded From patchwork Fri Mar 4 17:28:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769651 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 30170C43217 for ; Fri, 4 Mar 2022 17:36:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241387AbiCDRg4 (ORCPT ); Fri, 4 Mar 2022 12:36:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46822 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241410AbiCDRg0 (ORCPT ); Fri, 4 Mar 2022 12:36:26 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DB9CFC4295 for ; Fri, 4 Mar 2022 09:35:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415309; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tSkkv8IlHvaGufTNbPlZ5hq4BEbTEZB+75KA4cY5Zt0=; b=f5yIfOo/oiLVSOcnQ4OwYls2eFWJ8jn9cJo7sqbagXsvkX/YBLrAMX40fT/43ACoG23hiU YlcnK87l+mVg21h8wn0P0vyjI0PgwDV3erOyUpMiNN63YIvK4qrI2iao2d1vu2mQR6tiK1 87Tn0RLd8ihsP/Cb0NdpOXXbX+RwRvY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-363-giQO_BOyOtWSB_hzw5-eSQ-1; Fri, 04 Mar 2022 12:35:05 -0500 X-MC-Unique: giQO_BOyOtWSB_hzw5-eSQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AE98F18766D0; Fri, 4 Mar 2022 17:35:02 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id CE57186595; Fri, 4 Mar 2022 17:34:58 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 27/28] selftests/bpf: Add a test for BPF_F_INSERT_HEAD Date: Fri, 4 Mar 2022 18:28:51 +0100 Message-Id: <20220304172852.274126-28-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Insert 3 programs to check that we are doing the correct thing: '2', '1', '3' are inserted, but '1' is supposed to be executed first. Signed-off-by: Benjamin Tissoires --- new in v2 --- tools/testing/selftests/bpf/prog_tests/hid.c | 90 ++++++++++++++++++-- tools/testing/selftests/bpf/progs/hid.c | 36 ++++++++ 2 files changed, 121 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/hid.c b/tools/testing/selftests/bpf/prog_tests/hid.c index a2bab6a799a1..f7fec748a0b9 100644 --- a/tools/testing/selftests/bpf/prog_tests/hid.c +++ b/tools/testing/selftests/bpf/prog_tests/hid.c @@ -353,7 +353,7 @@ static int test_hid_raw_event(struct hid *hid_skel, int uhid_fd, int sysfs_fd) /* attach the first program */ hid_skel->links.hid_first_event = - bpf_program__attach_hid(hid_skel->progs.hid_first_event, sysfs_fd); + bpf_program__attach_hid(hid_skel->progs.hid_first_event, sysfs_fd, 0); if (!ASSERT_OK_PTR(hid_skel->links.hid_first_event, "attach_hid(hid_first_event)")) return PTR_ERR(hid_skel->links.hid_first_event); @@ -429,7 +429,7 @@ static int test_hid_set_get_data(struct hid *hid_skel, int uhid_fd, int sysfs_fd /* attach hid_set_get_data program */ hid_skel->links.hid_set_get_data = - bpf_program__attach_hid(hid_skel->progs.hid_set_get_data, sysfs_fd); + bpf_program__attach_hid(hid_skel->progs.hid_set_get_data, sysfs_fd, 0); if (!ASSERT_OK_PTR(hid_skel->links.hid_set_get_data, "attach_hid(hid_set_get_data)")) return PTR_ERR(hid_skel->links.hid_set_get_data); @@ -498,7 +498,7 @@ static int test_hid_user_call(struct hid *hid_skel, int uhid_fd, int sysfs_fd) ); /* attach hid_user program */ - hid_skel->links.hid_user = bpf_program__attach_hid(hid_skel->progs.hid_user, sysfs_fd); + hid_skel->links.hid_user = bpf_program__attach_hid(hid_skel->progs.hid_user, sysfs_fd, 0); if (!ASSERT_OK_PTR(hid_skel->links.hid_user, "attach_hid(hid_user)")) return PTR_ERR(hid_skel->links.hid_user); @@ -552,7 +552,7 @@ static int test_hid_user_raw_request_call(struct hid *hid_skel, int uhid_fd, int /* attach hid_user_raw_request program */ hid_skel->links.hid_user_raw_request = - bpf_program__attach_hid(hid_skel->progs.hid_user_raw_request, sysfs_fd); + bpf_program__attach_hid(hid_skel->progs.hid_user_raw_request, sysfs_fd, 0); if (!ASSERT_OK_PTR(hid_skel->links.hid_user_raw_request, "attach_hid(hid_user_raw_request)")) return PTR_ERR(hid_skel->links.hid_user_raw_request); @@ -582,6 +582,83 @@ static int test_hid_user_raw_request_call(struct hid *hid_skel, int uhid_fd, int return ret; } +/* + * Attach hid_insert{0,1,2} to the given uhid device, + * retrieve and open the matching hidraw node, + * inject one event in the uhid device, + * check that the programs have been inserted in the correct order. + */ +static int test_hid_attach_flags(struct hid *hid_skel, int uhid_fd, int sysfs_fd) +{ + int err, hidraw_ino, hidraw_fd = -1; + char hidraw_path[64] = {0}; + u8 buf[10] = {0}; + int ret = -1; + + /* attach hid_test_insert2 program */ + hid_skel->links.hid_test_insert2 = + bpf_program__attach_hid(hid_skel->progs.hid_test_insert2, sysfs_fd, 0); + if (!ASSERT_OK_PTR(hid_skel->links.hid_test_insert2, + "attach_hid(hid_test_insert2)")) + return PTR_ERR(hid_skel->links.hid_test_insert2); + + /* then attach hid_test_insert1 program before the previous*/ + hid_skel->links.hid_test_insert1 = + bpf_program__attach_hid(hid_skel->progs.hid_test_insert1, + sysfs_fd, + BPF_F_INSERT_HEAD); + if (!ASSERT_OK_PTR(hid_skel->links.hid_test_insert1, + "attach_hid(hid_test_insert1)")) + return PTR_ERR(hid_skel->links.hid_test_insert1); + + /* finally attach hid_test_insert3 at the end */ + hid_skel->links.hid_test_insert3 = + bpf_program__attach_hid(hid_skel->progs.hid_test_insert3, sysfs_fd, 0); + if (!ASSERT_OK_PTR(hid_skel->links.hid_test_insert3, + "attach_hid(hid_test_insert3)")) + return PTR_ERR(hid_skel->links.hid_test_insert3); + + hidraw_ino = get_hidraw(hid_skel->links.hid_test_insert1); + if (!ASSERT_GE(hidraw_ino, 0, "get_hidraw")) + goto cleanup; + + /* open hidraw node to check the other side of the pipe */ + sprintf(hidraw_path, "/dev/hidraw%d", hidraw_ino); + hidraw_fd = open(hidraw_path, O_RDWR | O_NONBLOCK); + + if (!ASSERT_GE(hidraw_fd, 0, "open_hidraw")) + goto cleanup; + + /* inject one event */ + buf[0] = 1; + send_event(uhid_fd, buf, 6); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(hidraw_fd, buf, sizeof(buf)); + if (!ASSERT_EQ(err, 6, "read_hidraw")) + goto cleanup; + + if (!ASSERT_EQ(buf[1], 1, "hid_test_insert1")) + goto cleanup; + + if (!ASSERT_EQ(buf[2], 2, "hid_test_insert2")) + goto cleanup; + + if (!ASSERT_EQ(buf[3], 3, "hid_test_insert3")) + goto cleanup; + + ret = 0; + +cleanup: + if (hidraw_fd >= 0) + close(hidraw_fd); + + hid__detach(hid_skel); + + return ret; +} + /* * Attach hid_rdesc_fixup to the given uhid device, * retrieve and open the matching hidraw node, @@ -598,7 +675,7 @@ static int test_rdesc_fixup(struct hid *hid_skel, int uhid_fd, int sysfs_fd) /* attach the program */ hid_skel->links.hid_rdesc_fixup = - bpf_program__attach_hid(hid_skel->progs.hid_rdesc_fixup, sysfs_fd); + bpf_program__attach_hid(hid_skel->progs.hid_rdesc_fixup, sysfs_fd, 0); if (!ASSERT_OK_PTR(hid_skel->links.hid_rdesc_fixup, "attach_hid(hid_rdesc_fixup)")) return PTR_ERR(hid_skel->links.hid_rdesc_fixup); @@ -695,6 +772,9 @@ void serial_test_hid_bpf(void) err = test_hid_user_raw_request_call(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_user_raw_request"); + err = test_hid_attach_flags(hid_skel, uhid_fd, sysfs_fd); + ASSERT_OK(err, "hid_user_raw_request"); + err = test_rdesc_fixup(hid_skel, uhid_fd, sysfs_fd); ASSERT_OK(err, "hid_rdesc_fixup"); diff --git a/tools/testing/selftests/bpf/progs/hid.c b/tools/testing/selftests/bpf/progs/hid.c index ea011ff9e752..40161aa8cb6e 100644 --- a/tools/testing/selftests/bpf/progs/hid.c +++ b/tools/testing/selftests/bpf/progs/hid.c @@ -178,3 +178,39 @@ int hid_user_raw_request(struct hid_bpf_ctx *ctx) return ret; } + +SEC("hid/device_event") +int hid_test_insert1(struct hid_bpf_ctx *ctx) +{ + /* we need to be run first */ + if (ctx->data[2] || ctx->data[3]) + return -1; + + ctx->data[1] = 1; + + return 0; +} + +SEC("hid/device_event") +int hid_test_insert2(struct hid_bpf_ctx *ctx) +{ + /* after insert0 and before insert2 */ + if (!ctx->data[1] || ctx->data[3]) + return -1; + + ctx->data[2] = 2; + + return 0; +} + +SEC("hid/device_event") +int hid_test_insert3(struct hid_bpf_ctx *ctx) +{ + /* at the end */ + if (!ctx->data[1] || !ctx->data[2]) + return -1; + + ctx->data[3] = 3; + + return 0; +} From patchwork Fri Mar 4 17:28:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 12769650 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54B49C4332F for ; Fri, 4 Mar 2022 17:36:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241367AbiCDRgz (ORCPT ); Fri, 4 Mar 2022 12:36:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241372AbiCDRge (ORCPT ); Fri, 4 Mar 2022 12:36:34 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B72B51D21E1 for ; Fri, 4 Mar 2022 09:35:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646415317; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NgcKpbYcf2hi8vkeeDFW+llAZ4317MhJ4ll5aBH+/Nc=; b=NbBTL7qDSMD96vk8yqglIGrbhBg7Wi4lFtgAQrvDAMcYtUMxcE1oPIMMjbc+Myy2fNSC+X 2Zn1L72LTSdM/D9Dwb8WuxxPwpAVxEIKJ7EovfABpMZB/0or4C3RWOd5jlghfmCdx9b7Bm hPFBpd8lOt2y1rDcCCuw+1KLcFjsdW0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-117-DY3KTqRHNQ-zHvi72pqlHg-1; Fri, 04 Mar 2022 12:35:12 -0500 X-MC-Unique: DY3KTqRHNQ-zHvi72pqlHg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 333015EF; Fri, 4 Mar 2022 17:35:10 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0A8B886595; Fri, 4 Mar 2022 17:35:02 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Shuah Khan , Dave Marchevsky , Joe Stringer Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Benjamin Tissoires Subject: [PATCH bpf-next v2 28/28] samples/bpf: fix bpf_program__attach_hid() api change Date: Fri, 4 Mar 2022 18:28:52 +0100 Message-Id: <20220304172852.274126-29-benjamin.tissoires@redhat.com> In-Reply-To: <20220304172852.274126-1-benjamin.tissoires@redhat.com> References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net Add the new flag parameter. Signed-off-by: Benjamin Tissoires --- new in v2 --- samples/bpf/hid_mouse_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bpf/hid_mouse_user.c b/samples/bpf/hid_mouse_user.c index d4f37caca2fa..bfae25e7b659 100644 --- a/samples/bpf/hid_mouse_user.c +++ b/samples/bpf/hid_mouse_user.c @@ -98,7 +98,7 @@ int main(int argc, char **argv) bpf_object__for_each_program(prog, obj) { progs[prog_count].fd = bpf_program__fd(prog); progs[prog_count].type = bpf_program__get_expected_attach_type(prog); - progs[prog_count].link = bpf_program__attach_hid(prog, sysfs_fd); + progs[prog_count].link = bpf_program__attach_hid(prog, sysfs_fd, 0); if (libbpf_get_error(progs[prog_count].link)) { fprintf(stderr, "bpf_prog_attach: err=%m\n"); progs[prog_count].fd = 0;