LCOV - code coverage report
Current view: top level - kernel - params.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 160 312 51.3 %
Date: 2015-04-12 14:34:49 Functions: 21 57 36.8 %

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

Generated by: LCOV version 1.11