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 : ¶m_lock)
24 : : #else
25 : : #define KPARAM_MUTEX(mod) (¶m_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 : 4503720 : static char dash2underscore(char c)
78 : : {
79 : 4503720 : if (c == '-')
80 : 858 : return '_';
81 : : return c;
82 : : }
83 : :
84 : 2111460 : bool parameqn(const char *a, const char *b, size_t n)
85 : : {
86 : 2111460 : size_t i;
87 : :
88 [ + + + + ]: 2252172 : for (i = 0; i < n; i++) {
89 [ - + + + : 2252718 : if (dash2underscore(a[i]) != dash2underscore(b[i]))
+ + - + +
+ + + ]
90 : : return false;
91 : : }
92 : : return true;
93 : : }
94 : :
95 : 2012400 : bool parameq(const char *a, const char *b)
96 : : {
97 : 2012400 : 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 : 4680 : 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 : 4680 : unsigned int i;
127 : 4680 : int err;
128 : :
129 : : /* Find parameter */
130 [ + + ]: 1971684 : for (i = 0; i < num_params; i++) {
131 [ - + ]: 1967004 : 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(¶ms[i]))
143 : 0 : err = params[i].ops->set(val, ¶ms[i]);
144 : : else
145 : : err = -EPERM;
146 : 0 : kernel_param_unlock(params[i].mod);
147 : 0 : return err;
148 : : }
149 : : }
150 : :
151 [ + - ]: 4680 : if (handle_unknown) {
152 : 4680 : pr_debug("doing %s: %s='%s'\n", doing, param, val);
153 : 4680 : 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 : 858 : 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 : 858 : char *param, *val, *err = NULL;
172 : :
173 : : /* Chew leading spaces */
174 : 858 : args = skip_spaces(args);
175 : :
176 : 858 : if (*args)
177 : : pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args);
178 : :
179 [ + + ]: 5538 : while (*args) {
180 : 4680 : int ret;
181 : 4680 : int irq_was_disabled;
182 : :
183 : 4680 : args = next_arg(args, ¶m, &val);
184 : : /* Stop at -- */
185 [ + + - + ]: 4680 : if (!val && strcmp(param, "--") == 0)
186 [ # # ]: 0 : return err ?: args;
187 : 4680 : irq_was_disabled = irqs_disabled();
188 : 4680 : ret = parse_one(param, val, doing, params, num,
189 : : min_level, max_level, arg, unknown);
190 [ + + - + ]: 4680 : if (irq_was_disabled && !irqs_disabled())
191 : 0 : pr_warn("%s: option '%s' enabled irq's!\n",
192 : : doing, param);
193 : :
194 [ + - - - ]: 4680 : switch (ret) {
195 : 4680 : case 0:
196 : 4680 : 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 : 156 : 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 : 156 : 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 : 78 : int param_get_bool(char *buffer, const struct kernel_param *kp)
299 : : {
300 : : /* Y and N chosen as being relatively non-coder friendly */
301 [ - + ]: 78 : 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 : 234 : static ssize_t param_attr_show(struct module_attribute *mattr,
539 : : struct module_kobject *mk, char *buf)
540 : : {
541 : 234 : int count;
542 : 234 : struct param_attribute *attribute = to_param_attr(mattr);
543 : :
544 [ + - ]: 234 : if (!attribute->param->ops->get)
545 : : return -EPERM;
546 : :
547 : 234 : kernel_param_lock(mk->mod);
548 : 234 : count = attribute->param->ops->get(buf, attribute->param);
549 : 234 : kernel_param_unlock(mk->mod);
550 : 234 : return count;
551 : : }
552 : :
553 : : /* sysfs always hands a nul-terminated string in buf. We rely on that. */
554 : 156 : static ssize_t param_attr_store(struct module_attribute *mattr,
555 : : struct module_kobject *mk,
556 : : const char *buf, size_t len)
557 : : {
558 : 156 : int err;
559 : 156 : struct param_attribute *attribute = to_param_attr(mattr);
560 : :
561 [ + - ]: 156 : if (!attribute->param->ops->set)
562 : : return -EPERM;
563 : :
564 : 156 : kernel_param_lock(mk->mod);
565 [ + - ]: 156 : if (param_check_unsafe(attribute->param))
566 : 156 : err = attribute->param->ops->set(buf, attribute->param);
567 : : else
568 : : err = -EPERM;
569 : 156 : kernel_param_unlock(mk->mod);
570 [ + - ]: 156 : if (!err)
571 : 156 : 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 : 390 : void kernel_param_lock(struct module *mod)
584 : : {
585 [ - - - + : 390 : mutex_lock(KPARAM_MUTEX(mod));
- + - - ]
586 : 0 : }
587 : :
588 : 390 : void kernel_param_unlock(struct module *mod)
589 : : {
590 [ - - - + : 390 : 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 : 78 : int module_param_sysfs_setup(struct module *mod,
688 : : const struct kernel_param *kparam,
689 : : unsigned int num_params)
690 : : {
691 : 78 : int i, err;
692 : 78 : bool params = false;
693 : :
694 [ + + ]: 312 : for (i = 0; i < num_params; i++) {
695 [ - + ]: 234 : if (kparam[i].perm == 0)
696 : 0 : continue;
697 : 234 : err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
698 [ - + ]: 234 : if (err) {
699 : 0 : free_module_param_attrs(&mod->mkobj);
700 : 0 : return err;
701 : : }
702 : : params = true;
703 : : }
704 : :
705 [ + - ]: 78 : if (!params)
706 : : return 0;
707 : :
708 : : /* Create the param group. */
709 : 78 : err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
710 [ - + ]: 78 : 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 : 32136 : static struct module_kobject * __init locate_module_kobject(const char *name)
743 : : {
744 : 32136 : struct module_kobject *mk;
745 : 32136 : struct kobject *kobj;
746 : 32136 : int err;
747 : :
748 : 32136 : kobj = kset_find_obj(module_kset, name);
749 [ + + ]: 32136 : if (kobj) {
750 : : mk = to_module_kobject(kobj);
751 : : } else {
752 : 8970 : mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
753 [ - + ]: 8970 : BUG_ON(!mk);
754 : :
755 : 8970 : mk->mod = THIS_MODULE;
756 : 8970 : mk->kobj.kset = module_kset;
757 : 8970 : err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
758 : : "%s", name);
759 : : #ifdef CONFIG_MODULES
760 [ + - ]: 8970 : if (!err)
761 : 8970 : err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
762 : : #endif
763 [ - + ]: 8970 : 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 : 8970 : kobject_get(&mk->kobj);
772 : : }
773 : :
774 : : return mk;
775 : : }
776 : :
777 : 30888 : static void __init kernel_add_sysfs_param(const char *name,
778 : : const struct kernel_param *kparam,
779 : : unsigned int name_skip)
780 : : {
781 : 30888 : struct module_kobject *mk;
782 : 30888 : int err;
783 : :
784 : 30888 : mk = locate_module_kobject(name);
785 [ + - ]: 30888 : if (!mk)
786 : : return;
787 : :
788 : : /* We need to remove old parameters before adding more. */
789 [ + + ]: 30888 : if (mk->mp)
790 : 22776 : sysfs_remove_group(&mk->kobj, &mk->mp->grp);
791 : :
792 : : /* These should not fail at boot. */
793 : 30888 : err = add_sysfs_param(mk, kparam, kparam->name + name_skip);
794 [ - + ]: 30888 : BUG_ON(err);
795 : 30888 : err = sysfs_create_group(&mk->kobj, &mk->mp->grp);
796 [ - + ]: 30888 : BUG_ON(err);
797 : 30888 : kobject_uevent(&mk->kobj, KOBJ_ADD);
798 : 30888 : 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 : 78 : static void __init param_sysfs_builtin(void)
812 : : {
813 : 78 : const struct kernel_param *kp;
814 : 78 : unsigned int name_len;
815 : 78 : char modname[MODULE_NAME_LEN];
816 : :
817 [ + + ]: 36504 : for (kp = __start___param; kp < __stop___param; kp++) {
818 : 36426 : char *dot;
819 : :
820 [ + + ]: 36426 : if (kp->perm == 0)
821 : 5538 : continue;
822 : :
823 : 30888 : dot = strchr(kp->name, '.');
824 [ + + ]: 30888 : if (!dot) {
825 : : /* This happens for core_param() */
826 : 702 : strcpy(modname, "kernel");
827 : 702 : name_len = 0;
828 : : } else {
829 : 30186 : name_len = dot - kp->name + 1;
830 : 30186 : strlcpy(modname, kp->name, name_len);
831 : : }
832 : 30888 : kernel_add_sysfs_param(modname, kp, name_len);
833 : : }
834 : 78 : }
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 : 78 : static void __init version_sysfs_builtin(void)
849 : : {
850 : 78 : const struct module_version_attribute **p;
851 : 78 : struct module_kobject *mk;
852 : 78 : int err;
853 : :
854 [ + + ]: 1326 : for (p = __start___modver; p < __stop___modver; p++) {
855 : 1248 : const struct module_version_attribute *vattr = *p;
856 : :
857 : 1248 : mk = locate_module_kobject(vattr->module_name);
858 [ + - ]: 1248 : if (mk) {
859 : 1248 : err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
860 [ - + ]: 1248 : WARN_ON_ONCE(err);
861 : 1248 : kobject_uevent(&mk->kobj, KOBJ_ADD);
862 : 1248 : kobject_put(&mk->kobj);
863 : : }
864 : : }
865 : 78 : }
866 : :
867 : : /* module-related sysfs stuff */
868 : :
869 : 234 : static ssize_t module_attr_show(struct kobject *kobj,
870 : : struct attribute *attr,
871 : : char *buf)
872 : : {
873 : 234 : struct module_attribute *attribute;
874 : 234 : struct module_kobject *mk;
875 : 234 : int ret;
876 : :
877 : 234 : attribute = to_module_attr(attr);
878 : 234 : mk = to_module_kobject(kobj);
879 : :
880 [ + - ]: 234 : if (!attribute->show)
881 : : return -EIO;
882 : :
883 : 234 : ret = attribute->show(attribute, mk, buf);
884 : :
885 : 234 : return ret;
886 : : }
887 : :
888 : 9126 : static ssize_t module_attr_store(struct kobject *kobj,
889 : : struct attribute *attr,
890 : : const char *buf, size_t len)
891 : : {
892 : 9126 : struct module_attribute *attribute;
893 : 9126 : struct module_kobject *mk;
894 : 9126 : int ret;
895 : :
896 : 9126 : attribute = to_module_attr(attr);
897 : 9126 : mk = to_module_kobject(kobj);
898 : :
899 [ + - ]: 9126 : if (!attribute->store)
900 : : return -EIO;
901 : :
902 : 9126 : ret = attribute->store(attribute, mk, buf, len);
903 : :
904 : 9126 : 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 : 41184 : static int uevent_filter(struct kset *kset, struct kobject *kobj)
913 : : {
914 [ + - ]: 41184 : struct kobj_type *ktype = get_ktype(kobj);
915 : :
916 [ + - ]: 41184 : if (ktype == &module_ktype)
917 : 41184 : 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 : 78 : static int __init param_sysfs_init(void)
943 : : {
944 : 78 : module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
945 [ - + ]: 78 : if (!module_kset) {
946 : 0 : printk(KERN_WARNING "%s (%d): error creating kset\n",
947 : : __FILE__, __LINE__);
948 : 0 : return -ENOMEM;
949 : : }
950 : 78 : module_sysfs_initialized = 1;
951 : :
952 : 78 : version_sysfs_builtin();
953 : 78 : param_sysfs_builtin();
954 : :
955 : 78 : return 0;
956 : : }
957 : : subsys_initcall(param_sysfs_init);
958 : :
959 : : #endif /* CONFIG_SYSFS */
|