hid_bpf_dispatch.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * HID-BPF support for Linux
  4. *
  5. * Copyright (c) 2022-2024 Benjamin Tissoires
  6. */
  7. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  8. #include <linux/bitops.h>
  9. #include <linux/btf.h>
  10. #include <linux/btf_ids.h>
  11. #include <linux/filter.h>
  12. #include <linux/hid.h>
  13. #include <linux/hid_bpf.h>
  14. #include <linux/init.h>
  15. #include <linux/kfifo.h>
  16. #include <linux/minmax.h>
  17. #include <linux/module.h>
  18. #include "hid_bpf_dispatch.h"
  19. struct hid_ops *hid_ops;
  20. EXPORT_SYMBOL(hid_ops);
  21. u8 *
  22. dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
  23. u32 *size, int interrupt, u64 source, bool from_bpf)
  24. {
  25. struct hid_bpf_ctx_kern ctx_kern = {
  26. .ctx = {
  27. .hid = hdev,
  28. .allocated_size = hdev->bpf.allocated_data,
  29. .size = *size,
  30. },
  31. .data = hdev->bpf.device_data,
  32. .from_bpf = from_bpf,
  33. };
  34. struct hid_bpf_ops *e;
  35. int ret;
  36. if (unlikely(hdev->bpf.destroyed))
  37. return ERR_PTR(-ENODEV);
  38. if (type >= HID_REPORT_TYPES)
  39. return ERR_PTR(-EINVAL);
  40. /* no program has been attached yet */
  41. if (!hdev->bpf.device_data)
  42. return data;
  43. memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
  44. memcpy(ctx_kern.data, data, *size);
  45. rcu_read_lock();
  46. list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
  47. if (e->hid_device_event) {
  48. ret = e->hid_device_event(&ctx_kern.ctx, type, source);
  49. if (ret < 0) {
  50. rcu_read_unlock();
  51. return ERR_PTR(ret);
  52. }
  53. if (ret)
  54. ctx_kern.ctx.size = ret;
  55. }
  56. }
  57. rcu_read_unlock();
  58. ret = ctx_kern.ctx.size;
  59. if (ret) {
  60. if (ret > ctx_kern.ctx.allocated_size)
  61. return ERR_PTR(-EINVAL);
  62. *size = ret;
  63. }
  64. return ctx_kern.data;
  65. }
  66. EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
  67. int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
  68. unsigned char reportnum, u8 *buf,
  69. u32 size, enum hid_report_type rtype,
  70. enum hid_class_request reqtype,
  71. u64 source, bool from_bpf)
  72. {
  73. struct hid_bpf_ctx_kern ctx_kern = {
  74. .ctx = {
  75. .hid = hdev,
  76. .allocated_size = size,
  77. .size = size,
  78. },
  79. .data = buf,
  80. .from_bpf = from_bpf,
  81. };
  82. struct hid_bpf_ops *e;
  83. int ret, idx;
  84. if (unlikely(hdev->bpf.destroyed))
  85. return -ENODEV;
  86. if (rtype >= HID_REPORT_TYPES)
  87. return -EINVAL;
  88. idx = srcu_read_lock(&hdev->bpf.srcu);
  89. list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
  90. srcu_read_lock_held(&hdev->bpf.srcu)) {
  91. if (!e->hid_hw_request)
  92. continue;
  93. ret = e->hid_hw_request(&ctx_kern.ctx, reportnum, rtype, reqtype, source);
  94. if (ret)
  95. goto out;
  96. }
  97. ret = 0;
  98. out:
  99. srcu_read_unlock(&hdev->bpf.srcu, idx);
  100. return ret;
  101. }
  102. EXPORT_SYMBOL_GPL(dispatch_hid_bpf_raw_requests);
  103. int dispatch_hid_bpf_output_report(struct hid_device *hdev,
  104. __u8 *buf, u32 size, u64 source,
  105. bool from_bpf)
  106. {
  107. struct hid_bpf_ctx_kern ctx_kern = {
  108. .ctx = {
  109. .hid = hdev,
  110. .allocated_size = size,
  111. .size = size,
  112. },
  113. .data = buf,
  114. .from_bpf = from_bpf,
  115. };
  116. struct hid_bpf_ops *e;
  117. int ret, idx;
  118. if (unlikely(hdev->bpf.destroyed))
  119. return -ENODEV;
  120. idx = srcu_read_lock(&hdev->bpf.srcu);
  121. list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
  122. srcu_read_lock_held(&hdev->bpf.srcu)) {
  123. if (!e->hid_hw_output_report)
  124. continue;
  125. ret = e->hid_hw_output_report(&ctx_kern.ctx, source);
  126. if (ret)
  127. goto out;
  128. }
  129. ret = 0;
  130. out:
  131. srcu_read_unlock(&hdev->bpf.srcu, idx);
  132. return ret;
  133. }
  134. EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report);
  135. u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size)
  136. {
  137. int ret;
  138. struct hid_bpf_ctx_kern ctx_kern = {
  139. .ctx = {
  140. .hid = hdev,
  141. .size = *size,
  142. .allocated_size = HID_MAX_DESCRIPTOR_SIZE,
  143. },
  144. };
  145. if (!hdev->bpf.rdesc_ops)
  146. goto ignore_bpf;
  147. ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
  148. if (!ctx_kern.data)
  149. goto ignore_bpf;
  150. memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
  151. ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
  152. if (ret < 0)
  153. goto ignore_bpf;
  154. if (ret) {
  155. if (ret > ctx_kern.ctx.allocated_size)
  156. goto ignore_bpf;
  157. *size = ret;
  158. }
  159. return krealloc(ctx_kern.data, *size, GFP_KERNEL);
  160. ignore_bpf:
  161. kfree(ctx_kern.data);
  162. return kmemdup(rdesc, *size, GFP_KERNEL);
  163. }
  164. EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
  165. static int device_match_id(struct device *dev, const void *id)
  166. {
  167. struct hid_device *hdev = to_hid_device(dev);
  168. return hdev->id == *(int *)id;
  169. }
  170. struct hid_device *hid_get_device(unsigned int hid_id)
  171. {
  172. struct device *dev;
  173. if (!hid_ops)
  174. return ERR_PTR(-EINVAL);
  175. dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
  176. if (!dev)
  177. return ERR_PTR(-EINVAL);
  178. return to_hid_device(dev);
  179. }
  180. void hid_put_device(struct hid_device *hid)
  181. {
  182. put_device(&hid->dev);
  183. }
  184. static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
  185. {
  186. u8 *alloc_data;
  187. unsigned int i, j, max_report_len = 0;
  188. size_t alloc_size = 0;
  189. /* compute the maximum report length for this device */
  190. for (i = 0; i < HID_REPORT_TYPES; i++) {
  191. struct hid_report_enum *report_enum = hdev->report_enum + i;
  192. for (j = 0; j < HID_MAX_IDS; j++) {
  193. struct hid_report *report = report_enum->report_id_hash[j];
  194. if (report)
  195. max_report_len = max(max_report_len, hid_report_len(report));
  196. }
  197. }
  198. /*
  199. * Give us a little bit of extra space and some predictability in the
  200. * buffer length we create. This way, we can tell users that they can
  201. * work on chunks of 64 bytes of memory without having the bpf verifier
  202. * scream at them.
  203. */
  204. alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
  205. alloc_data = kzalloc(alloc_size, GFP_KERNEL);
  206. if (!alloc_data)
  207. return -ENOMEM;
  208. *data = alloc_data;
  209. *size = alloc_size;
  210. return 0;
  211. }
  212. int hid_bpf_allocate_event_data(struct hid_device *hdev)
  213. {
  214. /* hdev->bpf.device_data is already allocated, abort */
  215. if (hdev->bpf.device_data)
  216. return 0;
  217. return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data);
  218. }
  219. int hid_bpf_reconnect(struct hid_device *hdev)
  220. {
  221. if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
  222. return device_reprobe(&hdev->dev);
  223. return 0;
  224. }
  225. /* Disables missing prototype warnings */
  226. __bpf_kfunc_start_defs();
  227. /**
  228. * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
  229. *
  230. * @ctx: The HID-BPF context
  231. * @offset: The offset within the memory
  232. * @rdwr_buf_size: the const size of the buffer
  233. *
  234. * @returns %NULL on error, an %__u8 memory pointer on success
  235. */
  236. __bpf_kfunc __u8 *
  237. hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
  238. {
  239. struct hid_bpf_ctx_kern *ctx_kern;
  240. if (!ctx)
  241. return NULL;
  242. ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
  243. if (rdwr_buf_size + offset > ctx->allocated_size)
  244. return NULL;
  245. return ctx_kern->data + offset;
  246. }
  247. /**
  248. * hid_bpf_allocate_context - Allocate a context to the given HID device
  249. *
  250. * @hid_id: the system unique identifier of the HID device
  251. *
  252. * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
  253. */
  254. __bpf_kfunc struct hid_bpf_ctx *
  255. hid_bpf_allocate_context(unsigned int hid_id)
  256. {
  257. struct hid_device *hdev;
  258. struct hid_bpf_ctx_kern *ctx_kern = NULL;
  259. hdev = hid_get_device(hid_id);
  260. if (IS_ERR(hdev))
  261. return NULL;
  262. ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
  263. if (!ctx_kern) {
  264. hid_put_device(hdev);
  265. return NULL;
  266. }
  267. ctx_kern->ctx.hid = hdev;
  268. return &ctx_kern->ctx;
  269. }
  270. /**
  271. * hid_bpf_release_context - Release the previously allocated context @ctx
  272. *
  273. * @ctx: the HID-BPF context to release
  274. *
  275. */
  276. __bpf_kfunc void
  277. hid_bpf_release_context(struct hid_bpf_ctx *ctx)
  278. {
  279. struct hid_bpf_ctx_kern *ctx_kern;
  280. struct hid_device *hid;
  281. ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
  282. hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */
  283. kfree(ctx_kern);
  284. /* get_device() is called by bus_find_device() */
  285. hid_put_device(hid);
  286. }
  287. static int
  288. __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
  289. enum hid_report_type rtype)
  290. {
  291. struct hid_report_enum *report_enum;
  292. struct hid_report *report;
  293. struct hid_device *hdev;
  294. u32 report_len;
  295. /* check arguments */
  296. if (!ctx || !hid_ops || !buf)
  297. return -EINVAL;
  298. switch (rtype) {
  299. case HID_INPUT_REPORT:
  300. case HID_OUTPUT_REPORT:
  301. case HID_FEATURE_REPORT:
  302. break;
  303. default:
  304. return -EINVAL;
  305. }
  306. if (*buf__sz < 1)
  307. return -EINVAL;
  308. hdev = (struct hid_device *)ctx->hid; /* discard const */
  309. report_enum = hdev->report_enum + rtype;
  310. report = hid_ops->hid_get_report(report_enum, buf);
  311. if (!report)
  312. return -EINVAL;
  313. report_len = hid_report_len(report);
  314. if (*buf__sz > report_len)
  315. *buf__sz = report_len;
  316. return 0;
  317. }
  318. /**
  319. * hid_bpf_hw_request - Communicate with a HID device
  320. *
  321. * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
  322. * @buf: a %PTR_TO_MEM buffer
  323. * @buf__sz: the size of the data to transfer
  324. * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
  325. * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
  326. *
  327. * @returns %0 on success, a negative error code otherwise.
  328. */
  329. __bpf_kfunc int
  330. hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
  331. enum hid_report_type rtype, enum hid_class_request reqtype)
  332. {
  333. struct hid_bpf_ctx_kern *ctx_kern;
  334. struct hid_device *hdev;
  335. size_t size = buf__sz;
  336. u8 *dma_data;
  337. int ret;
  338. ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
  339. if (ctx_kern->from_bpf)
  340. return -EDEADLOCK;
  341. /* check arguments */
  342. ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype);
  343. if (ret)
  344. return ret;
  345. switch (reqtype) {
  346. case HID_REQ_GET_REPORT:
  347. case HID_REQ_GET_IDLE:
  348. case HID_REQ_GET_PROTOCOL:
  349. case HID_REQ_SET_REPORT:
  350. case HID_REQ_SET_IDLE:
  351. case HID_REQ_SET_PROTOCOL:
  352. break;
  353. default:
  354. return -EINVAL;
  355. }
  356. hdev = (struct hid_device *)ctx->hid; /* discard const */
  357. dma_data = kmemdup(buf, size, GFP_KERNEL);
  358. if (!dma_data)
  359. return -ENOMEM;
  360. ret = hid_ops->hid_hw_raw_request(hdev,
  361. dma_data[0],
  362. dma_data,
  363. size,
  364. rtype,
  365. reqtype,
  366. (u64)(long)ctx,
  367. true); /* prevent infinite recursions */
  368. if (ret > 0)
  369. memcpy(buf, dma_data, ret);
  370. kfree(dma_data);
  371. return ret;
  372. }
  373. /**
  374. * hid_bpf_hw_output_report - Send an output report to a HID device
  375. *
  376. * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
  377. * @buf: a %PTR_TO_MEM buffer
  378. * @buf__sz: the size of the data to transfer
  379. *
  380. * Returns the number of bytes transferred on success, a negative error code otherwise.
  381. */
  382. __bpf_kfunc int
  383. hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
  384. {
  385. struct hid_bpf_ctx_kern *ctx_kern;
  386. struct hid_device *hdev;
  387. size_t size = buf__sz;
  388. u8 *dma_data;
  389. int ret;
  390. ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
  391. if (ctx_kern->from_bpf)
  392. return -EDEADLOCK;
  393. /* check arguments */
  394. ret = __hid_bpf_hw_check_params(ctx, buf, &size, HID_OUTPUT_REPORT);
  395. if (ret)
  396. return ret;
  397. hdev = (struct hid_device *)ctx->hid; /* discard const */
  398. dma_data = kmemdup(buf, size, GFP_KERNEL);
  399. if (!dma_data)
  400. return -ENOMEM;
  401. ret = hid_ops->hid_hw_output_report(hdev, dma_data, size, (u64)(long)ctx, true);
  402. kfree(dma_data);
  403. return ret;
  404. }
  405. static int
  406. __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
  407. size_t size, bool lock_already_taken)
  408. {
  409. struct hid_bpf_ctx_kern *ctx_kern;
  410. int ret;
  411. ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
  412. if (ctx_kern->from_bpf)
  413. return -EDEADLOCK;
  414. /* check arguments */
  415. ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
  416. if (ret)
  417. return ret;
  418. return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
  419. lock_already_taken);
  420. }
  421. /**
  422. * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device
  423. *
  424. * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
  425. * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
  426. * @buf: a %PTR_TO_MEM buffer
  427. * @buf__sz: the size of the data to transfer
  428. *
  429. * Returns %0 on success, a negative error code otherwise. This function will immediately
  430. * fail if the device is not available, thus can be safely used in IRQ context.
  431. */
  432. __bpf_kfunc int
  433. hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
  434. const size_t buf__sz)
  435. {
  436. struct hid_bpf_ctx_kern *ctx_kern;
  437. bool from_hid_event_hook;
  438. ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
  439. from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data;
  440. return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook);
  441. }
  442. /**
  443. * hid_bpf_input_report - Inject a HID report in the kernel from a HID device
  444. *
  445. * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
  446. * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
  447. * @buf: a %PTR_TO_MEM buffer
  448. * @buf__sz: the size of the data to transfer
  449. *
  450. * Returns %0 on success, a negative error code otherwise. This function will wait for the
  451. * device to be available before injecting the event, thus needs to be called in sleepable
  452. * context.
  453. */
  454. __bpf_kfunc int
  455. hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
  456. const size_t buf__sz)
  457. {
  458. int ret;
  459. ret = down_interruptible(&ctx->hid->driver_input_lock);
  460. if (ret)
  461. return ret;
  462. /* check arguments */
  463. ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */);
  464. up(&ctx->hid->driver_input_lock);
  465. return ret;
  466. }
  467. __bpf_kfunc_end_defs();
  468. /*
  469. * The following set contains all functions we agree BPF programs
  470. * can use.
  471. */
  472. BTF_KFUNCS_START(hid_bpf_kfunc_ids)
  473. BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
  474. BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
  475. BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
  476. BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
  477. BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
  478. BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
  479. BTF_ID_FLAGS(func, hid_bpf_try_input_report)
  480. BTF_KFUNCS_END(hid_bpf_kfunc_ids)
  481. static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
  482. .owner = THIS_MODULE,
  483. .set = &hid_bpf_kfunc_ids,
  484. };
  485. /* for syscall HID-BPF */
  486. BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
  487. BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
  488. BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
  489. BTF_ID_FLAGS(func, hid_bpf_hw_request)
  490. BTF_ID_FLAGS(func, hid_bpf_hw_output_report)
  491. BTF_ID_FLAGS(func, hid_bpf_input_report)
  492. BTF_KFUNCS_END(hid_bpf_syscall_kfunc_ids)
  493. static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
  494. .owner = THIS_MODULE,
  495. .set = &hid_bpf_syscall_kfunc_ids,
  496. };
  497. int hid_bpf_connect_device(struct hid_device *hdev)
  498. {
  499. bool need_to_allocate = false;
  500. struct hid_bpf_ops *e;
  501. rcu_read_lock();
  502. list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
  503. if (e->hid_device_event) {
  504. need_to_allocate = true;
  505. break;
  506. }
  507. }
  508. rcu_read_unlock();
  509. /* only allocate BPF data if there are programs attached */
  510. if (!need_to_allocate)
  511. return 0;
  512. return hid_bpf_allocate_event_data(hdev);
  513. }
  514. EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
  515. void hid_bpf_disconnect_device(struct hid_device *hdev)
  516. {
  517. kfree(hdev->bpf.device_data);
  518. hdev->bpf.device_data = NULL;
  519. hdev->bpf.allocated_data = 0;
  520. }
  521. EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
  522. void hid_bpf_destroy_device(struct hid_device *hdev)
  523. {
  524. if (!hdev)
  525. return;
  526. /* mark the device as destroyed in bpf so we don't reattach it */
  527. hdev->bpf.destroyed = true;
  528. __hid_bpf_ops_destroy_device(hdev);
  529. synchronize_srcu(&hdev->bpf.srcu);
  530. cleanup_srcu_struct(&hdev->bpf.srcu);
  531. }
  532. EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
  533. int hid_bpf_device_init(struct hid_device *hdev)
  534. {
  535. INIT_LIST_HEAD(&hdev->bpf.prog_list);
  536. mutex_init(&hdev->bpf.prog_list_lock);
  537. return init_srcu_struct(&hdev->bpf.srcu);
  538. }
  539. EXPORT_SYMBOL_GPL(hid_bpf_device_init);
  540. static int __init hid_bpf_init(void)
  541. {
  542. int err;
  543. /* Note: if we exit with an error any time here, we would entirely break HID, which
  544. * is probably not something we want. So we log an error and return success.
  545. *
  546. * This is not a big deal: nobody will be able to use the functionality.
  547. */
  548. err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
  549. if (err) {
  550. pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
  551. return 0;
  552. }
  553. err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
  554. if (err) {
  555. pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
  556. return 0;
  557. }
  558. return 0;
  559. }
  560. late_initcall(hid_bpf_init);
  561. MODULE_AUTHOR("Benjamin Tissoires");
  562. MODULE_LICENSE("GPL");