* [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path
@ 2010-07-09 4:37 Axel Lin
2010-07-13 1:03 ` Axel Lin
2010-07-13 1:35 ` Andrew Morton
0 siblings, 2 replies; 4+ messages in thread
From: Axel Lin @ 2010-07-09 4:37 UTC (permalink / raw)
To: linux-kernel
Cc: Carlos Corbacho, Matthew Garrett, Thomas Renninger, Alan Jenkins,
platform-driver-x86
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.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
drivers/platform/x86/acer-wmi.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 1ea6c43..3f44446 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)
obj->buffer.length == sizeof(struct wmab_ret)) {
ret = *((struct wmab_ret *) obj->buffer.pointer);
} else {
+ kfree(out.pointer);
return AE_ERROR;
}
@@ -598,6 +599,7 @@ static acpi_status AMW0_set_capabilities(void)
obj->buffer.length == sizeof(struct wmab_ret)) {
ret = *((struct wmab_ret *) obj->buffer.pointer);
} else {
+ kfree(out.pointer);
return AE_ERROR;
}
@@ -607,15 +609,22 @@ static acpi_status AMW0_set_capabilities(void)
args.ebx = 2 << 8;
args.ebx |= ACER_AMW0_BLUETOOTH_MASK;
+ /*
+ * It's ok to use existing buffer for next wmab_execute call.
+ * But we need to kfree(out.pointer) if next wmab_execute fail.
+ */
status = wmab_execute(&args, &out);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ kfree(out.pointer);
return status;
+ }
obj = (union acpi_object *) out.pointer;
if (obj && obj->type == ACPI_TYPE_BUFFER
&& obj->buffer.length == sizeof(struct wmab_ret)) {
ret = *((struct wmab_ret *) obj->buffer.pointer);
} else {
+ kfree(out.pointer);
return AE_ERROR;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path 2010-07-09 4:37 [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path Axel Lin @ 2010-07-13 1:03 ` Axel Lin 2010-07-13 1:35 ` Andrew Morton 1 sibling, 0 replies; 4+ messages in thread From: Axel Lin @ 2010-07-13 1:03 UTC (permalink / raw) To: linux-kernel Cc: Carlos Corbacho, Matthew Garrett, Thomas Renninger, Alan Jenkins, platform-driver-x86, Andrew Morton hi Andrew, I just found acer-wmi-fix-memory-leaks-in-wmab_execute-error-path.patch added to -mm tree. But I think the V2 version is the correct one. If the second wmab_execute fail (for any reason) , we need to free the existing buffer before return status. Sould I resend the patch? Regards, Axel 於 五,2010-07-09 於 12:37 +0800,Axel Lin 提到: > 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. > > Signed-off-by: Axel Lin <axel.lin@gmail.com> > --- > drivers/platform/x86/acer-wmi.c | 11 ++++++++++- > 1 files changed, 10 insertions(+), 1 deletions(-) > > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c > index 1ea6c43..3f44446 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) > obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > + kfree(out.pointer); > return AE_ERROR; > } > > @@ -598,6 +599,7 @@ static acpi_status AMW0_set_capabilities(void) > obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > + kfree(out.pointer); > return AE_ERROR; > } > > @@ -607,15 +609,22 @@ static acpi_status AMW0_set_capabilities(void) > args.ebx = 2 << 8; > args.ebx |= ACER_AMW0_BLUETOOTH_MASK; > > + /* > + * It's ok to use existing buffer for next wmab_execute call. > + * But we need to kfree(out.pointer) if next wmab_execute fail. > + */ > status = wmab_execute(&args, &out); > - if (ACPI_FAILURE(status)) > + if (ACPI_FAILURE(status)) { > + kfree(out.pointer); > return status; > + } > > obj = (union acpi_object *) out.pointer; > if (obj && obj->type == ACPI_TYPE_BUFFER > && obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > + kfree(out.pointer); > return AE_ERROR; > } > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path 2010-07-09 4:37 [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path Axel Lin 2010-07-13 1:03 ` Axel Lin @ 2010-07-13 1:35 ` Andrew Morton 2010-07-13 2:14 ` Axel Lin 1 sibling, 1 reply; 4+ messages in thread From: Andrew Morton @ 2010-07-13 1:35 UTC (permalink / raw) To: Axel Lin Cc: linux-kernel, Carlos Corbacho, Matthew Garrett, Thomas Renninger, Alan Jenkins, platform-driver-x86 On Fri, 09 Jul 2010 12:37:36 +0800 Axel Lin <axel.lin@gmail.com> wrote: > 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. > > Signed-off-by: Axel Lin <axel.lin@gmail.com> > --- > drivers/platform/x86/acer-wmi.c | 11 ++++++++++- > 1 files changed, 10 insertions(+), 1 deletions(-) > > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c > index 1ea6c43..3f44446 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) > obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > + kfree(out.pointer); > return AE_ERROR; > } > > @@ -598,6 +599,7 @@ static acpi_status AMW0_set_capabilities(void) > obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > + kfree(out.pointer); > return AE_ERROR; > } > > @@ -607,15 +609,22 @@ static acpi_status AMW0_set_capabilities(void) > args.ebx = 2 << 8; > args.ebx |= ACER_AMW0_BLUETOOTH_MASK; > > + /* > + * It's ok to use existing buffer for next wmab_execute call. > + * But we need to kfree(out.pointer) if next wmab_execute fail. > + */ > status = wmab_execute(&args, &out); > - if (ACPI_FAILURE(status)) > + if (ACPI_FAILURE(status)) { > + kfree(out.pointer); > return status; > + } > > obj = (union acpi_object *) out.pointer; > if (obj && obj->type == ACPI_TYPE_BUFFER > && obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > + kfree(out.pointer); > return AE_ERROR; > } I think it's best to remove the multiple-return-points approach in favour of the "goto single return point which undoes things" approach. that way we reduce the risk of later introducing more leaks. Please review: From: Andrew Morton <akpm@linux-foundation.org> avoid multiple return points remove unneeded cast remove unneeded initialisation of `status' Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk> Cc: Axel Lin <axel.lin@gmail.com> Cc: Carlos Corbacho <carlos@strangeworlds.co.uk> Cc: Matthew Garrett <mjg@redhat.com> Cc: Thomas Renninger <trenn@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> --- drivers/platform/x86/acer-wmi.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff -puN drivers/platform/x86/acer-wmi.c~acer-wmi-fix-memory-leaks-in-wmab_execute-error-path-v2-fix drivers/platform/x86/acer-wmi.c --- a/drivers/platform/x86/acer-wmi.c~acer-wmi-fix-memory-leaks-in-wmab_execute-error-path-v2-fix +++ a/drivers/platform/x86/acer-wmi.c @@ -571,7 +571,7 @@ static acpi_status AMW0_set_capabilities { struct wmab_args args; struct wmab_ret ret; - acpi_status status = AE_OK; + acpi_status status; struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -594,13 +594,13 @@ static acpi_status AMW0_set_capabilities if (ACPI_FAILURE(status)) return status; - obj = (union acpi_object *) out.pointer; + obj = out.pointer; if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == sizeof(struct wmab_ret)) { ret = *((struct wmab_ret *) obj->buffer.pointer); } else { - kfree(out.pointer); - return AE_ERROR; + status = AE_ERROR; + goto out; } if (ret.eax & 0x1) @@ -614,25 +614,21 @@ static acpi_status AMW0_set_capabilities * But we need to kfree(out.pointer) if next wmab_execute fail. */ status = wmab_execute(&args, &out); - if (ACPI_FAILURE(status)) { - kfree(out.pointer); - return status; - } + if (ACPI_FAILURE(status)) + goto out; obj = (union acpi_object *) out.pointer; if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == sizeof(struct wmab_ret)) { ret = *((struct wmab_ret *) obj->buffer.pointer); } else { - kfree(out.pointer); - return AE_ERROR; + status = AE_ERROR; + goto out; } if (ret.eax & 0x1) interface->capability |= ACER_CAP_BLUETOOTH; - kfree(out.pointer); - /* * This appears to be safe to enable, since all Wistron based laptops * appear to use the same EC register for brightness, even if they @@ -641,7 +637,10 @@ static acpi_status AMW0_set_capabilities if (quirks->brightness >= 0) interface->capability |= ACER_CAP_BRIGHTNESS; - return AE_OK; + status = AE_OK; +out: + kfree(out.pointer); + return status; } static struct wmi_interface AMW0_interface = { _ ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path 2010-07-13 1:35 ` Andrew Morton @ 2010-07-13 2:14 ` Axel Lin 0 siblings, 0 replies; 4+ messages in thread From: Axel Lin @ 2010-07-13 2:14 UTC (permalink / raw) To: Andrew Morton Cc: linux-kernel, Carlos Corbacho, Matthew Garrett, Thomas Renninger, Alan Jenkins, platform-driver-x86 2010/7/13 Andrew Morton <akpm@linux-foundation.org>: > On Fri, 09 Jul 2010 12:37:36 +0800 Axel Lin <axel.lin@gmail.com> wrote: > >> 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. >> >> Signed-off-by: Axel Lin <axel.lin@gmail.com> >> --- >> drivers/platform/x86/acer-wmi.c | 11 ++++++++++- >> 1 files changed, 10 insertions(+), 1 deletions(-) >> >> diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c >> index 1ea6c43..3f44446 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) >> obj->buffer.length == sizeof(struct wmab_ret)) { >> ret = *((struct wmab_ret *) obj->buffer.pointer); >> } else { >> + kfree(out.pointer); >> return AE_ERROR; >> } >> >> @@ -598,6 +599,7 @@ static acpi_status AMW0_set_capabilities(void) >> obj->buffer.length == sizeof(struct wmab_ret)) { >> ret = *((struct wmab_ret *) obj->buffer.pointer); >> } else { >> + kfree(out.pointer); >> return AE_ERROR; >> } >> >> @@ -607,15 +609,22 @@ static acpi_status AMW0_set_capabilities(void) >> args.ebx = 2 << 8; >> args.ebx |= ACER_AMW0_BLUETOOTH_MASK; >> >> + /* >> + * It's ok to use existing buffer for next wmab_execute call. >> + * But we need to kfree(out.pointer) if next wmab_execute fail. >> + */ >> status = wmab_execute(&args, &out); >> - if (ACPI_FAILURE(status)) >> + if (ACPI_FAILURE(status)) { >> + kfree(out.pointer); >> return status; >> + } >> >> obj = (union acpi_object *) out.pointer; >> if (obj && obj->type == ACPI_TYPE_BUFFER >> && obj->buffer.length == sizeof(struct wmab_ret)) { >> ret = *((struct wmab_ret *) obj->buffer.pointer); >> } else { >> + kfree(out.pointer); >> return AE_ERROR; >> } > > I think it's best to remove the multiple-return-points approach in > favour of the "goto single return point which undoes things" approach. > that way we reduce the risk of later introducing more leaks. > > Please review: > > From: Andrew Morton <akpm@linux-foundation.org> > > avoid multiple return points > remove unneeded cast > remove unneeded initialisation of `status' > > Cc: Alan Jenkins <alan-jenkins@tuffmail.co.uk> > Cc: Axel Lin <axel.lin@gmail.com> > Cc: Carlos Corbacho <carlos@strangeworlds.co.uk> > Cc: Matthew Garrett <mjg@redhat.com> > Cc: Thomas Renninger <trenn@suse.de> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org> I'm not the author, but since I'm in the CC list and it looks good to me. Acked-by: Axel Lin <axel.lin@gmail.com> > --- > > drivers/platform/x86/acer-wmi.c | 25 ++++++++++++------------- > 1 file changed, 12 insertions(+), 13 deletions(-) > > diff -puN drivers/platform/x86/acer-wmi.c~acer-wmi-fix-memory-leaks-in-wmab_execute-error-path-v2-fix drivers/platform/x86/acer-wmi.c > --- a/drivers/platform/x86/acer-wmi.c~acer-wmi-fix-memory-leaks-in-wmab_execute-error-path-v2-fix > +++ a/drivers/platform/x86/acer-wmi.c > @@ -571,7 +571,7 @@ static acpi_status AMW0_set_capabilities > { > struct wmab_args args; > struct wmab_ret ret; > - acpi_status status = AE_OK; > + acpi_status status; > struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; > union acpi_object *obj; > > @@ -594,13 +594,13 @@ static acpi_status AMW0_set_capabilities > if (ACPI_FAILURE(status)) > return status; > > - obj = (union acpi_object *) out.pointer; > + obj = out.pointer; > if (obj && obj->type == ACPI_TYPE_BUFFER && > obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > - kfree(out.pointer); > - return AE_ERROR; > + status = AE_ERROR; > + goto out; > } > > if (ret.eax & 0x1) > @@ -614,25 +614,21 @@ static acpi_status AMW0_set_capabilities > * But we need to kfree(out.pointer) if next wmab_execute fail. > */ > status = wmab_execute(&args, &out); > - if (ACPI_FAILURE(status)) { > - kfree(out.pointer); > - return status; > - } > + if (ACPI_FAILURE(status)) > + goto out; > > obj = (union acpi_object *) out.pointer; > if (obj && obj->type == ACPI_TYPE_BUFFER > && obj->buffer.length == sizeof(struct wmab_ret)) { > ret = *((struct wmab_ret *) obj->buffer.pointer); > } else { > - kfree(out.pointer); > - return AE_ERROR; > + status = AE_ERROR; > + goto out; > } > > if (ret.eax & 0x1) > interface->capability |= ACER_CAP_BLUETOOTH; > > - kfree(out.pointer); > - > /* > * This appears to be safe to enable, since all Wistron based laptops > * appear to use the same EC register for brightness, even if they > @@ -641,7 +637,10 @@ static acpi_status AMW0_set_capabilities > if (quirks->brightness >= 0) > interface->capability |= ACER_CAP_BRIGHTNESS; > > - return AE_OK; > + status = AE_OK; > +out: > + kfree(out.pointer); > + return status; > } > > static struct wmi_interface AMW0_interface = { > _ > > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-07-13 2:15 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-07-09 4:37 [PATCH v2] acer-wmi: fix memory leaks in wmab_execute error path Axel Lin 2010-07-13 1:03 ` Axel Lin 2010-07-13 1:35 ` Andrew Morton 2010-07-13 2:14 ` Axel Lin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox