From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
To: Greg KH <gregkh@linuxfoundation.org>,
Jiri Kosina <jikos@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
Yonghong Song <yhs@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@kernel.org>, Shuah Khan <shuah@kernel.org>,
Dave Marchevsky <davemarchevsky@fb.com>,
Joe Stringer <joe@cilium.io>, Jonathan Corbet <corbet@lwn.net>
Cc: Tero Kristo <tero.kristo@linux.intel.com>,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
netdev@vger.kernel.org, bpf@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org,
Benjamin Tissoires <benjamin.tissoires@redhat.com>
Subject: [PATCH bpf-next v3 12/17] bpf/hid: add more HID helpers
Date: Fri, 18 Mar 2022 17:15:23 +0100 [thread overview]
Message-ID: <20220318161528.1531164-13-benjamin.tissoires@redhat.com> (raw)
In-Reply-To: <20220318161528.1531164-1-benjamin.tissoires@redhat.com>
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.
The third exported helper allows to communicate with the HID device.
We give a data buffer, and call either HID_GET_REPORT or HID_SET_REPORT
on the device.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
changes in v3:
- renamed hid_{get|set}_data into hid_{get|set}_bits
- squashed with bpf/hid: add bpf_hid_raw_request helper function
changes in v2:
- split the patch with libbpf and HID left outside.
---
include/linux/bpf-hid.h | 6 +++
include/uapi/linux/bpf.h | 36 +++++++++++++++++
kernel/bpf/hid.c | 73 ++++++++++++++++++++++++++++++++++
tools/include/uapi/linux/bpf.h | 36 +++++++++++++++++
4 files changed, 151 insertions(+)
diff --git a/include/linux/bpf-hid.h b/include/linux/bpf-hid.h
index 7f596554fe8c..82b7466b5008 100644
--- a/include/linux/bpf-hid.h
+++ b/include/linux/bpf-hid.h
@@ -102,6 +102,12 @@ struct bpf_hid_hooks {
int (*pre_link_attach)(struct hid_device *hdev, enum bpf_hid_attach_type type);
void (*post_link_attach)(struct hid_device *hdev, enum bpf_hid_attach_type type);
void (*array_detach)(struct hid_device *hdev, enum bpf_hid_attach_type type);
+ int (*hid_get_bits)(struct hid_device *hdev, u8 *buf, size_t buf_size,
+ u64 offset, u32 n, u32 *data);
+ int (*hid_set_bits)(struct hid_device *hdev, u8 *buf, size_t buf_size,
+ u64 offset, u32 n, u32 data);
+ 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 0e8438e93768..41ab1d068369 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5155,6 +5155,39 @@ union bpf_attr {
* by a call to bpf_hid_discard;
* Return
* The pointer to the data. On error, a null value is returned.
+ *
+ * int bpf_hid_get_bits(void *ctx, u64 offset, u32 n, u32 *data)
+ * 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.
+ *
+ * n must be less or equal than 32, and we can address with bit
+ * precision the value in the buffer. data must be a pointer
+ * to a u32.
+ * Return
+ * The length of data copied into data. On error, a negative value
+ * is returned.
+ *
+ * int bpf_hid_set_bits(void *ctx, u64 offset, u32 n, u32 data)
+ * Description
+ * Set the data of size n (in bits) at the given offset (bits) in the
+ * ctx->event.data field.
+ *
+ * n must be less or equal than 32, and we can address with bit
+ * precision the value in the buffer.
+ * 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 report_type, u8 request_type)
+ * Description
+ * communicate with the HID device
+ *
+ * report_type is one of HID_INPUT_REPORT, HID_OUTPUT_REPORT, HID_FEATURE_REPORT
+ * request_type is one of HID_REQ_SET_REPORT or HID_REQ_GET_REPORT
+ * Return
+ * 0 on success.
+ * negative value on error.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -5352,6 +5385,9 @@ union bpf_attr {
FN(skb_set_tstamp), \
FN(ima_file_hash), \
FN(hid_get_data), \
+ FN(hid_get_bits), \
+ FN(hid_set_bits), \
+ 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 2dfeaaa8a83f..30a62e8e0f0a 100644
--- a/kernel/bpf/hid.c
+++ b/kernel/bpf/hid.c
@@ -66,12 +66,85 @@ static const struct bpf_func_proto bpf_hid_get_data_proto = {
.arg3_type = ARG_CONST_ALLOC_SIZE_OR_ZERO,
};
+BPF_CALL_4(bpf_hid_get_bits, struct hid_bpf_ctx_kern*, ctx, u64, offset, u32, n, u32*, data)
+{
+ if (!hid_hooks.hid_get_bits)
+ return -EOPNOTSUPP;
+
+ return hid_hooks.hid_get_bits(ctx->hdev,
+ ctx->data,
+ ctx->allocated_size,
+ offset, n,
+ data);
+}
+
+static const struct bpf_func_proto bpf_hid_get_bits_proto = {
+ .func = bpf_hid_get_bits,
+ .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_INT,
+};
+
+BPF_CALL_4(bpf_hid_set_bits, struct hid_bpf_ctx_kern*, ctx, u64, offset, u32, n, u32, data)
+{
+ if (!hid_hooks.hid_set_bits)
+ return -EOPNOTSUPP;
+
+ hid_hooks.hid_set_bits(ctx->hdev,
+ ctx->data,
+ ctx->allocated_size,
+ offset, n,
+ data);
+ return 0;
+}
+
+static const struct bpf_func_proto bpf_hid_set_bits_proto = {
+ .func = bpf_hid_set_bits,
+ .gpl_only = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+ .arg4_type = ARG_ANYTHING,
+};
+
+BPF_CALL_5(bpf_hid_raw_request, struct hid_bpf_ctx_kern*, ctx, void*, buf, u64, size,
+ u8, report_type, u8, request_type)
+{
+ if (!hid_hooks.hid_raw_request)
+ return -EOPNOTSUPP;
+
+ return hid_hooks.hid_raw_request(ctx->hdev, buf, size, report_type, request_type);
+}
+
+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)
{
switch (func_id) {
case BPF_FUNC_hid_get_data:
return &bpf_hid_get_data_proto;
+ case BPF_FUNC_hid_get_bits:
+ return &bpf_hid_get_bits_proto;
+ case BPF_FUNC_hid_set_bits:
+ return &bpf_hid_set_bits_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 0e8438e93768..41ab1d068369 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5155,6 +5155,39 @@ union bpf_attr {
* by a call to bpf_hid_discard;
* Return
* The pointer to the data. On error, a null value is returned.
+ *
+ * int bpf_hid_get_bits(void *ctx, u64 offset, u32 n, u32 *data)
+ * 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.
+ *
+ * n must be less or equal than 32, and we can address with bit
+ * precision the value in the buffer. data must be a pointer
+ * to a u32.
+ * Return
+ * The length of data copied into data. On error, a negative value
+ * is returned.
+ *
+ * int bpf_hid_set_bits(void *ctx, u64 offset, u32 n, u32 data)
+ * Description
+ * Set the data of size n (in bits) at the given offset (bits) in the
+ * ctx->event.data field.
+ *
+ * n must be less or equal than 32, and we can address with bit
+ * precision the value in the buffer.
+ * 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 report_type, u8 request_type)
+ * Description
+ * communicate with the HID device
+ *
+ * report_type is one of HID_INPUT_REPORT, HID_OUTPUT_REPORT, HID_FEATURE_REPORT
+ * request_type is one of HID_REQ_SET_REPORT or HID_REQ_GET_REPORT
+ * Return
+ * 0 on success.
+ * negative value on error.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -5352,6 +5385,9 @@ union bpf_attr {
FN(skb_set_tstamp), \
FN(ima_file_hash), \
FN(hid_get_data), \
+ FN(hid_get_bits), \
+ FN(hid_set_bits), \
+ FN(hid_raw_request), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
--
2.35.1
next prev parent reply other threads:[~2022-03-18 16:18 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-18 16:15 [PATCH bpf-next v3 00/17] Introduce eBPF support for HID devices Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 01/17] bpf: add new is_sys_admin_prog_type() helper Benjamin Tissoires
2022-03-18 18:07 ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 02/17] bpf: introduce hid program type Benjamin Tissoires
2022-03-18 20:48 ` Song Liu
2022-03-21 16:07 ` Benjamin Tissoires
2022-03-21 21:51 ` Song Liu
2022-03-22 11:06 ` Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 03/17] bpf/verifier: prevent non GPL programs to be loaded against HID Benjamin Tissoires
2022-03-18 20:51 ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 04/17] libbpf: add HID program type and API Benjamin Tissoires
2022-03-18 20:53 ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 05/17] HID: hook up with bpf Benjamin Tissoires
2022-03-18 21:02 ` Song Liu
2022-03-18 21:04 ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 06/17] HID: allow to change the report descriptor from an eBPF program Benjamin Tissoires
2022-03-18 21:10 ` Song Liu
2022-03-21 16:20 ` Benjamin Tissoires
2022-03-21 22:03 ` Song Liu
2022-03-22 22:51 ` Alexei Starovoitov
2022-03-23 16:08 ` Benjamin Tissoires
2022-03-25 17:00 ` Andrii Nakryiko
2022-03-28 6:56 ` Benjamin Tissoires
2022-03-28 21:35 ` Andrii Nakryiko
2022-03-29 13:53 ` Benjamin Tissoires
2022-04-01 13:21 ` Benjamin Tissoires
2022-03-30 21:27 ` Alexei Starovoitov
2022-03-18 16:15 ` [PATCH bpf-next v3 07/17] selftests/bpf: add tests for the HID-bpf initial implementation Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 08/17] selftests/bpf: add report descriptor fixup tests Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 09/17] selftests/bpf: Add a test for BPF_F_INSERT_HEAD Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 10/17] selftests/bpf: add test for user call of HID bpf programs Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 11/17] samples/bpf: add new hid_mouse example Benjamin Tissoires
2022-03-18 16:15 ` Benjamin Tissoires [this message]
2022-03-18 21:19 ` [PATCH bpf-next v3 12/17] bpf/hid: add more HID helpers Song Liu
2022-03-21 16:24 ` Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 13/17] HID: bpf: implement hid_bpf_get|set_bits Benjamin Tissoires
2022-03-18 21:20 ` Song Liu
2022-03-18 16:15 ` [PATCH bpf-next v3 14/17] HID: add implementation of bpf_hid_raw_request Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 15/17] selftests/bpf: add tests for hid_{get|set}_bits helpers Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 16/17] selftests/bpf: add tests for bpf_hid_hw_request Benjamin Tissoires
2022-03-18 16:15 ` [PATCH bpf-next v3 17/17] Documentation: add HID-BPF docs Benjamin Tissoires
2022-03-18 18:05 ` Song Liu
2022-03-29 13:04 ` [PATCH bpf-next v3 00/17] Introduce eBPF support for HID devices Tero Kristo
2022-04-01 9:37 ` Benjamin Tissoires
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220318161528.1531164-13-benjamin.tissoires@redhat.com \
--to=benjamin.tissoires@redhat.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=corbet@lwn.net \
--cc=daniel@iogearbox.net \
--cc=davemarchevsky@fb.com \
--cc=gregkh@linuxfoundation.org \
--cc=jikos@kernel.org \
--cc=joe@cilium.io \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=shuah@kernel.org \
--cc=songliubraving@fb.com \
--cc=tero.kristo@linux.intel.com \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).