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

Generated by: LCOV version 1.14