diff options
author | Axel Lin <axel.lin@gmail.com> | 2010-07-20 18:19:53 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-08-03 09:49:04 -0400 |
commit | 7677fbdff16f5b817bc3dc5d194a8b3350f8f9cb (patch) | |
tree | 2086eff81fa49d9b9a5ab569a7b867f30c7d24d6 /drivers/platform | |
parent | 669048639ca6d3fdfb2e75dd77b8f49434d57625 (diff) |
acer-wmi: fix memory leaks in wmab_execute error path
When acpi_evaluate_object() is passed ACPI_ALLOCATE_BUFFER, the caller
must kfree the returned buffer if AE_OK is returned.
Call Trace:
wmab_execute
-> wmi_evaluate_method
-> acpi_evaluate_object
Thus if callers of wmab_execute() pass ACPI_ALLOCATE_BUFFER, the return
buffer must be kfreed if wmab_execute return AE_OK.
[akpm@linux-foundation.org: avoid multiple return points, remove unneeded cast, remove unneeded initialisation of `status']
Signed-off-by: Axel Lin <axel.lin@gmail.com>
Acked-by: Carlos Corbacho <carlos@strangeworlds.co.uk>
Cc: Matthew Garrett <mjg@redhat.com>
Cc: Thomas Renninger <trenn@suse.de>
Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/acer-wmi.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 652ca1800a0a..b06678660956 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -555,6 +555,7 @@ static acpi_status AMW0_find_mailled(void) | |||
555 | obj->buffer.length == sizeof(struct wmab_ret)) { | 555 | obj->buffer.length == sizeof(struct wmab_ret)) { |
556 | ret = *((struct wmab_ret *) obj->buffer.pointer); | 556 | ret = *((struct wmab_ret *) obj->buffer.pointer); |
557 | } else { | 557 | } else { |
558 | kfree(out.pointer); | ||
558 | return AE_ERROR; | 559 | return AE_ERROR; |
559 | } | 560 | } |
560 | 561 | ||
@@ -570,7 +571,7 @@ static acpi_status AMW0_set_capabilities(void) | |||
570 | { | 571 | { |
571 | struct wmab_args args; | 572 | struct wmab_args args; |
572 | struct wmab_ret ret; | 573 | struct wmab_ret ret; |
573 | acpi_status status = AE_OK; | 574 | acpi_status status; |
574 | struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; | 575 | struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; |
575 | union acpi_object *obj; | 576 | union acpi_object *obj; |
576 | 577 | ||
@@ -593,12 +594,13 @@ static acpi_status AMW0_set_capabilities(void) | |||
593 | if (ACPI_FAILURE(status)) | 594 | if (ACPI_FAILURE(status)) |
594 | return status; | 595 | return status; |
595 | 596 | ||
596 | obj = (union acpi_object *) out.pointer; | 597 | obj = out.pointer; |
597 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 598 | if (obj && obj->type == ACPI_TYPE_BUFFER && |
598 | obj->buffer.length == sizeof(struct wmab_ret)) { | 599 | obj->buffer.length == sizeof(struct wmab_ret)) { |
599 | ret = *((struct wmab_ret *) obj->buffer.pointer); | 600 | ret = *((struct wmab_ret *) obj->buffer.pointer); |
600 | } else { | 601 | } else { |
601 | return AE_ERROR; | 602 | status = AE_ERROR; |
603 | goto out; | ||
602 | } | 604 | } |
603 | 605 | ||
604 | if (ret.eax & 0x1) | 606 | if (ret.eax & 0x1) |
@@ -607,23 +609,26 @@ static acpi_status AMW0_set_capabilities(void) | |||
607 | args.ebx = 2 << 8; | 609 | args.ebx = 2 << 8; |
608 | args.ebx |= ACER_AMW0_BLUETOOTH_MASK; | 610 | args.ebx |= ACER_AMW0_BLUETOOTH_MASK; |
609 | 611 | ||
612 | /* | ||
613 | * It's ok to use existing buffer for next wmab_execute call. | ||
614 | * But we need to kfree(out.pointer) if next wmab_execute fail. | ||
615 | */ | ||
610 | status = wmab_execute(&args, &out); | 616 | status = wmab_execute(&args, &out); |
611 | if (ACPI_FAILURE(status)) | 617 | if (ACPI_FAILURE(status)) |
612 | return status; | 618 | goto out; |
613 | 619 | ||
614 | obj = (union acpi_object *) out.pointer; | 620 | obj = (union acpi_object *) out.pointer; |
615 | if (obj && obj->type == ACPI_TYPE_BUFFER | 621 | if (obj && obj->type == ACPI_TYPE_BUFFER |
616 | && obj->buffer.length == sizeof(struct wmab_ret)) { | 622 | && obj->buffer.length == sizeof(struct wmab_ret)) { |
617 | ret = *((struct wmab_ret *) obj->buffer.pointer); | 623 | ret = *((struct wmab_ret *) obj->buffer.pointer); |
618 | } else { | 624 | } else { |
619 | return AE_ERROR; | 625 | status = AE_ERROR; |
626 | goto out; | ||
620 | } | 627 | } |
621 | 628 | ||
622 | if (ret.eax & 0x1) | 629 | if (ret.eax & 0x1) |
623 | interface->capability |= ACER_CAP_BLUETOOTH; | 630 | interface->capability |= ACER_CAP_BLUETOOTH; |
624 | 631 | ||
625 | kfree(out.pointer); | ||
626 | |||
627 | /* | 632 | /* |
628 | * This appears to be safe to enable, since all Wistron based laptops | 633 | * This appears to be safe to enable, since all Wistron based laptops |
629 | * appear to use the same EC register for brightness, even if they | 634 | * appear to use the same EC register for brightness, even if they |
@@ -632,7 +637,10 @@ static acpi_status AMW0_set_capabilities(void) | |||
632 | if (quirks->brightness >= 0) | 637 | if (quirks->brightness >= 0) |
633 | interface->capability |= ACER_CAP_BRIGHTNESS; | 638 | interface->capability |= ACER_CAP_BRIGHTNESS; |
634 | 639 | ||
635 | return AE_OK; | 640 | status = AE_OK; |
641 | out: | ||
642 | kfree(out.pointer); | ||
643 | return status; | ||
636 | } | 644 | } |
637 | 645 | ||
638 | static struct wmi_interface AMW0_interface = { | 646 | static struct wmi_interface AMW0_interface = { |