Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
0004  *
0005  * Runtime reactor interface.
0006  *
0007  * A runtime monitor can cause a reaction to the detection of an
0008  * exception on the model's execution. By default, the monitors have
0009  * tracing reactions, printing the monitor output via tracepoints.
0010  * But other reactions can be added (on-demand) via this interface.
0011  *
0012  * == Registering reactors ==
0013  *
0014  * The struct rv_reactor defines a callback function to be executed
0015  * in case of a model exception happens. The callback function
0016  * receives a message to be (optionally) printed before executing
0017  * the reaction.
0018  *
0019  * A RV reactor is registered via:
0020  *   int rv_register_reactor(struct rv_reactor *reactor)
0021  * And unregistered via:
0022  *   int rv_unregister_reactor(struct rv_reactor *reactor)
0023  *
0024  * These functions are exported to modules, enabling reactors to be
0025  * dynamically loaded.
0026  *
0027  * == User interface ==
0028  *
0029  * The user interface resembles the kernel tracing interface and
0030  * presents these files:
0031  *
0032  *  "available_reactors"
0033  *    - List the available reactors, one per line.
0034  *
0035  *    For example:
0036  *      # cat available_reactors
0037  *      nop
0038  *      panic
0039  *      printk
0040  *
0041  *  "reacting_on"
0042  *    - It is an on/off general switch for reactors, disabling
0043  *    all reactions.
0044  *
0045  *  "monitors/MONITOR/reactors"
0046  *    - List available reactors, with the select reaction for the given
0047  *    MONITOR inside []. The default one is the nop (no operation)
0048  *    reactor.
0049  *    - Writing the name of an reactor enables it to the given
0050  *    MONITOR.
0051  *
0052  *    For example:
0053  *      # cat monitors/wip/reactors
0054  *      [nop]
0055  *      panic
0056  *      printk
0057  *      # echo panic > monitors/wip/reactors
0058  *      # cat monitors/wip/reactors
0059  *      nop
0060  *      [panic]
0061  *      printk
0062  */
0063 
0064 #include <linux/slab.h>
0065 
0066 #include "rv.h"
0067 
0068 /*
0069  * Interface for the reactor register.
0070  */
0071 static LIST_HEAD(rv_reactors_list);
0072 
0073 static struct rv_reactor_def *get_reactor_rdef_by_name(char *name)
0074 {
0075     struct rv_reactor_def *r;
0076 
0077     list_for_each_entry(r, &rv_reactors_list, list) {
0078         if (strcmp(name, r->reactor->name) == 0)
0079             return r;
0080     }
0081     return NULL;
0082 }
0083 
0084 /*
0085  * Available reactors seq functions.
0086  */
0087 static int reactors_show(struct seq_file *m, void *p)
0088 {
0089     struct rv_reactor_def *rea_def = p;
0090 
0091     seq_printf(m, "%s\n", rea_def->reactor->name);
0092     return 0;
0093 }
0094 
0095 static void reactors_stop(struct seq_file *m, void *p)
0096 {
0097     mutex_unlock(&rv_interface_lock);
0098 }
0099 
0100 static void *reactors_start(struct seq_file *m, loff_t *pos)
0101 {
0102     mutex_lock(&rv_interface_lock);
0103     return seq_list_start(&rv_reactors_list, *pos);
0104 }
0105 
0106 static void *reactors_next(struct seq_file *m, void *p, loff_t *pos)
0107 {
0108     return seq_list_next(p, &rv_reactors_list, pos);
0109 }
0110 
0111 /*
0112  * available_reactors seq definition.
0113  */
0114 static const struct seq_operations available_reactors_seq_ops = {
0115     .start  = reactors_start,
0116     .next   = reactors_next,
0117     .stop   = reactors_stop,
0118     .show   = reactors_show
0119 };
0120 
0121 /*
0122  * available_reactors interface.
0123  */
0124 static int available_reactors_open(struct inode *inode, struct file *file)
0125 {
0126     return seq_open(file, &available_reactors_seq_ops);
0127 };
0128 
0129 static const struct file_operations available_reactors_ops = {
0130     .open    = available_reactors_open,
0131     .read    = seq_read,
0132     .llseek  = seq_lseek,
0133     .release = seq_release
0134 };
0135 
0136 /*
0137  * Monitor's reactor file.
0138  */
0139 static int monitor_reactor_show(struct seq_file *m, void *p)
0140 {
0141     struct rv_monitor_def *mdef = m->private;
0142     struct rv_reactor_def *rdef = p;
0143 
0144     if (mdef->rdef == rdef)
0145         seq_printf(m, "[%s]\n", rdef->reactor->name);
0146     else
0147         seq_printf(m, "%s\n", rdef->reactor->name);
0148     return 0;
0149 }
0150 
0151 /*
0152  * available_reactors seq definition.
0153  */
0154 static const struct seq_operations monitor_reactors_seq_ops = {
0155     .start  = reactors_start,
0156     .next   = reactors_next,
0157     .stop   = reactors_stop,
0158     .show   = monitor_reactor_show
0159 };
0160 
0161 static void monitor_swap_reactors(struct rv_monitor_def *mdef, struct rv_reactor_def *rdef,
0162                     bool reacting)
0163 {
0164     bool monitor_enabled;
0165 
0166     /* nothing to do */
0167     if (mdef->rdef == rdef)
0168         return;
0169 
0170     monitor_enabled = mdef->monitor->enabled;
0171     if (monitor_enabled)
0172         rv_disable_monitor(mdef);
0173 
0174     /* swap reactor's usage */
0175     mdef->rdef->counter--;
0176     rdef->counter++;
0177 
0178     mdef->rdef = rdef;
0179     mdef->reacting = reacting;
0180     mdef->monitor->react = rdef->reactor->react;
0181 
0182     if (monitor_enabled)
0183         rv_enable_monitor(mdef);
0184 }
0185 
0186 static ssize_t
0187 monitor_reactors_write(struct file *file, const char __user *user_buf,
0188               size_t count, loff_t *ppos)
0189 {
0190     char buff[MAX_RV_REACTOR_NAME_SIZE + 2];
0191     struct rv_monitor_def *mdef;
0192     struct rv_reactor_def *rdef;
0193     struct seq_file *seq_f;
0194     int retval = -EINVAL;
0195     bool enable;
0196     char *ptr;
0197     int len;
0198 
0199     if (count < 1 || count > MAX_RV_REACTOR_NAME_SIZE + 1)
0200         return -EINVAL;
0201 
0202     memset(buff, 0, sizeof(buff));
0203 
0204     retval = simple_write_to_buffer(buff, sizeof(buff) - 1, ppos, user_buf, count);
0205     if (retval < 0)
0206         return -EFAULT;
0207 
0208     ptr = strim(buff);
0209 
0210     len = strlen(ptr);
0211     if (!len)
0212         return count;
0213 
0214     /*
0215      * See monitor_reactors_open()
0216      */
0217     seq_f = file->private_data;
0218     mdef = seq_f->private;
0219 
0220     mutex_lock(&rv_interface_lock);
0221 
0222     retval = -EINVAL;
0223 
0224     list_for_each_entry(rdef, &rv_reactors_list, list) {
0225         if (strcmp(ptr, rdef->reactor->name) != 0)
0226             continue;
0227 
0228         if (rdef == get_reactor_rdef_by_name("nop"))
0229             enable = false;
0230         else
0231             enable = true;
0232 
0233         monitor_swap_reactors(mdef, rdef, enable);
0234 
0235         retval = count;
0236         break;
0237     }
0238 
0239     mutex_unlock(&rv_interface_lock);
0240 
0241     return retval;
0242 }
0243 
0244 /*
0245  * available_reactors interface.
0246  */
0247 static int monitor_reactors_open(struct inode *inode, struct file *file)
0248 {
0249     struct rv_monitor_def *mdef = inode->i_private;
0250     struct seq_file *seq_f;
0251     int ret;
0252 
0253     ret = seq_open(file, &monitor_reactors_seq_ops);
0254     if (ret < 0)
0255         return ret;
0256 
0257     /*
0258      * seq_open stores the seq_file on the file->private data.
0259      */
0260     seq_f = file->private_data;
0261 
0262     /*
0263      * Copy the create file "private" data to the seq_file private data.
0264      */
0265     seq_f->private = mdef;
0266 
0267     return 0;
0268 };
0269 
0270 static const struct file_operations monitor_reactors_ops = {
0271     .open    = monitor_reactors_open,
0272     .read    = seq_read,
0273     .llseek  = seq_lseek,
0274     .release = seq_release,
0275     .write = monitor_reactors_write
0276 };
0277 
0278 static int __rv_register_reactor(struct rv_reactor *reactor)
0279 {
0280     struct rv_reactor_def *r;
0281 
0282     list_for_each_entry(r, &rv_reactors_list, list) {
0283         if (strcmp(reactor->name, r->reactor->name) == 0) {
0284             pr_info("Reactor %s is already registered\n", reactor->name);
0285             return -EINVAL;
0286         }
0287     }
0288 
0289     r = kzalloc(sizeof(struct rv_reactor_def), GFP_KERNEL);
0290     if (!r)
0291         return -ENOMEM;
0292 
0293     r->reactor = reactor;
0294     r->counter = 0;
0295 
0296     list_add_tail(&r->list, &rv_reactors_list);
0297 
0298     return 0;
0299 }
0300 
0301 /**
0302  * rv_register_reactor - register a rv reactor.
0303  * @reactor:    The rv_reactor to be registered.
0304  *
0305  * Returns 0 if successful, error otherwise.
0306  */
0307 int rv_register_reactor(struct rv_reactor *reactor)
0308 {
0309     int retval = 0;
0310 
0311     if (strlen(reactor->name) >= MAX_RV_REACTOR_NAME_SIZE) {
0312         pr_info("Reactor %s has a name longer than %d\n",
0313             reactor->name, MAX_RV_MONITOR_NAME_SIZE);
0314         return -EINVAL;
0315     }
0316 
0317     mutex_lock(&rv_interface_lock);
0318     retval = __rv_register_reactor(reactor);
0319     mutex_unlock(&rv_interface_lock);
0320     return retval;
0321 }
0322 
0323 /**
0324  * rv_unregister_reactor - unregister a rv reactor.
0325  * @reactor:    The rv_reactor to be unregistered.
0326  *
0327  * Returns 0 if successful, error otherwise.
0328  */
0329 int rv_unregister_reactor(struct rv_reactor *reactor)
0330 {
0331     struct rv_reactor_def *ptr, *next;
0332     int ret = 0;
0333 
0334     mutex_lock(&rv_interface_lock);
0335 
0336     list_for_each_entry_safe(ptr, next, &rv_reactors_list, list) {
0337         if (strcmp(reactor->name, ptr->reactor->name) == 0) {
0338 
0339             if (!ptr->counter) {
0340                 list_del(&ptr->list);
0341             } else {
0342                 printk(KERN_WARNING
0343                        "rv: the rv_reactor %s is in use by %d monitor(s)\n",
0344                        ptr->reactor->name, ptr->counter);
0345                 printk(KERN_WARNING "rv: the rv_reactor %s cannot be removed\n",
0346                        ptr->reactor->name);
0347                 ret = -EBUSY;
0348                 break;
0349             }
0350         }
0351     }
0352 
0353     mutex_unlock(&rv_interface_lock);
0354     return ret;
0355 }
0356 
0357 /*
0358  * reacting_on interface.
0359  */
0360 static bool __read_mostly reacting_on;
0361 
0362 /**
0363  * rv_reacting_on - checks if reacting is on
0364  *
0365  * Returns 1 if on, 0 otherwise.
0366  */
0367 bool rv_reacting_on(void)
0368 {
0369     /* Ensures that concurrent monitors read consistent reacting_on */
0370     smp_rmb();
0371     return READ_ONCE(reacting_on);
0372 }
0373 
0374 static ssize_t reacting_on_read_data(struct file *filp,
0375                      char __user *user_buf,
0376                      size_t count, loff_t *ppos)
0377 {
0378     char *buff;
0379 
0380     buff = rv_reacting_on() ? "1\n" : "0\n";
0381 
0382     return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
0383 }
0384 
0385 static void turn_reacting_off(void)
0386 {
0387     WRITE_ONCE(reacting_on, false);
0388     /* Ensures that concurrent monitors read consistent reacting_on */
0389     smp_wmb();
0390 }
0391 
0392 static void turn_reacting_on(void)
0393 {
0394     WRITE_ONCE(reacting_on, true);
0395     /* Ensures that concurrent monitors read consistent reacting_on */
0396     smp_wmb();
0397 }
0398 
0399 static ssize_t reacting_on_write_data(struct file *filp, const char __user *user_buf,
0400                       size_t count, loff_t *ppos)
0401 {
0402     int retval;
0403     bool val;
0404 
0405     retval = kstrtobool_from_user(user_buf, count, &val);
0406     if (retval)
0407         return retval;
0408 
0409     mutex_lock(&rv_interface_lock);
0410 
0411     if (val)
0412         turn_reacting_on();
0413     else
0414         turn_reacting_off();
0415 
0416     /*
0417      * Wait for the execution of all events to finish
0418      * before returning to user-space.
0419      */
0420     tracepoint_synchronize_unregister();
0421 
0422     mutex_unlock(&rv_interface_lock);
0423 
0424     return count;
0425 }
0426 
0427 static const struct file_operations reacting_on_fops = {
0428     .open   = simple_open,
0429     .llseek = no_llseek,
0430     .write  = reacting_on_write_data,
0431     .read   = reacting_on_read_data,
0432 };
0433 
0434 /**
0435  * reactor_populate_monitor - creates per monitor reactors file
0436  * @mdef:   monitor's definition.
0437  *
0438  * Returns 0 if successful, error otherwise.
0439  */
0440 int reactor_populate_monitor(struct rv_monitor_def *mdef)
0441 {
0442     struct dentry *tmp;
0443 
0444     tmp = rv_create_file("reactors", RV_MODE_WRITE, mdef->root_d, mdef, &monitor_reactors_ops);
0445     if (!tmp)
0446         return -ENOMEM;
0447 
0448     /*
0449      * Configure as the rv_nop reactor.
0450      */
0451     mdef->rdef = get_reactor_rdef_by_name("nop");
0452     mdef->rdef->counter++;
0453     mdef->reacting = false;
0454 
0455     return 0;
0456 }
0457 
0458 /**
0459  * reactor_cleanup_monitor - cleanup a monitor reference
0460  * @mdef:       monitor's definition.
0461  */
0462 void reactor_cleanup_monitor(struct rv_monitor_def *mdef)
0463 {
0464     lockdep_assert_held(&rv_interface_lock);
0465     mdef->rdef->counter--;
0466     WARN_ON_ONCE(mdef->rdef->counter < 0);
0467 }
0468 
0469 /*
0470  * Nop reactor register
0471  */
0472 static void rv_nop_reaction(char *msg)
0473 {
0474 }
0475 
0476 static struct rv_reactor rv_nop = {
0477     .name = "nop",
0478     .description = "no-operation reactor: do nothing.",
0479     .react = rv_nop_reaction
0480 };
0481 
0482 int init_rv_reactors(struct dentry *root_dir)
0483 {
0484     struct dentry *available, *reacting;
0485     int retval;
0486 
0487     available = rv_create_file("available_reactors", RV_MODE_READ, root_dir, NULL,
0488                    &available_reactors_ops);
0489     if (!available)
0490         goto out_err;
0491 
0492     reacting = rv_create_file("reacting_on", RV_MODE_WRITE, root_dir, NULL, &reacting_on_fops);
0493     if (!reacting)
0494         goto rm_available;
0495 
0496     retval = __rv_register_reactor(&rv_nop);
0497     if (retval)
0498         goto rm_reacting;
0499 
0500     turn_reacting_on();
0501 
0502     return 0;
0503 
0504 rm_reacting:
0505     rv_remove(reacting);
0506 rm_available:
0507     rv_remove(available);
0508 out_err:
0509     return -ENOMEM;
0510 }