1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
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
64#include <linux/lockdep.h>
65#include <linux/slab.h>
66
67#include "rv.h"
68
69/*
70 * Interface for the reactor register.
71 */
72static LIST_HEAD(rv_reactors_list);
73
74static struct rv_reactor *get_reactor_rdef_by_name(char *name)
75{
76 struct rv_reactor *r;
77
78 list_for_each_entry(r, &rv_reactors_list, list) {
79 if (strcmp(name, r->name) == 0)
80 return r;
81 }
82 return NULL;
83}
84
85/*
86 * Available reactors seq functions.
87 */
88static int reactors_show(struct seq_file *m, void *p)
89{
90 struct rv_reactor *reactor = container_of(p, struct rv_reactor, list);
91
92 seq_printf(m, fmt: "%s\n", reactor->name);
93 return 0;
94}
95
96static void reactors_stop(struct seq_file *m, void *p)
97{
98 mutex_unlock(lock: &rv_interface_lock);
99}
100
101static void *reactors_start(struct seq_file *m, loff_t *pos)
102{
103 mutex_lock(&rv_interface_lock);
104 return seq_list_start(head: &rv_reactors_list, pos: *pos);
105}
106
107static void *reactors_next(struct seq_file *m, void *p, loff_t *pos)
108{
109 return seq_list_next(v: p, head: &rv_reactors_list, ppos: pos);
110}
111
112/*
113 * available_reactors seq definition.
114 */
115static const struct seq_operations available_reactors_seq_ops = {
116 .start = reactors_start,
117 .next = reactors_next,
118 .stop = reactors_stop,
119 .show = reactors_show
120};
121
122/*
123 * available_reactors interface.
124 */
125static int available_reactors_open(struct inode *inode, struct file *file)
126{
127 return seq_open(file, &available_reactors_seq_ops);
128};
129
130static const struct file_operations available_reactors_ops = {
131 .open = available_reactors_open,
132 .read = seq_read,
133 .llseek = seq_lseek,
134 .release = seq_release
135};
136
137/*
138 * Monitor's reactor file.
139 */
140static int monitor_reactor_show(struct seq_file *m, void *p)
141{
142 struct rv_monitor *mon = m->private;
143 struct rv_reactor *reactor = container_of(p, struct rv_reactor, list);
144
145 if (mon->reactor == reactor)
146 seq_printf(m, fmt: "[%s]\n", reactor->name);
147 else
148 seq_printf(m, fmt: "%s\n", reactor->name);
149 return 0;
150}
151
152/*
153 * available_reactors seq definition.
154 */
155static const struct seq_operations monitor_reactors_seq_ops = {
156 .start = reactors_start,
157 .next = reactors_next,
158 .stop = reactors_stop,
159 .show = monitor_reactor_show
160};
161
162static void monitor_swap_reactors_single(struct rv_monitor *mon,
163 struct rv_reactor *reactor,
164 bool nested)
165{
166 bool monitor_enabled;
167
168 /* nothing to do */
169 if (mon->reactor == reactor)
170 return;
171
172 monitor_enabled = mon->enabled;
173 if (monitor_enabled)
174 rv_disable_monitor(mon);
175
176 mon->reactor = reactor;
177 mon->react = reactor->react;
178
179 /* enable only once if iterating through a container */
180 if (monitor_enabled && !nested)
181 rv_enable_monitor(mon);
182}
183
184static void monitor_swap_reactors(struct rv_monitor *mon, struct rv_reactor *reactor)
185{
186 struct rv_monitor *p = mon;
187
188 if (rv_is_container_monitor(mon))
189 list_for_each_entry_continue(p, &rv_monitors_list, list) {
190 if (p->parent != mon)
191 break;
192 monitor_swap_reactors_single(mon: p, reactor, nested: true);
193 }
194 /*
195 * This call enables and disables the monitor if they were active.
196 * In case of a container, we already disabled all and will enable all.
197 * All nested monitors are enabled also if they were off, we may refine
198 * this logic in the future.
199 */
200 monitor_swap_reactors_single(mon, reactor, nested: false);
201}
202
203static ssize_t
204monitor_reactors_write(struct file *file, const char __user *user_buf,
205 size_t count, loff_t *ppos)
206{
207 char buff[MAX_RV_REACTOR_NAME_SIZE + 2];
208 struct rv_monitor *mon;
209 struct rv_reactor *reactor;
210 struct seq_file *seq_f;
211 int retval = -EINVAL;
212 char *ptr;
213 int len;
214
215 if (count < 1 || count > MAX_RV_REACTOR_NAME_SIZE + 1)
216 return -EINVAL;
217
218 memset(buff, 0, sizeof(buff));
219
220 retval = simple_write_to_buffer(to: buff, available: sizeof(buff) - 1, ppos, from: user_buf, count);
221 if (retval < 0)
222 return -EFAULT;
223
224 ptr = strim(buff);
225
226 len = strlen(ptr);
227 if (!len)
228 return count;
229
230 /*
231 * See monitor_reactors_open()
232 */
233 seq_f = file->private_data;
234 mon = seq_f->private;
235
236 guard(mutex)(T: &rv_interface_lock);
237
238 list_for_each_entry(reactor, &rv_reactors_list, list) {
239 if (strcmp(ptr, reactor->name) != 0)
240 continue;
241
242 monitor_swap_reactors(mon, reactor);
243
244 return count;
245 }
246
247 return -EINVAL;
248}
249
250/*
251 * available_reactors interface.
252 */
253static int monitor_reactors_open(struct inode *inode, struct file *file)
254{
255 struct rv_monitor *mon = inode->i_private;
256 struct seq_file *seq_f;
257 int ret;
258
259 ret = seq_open(file, &monitor_reactors_seq_ops);
260 if (ret < 0)
261 return ret;
262
263 /*
264 * seq_open stores the seq_file on the file->private data.
265 */
266 seq_f = file->private_data;
267
268 /*
269 * Copy the create file "private" data to the seq_file private data.
270 */
271 seq_f->private = mon;
272
273 return 0;
274};
275
276static const struct file_operations monitor_reactors_ops = {
277 .open = monitor_reactors_open,
278 .read = seq_read,
279 .llseek = seq_lseek,
280 .release = seq_release,
281 .write = monitor_reactors_write
282};
283
284static int __rv_register_reactor(struct rv_reactor *reactor)
285{
286 struct rv_reactor *r;
287
288 list_for_each_entry(r, &rv_reactors_list, list) {
289 if (strcmp(reactor->name, r->name) == 0) {
290 pr_info("Reactor %s is already registered\n", reactor->name);
291 return -EINVAL;
292 }
293 }
294
295 list_add_tail(new: &reactor->list, head: &rv_reactors_list);
296
297 return 0;
298}
299
300/**
301 * rv_register_reactor - register a rv reactor.
302 * @reactor: The rv_reactor to be registered.
303 *
304 * Returns 0 if successful, error otherwise.
305 */
306int rv_register_reactor(struct rv_reactor *reactor)
307{
308 if (strlen(reactor->name) >= MAX_RV_REACTOR_NAME_SIZE) {
309 pr_info("Reactor %s has a name longer than %d\n",
310 reactor->name, MAX_RV_MONITOR_NAME_SIZE);
311 return -EINVAL;
312 }
313
314 guard(mutex)(T: &rv_interface_lock);
315 return __rv_register_reactor(reactor);
316}
317
318/**
319 * rv_unregister_reactor - unregister a rv reactor.
320 * @reactor: The rv_reactor to be unregistered.
321 *
322 * Returns 0 if successful, error otherwise.
323 */
324int rv_unregister_reactor(struct rv_reactor *reactor)
325{
326 guard(mutex)(T: &rv_interface_lock);
327 list_del(entry: &reactor->list);
328 return 0;
329}
330
331/*
332 * reacting_on interface.
333 */
334static bool __read_mostly reacting_on;
335
336/**
337 * rv_reacting_on - checks if reacting is on
338 *
339 * Returns 1 if on, 0 otherwise.
340 */
341static bool rv_reacting_on(void)
342{
343 /* Ensures that concurrent monitors read consistent reacting_on */
344 smp_rmb();
345 return READ_ONCE(reacting_on);
346}
347
348static ssize_t reacting_on_read_data(struct file *filp,
349 char __user *user_buf,
350 size_t count, loff_t *ppos)
351{
352 char *buff;
353
354 buff = rv_reacting_on() ? "1\n" : "0\n";
355
356 return simple_read_from_buffer(to: user_buf, count, ppos, from: buff, strlen(buff)+1);
357}
358
359static void turn_reacting_off(void)
360{
361 WRITE_ONCE(reacting_on, false);
362 /* Ensures that concurrent monitors read consistent reacting_on */
363 smp_wmb();
364}
365
366static void turn_reacting_on(void)
367{
368 WRITE_ONCE(reacting_on, true);
369 /* Ensures that concurrent monitors read consistent reacting_on */
370 smp_wmb();
371}
372
373static ssize_t reacting_on_write_data(struct file *filp, const char __user *user_buf,
374 size_t count, loff_t *ppos)
375{
376 int retval;
377 bool val;
378
379 retval = kstrtobool_from_user(s: user_buf, count, res: &val);
380 if (retval)
381 return retval;
382
383 guard(mutex)(T: &rv_interface_lock);
384
385 if (val)
386 turn_reacting_on();
387 else
388 turn_reacting_off();
389
390 /*
391 * Wait for the execution of all events to finish
392 * before returning to user-space.
393 */
394 tracepoint_synchronize_unregister();
395
396 return count;
397}
398
399static const struct file_operations reacting_on_fops = {
400 .open = simple_open,
401 .write = reacting_on_write_data,
402 .read = reacting_on_read_data,
403};
404
405/**
406 * reactor_populate_monitor - creates per monitor reactors file
407 * @mon: The monitor.
408 * @root: The directory of the monitor.
409 *
410 * Returns 0 if successful, error otherwise.
411 */
412int reactor_populate_monitor(struct rv_monitor *mon, struct dentry *root)
413{
414 struct dentry *tmp;
415
416 tmp = rv_create_file(name: "reactors", RV_MODE_WRITE, parent: root, data: mon, fops: &monitor_reactors_ops);
417 if (!tmp)
418 return -ENOMEM;
419
420 /*
421 * Configure as the rv_nop reactor.
422 */
423 mon->reactor = get_reactor_rdef_by_name(name: "nop");
424
425 return 0;
426}
427
428/*
429 * Nop reactor register
430 */
431__printf(1, 0) static void rv_nop_reaction(const char *msg, va_list args)
432{
433}
434
435static struct rv_reactor rv_nop = {
436 .name = "nop",
437 .description = "no-operation reactor: do nothing.",
438 .react = rv_nop_reaction
439};
440
441int init_rv_reactors(struct dentry *root_dir)
442{
443 int retval;
444
445 struct dentry *available __free(rv_remove) =
446 rv_create_file(name: "available_reactors", RV_MODE_READ, parent: root_dir,
447 NULL, fops: &available_reactors_ops);
448
449 struct dentry *reacting __free(rv_remove) =
450 rv_create_file(name: "reacting_on", RV_MODE_WRITE, parent: root_dir, NULL, fops: &reacting_on_fops);
451
452 if (!reacting || !available)
453 return -ENOMEM;
454
455 retval = __rv_register_reactor(reactor: &rv_nop);
456 if (retval)
457 return retval;
458
459 turn_reacting_on();
460
461 retain_and_null_ptr(available);
462 retain_and_null_ptr(reacting);
463 return 0;
464}
465
466void rv_react(struct rv_monitor *monitor, const char *msg, ...)
467{
468 static DEFINE_WAIT_OVERRIDE_MAP(rv_react_map, LD_WAIT_FREE);
469 va_list args;
470
471 if (!rv_reacting_on() || !monitor->react)
472 return;
473
474 va_start(args, msg);
475
476 lock_map_acquire_try(&rv_react_map);
477 monitor->react(msg, args);
478 lock_map_release(&rv_react_map);
479
480 va_end(args);
481}
482

source code of linux/kernel/trace/rv/rv_reactors.c