diff options
author | Axel Lin <axel.lin@gmail.com> | 2011-07-10 21:57:43 -0400 |
---|---|---|
committer | Liam Girdwood <lrg@slimlogic.co.uk> | 2011-07-22 06:41:57 -0400 |
commit | 39aa9b6e3cb1b2a564d3422eedb7f725179162d3 (patch) | |
tree | 4c4ab6357e1d422971212504d8cb3d441ca8d638 /drivers/regulator | |
parent | d04156bca629740a661fd0738cd69ba1f08b2b20 (diff) |
regulator: tps65910: Fix array access out of bounds bug
For tps65910, the number of regulator is 13. ( ARRAY_SIZE(tps65910_regs) is 13)
For tps65911, the number of regulator is 12. ( ARRAY_SIZE(tps65911_regs) is 12)
If we are using this driver for tps65911,
we hit array access out of bounds bug in tps65910_probe() because
current implementation always assume the number of regulator is 13 and
thus it will access tps65911_regs[12].
Fix it by setting correct num_regulators for both chips in tps65910_probe(),
and allocated neccessay memory accordingly.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/tps65910-regulator.c | 55 |
1 files changed, 43 insertions, 12 deletions
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 8e0edab74786..66d2d60b436a 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #define TPS65911_REG_LDO7 11 | 49 | #define TPS65911_REG_LDO7 11 |
50 | #define TPS65911_REG_LDO8 12 | 50 | #define TPS65911_REG_LDO8 12 |
51 | 51 | ||
52 | #define TPS65910_NUM_REGULATOR 13 | ||
53 | #define TPS65910_SUPPLY_STATE_ENABLED 0x1 | 52 | #define TPS65910_SUPPLY_STATE_ENABLED 0x1 |
54 | 53 | ||
55 | /* supported VIO voltages in milivolts */ | 54 | /* supported VIO voltages in milivolts */ |
@@ -264,11 +263,12 @@ static struct tps_info tps65911_regs[] = { | |||
264 | }; | 263 | }; |
265 | 264 | ||
266 | struct tps65910_reg { | 265 | struct tps65910_reg { |
267 | struct regulator_desc desc[TPS65910_NUM_REGULATOR]; | 266 | struct regulator_desc *desc; |
268 | struct tps65910 *mfd; | 267 | struct tps65910 *mfd; |
269 | struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; | 268 | struct regulator_dev **rdev; |
270 | struct tps_info *info[TPS65910_NUM_REGULATOR]; | 269 | struct tps_info **info; |
271 | struct mutex mutex; | 270 | struct mutex mutex; |
271 | int num_regulators; | ||
272 | int mode; | 272 | int mode; |
273 | int (*get_ctrl_reg)(int); | 273 | int (*get_ctrl_reg)(int); |
274 | }; | 274 | }; |
@@ -902,10 +902,12 @@ static __devinit int tps65910_probe(struct platform_device *pdev) | |||
902 | switch(tps65910_chip_id(tps65910)) { | 902 | switch(tps65910_chip_id(tps65910)) { |
903 | case TPS65910: | 903 | case TPS65910: |
904 | pmic->get_ctrl_reg = &tps65910_get_ctrl_register; | 904 | pmic->get_ctrl_reg = &tps65910_get_ctrl_register; |
905 | pmic->num_regulators = ARRAY_SIZE(tps65910_regs); | ||
905 | info = tps65910_regs; | 906 | info = tps65910_regs; |
906 | break; | 907 | break; |
907 | case TPS65911: | 908 | case TPS65911: |
908 | pmic->get_ctrl_reg = &tps65911_get_ctrl_register; | 909 | pmic->get_ctrl_reg = &tps65911_get_ctrl_register; |
910 | pmic->num_regulators = ARRAY_SIZE(tps65911_regs); | ||
909 | info = tps65911_regs; | 911 | info = tps65911_regs; |
910 | break; | 912 | break; |
911 | default: | 913 | default: |
@@ -914,7 +916,28 @@ static __devinit int tps65910_probe(struct platform_device *pdev) | |||
914 | return -ENODEV; | 916 | return -ENODEV; |
915 | } | 917 | } |
916 | 918 | ||
917 | for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { | 919 | pmic->desc = kcalloc(pmic->num_regulators, |
920 | sizeof(struct regulator_desc), GFP_KERNEL); | ||
921 | if (!pmic->desc) { | ||
922 | err = -ENOMEM; | ||
923 | goto err_free_pmic; | ||
924 | } | ||
925 | |||
926 | pmic->info = kcalloc(pmic->num_regulators, | ||
927 | sizeof(struct tps_info *), GFP_KERNEL); | ||
928 | if (!pmic->info) { | ||
929 | err = -ENOMEM; | ||
930 | goto err_free_desc; | ||
931 | } | ||
932 | |||
933 | pmic->rdev = kcalloc(pmic->num_regulators, | ||
934 | sizeof(struct regulator_dev *), GFP_KERNEL); | ||
935 | if (!pmic->rdev) { | ||
936 | err = -ENOMEM; | ||
937 | goto err_free_info; | ||
938 | } | ||
939 | |||
940 | for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) { | ||
918 | /* Register the regulators */ | 941 | /* Register the regulators */ |
919 | pmic->info[i] = info; | 942 | pmic->info[i] = info; |
920 | 943 | ||
@@ -946,7 +969,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) | |||
946 | "failed to register %s regulator\n", | 969 | "failed to register %s regulator\n", |
947 | pdev->name); | 970 | pdev->name); |
948 | err = PTR_ERR(rdev); | 971 | err = PTR_ERR(rdev); |
949 | goto err; | 972 | goto err_unregister_regulator; |
950 | } | 973 | } |
951 | 974 | ||
952 | /* Save regulator for cleanup */ | 975 | /* Save regulator for cleanup */ |
@@ -954,23 +977,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev) | |||
954 | } | 977 | } |
955 | return 0; | 978 | return 0; |
956 | 979 | ||
957 | err: | 980 | err_unregister_regulator: |
958 | while (--i >= 0) | 981 | while (--i >= 0) |
959 | regulator_unregister(pmic->rdev[i]); | 982 | regulator_unregister(pmic->rdev[i]); |
960 | 983 | kfree(pmic->rdev); | |
984 | err_free_info: | ||
985 | kfree(pmic->info); | ||
986 | err_free_desc: | ||
987 | kfree(pmic->desc); | ||
988 | err_free_pmic: | ||
961 | kfree(pmic); | 989 | kfree(pmic); |
962 | return err; | 990 | return err; |
963 | } | 991 | } |
964 | 992 | ||
965 | static int __devexit tps65910_remove(struct platform_device *pdev) | 993 | static int __devexit tps65910_remove(struct platform_device *pdev) |
966 | { | 994 | { |
967 | struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); | 995 | struct tps65910_reg *pmic = platform_get_drvdata(pdev); |
968 | int i; | 996 | int i; |
969 | 997 | ||
970 | for (i = 0; i < TPS65910_NUM_REGULATOR; i++) | 998 | for (i = 0; i < pmic->num_regulators; i++) |
971 | regulator_unregister(tps65910_reg->rdev[i]); | 999 | regulator_unregister(pmic->rdev[i]); |
972 | 1000 | ||
973 | kfree(tps65910_reg); | 1001 | kfree(pmic->rdev); |
1002 | kfree(pmic->info); | ||
1003 | kfree(pmic->desc); | ||
1004 | kfree(pmic); | ||
974 | return 0; | 1005 | return 0; |
975 | } | 1006 | } |
976 | 1007 | ||