LCOV - code coverage report
Current view: top level - kernel - params.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 164 367 44.7 %
Date: 2021-04-22 12:43:58 Functions: 15 57 26.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* Helpers for initial module or kernel cmdline parsing
       3             :    Copyright (C) 2001 Rusty Russell.
       4             : 
       5             : */
       6             : #include <linux/kernel.h>
       7             : #include <linux/string.h>
       8             : #include <linux/errno.h>
       9             : #include <linux/module.h>
      10             : #include <linux/moduleparam.h>
      11             : #include <linux/device.h>
      12             : #include <linux/err.h>
      13             : #include <linux/slab.h>
      14             : #include <linux/ctype.h>
      15             : #include <linux/security.h>
      16             : 
      17             : #ifdef CONFIG_SYSFS
      18             : /* Protects all built-in parameters, modules use their own param_lock */
      19             : static DEFINE_MUTEX(param_lock);
      20             : 
      21             : /* Use the module's mutex, or if built-in use the built-in mutex */
      22             : #ifdef CONFIG_MODULES
      23             : #define KPARAM_MUTEX(mod)       ((mod) ? &(mod)->param_lock : &param_lock)
      24             : #else
      25             : #define KPARAM_MUTEX(mod)       (&param_lock)
      26             : #endif
      27             : 
      28           0 : static inline void check_kparam_locked(struct module *mod)
      29             : {
      30           0 :         BUG_ON(!mutex_is_locked(KPARAM_MUTEX(mod)));
      31           0 : }
      32             : #else
      33             : static inline void check_kparam_locked(struct module *mod)
      34             : {
      35             : }
      36             : #endif /* !CONFIG_SYSFS */
      37             : 
      38             : /* This just allows us to keep track of which parameters are kmalloced. */
      39             : struct kmalloced_param {
      40             :         struct list_head list;
      41             :         char val[];
      42             : };
      43             : static LIST_HEAD(kmalloced_params);
      44             : static DEFINE_SPINLOCK(kmalloced_params_lock);
      45             : 
      46           0 : static void *kmalloc_parameter(unsigned int size)
      47             : {
      48           0 :         struct kmalloced_param *p;
      49             : 
      50           0 :         p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
      51           0 :         if (!p)
      52             :                 return NULL;
      53             : 
      54           0 :         spin_lock(&kmalloced_params_lock);
      55           0 :         list_add(&p->list, &kmalloced_params);
      56           0 :         spin_unlock(&kmalloced_params_lock);
      57             : 
      58           0 :         return p->val;
      59             : }
      60             : 
      61             : /* Does nothing if parameter wasn't kmalloced above. */
      62           0 : static void maybe_kfree_parameter(void *param)
      63             : {
      64           0 :         struct kmalloced_param *p;
      65             : 
      66           0 :         spin_lock(&kmalloced_params_lock);
      67           0 :         list_for_each_entry(p, &kmalloced_params, list) {
      68           0 :                 if (p->val == param) {
      69           0 :                         list_del(&p->list);
      70           0 :                         kfree(p);
      71           0 :                         break;
      72             :                 }
      73             :         }
      74           0 :         spin_unlock(&kmalloced_params_lock);
      75           0 : }
      76             : 
      77       15288 : static char dash2underscore(char c)
      78             : {
      79       15288 :         if (c == '-')
      80           0 :                 return '_';
      81             :         return c;
      82             : }
      83             : 
      84        6242 : bool parameqn(const char *a, const char *b, size_t n)
      85             : {
      86        6242 :         size_t i;
      87             : 
      88        7666 :         for (i = 0; i < n; i++) {
      89        7644 :                 if (dash2underscore(a[i]) != dash2underscore(b[i]))
      90             :                         return false;
      91             :         }
      92             :         return true;
      93             : }
      94             : 
      95        6000 : bool parameq(const char *a, const char *b)
      96             : {
      97        6000 :         return parameqn(a, b, strlen(a)+1);
      98             : }
      99             : 
     100           2 : static bool param_check_unsafe(const struct kernel_param *kp)
     101             : {
     102           2 :         if (kp->flags & KERNEL_PARAM_FL_HWPARAM &&
     103           0 :             security_locked_down(LOCKDOWN_MODULE_PARAMETERS))
     104             :                 return false;
     105             : 
     106           2 :         if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
     107           0 :                 pr_notice("Setting dangerous option %s - tainting kernel\n",
     108             :                           kp->name);
     109           0 :                 add_taint(TAINT_USER, LOCKDEP_STILL_OK);
     110             :         }
     111             : 
     112             :         return true;
     113             : }
     114             : 
     115          66 : static int parse_one(char *param,
     116             :                      char *val,
     117             :                      const char *doing,
     118             :                      const struct kernel_param *params,
     119             :                      unsigned num_params,
     120             :                      s16 min_level,
     121             :                      s16 max_level,
     122             :                      void *arg,
     123             :                      int (*handle_unknown)(char *param, char *val,
     124             :                                      const char *doing, void *arg))
     125             : {
     126          66 :         unsigned int i;
     127          66 :         int err;
     128             : 
     129             :         /* Find parameter */
     130        5538 :         for (i = 0; i < num_params; i++) {
     131        5490 :                 if (parameq(param, params[i].name)) {
     132          18 :                         if (params[i].level < min_level
     133          16 :                             || params[i].level > max_level)
     134             :                                 return 0;
     135             :                         /* No one handled NULL, so do it here. */
     136           2 :                         if (!val &&
     137           0 :                             !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG))
     138             :                                 return -EINVAL;
     139           2 :                         pr_debug("handling %s with %p\n", param,
     140             :                                 params[i].ops->set);
     141           4 :                         kernel_param_lock(params[i].mod);
     142           2 :                         if (param_check_unsafe(&params[i]))
     143           2 :                                 err = params[i].ops->set(val, &params[i]);
     144             :                         else
     145             :                                 err = -EPERM;
     146           2 :                         kernel_param_unlock(params[i].mod);
     147           2 :                         return err;
     148             :                 }
     149             :         }
     150             : 
     151          48 :         if (handle_unknown) {
     152          48 :                 pr_debug("doing %s: %s='%s'\n", doing, param, val);
     153          48 :                 return handle_unknown(param, val, doing, arg);
     154             :         }
     155             : 
     156             :         pr_debug("Unknown argument '%s'\n", param);
     157             :         return -ENOENT;
     158             : }
     159             : 
     160             : /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
     161          11 : char *parse_args(const char *doing,
     162             :                  char *args,
     163             :                  const struct kernel_param *params,
     164             :                  unsigned num,
     165             :                  s16 min_level,
     166             :                  s16 max_level,
     167             :                  void *arg,
     168             :                  int (*unknown)(char *param, char *val,
     169             :                                 const char *doing, void *arg))
     170             : {
     171          11 :         char *param, *val, *err = NULL;
     172             : 
     173             :         /* Chew leading spaces */
     174          11 :         args = skip_spaces(args);
     175             : 
     176          11 :         if (*args)
     177             :                 pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args);
     178             : 
     179          77 :         while (*args) {
     180          66 :                 int ret;
     181          66 :                 int irq_was_disabled;
     182             : 
     183          66 :                 args = next_arg(args, &param, &val);
     184             :                 /* Stop at -- */
     185          66 :                 if (!val && strcmp(param, "--") == 0)
     186           0 :                         return err ?: args;
     187          66 :                 irq_was_disabled = irqs_disabled();
     188          66 :                 ret = parse_one(param, val, doing, params, num,
     189             :                                 min_level, max_level, arg, unknown);
     190          66 :                 if (irq_was_disabled && !irqs_disabled())
     191           0 :                         pr_warn("%s: option '%s' enabled irq's!\n",
     192             :                                 doing, param);
     193             : 
     194          66 :                 switch (ret) {
     195          66 :                 case 0:
     196          66 :                         continue;
     197           0 :                 case -ENOENT:
     198           0 :                         pr_err("%s: Unknown parameter `%s'\n", doing, param);
     199           0 :                         break;
     200           0 :                 case -ENOSPC:
     201           0 :                         pr_err("%s: `%s' too large for parameter `%s'\n",
     202             :                                doing, val ?: "", param);
     203           0 :                         break;
     204           0 :                 default:
     205           0 :                         pr_err("%s: `%s' invalid for parameter `%s'\n",
     206             :                                doing, val ?: "", param);
     207           0 :                         break;
     208             :                 }
     209             : 
     210           0 :                 err = ERR_PTR(ret);
     211             :         }
     212             : 
     213             :         return err;
     214             : }
     215             : 
     216             : /* Lazy bastard, eh? */
     217             : #define STANDARD_PARAM_DEF(name, type, format, strtolfn)                \
     218             :         int param_set_##name(const char *val, const struct kernel_param *kp) \
     219             :         {                                                               \
     220             :                 return strtolfn(val, 0, (type *)kp->arg);            \
     221             :         }                                                               \
     222             :         int param_get_##name(char *buffer, const struct kernel_param *kp) \
     223             :         {                                                               \
     224             :                 return scnprintf(buffer, PAGE_SIZE, format "\n",      \
     225             :                                 *((type *)kp->arg));                 \
     226             :         }                                                               \
     227             :         const struct kernel_param_ops param_ops_##name = {                      \
     228             :                 .set = param_set_##name,                                \
     229             :                 .get = param_get_##name,                                \
     230             :         };                                                              \
     231             :         EXPORT_SYMBOL(param_set_##name);                                \
     232             :         EXPORT_SYMBOL(param_get_##name);                                \
     233             :         EXPORT_SYMBOL(param_ops_##name)
     234             : 
     235             : 
     236           0 : STANDARD_PARAM_DEF(byte,        unsigned char,          "%hhu",               kstrtou8);
     237           0 : STANDARD_PARAM_DEF(short,       short,                  "%hi",                kstrtos16);
     238           0 : STANDARD_PARAM_DEF(ushort,      unsigned short,         "%hu",                kstrtou16);
     239           2 : STANDARD_PARAM_DEF(int,         int,                    "%i",         kstrtoint);
     240           0 : STANDARD_PARAM_DEF(uint,        unsigned int,           "%u",         kstrtouint);
     241           0 : STANDARD_PARAM_DEF(long,        long,                   "%li",                kstrtol);
     242           0 : STANDARD_PARAM_DEF(ulong,       unsigned long,          "%lu",                kstrtoul);
     243           0 : STANDARD_PARAM_DEF(ullong,      unsigned long long,     "%llu",               kstrtoull);
     244           0 : STANDARD_PARAM_DEF(hexint,      unsigned int,           "%#08x",      kstrtouint);
     245             : 
     246           0 : int param_set_charp(const char *val, const struct kernel_param *kp)
     247             : {
     248           0 :         if (strlen(val) > 1024) {
     249           0 :                 pr_err("%s: string parameter too long\n", kp->name);
     250           0 :                 return -ENOSPC;
     251             :         }
     252             : 
     253           0 :         maybe_kfree_parameter(*(char **)kp->arg);
     254             : 
     255             :         /* This is a hack.  We can't kmalloc in early boot, and we
     256             :          * don't need to; this mangled commandline is preserved. */
     257           0 :         if (slab_is_available()) {
     258           0 :                 *(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
     259           0 :                 if (!*(char **)kp->arg)
     260             :                         return -ENOMEM;
     261           0 :                 strcpy(*(char **)kp->arg, val);
     262             :         } else
     263           0 :                 *(const char **)kp->arg = val;
     264             : 
     265             :         return 0;
     266             : }
     267             : EXPORT_SYMBOL(param_set_charp);
     268             : 
     269           0 : int param_get_charp(char *buffer, const struct kernel_param *kp)
     270             : {
     271           0 :         return scnprintf(buffer, PAGE_SIZE, "%s\n", *((char **)kp->arg));
     272             : }
     273             : EXPORT_SYMBOL(param_get_charp);
     274             : 
     275           0 : void param_free_charp(void *arg)
     276             : {
     277           0 :         maybe_kfree_parameter(*((char **)arg));
     278           0 : }
     279             : EXPORT_SYMBOL(param_free_charp);
     280             : 
     281             : const struct kernel_param_ops param_ops_charp = {
     282             :         .set = param_set_charp,
     283             :         .get = param_get_charp,
     284             :         .free = param_free_charp,
     285             : };
     286             : EXPORT_SYMBOL(param_ops_charp);
     287             : 
     288             : /* Actually could be a bool or an int, for historical reasons. */
     289           0 : int param_set_bool(const char *val, const struct kernel_param *kp)
     290             : {
     291             :         /* No equals means "set"... */
     292           0 :         if (!val) val = "1";
     293             : 
     294             :         /* One of =[yYnN01] */
     295           0 :         return strtobool(val, kp->arg);
     296             : }
     297             : EXPORT_SYMBOL(param_set_bool);
     298             : 
     299           0 : int param_get_bool(char *buffer, const struct kernel_param *kp)
     300             : {
     301             :         /* Y and N chosen as being relatively non-coder friendly */
     302           0 :         return sprintf(buffer, "%c\n", *(bool *)kp->arg ? 'Y' : 'N');
     303             : }
     304             : EXPORT_SYMBOL(param_get_bool);
     305             : 
     306             : const struct kernel_param_ops param_ops_bool = {
     307             :         .flags = KERNEL_PARAM_OPS_FL_NOARG,
     308             :         .set = param_set_bool,
     309             :         .get = param_get_bool,
     310             : };
     311             : EXPORT_SYMBOL(param_ops_bool);
     312             : 
     313           0 : int param_set_bool_enable_only(const char *val, const struct kernel_param *kp)
     314             : {
     315           0 :         int err = 0;
     316           0 :         bool new_value;
     317           0 :         bool orig_value = *(bool *)kp->arg;
     318           0 :         struct kernel_param dummy_kp = *kp;
     319             : 
     320           0 :         dummy_kp.arg = &new_value;
     321             : 
     322           0 :         err = param_set_bool(val, &dummy_kp);
     323           0 :         if (err)
     324             :                 return err;
     325             : 
     326             :         /* Don't let them unset it once it's set! */
     327           0 :         if (!new_value && orig_value)
     328             :                 return -EROFS;
     329             : 
     330           0 :         if (new_value)
     331           0 :                 err = param_set_bool(val, kp);
     332             : 
     333             :         return err;
     334             : }
     335             : EXPORT_SYMBOL_GPL(param_set_bool_enable_only);
     336             : 
     337             : const struct kernel_param_ops param_ops_bool_enable_only = {
     338             :         .flags = KERNEL_PARAM_OPS_FL_NOARG,
     339             :         .set = param_set_bool_enable_only,
     340             :         .get = param_get_bool,
     341             : };
     342             : EXPORT_SYMBOL_GPL(param_ops_bool_enable_only);
     343             : 
     344             : /* This one must be bool. */
     345           0 : int param_set_invbool(const char *val, const struct kernel_param *kp)
     346             : {
     347           0 :         int ret;
     348           0 :         bool boolval;
     349           0 :         struct kernel_param dummy;
     350             : 
     351           0 :         dummy.arg = &boolval;
     352           0 :         ret = param_set_bool(val, &dummy);
     353           0 :         if (ret == 0)
     354           0 :                 *(bool *)kp->arg = !boolval;
     355           0 :         return ret;
     356             : }
     357             : EXPORT_SYMBOL(param_set_invbool);
     358             : 
     359           0 : int param_get_invbool(char *buffer, const struct kernel_param *kp)
     360             : {
     361           0 :         return sprintf(buffer, "%c\n", (*(bool *)kp->arg) ? 'N' : 'Y');
     362             : }
     363             : EXPORT_SYMBOL(param_get_invbool);
     364             : 
     365             : const struct kernel_param_ops param_ops_invbool = {
     366             :         .set = param_set_invbool,
     367             :         .get = param_get_invbool,
     368             : };
     369             : EXPORT_SYMBOL(param_ops_invbool);
     370             : 
     371           0 : int param_set_bint(const char *val, const struct kernel_param *kp)
     372             : {
     373             :         /* Match bool exactly, by re-using it. */
     374           0 :         struct kernel_param boolkp = *kp;
     375           0 :         bool v;
     376           0 :         int ret;
     377             : 
     378           0 :         boolkp.arg = &v;
     379             : 
     380           0 :         ret = param_set_bool(val, &boolkp);
     381           0 :         if (ret == 0)
     382           0 :                 *(int *)kp->arg = v;
     383           0 :         return ret;
     384             : }
     385             : EXPORT_SYMBOL(param_set_bint);
     386             : 
     387             : const struct kernel_param_ops param_ops_bint = {
     388             :         .flags = KERNEL_PARAM_OPS_FL_NOARG,
     389             :         .set = param_set_bint,
     390             :         .get = param_get_int,
     391             : };
     392             : EXPORT_SYMBOL(param_ops_bint);
     393             : 
     394             : /* We break the rule and mangle the string. */
     395           0 : static int param_array(struct module *mod,
     396             :                        const char *name,
     397             :                        const char *val,
     398             :                        unsigned int min, unsigned int max,
     399             :                        void *elem, int elemsize,
     400             :                        int (*set)(const char *, const struct kernel_param *kp),
     401             :                        s16 level,
     402             :                        unsigned int *num)
     403             : {
     404           0 :         int ret;
     405           0 :         struct kernel_param kp;
     406           0 :         char save;
     407             : 
     408             :         /* Get the name right for errors. */
     409           0 :         kp.name = name;
     410           0 :         kp.arg = elem;
     411           0 :         kp.level = level;
     412             : 
     413           0 :         *num = 0;
     414             :         /* We expect a comma-separated list of values. */
     415           0 :         do {
     416           0 :                 int len;
     417             : 
     418           0 :                 if (*num == max) {
     419           0 :                         pr_err("%s: can only take %i arguments\n", name, max);
     420           0 :                         return -EINVAL;
     421             :                 }
     422           0 :                 len = strcspn(val, ",");
     423             : 
     424             :                 /* nul-terminate and parse */
     425           0 :                 save = val[len];
     426           0 :                 ((char *)val)[len] = '\0';
     427           0 :                 check_kparam_locked(mod);
     428           0 :                 ret = set(val, &kp);
     429             : 
     430           0 :                 if (ret != 0)
     431           0 :                         return ret;
     432           0 :                 kp.arg += elemsize;
     433           0 :                 val += len+1;
     434           0 :                 (*num)++;
     435           0 :         } while (save == ',');
     436             : 
     437           0 :         if (*num < min) {
     438           0 :                 pr_err("%s: needs at least %i arguments\n", name, min);
     439           0 :                 return -EINVAL;
     440             :         }
     441             :         return 0;
     442             : }
     443             : 
     444           0 : static int param_array_set(const char *val, const struct kernel_param *kp)
     445             : {
     446           0 :         const struct kparam_array *arr = kp->arr;
     447           0 :         unsigned int temp_num;
     448             : 
     449           0 :         return param_array(kp->mod, kp->name, val, 1, arr->max, arr->elem,
     450           0 :                            arr->elemsize, arr->ops->set, kp->level,
     451           0 :                            arr->num ?: &temp_num);
     452             : }
     453             : 
     454           0 : static int param_array_get(char *buffer, const struct kernel_param *kp)
     455             : {
     456           0 :         int i, off, ret;
     457           0 :         const struct kparam_array *arr = kp->arr;
     458           0 :         struct kernel_param p = *kp;
     459             : 
     460           0 :         for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
     461             :                 /* Replace \n with comma */
     462           0 :                 if (i)
     463           0 :                         buffer[off - 1] = ',';
     464           0 :                 p.arg = arr->elem + arr->elemsize * i;
     465           0 :                 check_kparam_locked(p.mod);
     466           0 :                 ret = arr->ops->get(buffer + off, &p);
     467           0 :                 if (ret < 0)
     468           0 :                         return ret;
     469           0 :                 off += ret;
     470             :         }
     471           0 :         buffer[off] = '\0';
     472           0 :         return off;
     473             : }
     474             : 
     475           0 : static void param_array_free(void *arg)
     476             : {
     477           0 :         unsigned int i;
     478           0 :         const struct kparam_array *arr = arg;
     479             : 
     480           0 :         if (arr->ops->free)
     481           0 :                 for (i = 0; i < (arr->num ? *arr->num : arr->max); i++)
     482           0 :                         arr->ops->free(arr->elem + arr->elemsize * i);
     483           0 : }
     484             : 
     485             : const struct kernel_param_ops param_array_ops = {
     486             :         .set = param_array_set,
     487             :         .get = param_array_get,
     488             :         .free = param_array_free,
     489             : };
     490             : EXPORT_SYMBOL(param_array_ops);
     491             : 
     492           0 : int param_set_copystring(const char *val, const struct kernel_param *kp)
     493             : {
     494           0 :         const struct kparam_string *kps = kp->str;
     495             : 
     496           0 :         if (strlen(val)+1 > kps->maxlen) {
     497           0 :                 pr_err("%s: string doesn't fit in %u chars.\n",
     498             :                        kp->name, kps->maxlen-1);
     499           0 :                 return -ENOSPC;
     500             :         }
     501           0 :         strcpy(kps->string, val);
     502           0 :         return 0;
     503             : }
     504             : EXPORT_SYMBOL(param_set_copystring);
     505             : 
     506           0 : int param_get_string(char *buffer, const struct kernel_param *kp)
     507             : {
     508           0 :         const struct kparam_string *kps = kp->str;
     509           0 :         return scnprintf(buffer, PAGE_SIZE, "%s\n", kps->string);
     510             : }
     511             : EXPORT_SYMBOL(param_get_string);
     512             : 
     513             : const struct kernel_param_ops param_ops_string = {
     514             :         .set = param_set_copystring,
     515             :         .get = param_get_string,
     516             : };
     517             : EXPORT_SYMBOL(param_ops_string);
     518             : 
     519             : /* sysfs output in /sys/modules/XYZ/parameters/ */
     520             : #define to_module_attr(n) container_of(n, struct module_attribute, attr)
     521             : #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
     522             : 
     523             : struct param_attribute
     524             : {
     525             :         struct module_attribute mattr;
     526             :         const struct kernel_param *param;
     527             : };
     528             : 
     529             : struct module_param_attrs
     530             : {
     531             :         unsigned int num;
     532             :         struct attribute_group grp;
     533             :         struct param_attribute attrs[];
     534             : };
     535             : 
     536             : #ifdef CONFIG_SYSFS
     537             : #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
     538             : 
     539           2 : static ssize_t param_attr_show(struct module_attribute *mattr,
     540             :                                struct module_kobject *mk, char *buf)
     541             : {
     542           2 :         int count;
     543           2 :         struct param_attribute *attribute = to_param_attr(mattr);
     544             : 
     545           2 :         if (!attribute->param->ops->get)
     546             :                 return -EPERM;
     547             : 
     548           4 :         kernel_param_lock(mk->mod);
     549           2 :         count = attribute->param->ops->get(buf, attribute->param);
     550           4 :         kernel_param_unlock(mk->mod);
     551           2 :         return count;
     552             : }
     553             : 
     554             : /* sysfs always hands a nul-terminated string in buf.  We rely on that. */
     555           0 : static ssize_t param_attr_store(struct module_attribute *mattr,
     556             :                                 struct module_kobject *mk,
     557             :                                 const char *buf, size_t len)
     558             : {
     559           0 :         int err;
     560           0 :         struct param_attribute *attribute = to_param_attr(mattr);
     561             : 
     562           0 :         if (!attribute->param->ops->set)
     563             :                 return -EPERM;
     564             : 
     565           0 :         kernel_param_lock(mk->mod);
     566           0 :         if (param_check_unsafe(attribute->param))
     567           0 :                 err = attribute->param->ops->set(buf, attribute->param);
     568             :         else
     569             :                 err = -EPERM;
     570           0 :         kernel_param_unlock(mk->mod);
     571           0 :         if (!err)
     572           0 :                 return len;
     573           0 :         return err;
     574             : }
     575             : #endif
     576             : 
     577             : #ifdef CONFIG_MODULES
     578             : #define __modinit
     579             : #else
     580             : #define __modinit __init
     581             : #endif
     582             : 
     583             : #ifdef CONFIG_SYSFS
     584           4 : void kernel_param_lock(struct module *mod)
     585             : {
     586           4 :         mutex_lock(KPARAM_MUTEX(mod));
     587           0 : }
     588             : 
     589           4 : void kernel_param_unlock(struct module *mod)
     590             : {
     591           4 :         mutex_unlock(KPARAM_MUTEX(mod));
     592           0 : }
     593             : 
     594             : EXPORT_SYMBOL(kernel_param_lock);
     595             : EXPORT_SYMBOL(kernel_param_unlock);
     596             : 
     597             : /*
     598             :  * add_sysfs_param - add a parameter to sysfs
     599             :  * @mk: struct module_kobject
     600             :  * @kp: the actual parameter definition to add to sysfs
     601             :  * @name: name of parameter
     602             :  *
     603             :  * Create a kobject if for a (per-module) parameter if mp NULL, and
     604             :  * create file in sysfs.  Returns an error on out of memory.  Always cleans up
     605             :  * if there's an error.
     606             :  */
     607         110 : static __modinit int add_sysfs_param(struct module_kobject *mk,
     608             :                                      const struct kernel_param *kp,
     609             :                                      const char *name)
     610             : {
     611         110 :         struct module_param_attrs *new_mp;
     612         110 :         struct attribute **new_attrs;
     613         110 :         unsigned int i;
     614             : 
     615             :         /* We don't bother calling this with invisible parameters. */
     616         110 :         BUG_ON(!kp->perm);
     617             : 
     618         110 :         if (!mk->mp) {
     619             :                 /* First allocation. */
     620          26 :                 mk->mp = kzalloc(sizeof(*mk->mp), GFP_KERNEL);
     621          26 :                 if (!mk->mp)
     622             :                         return -ENOMEM;
     623          26 :                 mk->mp->grp.name = "parameters";
     624             :                 /* NULL-terminated attribute array. */
     625          26 :                 mk->mp->grp.attrs = kzalloc(sizeof(mk->mp->grp.attrs[0]),
     626             :                                             GFP_KERNEL);
     627             :                 /* Caller will cleanup via free_module_param_attrs */
     628          26 :                 if (!mk->mp->grp.attrs)
     629             :                         return -ENOMEM;
     630             :         }
     631             : 
     632             :         /* Enlarge allocations. */
     633         220 :         new_mp = krealloc(mk->mp,
     634             :                           sizeof(*mk->mp) +
     635         110 :                           sizeof(mk->mp->attrs[0]) * (mk->mp->num + 1),
     636             :                           GFP_KERNEL);
     637         110 :         if (!new_mp)
     638             :                 return -ENOMEM;
     639         110 :         mk->mp = new_mp;
     640             : 
     641             :         /* Extra pointer for NULL terminator */
     642         220 :         new_attrs = krealloc(mk->mp->grp.attrs,
     643         110 :                              sizeof(mk->mp->grp.attrs[0]) * (mk->mp->num + 2),
     644             :                              GFP_KERNEL);
     645         110 :         if (!new_attrs)
     646             :                 return -ENOMEM;
     647         110 :         mk->mp->grp.attrs = new_attrs;
     648             : 
     649             :         /* Tack new one on the end. */
     650         110 :         memset(&mk->mp->attrs[mk->mp->num], 0, sizeof(mk->mp->attrs[0]));
     651         110 :         sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr);
     652         110 :         mk->mp->attrs[mk->mp->num].param = kp;
     653         110 :         mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show;
     654             :         /* Do not allow runtime DAC changes to make param writable. */
     655         110 :         if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
     656          78 :                 mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store;
     657             :         else
     658          32 :                 mk->mp->attrs[mk->mp->num].mattr.store = NULL;
     659         110 :         mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name;
     660         110 :         mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm;
     661         110 :         mk->mp->num++;
     662             : 
     663             :         /* Fix up all the pointers, since krealloc can move us */
     664         644 :         for (i = 0; i < mk->mp->num; i++)
     665         534 :                 mk->mp->grp.attrs[i] = &mk->mp->attrs[i].mattr.attr;
     666         110 :         mk->mp->grp.attrs[mk->mp->num] = NULL;
     667         110 :         return 0;
     668             : }
     669             : 
     670             : #ifdef CONFIG_MODULES
     671             : static void free_module_param_attrs(struct module_kobject *mk)
     672             : {
     673             :         if (mk->mp)
     674             :                 kfree(mk->mp->grp.attrs);
     675             :         kfree(mk->mp);
     676             :         mk->mp = NULL;
     677             : }
     678             : 
     679             : /*
     680             :  * module_param_sysfs_setup - setup sysfs support for one module
     681             :  * @mod: module
     682             :  * @kparam: module parameters (array)
     683             :  * @num_params: number of module parameters
     684             :  *
     685             :  * Adds sysfs entries for module parameters under
     686             :  * /sys/module/[mod->name]/parameters/
     687             :  */
     688             : int module_param_sysfs_setup(struct module *mod,
     689             :                              const struct kernel_param *kparam,
     690             :                              unsigned int num_params)
     691             : {
     692             :         int i, err;
     693             :         bool params = false;
     694             : 
     695             :         for (i = 0; i < num_params; i++) {
     696             :                 if (kparam[i].perm == 0)
     697             :                         continue;
     698             :                 err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
     699             :                 if (err) {
     700             :                         free_module_param_attrs(&mod->mkobj);
     701             :                         return err;
     702             :                 }
     703             :                 params = true;
     704             :         }
     705             : 
     706             :         if (!params)
     707             :                 return 0;
     708             : 
     709             :         /* Create the param group. */
     710             :         err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
     711             :         if (err)
     712             :                 free_module_param_attrs(&mod->mkobj);
     713             :         return err;
     714             : }
     715             : 
     716             : /*
     717             :  * module_param_sysfs_remove - remove sysfs support for one module
     718             :  * @mod: module
     719             :  *
     720             :  * Remove sysfs entries for module parameters and the corresponding
     721             :  * kobject.
     722             :  */
     723             : void module_param_sysfs_remove(struct module *mod)
     724             : {
     725             :         if (mod->mkobj.mp) {
     726             :                 sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
     727             :                 /* We are positive that no one is using any param
     728             :                  * attrs at this point.  Deallocate immediately. */
     729             :                 free_module_param_attrs(&mod->mkobj);
     730             :         }
     731             : }
     732             : #endif
     733             : 
     734           0 : void destroy_params(const struct kernel_param *params, unsigned num)
     735             : {
     736           0 :         unsigned int i;
     737             : 
     738           0 :         for (i = 0; i < num; i++)
     739           0 :                 if (params[i].ops->free)
     740           0 :                         params[i].ops->free(params[i].arg);
     741           0 : }
     742             : 
     743         111 : static struct module_kobject * __init locate_module_kobject(const char *name)
     744             : {
     745         111 :         struct module_kobject *mk;
     746         111 :         struct kobject *kobj;
     747         111 :         int err;
     748             : 
     749         111 :         kobj = kset_find_obj(module_kset, name);
     750         111 :         if (kobj) {
     751         111 :                 mk = to_module_kobject(kobj);
     752             :         } else {
     753          26 :                 mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
     754          26 :                 BUG_ON(!mk);
     755             : 
     756          26 :                 mk->mod = THIS_MODULE;
     757          26 :                 mk->kobj.kset = module_kset;
     758          26 :                 err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
     759             :                                            "%s", name);
     760             : #ifdef CONFIG_MODULES
     761             :                 if (!err)
     762             :                         err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
     763             : #endif
     764          26 :                 if (err) {
     765           0 :                         kobject_put(&mk->kobj);
     766           0 :                         pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",
     767             :                                 name, err);
     768           0 :                         return NULL;
     769             :                 }
     770             : 
     771             :                 /* So that we hold reference in both cases. */
     772          26 :                 kobject_get(&mk->kobj);
     773             :         }
     774             : 
     775             :         return mk;
     776             : }
     777             : 
     778         110 : static void __init kernel_add_sysfs_param(const char *name,
     779             :                                           const struct kernel_param *kparam,
     780             :                                           unsigned int name_skip)
     781             : {
     782         110 :         struct module_kobject *mk;
     783         110 :         int err;
     784             : 
     785         110 :         mk = locate_module_kobject(name);
     786         110 :         if (!mk)
     787             :                 return;
     788             : 
     789             :         /* We need to remove old parameters before adding more. */
     790         110 :         if (mk->mp)
     791          84 :                 sysfs_remove_group(&mk->kobj, &mk->mp->grp);
     792             : 
     793             :         /* These should not fail at boot. */
     794         110 :         err = add_sysfs_param(mk, kparam, kparam->name + name_skip);
     795         110 :         BUG_ON(err);
     796         110 :         err = sysfs_create_group(&mk->kobj, &mk->mp->grp);
     797         110 :         BUG_ON(err);
     798         110 :         kobject_uevent(&mk->kobj, KOBJ_ADD);
     799         110 :         kobject_put(&mk->kobj);
     800             : }
     801             : 
     802             : /*
     803             :  * param_sysfs_builtin - add sysfs parameters for built-in modules
     804             :  *
     805             :  * Add module_parameters to sysfs for "modules" built into the kernel.
     806             :  *
     807             :  * The "module" name (KBUILD_MODNAME) is stored before a dot, the
     808             :  * "parameter" name is stored behind a dot in kernel_param->name. So,
     809             :  * extract the "module" name for all built-in kernel_param-eters,
     810             :  * and for all who have the same, call kernel_add_sysfs_param.
     811             :  */
     812           1 : static void __init param_sysfs_builtin(void)
     813             : {
     814           1 :         const struct kernel_param *kp;
     815           1 :         unsigned int name_len;
     816           1 :         char modname[MODULE_NAME_LEN];
     817             : 
     818         123 :         for (kp = __start___param; kp < __stop___param; kp++) {
     819         122 :                 char *dot;
     820             : 
     821         122 :                 if (kp->perm == 0)
     822          12 :                         continue;
     823             : 
     824         110 :                 dot = strchr(kp->name, '.');
     825         110 :                 if (!dot) {
     826             :                         /* This happens for core_param() */
     827           8 :                         strcpy(modname, "kernel");
     828           8 :                         name_len = 0;
     829             :                 } else {
     830         102 :                         name_len = dot - kp->name + 1;
     831         102 :                         strlcpy(modname, kp->name, name_len);
     832             :                 }
     833         110 :                 kernel_add_sysfs_param(modname, kp, name_len);
     834             :         }
     835           1 : }
     836             : 
     837           0 : ssize_t __modver_version_show(struct module_attribute *mattr,
     838             :                               struct module_kobject *mk, char *buf)
     839             : {
     840           0 :         struct module_version_attribute *vattr =
     841           0 :                 container_of(mattr, struct module_version_attribute, mattr);
     842             : 
     843           0 :         return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
     844             : }
     845             : 
     846             : extern const struct module_version_attribute __start___modver[];
     847             : extern const struct module_version_attribute __stop___modver[];
     848             : 
     849           1 : static void __init version_sysfs_builtin(void)
     850             : {
     851           1 :         const struct module_version_attribute *vattr;
     852           1 :         struct module_kobject *mk;
     853           1 :         int err;
     854             : 
     855           2 :         for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
     856           1 :                 mk = locate_module_kobject(vattr->module_name);
     857           1 :                 if (mk) {
     858           1 :                         err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
     859           1 :                         WARN_ON_ONCE(err);
     860           1 :                         kobject_uevent(&mk->kobj, KOBJ_ADD);
     861           1 :                         kobject_put(&mk->kobj);
     862             :                 }
     863             :         }
     864           1 : }
     865             : 
     866             : /* module-related sysfs stuff */
     867             : 
     868           2 : static ssize_t module_attr_show(struct kobject *kobj,
     869             :                                 struct attribute *attr,
     870             :                                 char *buf)
     871             : {
     872           2 :         struct module_attribute *attribute;
     873           2 :         struct module_kobject *mk;
     874           2 :         int ret;
     875             : 
     876           2 :         attribute = to_module_attr(attr);
     877           2 :         mk = to_module_kobject(kobj);
     878             : 
     879           2 :         if (!attribute->show)
     880             :                 return -EIO;
     881             : 
     882           2 :         ret = attribute->show(attribute, mk, buf);
     883             : 
     884           2 :         return ret;
     885             : }
     886             : 
     887           0 : static ssize_t module_attr_store(struct kobject *kobj,
     888             :                                 struct attribute *attr,
     889             :                                 const char *buf, size_t len)
     890             : {
     891           0 :         struct module_attribute *attribute;
     892           0 :         struct module_kobject *mk;
     893           0 :         int ret;
     894             : 
     895           0 :         attribute = to_module_attr(attr);
     896           0 :         mk = to_module_kobject(kobj);
     897             : 
     898           0 :         if (!attribute->store)
     899             :                 return -EIO;
     900             : 
     901           0 :         ret = attribute->store(attribute, mk, buf, len);
     902             : 
     903           0 :         return ret;
     904             : }
     905             : 
     906             : static const struct sysfs_ops module_sysfs_ops = {
     907             :         .show = module_attr_show,
     908             :         .store = module_attr_store,
     909             : };
     910             : 
     911         111 : static int uevent_filter(struct kset *kset, struct kobject *kobj)
     912             : {
     913         111 :         struct kobj_type *ktype = get_ktype(kobj);
     914             : 
     915         111 :         if (ktype == &module_ktype)
     916         111 :                 return 1;
     917             :         return 0;
     918             : }
     919             : 
     920             : static const struct kset_uevent_ops module_uevent_ops = {
     921             :         .filter = uevent_filter,
     922             : };
     923             : 
     924             : struct kset *module_kset;
     925             : int module_sysfs_initialized;
     926             : 
     927           0 : static void module_kobj_release(struct kobject *kobj)
     928             : {
     929           0 :         struct module_kobject *mk = to_module_kobject(kobj);
     930           0 :         complete(mk->kobj_completion);
     931           0 : }
     932             : 
     933             : struct kobj_type module_ktype = {
     934             :         .release   =    module_kobj_release,
     935             :         .sysfs_ops =    &module_sysfs_ops,
     936             : };
     937             : 
     938             : /*
     939             :  * param_sysfs_init - wrapper for built-in params support
     940             :  */
     941           1 : static int __init param_sysfs_init(void)
     942             : {
     943           1 :         module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
     944           1 :         if (!module_kset) {
     945           0 :                 printk(KERN_WARNING "%s (%d): error creating kset\n",
     946             :                         __FILE__, __LINE__);
     947           0 :                 return -ENOMEM;
     948             :         }
     949           1 :         module_sysfs_initialized = 1;
     950             : 
     951           1 :         version_sysfs_builtin();
     952           1 :         param_sysfs_builtin();
     953             : 
     954           1 :         return 0;
     955             : }
     956             : subsys_initcall(param_sysfs_init);
     957             : 
     958             : #endif /* CONFIG_SYSFS */

Generated by: LCOV version 1.14