LCOV - code coverage report
Current view: top level - kernel - params.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 119 314 37.9 %
Date: 2022-12-09 01:23:36 Functions: 14 58 24.1 %

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

Generated by: LCOV version 1.14