selftests/hid: Add a test for BPF_F_INSERT_HEAD
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Thu, 3 Nov 2022 15:57:53 +0000 (16:57 +0100)
committerJiri Kosina <jkosina@suse.cz>
Tue, 15 Nov 2022 15:28:39 +0000 (16:28 +0100)
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 <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
tools/testing/selftests/hid/hid_bpf.c
tools/testing/selftests/hid/progs/hid.c

index eb329b5d299febf0e8a07b04d99e21fb6248a45b..6615c26fb5dd4412cee316888c87f588c4c10f1c 100644 (file)
@@ -88,6 +88,7 @@ struct attach_prog_args {
        int prog_fd;
        unsigned int hid;
        int retval;
+       int insert_head;
 };
 
 struct hid_hw_request_syscall_args {
@@ -490,6 +491,7 @@ FIXTURE_SETUP(hid_bpf)
 
 struct test_program {
        const char *name;
+       int insert_head;
 };
 #define LOAD_PROGRAMS(progs) \
        load_programs(progs, ARRAY_SIZE(progs), _metadata, self, variant)
@@ -539,6 +541,7 @@ static void load_programs(const struct test_program programs[],
 
                args.prog_fd = bpf_program__fd(prog);
                args.hid = self->hid_id;
+               args.insert_head = programs[i].insert_head;
                err = bpf_prog_test_run_opts(attach_fd, &tattr);
                ASSERT_OK(args.retval) TH_LOG("attach_hid(%s): %d", programs[i].name, args.retval);
        }
@@ -740,6 +743,46 @@ TEST_F(hid_bpf, test_hid_user_raw_request_call)
        ASSERT_EQ(args.data[1], 2);
 }
 
+/*
+ * 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.
+ */
+TEST_F(hid_bpf, test_hid_attach_flags)
+{
+       const struct test_program progs[] = {
+               {
+                       .name = "hid_test_insert2",
+                       .insert_head = 0,
+               },
+               {
+                       .name = "hid_test_insert1",
+                       .insert_head = 1,
+               },
+               {
+                       .name = "hid_test_insert3",
+                       .insert_head = 0,
+               },
+       };
+       __u8 buf[10] = {0};
+       int err;
+
+       LOAD_PROGRAMS(progs);
+
+       /* inject one event */
+       buf[0] = 1;
+       uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+
+       /* read the data from hidraw */
+       memset(buf, 0, sizeof(buf));
+       err = read(self->hidraw_fd, buf, sizeof(buf));
+       ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
+       ASSERT_EQ(buf[1], 1);
+       ASSERT_EQ(buf[2], 2);
+       ASSERT_EQ(buf[3], 3);
+}
+
 /*
  * Attach hid_rdesc_fixup to the given uhid device,
  * retrieve and open the matching hidraw node,
index 5758366a90e64f1a568618f7c46b1104e4ff14cc..6a86af0aa5450cf30903498a6be76eb1c6d7209e 100644 (file)
@@ -11,6 +11,7 @@ struct attach_prog_args {
        int prog_fd;
        unsigned int hid;
        int retval;
+       int insert_head;
 };
 
 __u64 callback_check = 52;
@@ -49,7 +50,8 @@ int attach_prog(struct attach_prog_args *ctx)
 {
        ctx->retval = hid_bpf_attach_prog(ctx->hid,
                                          ctx->prog_fd,
-                                         0);
+                                         ctx->insert_head ? HID_BPF_FLAG_INSERT_HEAD :
+                                                            HID_BPF_FLAG_NONE);
        return 0;
 }
 
@@ -141,3 +143,54 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hid_ctx)
 
        return sizeof(rdesc) + 73;
 }
+
+SEC("?fmod_ret/hid_bpf_device_event")
+int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx)
+{
+       __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
+
+       if (!data)
+               return 0; /* EPERM check */
+
+       /* we need to be run first */
+       if (data[2] || data[3])
+               return -1;
+
+       data[1] = 1;
+
+       return 0;
+}
+
+SEC("?fmod_ret/hid_bpf_device_event")
+int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx)
+{
+       __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
+
+       if (!data)
+               return 0; /* EPERM check */
+
+       /* after insert0 and before insert2 */
+       if (!data[1] || data[3])
+               return -1;
+
+       data[2] = 2;
+
+       return 0;
+}
+
+SEC("?fmod_ret/hid_bpf_device_event")
+int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx)
+{
+       __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
+
+       if (!data)
+               return 0; /* EPERM check */
+
+       /* at the end */
+       if (!data[1] || !data[2])
+               return -1;
+
+       data[3] = 3;
+
+       return 0;
+}