rv_reactors.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
  4. *
  5. * Runtime reactor interface.
  6. *
  7. * A runtime monitor can cause a reaction to the detection of an
  8. * exception on the model's execution. By default, the monitors have
  9. * tracing reactions, printing the monitor output via tracepoints.
  10. * But other reactions can be added (on-demand) via this interface.
  11. *
  12. * == Registering reactors ==
  13. *
  14. * The struct rv_reactor defines a callback function to be executed
  15. * in case of a model exception happens. The callback function
  16. * receives a message to be (optionally) printed before executing
  17. * the reaction.
  18. *
  19. * A RV reactor is registered via:
  20. * int rv_register_reactor(struct rv_reactor *reactor)
  21. * And unregistered via:
  22. * int rv_unregister_reactor(struct rv_reactor *reactor)
  23. *
  24. * These functions are exported to modules, enabling reactors to be
  25. * dynamically loaded.
  26. *
  27. * == User interface ==
  28. *
  29. * The user interface resembles the kernel tracing interface and
  30. * presents these files:
  31. *
  32. * "available_reactors"
  33. * - List the available reactors, one per line.
  34. *
  35. * For example:
  36. * # cat available_reactors
  37. * nop
  38. * panic
  39. * printk
  40. *
  41. * "reacting_on"
  42. * - It is an on/off general switch for reactors, disabling
  43. * all reactions.
  44. *
  45. * "monitors/MONITOR/reactors"
  46. * - List available reactors, with the select reaction for the given
  47. * MONITOR inside []. The default one is the nop (no operation)
  48. * reactor.
  49. * - Writing the name of an reactor enables it to the given
  50. * MONITOR.
  51. *
  52. * For example:
  53. * # cat monitors/wip/reactors
  54. * [nop]
  55. * panic
  56. * printk
  57. * # echo panic > monitors/wip/reactors
  58. * # cat monitors/wip/reactors
  59. * nop
  60. * [panic]
  61. * printk
  62. */
  63. #include <linux/slab.h>
  64. #include "rv.h"
  65. /*
  66. * Interface for the reactor register.
  67. */
  68. static LIST_HEAD(rv_reactors_list);
  69. static struct rv_reactor_def *get_reactor_rdef_by_name(char *name)
  70. {
  71. struct rv_reactor_def *r;
  72. list_for_each_entry(r, &rv_reactors_list, list) {
  73. if (strcmp(name, r->reactor->name) == 0)
  74. return r;
  75. }
  76. return NULL;
  77. }
  78. /*
  79. * Available reactors seq functions.
  80. */
  81. static int reactors_show(struct seq_file *m, void *p)
  82. {
  83. struct rv_reactor_def *rea_def = p;
  84. seq_printf(m, "%s\n", rea_def->reactor->name);
  85. return 0;
  86. }
  87. static void reactors_stop(struct seq_file *m, void *p)
  88. {
  89. mutex_unlock(&rv_interface_lock);
  90. }
  91. static void *reactors_start(struct seq_file *m, loff_t *pos)
  92. {
  93. mutex_lock(&rv_interface_lock);
  94. return seq_list_start(&rv_reactors_list, *pos);
  95. }
  96. static void *reactors_next(struct seq_file *m, void *p, loff_t *pos)
  97. {
  98. return seq_list_next(p, &rv_reactors_list, pos);
  99. }
  100. /*
  101. * available_reactors seq definition.
  102. */
  103. static const struct seq_operations available_reactors_seq_ops = {
  104. .start = reactors_start,
  105. .next = reactors_next,
  106. .stop = reactors_stop,
  107. .show = reactors_show
  108. };
  109. /*
  110. * available_reactors interface.
  111. */
  112. static int available_reactors_open(struct inode *inode, struct file *file)
  113. {
  114. return seq_open(file, &available_reactors_seq_ops);
  115. };
  116. static const struct file_operations available_reactors_ops = {
  117. .open = available_reactors_open,
  118. .read = seq_read,
  119. .llseek = seq_lseek,
  120. .release = seq_release
  121. };
  122. /*
  123. * Monitor's reactor file.
  124. */
  125. static int monitor_reactor_show(struct seq_file *m, void *p)
  126. {
  127. struct rv_monitor_def *mdef = m->private;
  128. struct rv_reactor_def *rdef = p;
  129. if (mdef->rdef == rdef)
  130. seq_printf(m, "[%s]\n", rdef->reactor->name);
  131. else
  132. seq_printf(m, "%s\n", rdef->reactor->name);
  133. return 0;
  134. }
  135. /*
  136. * available_reactors seq definition.
  137. */
  138. static const struct seq_operations monitor_reactors_seq_ops = {
  139. .start = reactors_start,
  140. .next = reactors_next,
  141. .stop = reactors_stop,
  142. .show = monitor_reactor_show
  143. };
  144. static void monitor_swap_reactors(struct rv_monitor_def *mdef, struct rv_reactor_def *rdef,
  145. bool reacting)
  146. {
  147. bool monitor_enabled;
  148. /* nothing to do */
  149. if (mdef->rdef == rdef)
  150. return;
  151. monitor_enabled = mdef->monitor->enabled;
  152. if (monitor_enabled)
  153. rv_disable_monitor(mdef);
  154. /* swap reactor's usage */
  155. mdef->rdef->counter--;
  156. rdef->counter++;
  157. mdef->rdef = rdef;
  158. mdef->reacting = reacting;
  159. mdef->monitor->react = rdef->reactor->react;
  160. if (monitor_enabled)
  161. rv_enable_monitor(mdef);
  162. }
  163. static ssize_t
  164. monitor_reactors_write(struct file *file, const char __user *user_buf,
  165. size_t count, loff_t *ppos)
  166. {
  167. char buff[MAX_RV_REACTOR_NAME_SIZE + 2];
  168. struct rv_monitor_def *mdef;
  169. struct rv_reactor_def *rdef;
  170. struct seq_file *seq_f;
  171. int retval = -EINVAL;
  172. bool enable;
  173. char *ptr;
  174. int len;
  175. if (count < 1 || count > MAX_RV_REACTOR_NAME_SIZE + 1)
  176. return -EINVAL;
  177. memset(buff, 0, sizeof(buff));
  178. retval = simple_write_to_buffer(buff, sizeof(buff) - 1, ppos, user_buf, count);
  179. if (retval < 0)
  180. return -EFAULT;
  181. ptr = strim(buff);
  182. len = strlen(ptr);
  183. if (!len)
  184. return count;
  185. /*
  186. * See monitor_reactors_open()
  187. */
  188. seq_f = file->private_data;
  189. mdef = seq_f->private;
  190. mutex_lock(&rv_interface_lock);
  191. retval = -EINVAL;
  192. list_for_each_entry(rdef, &rv_reactors_list, list) {
  193. if (strcmp(ptr, rdef->reactor->name) != 0)
  194. continue;
  195. if (rdef == get_reactor_rdef_by_name("nop"))
  196. enable = false;
  197. else
  198. enable = true;
  199. monitor_swap_reactors(mdef, rdef, enable);
  200. retval = count;
  201. break;
  202. }
  203. mutex_unlock(&rv_interface_lock);
  204. return retval;
  205. }
  206. /*
  207. * available_reactors interface.
  208. */
  209. static int monitor_reactors_open(struct inode *inode, struct file *file)
  210. {
  211. struct rv_monitor_def *mdef = inode->i_private;
  212. struct seq_file *seq_f;
  213. int ret;
  214. ret = seq_open(file, &monitor_reactors_seq_ops);
  215. if (ret < 0)
  216. return ret;
  217. /*
  218. * seq_open stores the seq_file on the file->private data.
  219. */
  220. seq_f = file->private_data;
  221. /*
  222. * Copy the create file "private" data to the seq_file private data.
  223. */
  224. seq_f->private = mdef;
  225. return 0;
  226. };
  227. static const struct file_operations monitor_reactors_ops = {
  228. .open = monitor_reactors_open,
  229. .read = seq_read,
  230. .llseek = seq_lseek,
  231. .release = seq_release,
  232. .write = monitor_reactors_write
  233. };
  234. static int __rv_register_reactor(struct rv_reactor *reactor)
  235. {
  236. struct rv_reactor_def *r;
  237. list_for_each_entry(r, &rv_reactors_list, list) {
  238. if (strcmp(reactor->name, r->reactor->name) == 0) {
  239. pr_info("Reactor %s is already registered\n", reactor->name);
  240. return -EINVAL;
  241. }
  242. }
  243. r = kzalloc(sizeof(struct rv_reactor_def), GFP_KERNEL);
  244. if (!r)
  245. return -ENOMEM;
  246. r->reactor = reactor;
  247. r->counter = 0;
  248. list_add_tail(&r->list, &rv_reactors_list);
  249. return 0;
  250. }
  251. /**
  252. * rv_register_reactor - register a rv reactor.
  253. * @reactor: The rv_reactor to be registered.
  254. *
  255. * Returns 0 if successful, error otherwise.
  256. */
  257. int rv_register_reactor(struct rv_reactor *reactor)
  258. {
  259. int retval = 0;
  260. if (strlen(reactor->name) >= MAX_RV_REACTOR_NAME_SIZE) {
  261. pr_info("Reactor %s has a name longer than %d\n",
  262. reactor->name, MAX_RV_MONITOR_NAME_SIZE);
  263. return -EINVAL;
  264. }
  265. mutex_lock(&rv_interface_lock);
  266. retval = __rv_register_reactor(reactor);
  267. mutex_unlock(&rv_interface_lock);
  268. return retval;
  269. }
  270. /**
  271. * rv_unregister_reactor - unregister a rv reactor.
  272. * @reactor: The rv_reactor to be unregistered.
  273. *
  274. * Returns 0 if successful, error otherwise.
  275. */
  276. int rv_unregister_reactor(struct rv_reactor *reactor)
  277. {
  278. struct rv_reactor_def *ptr, *next;
  279. int ret = 0;
  280. mutex_lock(&rv_interface_lock);
  281. list_for_each_entry_safe(ptr, next, &rv_reactors_list, list) {
  282. if (strcmp(reactor->name, ptr->reactor->name) == 0) {
  283. if (!ptr->counter) {
  284. list_del(&ptr->list);
  285. } else {
  286. printk(KERN_WARNING
  287. "rv: the rv_reactor %s is in use by %d monitor(s)\n",
  288. ptr->reactor->name, ptr->counter);
  289. printk(KERN_WARNING "rv: the rv_reactor %s cannot be removed\n",
  290. ptr->reactor->name);
  291. ret = -EBUSY;
  292. break;
  293. }
  294. }
  295. }
  296. mutex_unlock(&rv_interface_lock);
  297. return ret;
  298. }
  299. /*
  300. * reacting_on interface.
  301. */
  302. static bool __read_mostly reacting_on;
  303. /**
  304. * rv_reacting_on - checks if reacting is on
  305. *
  306. * Returns 1 if on, 0 otherwise.
  307. */
  308. bool rv_reacting_on(void)
  309. {
  310. /* Ensures that concurrent monitors read consistent reacting_on */
  311. smp_rmb();
  312. return READ_ONCE(reacting_on);
  313. }
  314. static ssize_t reacting_on_read_data(struct file *filp,
  315. char __user *user_buf,
  316. size_t count, loff_t *ppos)
  317. {
  318. char *buff;
  319. buff = rv_reacting_on() ? "1\n" : "0\n";
  320. return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
  321. }
  322. static void turn_reacting_off(void)
  323. {
  324. WRITE_ONCE(reacting_on, false);
  325. /* Ensures that concurrent monitors read consistent reacting_on */
  326. smp_wmb();
  327. }
  328. static void turn_reacting_on(void)
  329. {
  330. WRITE_ONCE(reacting_on, true);
  331. /* Ensures that concurrent monitors read consistent reacting_on */
  332. smp_wmb();
  333. }
  334. static ssize_t reacting_on_write_data(struct file *filp, const char __user *user_buf,
  335. size_t count, loff_t *ppos)
  336. {
  337. int retval;
  338. bool val;
  339. retval = kstrtobool_from_user(user_buf, count, &val);
  340. if (retval)
  341. return retval;
  342. mutex_lock(&rv_interface_lock);
  343. if (val)
  344. turn_reacting_on();
  345. else
  346. turn_reacting_off();
  347. /*
  348. * Wait for the execution of all events to finish
  349. * before returning to user-space.
  350. */
  351. tracepoint_synchronize_unregister();
  352. mutex_unlock(&rv_interface_lock);
  353. return count;
  354. }
  355. static const struct file_operations reacting_on_fops = {
  356. .open = simple_open,
  357. .llseek = no_llseek,
  358. .write = reacting_on_write_data,
  359. .read = reacting_on_read_data,
  360. };
  361. /**
  362. * reactor_populate_monitor - creates per monitor reactors file
  363. * @mdef: monitor's definition.
  364. *
  365. * Returns 0 if successful, error otherwise.
  366. */
  367. int reactor_populate_monitor(struct rv_monitor_def *mdef)
  368. {
  369. struct dentry *tmp;
  370. tmp = rv_create_file("reactors", RV_MODE_WRITE, mdef->root_d, mdef, &monitor_reactors_ops);
  371. if (!tmp)
  372. return -ENOMEM;
  373. /*
  374. * Configure as the rv_nop reactor.
  375. */
  376. mdef->rdef = get_reactor_rdef_by_name("nop");
  377. mdef->rdef->counter++;
  378. mdef->reacting = false;
  379. return 0;
  380. }
  381. /**
  382. * reactor_cleanup_monitor - cleanup a monitor reference
  383. * @mdef: monitor's definition.
  384. */
  385. void reactor_cleanup_monitor(struct rv_monitor_def *mdef)
  386. {
  387. lockdep_assert_held(&rv_interface_lock);
  388. mdef->rdef->counter--;
  389. WARN_ON_ONCE(mdef->rdef->counter < 0);
  390. }
  391. /*
  392. * Nop reactor register
  393. */
  394. static void rv_nop_reaction(char *msg)
  395. {
  396. }
  397. static struct rv_reactor rv_nop = {
  398. .name = "nop",
  399. .description = "no-operation reactor: do nothing.",
  400. .react = rv_nop_reaction
  401. };
  402. int init_rv_reactors(struct dentry *root_dir)
  403. {
  404. struct dentry *available, *reacting;
  405. int retval;
  406. available = rv_create_file("available_reactors", RV_MODE_READ, root_dir, NULL,
  407. &available_reactors_ops);
  408. if (!available)
  409. goto out_err;
  410. reacting = rv_create_file("reacting_on", RV_MODE_WRITE, root_dir, NULL, &reacting_on_fops);
  411. if (!reacting)
  412. goto rm_available;
  413. retval = __rv_register_reactor(&rv_nop);
  414. if (retval)
  415. goto rm_reacting;
  416. turn_reacting_on();
  417. return 0;
  418. rm_reacting:
  419. rv_remove(reacting);
  420. rm_available:
  421. rv_remove(available);
  422. out_err:
  423. return -ENOMEM;
  424. }