Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/hid: Add a test for BPF_F_INSERT_HEAD

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>

authored by

Benjamin Tissoires and committed by
Jiri Kosina
80e189f2 e8445737

+97 -1
+43
tools/testing/selftests/hid/hid_bpf.c
··· 88 88 int prog_fd; 89 89 unsigned int hid; 90 90 int retval; 91 + int insert_head; 91 92 }; 92 93 93 94 struct hid_hw_request_syscall_args { ··· 491 490 492 491 struct test_program { 493 492 const char *name; 493 + int insert_head; 494 494 }; 495 495 #define LOAD_PROGRAMS(progs) \ 496 496 load_programs(progs, ARRAY_SIZE(progs), _metadata, self, variant) ··· 541 539 542 540 args.prog_fd = bpf_program__fd(prog); 543 541 args.hid = self->hid_id; 542 + args.insert_head = programs[i].insert_head; 544 543 err = bpf_prog_test_run_opts(attach_fd, &tattr); 545 544 ASSERT_OK(args.retval) TH_LOG("attach_hid(%s): %d", programs[i].name, args.retval); 546 545 } ··· 741 738 ASSERT_EQ(args.retval, 2); 742 739 743 740 ASSERT_EQ(args.data[1], 2); 741 + } 742 + 743 + /* 744 + * Attach hid_insert{0,1,2} to the given uhid device, 745 + * retrieve and open the matching hidraw node, 746 + * inject one event in the uhid device, 747 + * check that the programs have been inserted in the correct order. 748 + */ 749 + TEST_F(hid_bpf, test_hid_attach_flags) 750 + { 751 + const struct test_program progs[] = { 752 + { 753 + .name = "hid_test_insert2", 754 + .insert_head = 0, 755 + }, 756 + { 757 + .name = "hid_test_insert1", 758 + .insert_head = 1, 759 + }, 760 + { 761 + .name = "hid_test_insert3", 762 + .insert_head = 0, 763 + }, 764 + }; 765 + __u8 buf[10] = {0}; 766 + int err; 767 + 768 + LOAD_PROGRAMS(progs); 769 + 770 + /* inject one event */ 771 + buf[0] = 1; 772 + uhid_send_event(_metadata, self->uhid_fd, buf, 6); 773 + 774 + /* read the data from hidraw */ 775 + memset(buf, 0, sizeof(buf)); 776 + err = read(self->hidraw_fd, buf, sizeof(buf)); 777 + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); 778 + ASSERT_EQ(buf[1], 1); 779 + ASSERT_EQ(buf[2], 2); 780 + ASSERT_EQ(buf[3], 3); 744 781 } 745 782 746 783 /*
+54 -1
tools/testing/selftests/hid/progs/hid.c
··· 11 11 int prog_fd; 12 12 unsigned int hid; 13 13 int retval; 14 + int insert_head; 14 15 }; 15 16 16 17 __u64 callback_check = 52; ··· 50 49 { 51 50 ctx->retval = hid_bpf_attach_prog(ctx->hid, 52 51 ctx->prog_fd, 53 - 0); 52 + ctx->insert_head ? HID_BPF_FLAG_INSERT_HEAD : 53 + HID_BPF_FLAG_NONE); 54 54 return 0; 55 55 } 56 56 ··· 142 140 data[4] = 0x42; 143 141 144 142 return sizeof(rdesc) + 73; 143 + } 144 + 145 + SEC("?fmod_ret/hid_bpf_device_event") 146 + int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx) 147 + { 148 + __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 149 + 150 + if (!data) 151 + return 0; /* EPERM check */ 152 + 153 + /* we need to be run first */ 154 + if (data[2] || data[3]) 155 + return -1; 156 + 157 + data[1] = 1; 158 + 159 + return 0; 160 + } 161 + 162 + SEC("?fmod_ret/hid_bpf_device_event") 163 + int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx) 164 + { 165 + __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 166 + 167 + if (!data) 168 + return 0; /* EPERM check */ 169 + 170 + /* after insert0 and before insert2 */ 171 + if (!data[1] || data[3]) 172 + return -1; 173 + 174 + data[2] = 2; 175 + 176 + return 0; 177 + } 178 + 179 + SEC("?fmod_ret/hid_bpf_device_event") 180 + int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx) 181 + { 182 + __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */); 183 + 184 + if (!data) 185 + return 0; /* EPERM check */ 186 + 187 + /* at the end */ 188 + if (!data[1] || !data[2]) 189 + return -1; 190 + 191 + data[3] = 3; 192 + 193 + return 0; 145 194 }