trace_probe_kernel.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __TRACE_PROBE_KERNEL_H_
  3. #define __TRACE_PROBE_KERNEL_H_
  4. /*
  5. * This depends on trace_probe.h, but can not include it due to
  6. * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c.
  7. * Which means that any other user must include trace_probe.h before including
  8. * this file.
  9. */
  10. /* Return the length of string -- including null terminal byte */
  11. static nokprobe_inline int
  12. kern_fetch_store_strlen_user(unsigned long addr)
  13. {
  14. const void __user *uaddr = (__force const void __user *)addr;
  15. return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
  16. }
  17. /* Return the length of string -- including null terminal byte */
  18. static nokprobe_inline int
  19. kern_fetch_store_strlen(unsigned long addr)
  20. {
  21. int ret, len = 0;
  22. u8 c;
  23. #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
  24. if (addr < TASK_SIZE)
  25. return kern_fetch_store_strlen_user(addr);
  26. #endif
  27. do {
  28. ret = copy_from_kernel_nofault(&c, (u8 *)addr + len, 1);
  29. len++;
  30. } while (c && ret == 0 && len < MAX_STRING_SIZE);
  31. return (ret < 0) ? ret : len;
  32. }
  33. static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base)
  34. {
  35. if (ret < 0)
  36. ret = 0;
  37. *(u32 *)dest = make_data_loc(ret, __dest - base);
  38. }
  39. /*
  40. * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf
  41. * with max length and relative data location.
  42. */
  43. static nokprobe_inline int
  44. kern_fetch_store_string_user(unsigned long addr, void *dest, void *base)
  45. {
  46. const void __user *uaddr = (__force const void __user *)addr;
  47. int maxlen = get_loc_len(*(u32 *)dest);
  48. void *__dest;
  49. long ret;
  50. if (unlikely(!maxlen))
  51. return -ENOMEM;
  52. __dest = get_loc_data(dest, base);
  53. ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
  54. set_data_loc(ret, dest, __dest, base);
  55. return ret;
  56. }
  57. /*
  58. * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max
  59. * length and relative data location.
  60. */
  61. static nokprobe_inline int
  62. kern_fetch_store_string(unsigned long addr, void *dest, void *base)
  63. {
  64. int maxlen = get_loc_len(*(u32 *)dest);
  65. void *__dest;
  66. long ret;
  67. #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
  68. if ((unsigned long)addr < TASK_SIZE)
  69. return kern_fetch_store_string_user(addr, dest, base);
  70. #endif
  71. if (unlikely(!maxlen))
  72. return -ENOMEM;
  73. __dest = get_loc_data(dest, base);
  74. /*
  75. * Try to get string again, since the string can be changed while
  76. * probing.
  77. */
  78. ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
  79. set_data_loc(ret, dest, __dest, base);
  80. return ret;
  81. }
  82. #endif /* __TRACE_PROBE_KERNEL_H_ */