aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/params.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/params.c')
-rw-r--r--kernel/params.c121
1 files changed, 63 insertions, 58 deletions
diff --git a/kernel/params.c b/kernel/params.c
index 34f527023794..0af9b2c4e56c 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -19,6 +19,7 @@
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/moduleparam.h>
22#include <linux/device.h> 23#include <linux/device.h>
23#include <linux/err.h> 24#include <linux/err.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
@@ -83,6 +84,15 @@ bool parameq(const char *a, const char *b)
83 return parameqn(a, b, strlen(a)+1); 84 return parameqn(a, b, strlen(a)+1);
84} 85}
85 86
87static void param_check_unsafe(const struct kernel_param *kp)
88{
89 if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
90 pr_warn("Setting dangerous option %s - tainting kernel\n",
91 kp->name);
92 add_taint(TAINT_USER, LOCKDEP_STILL_OK);
93 }
94}
95
86static int parse_one(char *param, 96static int parse_one(char *param,
87 char *val, 97 char *val,
88 const char *doing, 98 const char *doing,
@@ -104,11 +114,12 @@ static int parse_one(char *param,
104 return 0; 114 return 0;
105 /* No one handled NULL, so do it here. */ 115 /* No one handled NULL, so do it here. */
106 if (!val && 116 if (!val &&
107 !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG)) 117 !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG))
108 return -EINVAL; 118 return -EINVAL;
109 pr_debug("handling %s with %p\n", param, 119 pr_debug("handling %s with %p\n", param,
110 params[i].ops->set); 120 params[i].ops->set);
111 mutex_lock(&param_lock); 121 mutex_lock(&param_lock);
122 param_check_unsafe(&params[i]);
112 err = params[i].ops->set(val, &params[i]); 123 err = params[i].ops->set(val, &params[i]);
113 mutex_unlock(&param_lock); 124 mutex_unlock(&param_lock);
114 return err; 125 return err;
@@ -318,7 +329,7 @@ int param_get_bool(char *buffer, const struct kernel_param *kp)
318EXPORT_SYMBOL(param_get_bool); 329EXPORT_SYMBOL(param_get_bool);
319 330
320struct kernel_param_ops param_ops_bool = { 331struct kernel_param_ops param_ops_bool = {
321 .flags = KERNEL_PARAM_FL_NOARG, 332 .flags = KERNEL_PARAM_OPS_FL_NOARG,
322 .set = param_set_bool, 333 .set = param_set_bool,
323 .get = param_get_bool, 334 .get = param_get_bool,
324}; 335};
@@ -369,7 +380,7 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
369EXPORT_SYMBOL(param_set_bint); 380EXPORT_SYMBOL(param_set_bint);
370 381
371struct kernel_param_ops param_ops_bint = { 382struct kernel_param_ops param_ops_bint = {
372 .flags = KERNEL_PARAM_FL_NOARG, 383 .flags = KERNEL_PARAM_OPS_FL_NOARG,
373 .set = param_set_bint, 384 .set = param_set_bint,
374 .get = param_get_int, 385 .get = param_get_int,
375}; 386};
@@ -503,8 +514,6 @@ EXPORT_SYMBOL(param_ops_string);
503#define to_module_attr(n) container_of(n, struct module_attribute, attr) 514#define to_module_attr(n) container_of(n, struct module_attribute, attr)
504#define to_module_kobject(n) container_of(n, struct module_kobject, kobj) 515#define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
505 516
506extern struct kernel_param __start___param[], __stop___param[];
507
508struct param_attribute 517struct param_attribute
509{ 518{
510 struct module_attribute mattr; 519 struct module_attribute mattr;
@@ -552,6 +561,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
552 return -EPERM; 561 return -EPERM;
553 562
554 mutex_lock(&param_lock); 563 mutex_lock(&param_lock);
564 param_check_unsafe(attribute->param);
555 err = attribute->param->ops->set(buf, attribute->param); 565 err = attribute->param->ops->set(buf, attribute->param);
556 mutex_unlock(&param_lock); 566 mutex_unlock(&param_lock);
557 if (!err) 567 if (!err)
@@ -593,74 +603,67 @@ static __modinit int add_sysfs_param(struct module_kobject *mk,
593 const struct kernel_param *kp, 603 const struct kernel_param *kp,
594 const char *name) 604 const char *name)
595{ 605{
596 struct module_param_attrs *new; 606 struct module_param_attrs *new_mp;
597 struct attribute **attrs; 607 struct attribute **new_attrs;
598 int err, num; 608 unsigned int i;
599 609
600 /* We don't bother calling this with invisible parameters. */ 610 /* We don't bother calling this with invisible parameters. */
601 BUG_ON(!kp->perm); 611 BUG_ON(!kp->perm);
602 612
603 if (!mk->mp) { 613 if (!mk->mp) {
604 num = 0; 614 /* First allocation. */
605 attrs = NULL; 615 mk->mp = kzalloc(sizeof(*mk->mp), GFP_KERNEL);
606 } else { 616 if (!mk->mp)
607 num = mk->mp->num; 617 return -ENOMEM;
608 attrs = mk->mp->grp.attrs; 618 mk->mp->grp.name = "parameters";
619 /* NULL-terminated attribute array. */
620 mk->mp->grp.attrs = kzalloc(sizeof(mk->mp->grp.attrs[0]),
621 GFP_KERNEL);
622 /* Caller will cleanup via free_module_param_attrs */
623 if (!mk->mp->grp.attrs)
624 return -ENOMEM;
609 } 625 }
610 626
611 /* Enlarge. */ 627 /* Enlarge allocations. */
612 new = krealloc(mk->mp, 628 new_mp = krealloc(mk->mp,
613 sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (num+1), 629 sizeof(*mk->mp) +
614 GFP_KERNEL); 630 sizeof(mk->mp->attrs[0]) * (mk->mp->num + 1),
615 if (!new) { 631 GFP_KERNEL);
616 kfree(attrs); 632 if (!new_mp)
617 err = -ENOMEM; 633 return -ENOMEM;
618 goto fail; 634 mk->mp = new_mp;
619 }
620 /* Despite looking like the typical realloc() bug, this is safe.
621 * We *want* the old 'attrs' to be freed either way, and we'll store
622 * the new one in the success case. */
623 attrs = krealloc(attrs, sizeof(new->grp.attrs[0])*(num+2), GFP_KERNEL);
624 if (!attrs) {
625 err = -ENOMEM;
626 goto fail_free_new;
627 }
628 635
629 /* Sysfs wants everything zeroed. */ 636 /* Extra pointer for NULL terminator */
630 memset(new, 0, sizeof(*new)); 637 new_attrs = krealloc(mk->mp->grp.attrs,
631 memset(&new->attrs[num], 0, sizeof(new->attrs[num])); 638 sizeof(mk->mp->grp.attrs[0]) * (mk->mp->num + 2),
632 memset(&attrs[num], 0, sizeof(attrs[num])); 639 GFP_KERNEL);
633 new->grp.name = "parameters"; 640 if (!new_attrs)
634 new->grp.attrs = attrs; 641 return -ENOMEM;
642 mk->mp->grp.attrs = new_attrs;
635 643
636 /* Tack new one on the end. */ 644 /* Tack new one on the end. */
637 sysfs_attr_init(&new->attrs[num].mattr.attr); 645 sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr);
638 new->attrs[num].param = kp; 646 mk->mp->attrs[mk->mp->num].param = kp;
639 new->attrs[num].mattr.show = param_attr_show; 647 mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show;
640 new->attrs[num].mattr.store = param_attr_store; 648 /* Do not allow runtime DAC changes to make param writable. */
641 new->attrs[num].mattr.attr.name = (char *)name; 649 if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
642 new->attrs[num].mattr.attr.mode = kp->perm; 650 mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store;
643 new->num = num+1; 651 mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name;
652 mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm;
653 mk->mp->num++;
644 654
645 /* Fix up all the pointers, since krealloc can move us */ 655 /* Fix up all the pointers, since krealloc can move us */
646 for (num = 0; num < new->num; num++) 656 for (i = 0; i < mk->mp->num; i++)
647 new->grp.attrs[num] = &new->attrs[num].mattr.attr; 657 mk->mp->grp.attrs[i] = &mk->mp->attrs[i].mattr.attr;
648 new->grp.attrs[num] = NULL; 658 mk->mp->grp.attrs[mk->mp->num] = NULL;
649
650 mk->mp = new;
651 return 0; 659 return 0;
652
653fail_free_new:
654 kfree(new);
655fail:
656 mk->mp = NULL;
657 return err;
658} 660}
659 661
660#ifdef CONFIG_MODULES 662#ifdef CONFIG_MODULES
661static void free_module_param_attrs(struct module_kobject *mk) 663static void free_module_param_attrs(struct module_kobject *mk)
662{ 664{
663 kfree(mk->mp->grp.attrs); 665 if (mk->mp)
666 kfree(mk->mp->grp.attrs);
664 kfree(mk->mp); 667 kfree(mk->mp);
665 mk->mp = NULL; 668 mk->mp = NULL;
666} 669}
@@ -685,8 +688,10 @@ int module_param_sysfs_setup(struct module *mod,
685 if (kparam[i].perm == 0) 688 if (kparam[i].perm == 0)
686 continue; 689 continue;
687 err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name); 690 err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
688 if (err) 691 if (err) {
692 free_module_param_attrs(&mod->mkobj);
689 return err; 693 return err;
694 }
690 params = true; 695 params = true;
691 } 696 }
692 697
@@ -763,7 +768,7 @@ static struct module_kobject * __init locate_module_kobject(const char *name)
763} 768}
764 769
765static void __init kernel_add_sysfs_param(const char *name, 770static void __init kernel_add_sysfs_param(const char *name,
766 struct kernel_param *kparam, 771 const struct kernel_param *kparam,
767 unsigned int name_skip) 772 unsigned int name_skip)
768{ 773{
769 struct module_kobject *mk; 774 struct module_kobject *mk;
@@ -798,7 +803,7 @@ static void __init kernel_add_sysfs_param(const char *name,
798 */ 803 */
799static void __init param_sysfs_builtin(void) 804static void __init param_sysfs_builtin(void)
800{ 805{
801 struct kernel_param *kp; 806 const struct kernel_param *kp;
802 unsigned int name_len; 807 unsigned int name_len;
803 char modname[MODULE_NAME_LEN]; 808 char modname[MODULE_NAME_LEN];
804 809