Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp754792pxp; Fri, 11 Mar 2022 14:15:23 -0800 (PST) X-Google-Smtp-Source: ABdhPJxEqXXN+0mCbC0Mm3uNe2e4+GisUEJAaTHgqOUHRQyGvMBGeZ1n2WPOztFcnXMBuNOtB9wT X-Received: by 2002:a17:902:bc86:b0:151:ec83:4a8b with SMTP id bb6-20020a170902bc8600b00151ec834a8bmr12074544plb.69.1647036923700; Fri, 11 Mar 2022 14:15:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1647036923; cv=none; d=google.com; s=arc-20160816; b=aFeNbRaMJkLeAjNSzXyFi8/nDuWTTWJE0bDe3CNd7PiJqXVqfqjjjFJjlaArqj9VVi WGNQvG5vYoj3GWFkiDRfK5v5IY+208YSJ4yHqEOd8+nsDVlNdf9f57egscXoveUlFUjg 6EUGRUCdxY2lExASpoDA78q4OmQe+13kRE3emge7ipDbuzdLLkfZfEsDKKBEERdPBqBD x6D7zwvf6Udxmc+PlhxmCSLpiHpRjbMrj4AdomIiyZaDWpCgVtjWYpU+UFQ8USrIC6ye w9mQWp5Bbs1Sfj41MnTSVS+iylJAe1swciIpMViM30o45ojCtMQ2isA5UEIREcoICzqq /7fA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=F/08TVTeX7qJdWIo3uuJ3+sRiIGvopv0E/DcuimI5Vg=; b=Aj2AQyYLj4bD6iIb8hLZTX8r/qd/isW+uT3oGEeLegZyv76J9Kj0yfSs0ZMBZ4wH+W fonr9aWvLMVyFRnYrfH/mFGu3v4S+QFObLT1TqDcPKsX1SNPo4j0vvi2z466eacbyo7a lZfbluKnH8mgCiJ2cVMQrjn1yFc3Ypry6qETUOMQJ6w+QyL6keC6tpq3DR6pFma0CI4g 72w5en8FSEqMgvhLBdvD7HD6Xz807RiXTF7JCOrMQ+xVW5uASQJO7/itaHP1R+F7zOx7 leJ3UdYN9sBm3Bcra/cgKxgTel91BWaWYGnc1UKY99FBtFFu6X7pZPB7mIJfghENCB76 3//Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Xllc8A2h; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id f1-20020a170902ce8100b0015306ea89edsi8462286plg.485.2022.03.11.14.15.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Mar 2022 14:15:23 -0800 (PST) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Xllc8A2h; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 232E3227593; Fri, 11 Mar 2022 13:24:42 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348498AbiCKPKA (ORCPT + 99 others); Fri, 11 Mar 2022 10:10:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55094 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348486AbiCKPJ4 (ORCPT ); Fri, 11 Mar 2022 10:09: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 A192A1C3D19 for ; Fri, 11 Mar 2022 07:08:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1647011331; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=F/08TVTeX7qJdWIo3uuJ3+sRiIGvopv0E/DcuimI5Vg=; b=Xllc8A2hVB9jhzH/hZYW0T9z+3X6B+qLlOkkvBsRaOxRR8yK9m9m3sG4hK12lLWNX185Nb 3QHSgpAj13DHa2SOzDWjDzeWgfCGtBrI+ZVRLzAGpXGdL7n6xaq+4xuS6bWodDJxxmiUJk 2Gs7NdGkCbDjsg6QhiLiu8x1wmbFkv4= Received: from mail-pf1-f197.google.com (mail-pf1-f197.google.com [209.85.210.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-540-5EQoofBUOE-procQz5FN3w-1; Fri, 11 Mar 2022 10:08:50 -0500 X-MC-Unique: 5EQoofBUOE-procQz5FN3w-1 Received: by mail-pf1-f197.google.com with SMTP id y27-20020aa7943b000000b004f6decccdb5so5415378pfo.1 for ; Fri, 11 Mar 2022 07:08:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=F/08TVTeX7qJdWIo3uuJ3+sRiIGvopv0E/DcuimI5Vg=; b=3nGp2ogP1cCe2w0/HcnnffVWpGKG75czmeL6HzjPBynlpLT57y2xmesb5/HCfWjghw /kZ7MDqqckFnIH6SmGuFyz/k4WlzRsoZcRKFa/JY5KBzgrYY2V1RPt3HJZOmHKQ7358Z ytO04vxpT5OVPJwm1DvPCm6qhex42YF1icvtK9mmbxtTWVlBJ3Bph6pC83/rcXiCEEAp 2Wlr4Wji9hGNqfO0vW3mFLqe8DUC+LSs8ilJt9l8mRftsqiy3NaJQ6AlxwZJ5/e6iX0j R0tdVbgJklpC3cso0c3E0oVehTMFlnZhecxOl/eL52ma665q7WKRmqKPCMFHZjrJu0kt A5eQ== X-Gm-Message-State: AOAM532a4TAyX+5w0eszfRuuySvru3vd16UwX9frsFUHx9Q8U4VQI2fd ZKKy5bMdWc/xJ4Kq34n37euDBkkdHjVJqp/tPQcVZ2L+Ml6hMxUWA+CiRKBh/pwqlyzheMnPYwh LcndFmNJKh4LnUHm5La7n+Lxd8R1TipTYvpsmuUjs X-Received: by 2002:a17:902:e051:b0:151:b485:3453 with SMTP id x17-20020a170902e05100b00151b4853453mr10676967plx.116.1647011329125; Fri, 11 Mar 2022 07:08:49 -0800 (PST) X-Received: by 2002:a17:902:e051:b0:151:b485:3453 with SMTP id x17-20020a170902e05100b00151b4853453mr10676930plx.116.1647011328721; Fri, 11 Mar 2022 07:08:48 -0800 (PST) MIME-Version: 1.0 References: <20220304172852.274126-1-benjamin.tissoires@redhat.com> <20220304172852.274126-13-benjamin.tissoires@redhat.com> In-Reply-To: From: Benjamin Tissoires Date: Fri, 11 Mar 2022 16:08:37 +0100 Message-ID: Subject: Re: [PATCH bpf-next v2 12/28] bpf/hid: add hid_{get|set}_data helpers To: Song Liu Cc: 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 , Tero Kristo , lkml , "open list:HID CORE LAYER" , Networking , bpf , linux-kselftest@vger.kernel.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Mar 11, 2022 at 1:41 AM Song Liu wrote: > > On Sat, Mar 5, 2022 at 2:47 AM Greg KH wrote: > > > > On Sat, Mar 05, 2022 at 11:33:07AM +0100, Benjamin Tissoires wrote: > > > On Fri, Mar 4, 2022 at 7:41 PM Greg KH wrote: > > > > > > > > On Fri, Mar 04, 2022 at 06:28:36PM +0100, Benjamin Tissoires wrote: > > > > > 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 > > > > > > > > > > --- > > > > > > > > > > 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. > > > > > > > > > > Quick answer on this one (before going deeper with the other remarks next week): > > > > > > > Wait, nevermind my reviewed-by previously, see my comment about how this > > > > might be split into 4: > > > > bpf_hid_set_bytes() > > > > bpf_hid_get_bytes() > > > > bpf_hid_set_bits() > > > > bpf_hid_get_bits() > > > > > > > > Should be easier to understand and maintain over time, right? > > > > > > Yes, definitively. I thought about adding a `bytes` suffix to the > > > function name for n > 32, but not the `bits` one, meaning the API was > > > still bunkers in my head. > > Do we really need per-bit access? I was under the impression that only > one BPF program is working on a ctx/buffer at a time, so we can just do > read-modify-write at byte level, no? > Yes, we really need per-bit access, and yes only one BPF program is working on a ctx/buffer at a time. The per-bit access is a HID requirement and a much more convenient way of accessing data in the buffer. Well, there is another advantage too that I'll add later. Basically, in the HID world, HW makers are trying to 'compact' the reports their device is sending to a minimum value. For instance, when you have a 3 buttons + wheel mouse you may need: 3 bits of information for the 3 buttons 4 bits for the wheel 16 bits for X 16 bits for Y. This usually translates almost verbatim in the report (we can add one bit of padding between buttons and wheel), which means that accessing the wheel data requires the user to access the offset 4 (bits) of size 4 bits in the report. Some HW vendors are not even bothering aligning the data, so this can be messy from time to time with just plain byte access. All in all, the HID report descriptor gives you that information, and internally, the HID stack stores the offset in bits and the sizes in bits to access them without too much trouble. The second advantage I have with these 2 accessors is that it allows me to not know statically the offset and size values. Because the helper in the kernel checks them for me, I can use registers values that are unknown to the verifier and can basically have: ``` __u64 offsetX = 0; __u64 offsetY = 0; __u32 sizeX = 0; __u32 sizeY = 0; SEC("hid/device_event") int invert_xy(struct hid_bpf_ctx *ctx) { __u16 x, y; if (sizeX == 16) { x = bpf_hid_get_bits(ctx, offsetX, sizeX); bpf_hid_set_bits(ctx, offsetX, -x); } if (sizeY == 16) { y = bpf_hid_get_bits(ctx, offsetY, sizeY); bpf_hid_set_bits(ctx, offsetY, -y); } return 0; } ``` Then, I have my userspace program parse the report descriptor, set the correct values for size{X|Y} and offset{X|Y} and I can have this program compiled once and redistributed many times. Cheers, Benjamin