aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2013-03-16 07:44:32 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-03-27 18:36:17 -0400
commitaaed651ff619993fb2101a22b32dd0664e54921b (patch)
tree43d78fe1b6f8eb754005153bcc8d694198789ffc /drivers/pinctrl
parent50cf7c8ab324de348990bb028ad9ed10872d527a (diff)
pinctrl: mvebu: prevent walking off the end of group array
While investigating (ab)use of krealloc, David found this bug. It's unlikely to occur, but now we detect the condition and error out appropriately. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: Jason Cooper <jason@lakedaemon.net> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Acked-by: Jason Cooper <jason@lakedaemon.net> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 61149914882d..38d3b22e172d 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -478,8 +478,12 @@ static const struct pinctrl_ops mvebu_pinctrl_ops = {
478 .dt_free_map = mvebu_pinctrl_dt_free_map, 478 .dt_free_map = mvebu_pinctrl_dt_free_map,
479}; 479};
480 480
481static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name) 481static int _add_function(struct mvebu_pinctrl_function *funcs, int *funcsize,
482 const char *name)
482{ 483{
484 if (*funcsize <= 0)
485 return -EOVERFLOW;
486
483 while (funcs->num_groups) { 487 while (funcs->num_groups) {
484 /* function already there */ 488 /* function already there */
485 if (strcmp(funcs->name, name) == 0) { 489 if (strcmp(funcs->name, name) == 0) {
@@ -488,8 +492,12 @@ static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
488 } 492 }
489 funcs++; 493 funcs++;
490 } 494 }
495
496 /* append new unique function */
491 funcs->name = name; 497 funcs->name = name;
492 funcs->num_groups = 1; 498 funcs->num_groups = 1;
499 (*funcsize)--;
500
493 return 0; 501 return 0;
494} 502}
495 503
@@ -497,12 +505,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
497 struct mvebu_pinctrl *pctl) 505 struct mvebu_pinctrl *pctl)
498{ 506{
499 struct mvebu_pinctrl_function *funcs; 507 struct mvebu_pinctrl_function *funcs;
500 int num = 0; 508 int num = 0, funcsize = pctl->desc.npins;
501 int n, s; 509 int n, s;
502 510
503 /* we allocate functions for number of pins and hope 511 /* we allocate functions for number of pins and hope
504 * there are less unique functions than pins available */ 512 * there are fewer unique functions than pins available */
505 funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins * 513 funcs = devm_kzalloc(&pdev->dev, funcsize *
506 sizeof(struct mvebu_pinctrl_function), GFP_KERNEL); 514 sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
507 if (!funcs) 515 if (!funcs)
508 return -ENOMEM; 516 return -ENOMEM;
@@ -510,26 +518,27 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
510 for (n = 0; n < pctl->num_groups; n++) { 518 for (n = 0; n < pctl->num_groups; n++) {
511 struct mvebu_pinctrl_group *grp = &pctl->groups[n]; 519 struct mvebu_pinctrl_group *grp = &pctl->groups[n];
512 for (s = 0; s < grp->num_settings; s++) { 520 for (s = 0; s < grp->num_settings; s++) {
521 int ret;
522
513 /* skip unsupported settings on this variant */ 523 /* skip unsupported settings on this variant */
514 if (pctl->variant && 524 if (pctl->variant &&
515 !(pctl->variant & grp->settings[s].variant)) 525 !(pctl->variant & grp->settings[s].variant))
516 continue; 526 continue;
517 527
518 /* check for unique functions and count groups */ 528 /* check for unique functions and count groups */
519 if (_add_function(funcs, grp->settings[s].name)) 529 ret = _add_function(funcs, &funcsize,
530 grp->settings[s].name);
531 if (ret == -EOVERFLOW)
532 dev_err(&pdev->dev,
533 "More functions than pins(%d)\n",
534 pctl->desc.npins);
535 if (ret < 0)
520 continue; 536 continue;
521 537
522 num++; 538 num++;
523 } 539 }
524 } 540 }
525 541
526 /* with the number of unique functions and it's groups known,
527 reallocate functions and assign group names */
528 funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
529 GFP_KERNEL);
530 if (!funcs)
531 return -ENOMEM;
532
533 pctl->num_functions = num; 542 pctl->num_functions = num;
534 pctl->functions = funcs; 543 pctl->functions = funcs;
535 544