LCOV - code coverage report
Current view: top level - kernel - params.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 154 348 44.3 %
Date: 2022-04-01 14:17:54 Functions: 20 55 36.4 %
Branches: 67 198 33.8 %

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

Generated by: LCOV version 1.14