trace_events_inject.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * trace_events_inject - trace event injection
  4. *
  5. * Copyright (C) 2019 Cong Wang <cwang@twitter.com>
  6. */
  7. #include <linux/module.h>
  8. #include <linux/ctype.h>
  9. #include <linux/mutex.h>
  10. #include <linux/slab.h>
  11. #include <linux/rculist.h>
  12. #include "trace.h"
  13. static int
  14. trace_inject_entry(struct trace_event_file *file, void *rec, int len)
  15. {
  16. struct trace_event_buffer fbuffer;
  17. int written = 0;
  18. void *entry;
  19. rcu_read_lock_sched();
  20. entry = trace_event_buffer_reserve(&fbuffer, file, len);
  21. if (entry) {
  22. memcpy(entry, rec, len);
  23. written = len;
  24. trace_event_buffer_commit(&fbuffer);
  25. }
  26. rcu_read_unlock_sched();
  27. return written;
  28. }
  29. static int
  30. parse_field(char *str, struct trace_event_call *call,
  31. struct ftrace_event_field **pf, u64 *pv)
  32. {
  33. struct ftrace_event_field *field;
  34. char *field_name;
  35. int s, i = 0;
  36. int len;
  37. u64 val;
  38. if (!str[i])
  39. return 0;
  40. /* First find the field to associate to */
  41. while (isspace(str[i]))
  42. i++;
  43. s = i;
  44. while (isalnum(str[i]) || str[i] == '_')
  45. i++;
  46. len = i - s;
  47. if (!len)
  48. return -EINVAL;
  49. field_name = kmemdup_nul(str + s, len, GFP_KERNEL);
  50. if (!field_name)
  51. return -ENOMEM;
  52. field = trace_find_event_field(call, field_name);
  53. kfree(field_name);
  54. if (!field)
  55. return -ENOENT;
  56. *pf = field;
  57. while (isspace(str[i]))
  58. i++;
  59. if (str[i] != '=')
  60. return -EINVAL;
  61. i++;
  62. while (isspace(str[i]))
  63. i++;
  64. s = i;
  65. if (isdigit(str[i]) || str[i] == '-') {
  66. char *num, c;
  67. int ret;
  68. /* Make sure the field is not a string */
  69. if (is_string_field(field))
  70. return -EINVAL;
  71. if (str[i] == '-')
  72. i++;
  73. /* We allow 0xDEADBEEF */
  74. while (isalnum(str[i]))
  75. i++;
  76. num = str + s;
  77. c = str[i];
  78. if (c != '\0' && !isspace(c))
  79. return -EINVAL;
  80. str[i] = '\0';
  81. /* Make sure it is a value */
  82. if (field->is_signed)
  83. ret = kstrtoll(num, 0, &val);
  84. else
  85. ret = kstrtoull(num, 0, &val);
  86. str[i] = c;
  87. if (ret)
  88. return ret;
  89. *pv = val;
  90. return i;
  91. } else if (str[i] == '\'' || str[i] == '"') {
  92. char q = str[i];
  93. /* Make sure the field is OK for strings */
  94. if (!is_string_field(field))
  95. return -EINVAL;
  96. for (i++; str[i]; i++) {
  97. if (str[i] == '\\' && str[i + 1]) {
  98. i++;
  99. continue;
  100. }
  101. if (str[i] == q)
  102. break;
  103. }
  104. if (!str[i])
  105. return -EINVAL;
  106. /* Skip quotes */
  107. s++;
  108. len = i - s;
  109. if (len >= MAX_FILTER_STR_VAL)
  110. return -EINVAL;
  111. *pv = (unsigned long)(str + s);
  112. str[i] = 0;
  113. /* go past the last quote */
  114. i++;
  115. return i;
  116. }
  117. return -EINVAL;
  118. }
  119. static int trace_get_entry_size(struct trace_event_call *call)
  120. {
  121. struct ftrace_event_field *field;
  122. struct list_head *head;
  123. int size = 0;
  124. head = trace_get_fields(call);
  125. list_for_each_entry(field, head, link) {
  126. if (field->size + field->offset > size)
  127. size = field->size + field->offset;
  128. }
  129. return size;
  130. }
  131. static void *trace_alloc_entry(struct trace_event_call *call, int *size)
  132. {
  133. int entry_size = trace_get_entry_size(call);
  134. struct ftrace_event_field *field;
  135. struct list_head *head;
  136. void *entry = NULL;
  137. /* We need an extra '\0' at the end. */
  138. entry = kzalloc(entry_size + 1, GFP_KERNEL);
  139. if (!entry)
  140. return NULL;
  141. head = trace_get_fields(call);
  142. list_for_each_entry(field, head, link) {
  143. if (!is_string_field(field))
  144. continue;
  145. if (field->filter_type == FILTER_STATIC_STRING)
  146. continue;
  147. if (field->filter_type == FILTER_DYN_STRING ||
  148. field->filter_type == FILTER_RDYN_STRING) {
  149. u32 *str_item;
  150. int str_loc = entry_size & 0xffff;
  151. if (field->filter_type == FILTER_RDYN_STRING)
  152. str_loc -= field->offset + field->size;
  153. str_item = (u32 *)(entry + field->offset);
  154. *str_item = str_loc; /* string length is 0. */
  155. } else {
  156. char **paddr;
  157. paddr = (char **)(entry + field->offset);
  158. *paddr = "";
  159. }
  160. }
  161. *size = entry_size + 1;
  162. return entry;
  163. }
  164. #define INJECT_STRING "STATIC STRING CAN NOT BE INJECTED"
  165. /* Caller is responsible to free the *pentry. */
  166. static int parse_entry(char *str, struct trace_event_call *call, void **pentry)
  167. {
  168. struct ftrace_event_field *field;
  169. void *entry = NULL;
  170. int entry_size;
  171. u64 val = 0;
  172. int len;
  173. entry = trace_alloc_entry(call, &entry_size);
  174. *pentry = entry;
  175. if (!entry)
  176. return -ENOMEM;
  177. tracing_generic_entry_update(entry, call->event.type,
  178. tracing_gen_ctx());
  179. while ((len = parse_field(str, call, &field, &val)) > 0) {
  180. if (is_function_field(field))
  181. return -EINVAL;
  182. if (is_string_field(field)) {
  183. char *addr = (char *)(unsigned long) val;
  184. if (field->filter_type == FILTER_STATIC_STRING) {
  185. strscpy(entry + field->offset, addr, field->size);
  186. } else if (field->filter_type == FILTER_DYN_STRING ||
  187. field->filter_type == FILTER_RDYN_STRING) {
  188. int str_len = strlen(addr) + 1;
  189. int str_loc = entry_size & 0xffff;
  190. u32 *str_item;
  191. entry_size += str_len;
  192. *pentry = krealloc(entry, entry_size, GFP_KERNEL);
  193. if (!*pentry) {
  194. kfree(entry);
  195. return -ENOMEM;
  196. }
  197. entry = *pentry;
  198. strscpy(entry + (entry_size - str_len), addr, str_len);
  199. str_item = (u32 *)(entry + field->offset);
  200. if (field->filter_type == FILTER_RDYN_STRING)
  201. str_loc -= field->offset + field->size;
  202. *str_item = (str_len << 16) | str_loc;
  203. } else {
  204. char **paddr;
  205. paddr = (char **)(entry + field->offset);
  206. *paddr = INJECT_STRING;
  207. }
  208. } else {
  209. switch (field->size) {
  210. case 1: {
  211. u8 tmp = (u8) val;
  212. memcpy(entry + field->offset, &tmp, 1);
  213. break;
  214. }
  215. case 2: {
  216. u16 tmp = (u16) val;
  217. memcpy(entry + field->offset, &tmp, 2);
  218. break;
  219. }
  220. case 4: {
  221. u32 tmp = (u32) val;
  222. memcpy(entry + field->offset, &tmp, 4);
  223. break;
  224. }
  225. case 8:
  226. memcpy(entry + field->offset, &val, 8);
  227. break;
  228. default:
  229. return -EINVAL;
  230. }
  231. }
  232. str += len;
  233. }
  234. if (len < 0)
  235. return len;
  236. return entry_size;
  237. }
  238. static ssize_t
  239. event_inject_write(struct file *filp, const char __user *ubuf, size_t cnt,
  240. loff_t *ppos)
  241. {
  242. struct trace_event_call *call;
  243. struct trace_event_file *file;
  244. int err = -ENODEV, size;
  245. void *entry = NULL;
  246. char *buf;
  247. if (cnt >= PAGE_SIZE)
  248. return -EINVAL;
  249. buf = memdup_user_nul(ubuf, cnt);
  250. if (IS_ERR(buf))
  251. return PTR_ERR(buf);
  252. strim(buf);
  253. mutex_lock(&event_mutex);
  254. file = event_file_file(filp);
  255. if (file) {
  256. call = file->event_call;
  257. size = parse_entry(buf, call, &entry);
  258. if (size < 0)
  259. err = size;
  260. else
  261. err = trace_inject_entry(file, entry, size);
  262. }
  263. mutex_unlock(&event_mutex);
  264. kfree(entry);
  265. kfree(buf);
  266. if (err < 0)
  267. return err;
  268. *ppos += err;
  269. return cnt;
  270. }
  271. static ssize_t
  272. event_inject_read(struct file *file, char __user *buf, size_t size,
  273. loff_t *ppos)
  274. {
  275. return -EPERM;
  276. }
  277. const struct file_operations event_inject_fops = {
  278. .open = tracing_open_file_tr,
  279. .read = event_inject_read,
  280. .write = event_inject_write,
  281. .release = tracing_release_file_tr,
  282. };