1 // SPDX-License-Identifier: GPL-2.0-only 2 3 /* 4 * HID-BPF support for Linux 5 * 6 * Copyright (c) 2022 Benjamin Tissoires 7 */ 8 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 #include <linux/bitops.h> 11 #include <linux/btf.h> 12 #include <linux/btf_ids.h> 13 #include <linux/filter.h> 14 #include <linux/hid.h> 15 #include <linux/hid_bpf.h> 16 #include <linux/init.h> 17 #include <linux/kfifo.h> 18 #include <linux/module.h> 19 #include <linux/workqueue.h> 20 #include "hid_bpf_dispatch.h" 21 #include "entrypoints/entrypoints.lskel.h" 22 23 struct hid_bpf_ops *hid_bpf_ops; 24 EXPORT_SYMBOL(hid_bpf_ops); 25 26 /** 27 * hid_bpf_device_event - Called whenever an event is coming in from the device 28 * 29 * @ctx: The HID-BPF context 30 * 31 * @return %0 on success and keep processing; a positive value to change the 32 * incoming size buffer; a negative error code to interrupt the processing 33 * of this event 34 * 35 * Declare an %fmod_ret tracing bpf program to this function and attach this 36 * program through hid_bpf_attach_prog() to have this helper called for 37 * any incoming event from the device itself. 38 * 39 * The function is called while on IRQ context, so we can not sleep. 40 */ 41 /* never used by the kernel but declared so we can load and attach a tracepoint */ 42 __weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx) 43 { 44 return 0; 45 } 46 ALLOW_ERROR_INJECTION(hid_bpf_device_event, ERRNO); 47 48 u8 * 49 dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data, 50 u32 *size, int interrupt) 51 { 52 struct hid_bpf_ctx_kern ctx_kern = { 53 .ctx = { 54 .hid = hdev, 55 .report_type = type, 56 .allocated_size = hdev->bpf.allocated_data, 57 .size = *size, 58 }, 59 .data = hdev->bpf.device_data, 60 }; 61 int ret; 62 63 if (type >= HID_REPORT_TYPES) 64 return ERR_PTR(-EINVAL); 65 66 /* no program has been attached yet */ 67 if (!hdev->bpf.device_data) 68 return data; 69 70 memset(ctx_kern.data, 0, hdev->bpf.allocated_data); 71 memcpy(ctx_kern.data, data, *size); 72 73 ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern); 74 if (ret < 0) 75 return ERR_PTR(ret); 76 77 if (ret) { 78 if (ret > ctx_kern.ctx.allocated_size) 79 return ERR_PTR(-EINVAL); 80 81 *size = ret; 82 } 83 84 return ctx_kern.data; 85 } 86 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event); 87 88 /** 89 * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx 90 * 91 * @ctx: The HID-BPF context 92 * @offset: The offset within the memory 93 * @rdwr_buf_size: the const size of the buffer 94 * 95 * @returns %NULL on error, an %__u8 memory pointer on success 96 */ 97 noinline __u8 * 98 hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size) 99 { 100 struct hid_bpf_ctx_kern *ctx_kern; 101 102 if (!ctx) 103 return NULL; 104 105 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 106 107 if (rdwr_buf_size + offset > ctx->allocated_size) 108 return NULL; 109 110 return ctx_kern->data + offset; 111 } 112 113 /* 114 * The following set contains all functions we agree BPF programs 115 * can use. 116 */ 117 BTF_SET8_START(hid_bpf_kfunc_ids) 118 BTF_ID_FLAGS(func, call_hid_bpf_prog_put_deferred) 119 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL) 120 BTF_SET8_END(hid_bpf_kfunc_ids) 121 122 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = { 123 .owner = THIS_MODULE, 124 .set = &hid_bpf_kfunc_ids, 125 }; 126 127 static int device_match_id(struct device *dev, const void *id) 128 { 129 struct hid_device *hdev = to_hid_device(dev); 130 131 return hdev->id == *(int *)id; 132 } 133 134 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size) 135 { 136 u8 *alloc_data; 137 unsigned int i, j, max_report_len = 0; 138 size_t alloc_size = 0; 139 140 /* compute the maximum report length for this device */ 141 for (i = 0; i < HID_REPORT_TYPES; i++) { 142 struct hid_report_enum *report_enum = hdev->report_enum + i; 143 144 for (j = 0; j < HID_MAX_IDS; j++) { 145 struct hid_report *report = report_enum->report_id_hash[j]; 146 147 if (report) 148 max_report_len = max(max_report_len, hid_report_len(report)); 149 } 150 } 151 152 /* 153 * Give us a little bit of extra space and some predictability in the 154 * buffer length we create. This way, we can tell users that they can 155 * work on chunks of 64 bytes of memory without having the bpf verifier 156 * scream at them. 157 */ 158 alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64; 159 160 alloc_data = kzalloc(alloc_size, GFP_KERNEL); 161 if (!alloc_data) 162 return -ENOMEM; 163 164 *data = alloc_data; 165 *size = alloc_size; 166 167 return 0; 168 } 169 170 static int hid_bpf_allocate_event_data(struct hid_device *hdev) 171 { 172 /* hdev->bpf.device_data is already allocated, abort */ 173 if (hdev->bpf.device_data) 174 return 0; 175 176 return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data); 177 } 178 179 /** 180 * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device 181 * 182 * @hid_id: the system unique identifier of the HID device 183 * @prog_fd: an fd in the user process representing the program to attach 184 * @flags: any logical OR combination of &enum hid_bpf_attach_flags 185 * 186 * @returns %0 on success, an error code otherwise. 187 */ 188 /* called from syscall */ 189 noinline int 190 hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags) 191 { 192 struct hid_device *hdev; 193 struct device *dev; 194 int err, prog_type = hid_bpf_get_prog_attach_type(prog_fd); 195 196 if (!hid_bpf_ops) 197 return -EINVAL; 198 199 if (prog_type < 0) 200 return prog_type; 201 202 if (prog_type >= HID_BPF_PROG_TYPE_MAX) 203 return -EINVAL; 204 205 if ((flags & ~HID_BPF_FLAG_MASK)) 206 return -EINVAL; 207 208 dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id); 209 if (!dev) 210 return -EINVAL; 211 212 hdev = to_hid_device(dev); 213 214 if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) { 215 err = hid_bpf_allocate_event_data(hdev); 216 if (err) 217 return err; 218 } 219 220 return __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags); 221 } 222 223 /** 224 * hid_bpf_allocate_context - Allocate a context to the given HID device 225 * 226 * @hid_id: the system unique identifier of the HID device 227 * 228 * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error. 229 */ 230 noinline struct hid_bpf_ctx * 231 hid_bpf_allocate_context(unsigned int hid_id) 232 { 233 struct hid_device *hdev; 234 struct hid_bpf_ctx_kern *ctx_kern = NULL; 235 struct device *dev; 236 237 if (!hid_bpf_ops) 238 return NULL; 239 240 dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id); 241 if (!dev) 242 return NULL; 243 244 hdev = to_hid_device(dev); 245 246 ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL); 247 if (!ctx_kern) 248 return NULL; 249 250 ctx_kern->ctx.hid = hdev; 251 252 return &ctx_kern->ctx; 253 } 254 255 /** 256 * hid_bpf_release_context - Release the previously allocated context @ctx 257 * 258 * @ctx: the HID-BPF context to release 259 * 260 */ 261 noinline void 262 hid_bpf_release_context(struct hid_bpf_ctx *ctx) 263 { 264 struct hid_bpf_ctx_kern *ctx_kern; 265 266 if (!ctx) 267 return; 268 269 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); 270 271 kfree(ctx_kern); 272 } 273 274 /** 275 * hid_bpf_hw_request - Communicate with a HID device 276 * 277 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context() 278 * @buf: a %PTR_TO_MEM buffer 279 * @buf__sz: the size of the data to transfer 280 * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT) 281 * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...) 282 * 283 * @returns %0 on success, a negative error code otherwise. 284 */ 285 noinline int 286 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, 287 enum hid_report_type rtype, enum hid_class_request reqtype) 288 { 289 struct hid_device *hdev; 290 struct hid_report *report; 291 struct hid_report_enum *report_enum; 292 u8 *dma_data; 293 u32 report_len; 294 int ret; 295 296 /* check arguments */ 297 if (!ctx || !hid_bpf_ops || !buf) 298 return -EINVAL; 299 300 switch (rtype) { 301 case HID_INPUT_REPORT: 302 case HID_OUTPUT_REPORT: 303 case HID_FEATURE_REPORT: 304 break; 305 default: 306 return -EINVAL; 307 } 308 309 switch (reqtype) { 310 case HID_REQ_GET_REPORT: 311 case HID_REQ_GET_IDLE: 312 case HID_REQ_GET_PROTOCOL: 313 case HID_REQ_SET_REPORT: 314 case HID_REQ_SET_IDLE: 315 case HID_REQ_SET_PROTOCOL: 316 break; 317 default: 318 return -EINVAL; 319 } 320 321 if (buf__sz < 1) 322 return -EINVAL; 323 324 hdev = (struct hid_device *)ctx->hid; /* discard const */ 325 326 report_enum = hdev->report_enum + rtype; 327 report = hid_bpf_ops->hid_get_report(report_enum, buf); 328 if (!report) 329 return -EINVAL; 330 331 report_len = hid_report_len(report); 332 333 if (buf__sz > report_len) 334 buf__sz = report_len; 335 336 dma_data = kmemdup(buf, buf__sz, GFP_KERNEL); 337 if (!dma_data) 338 return -ENOMEM; 339 340 ret = hid_bpf_ops->hid_hw_raw_request(hdev, 341 dma_data[0], 342 dma_data, 343 buf__sz, 344 rtype, 345 reqtype); 346 347 if (ret > 0) 348 memcpy(buf, dma_data, ret); 349 350 kfree(dma_data); 351 return ret; 352 } 353 354 /* for syscall HID-BPF */ 355 BTF_SET8_START(hid_bpf_syscall_kfunc_ids) 356 BTF_ID_FLAGS(func, hid_bpf_attach_prog) 357 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL) 358 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE) 359 BTF_ID_FLAGS(func, hid_bpf_hw_request) 360 BTF_SET8_END(hid_bpf_syscall_kfunc_ids) 361 362 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = { 363 .owner = THIS_MODULE, 364 .set = &hid_bpf_syscall_kfunc_ids, 365 }; 366 367 int hid_bpf_connect_device(struct hid_device *hdev) 368 { 369 struct hid_bpf_prog_list *prog_list; 370 371 rcu_read_lock(); 372 prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]); 373 rcu_read_unlock(); 374 375 /* only allocate BPF data if there are programs attached */ 376 if (!prog_list) 377 return 0; 378 379 return hid_bpf_allocate_event_data(hdev); 380 } 381 EXPORT_SYMBOL_GPL(hid_bpf_connect_device); 382 383 void hid_bpf_disconnect_device(struct hid_device *hdev) 384 { 385 kfree(hdev->bpf.device_data); 386 hdev->bpf.device_data = NULL; 387 hdev->bpf.allocated_data = 0; 388 } 389 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device); 390 391 void hid_bpf_destroy_device(struct hid_device *hdev) 392 { 393 if (!hdev) 394 return; 395 396 /* mark the device as destroyed in bpf so we don't reattach it */ 397 hdev->bpf.destroyed = true; 398 399 __hid_bpf_destroy_device(hdev); 400 } 401 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device); 402 403 void hid_bpf_device_init(struct hid_device *hdev) 404 { 405 spin_lock_init(&hdev->bpf.progs_lock); 406 } 407 EXPORT_SYMBOL_GPL(hid_bpf_device_init); 408 409 static int __init hid_bpf_init(void) 410 { 411 int err; 412 413 /* Note: if we exit with an error any time here, we would entirely break HID, which 414 * is probably not something we want. So we log an error and return success. 415 * 416 * This is not a big deal: the syscall allowing to attach a BPF program to a HID device 417 * will not be available, so nobody will be able to use the functionality. 418 */ 419 420 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set); 421 if (err) { 422 pr_warn("error while setting HID BPF tracing kfuncs: %d", err); 423 return 0; 424 } 425 426 err = hid_bpf_preload_skel(); 427 if (err) { 428 pr_warn("error while preloading HID BPF dispatcher: %d", err); 429 return 0; 430 } 431 432 /* register syscalls after we are sure we can load our preloaded bpf program */ 433 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set); 434 if (err) { 435 pr_warn("error while setting HID BPF syscall kfuncs: %d", err); 436 return 0; 437 } 438 439 return 0; 440 } 441 442 static void __exit hid_bpf_exit(void) 443 { 444 /* HID depends on us, so if we hit that code, we are guaranteed that hid 445 * has been removed and thus we do not need to clear the HID devices 446 */ 447 hid_bpf_free_links_and_skel(); 448 } 449 450 late_initcall(hid_bpf_init); 451 module_exit(hid_bpf_exit); 452 MODULE_AUTHOR("Benjamin Tissoires"); 453 MODULE_LICENSE("GPL"); 454