mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Hugh Dickins <hughd@google.com>
To: Holger Macht <holger@homac.de>
Cc: Hillf Danton <dhillf@gmail.com>, Matthew Garrett <mjg@redhat.com>,
	Jeff Garzik <jgarzik@redhat.com>,
	Stephen Rothwell <sfr@canb.auug.org.au>,
	linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: linux-next: dock_link_device is oopsy
Date: Sat, 18 Feb 2012 10:46:04 -0800 (PST)	[thread overview]
Message-ID: <alpine.LSU.2.00.1202181034380.3512@eggly.anvils> (raw)
In-Reply-To: <20120218140449.GA2558@homac.suse.de>

On Sat, 18 Feb 2012, Holger Macht wrote:
> How about that one?

It's more broken than that.  Here's my attempt.  It boots on the
systems with dock_station_count 0, and it boots on my laptop with
dock_station_count 2; but I don't actually have any docking station,
so it still doesn't test very much (dock is 0 after the loop).

I have no idea if what goes on in the loop is correct, but it looks
to me as if (as predicted) there's further breakage, that it would
have been writing beyond the end of what it allocated if I did have
a docking station.

Hugh

[PATCH] dock: fix bootup oops and other dock_link breakage

dock_link_device() and dock_unlink_device() should bail out early
to avoid oops on zero-length kmalloc() when dock_station_count is 0.

But isn't there an off-by-one in that kmalloc() length anyway?
An extra NULL appended at the end suggests so.

Rework the ordering with gotos on failure to fix several issues.

And presumably dock_unlink_device() should be presenting the same
interface as dock_link_device(), with NULL returned when none found.

Signed-off-by: Hugh Dickins <hughd@google.com>
---

 drivers/acpi/dock.c |   69 +++++++++++++++++++++++++++++-------------
 1 file changed, 49 insertions(+), 20 deletions(-)

--- linux-next/drivers/acpi/dock.c	2012-02-17 08:02:12.280064984 -0800
+++ fixed/drivers/acpi/dock.c	2012-02-18 09:57:54.926244796 -0800
@@ -281,21 +281,25 @@ EXPORT_SYMBOL_GPL(is_dock_device);
  */
 struct device **dock_link_device(acpi_handle handle)
 {
-	struct device *dev = acpi_get_physical_device(handle);
+	struct device *dev;
 	struct dock_station *dock_station;
 	int ret, dock = 0;
 	struct device **devices;
 
-	devices = kmalloc(dock_station_count * sizeof(struct device *),
-			  GFP_KERNEL);
+	if (!dock_station_count)
+		return NULL;
 
-	if (!dev)
+	if (is_dock(handle))
 		return NULL;
 
-	if (is_dock(handle)) {
-		put_device(dev);
+	dev = acpi_get_physical_device(handle);
+	if (!dev)
 		return NULL;
-	}
+
+	devices = kmalloc((dock_station_count + 1) * sizeof(struct device *),
+			  GFP_KERNEL);
+	if (!devices)
+		goto put;
 
 	list_for_each_entry(dock_station, &dock_stations, sibling) {
 		if (find_dock_dependent_device(dock_station, handle)) {
@@ -304,13 +308,23 @@ struct device **dock_link_device(acpi_ha
 			WARN_ON(ret);
 			devices[dock] = &dock_station->dock_device->dev;
 			dock++;
+			if (dock == dock_station_count)
+				goto out;
 		}
 	}
-	if (!dock)
-		put_device(dev);
 
+	if (!dock)
+		goto free;
+out:
+	/* Keep a reference to the device while the link exists */
 	devices[dock] = NULL;
 	return devices;
+
+free:
+	kfree(devices);
+put:
+	put_device(dev);
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(dock_link_device);
 
@@ -320,20 +334,25 @@ EXPORT_SYMBOL_GPL(dock_link_device);
  */
 struct device **dock_unlink_device(acpi_handle handle)
 {
-	struct device *dev = acpi_get_physical_device(handle);
+	struct device *dev;
 	struct dock_station *dock_station;
 	int dock = 0;
-	struct device **devices =
-		kmalloc(dock_station_count * sizeof(struct device *),
-			GFP_KERNEL);
+	struct device **devices;
 
-	if (!dev)
+	if (!dock_station_count)
 		return NULL;
 
-	if (is_dock(handle)) {
-		put_device(dev);
+	if (is_dock(handle))
 		return NULL;
-	}
+
+	dev = acpi_get_physical_device(handle);
+	if (!dev)
+		return NULL;
+
+	devices = kmalloc((dock_station_count + 1) * sizeof(struct device *),
+			  GFP_KERNEL);
+	if (!devices)
+		goto put;
 
 	list_for_each_entry(dock_station, &dock_stations, sibling) {
 		if (find_dock_dependent_device(dock_station, handle)) {
@@ -341,15 +360,25 @@ struct device **dock_unlink_device(acpi_
 					  dev_name(dev));
 			devices[dock] = &dock_station->dock_device->dev;
 			dock++;
+			if (dock == dock_station_count)
+				goto out;
 		}
 	}
-	/* An extra reference has been held while the link existed */
-	if (dock)
-		put_device(dev);
 
+	if (!dock)
+		goto free;
+out:
+	/* An extra reference has been held while the link existed */
+	put_device(dev);
 	put_device(dev);
 	devices[dock] = NULL;
 	return devices;
+
+free:
+	kfree(devices);
+put:
+	put_device(dev);
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(dock_unlink_device);
 

  parent reply	other threads:[~2012-02-18 18:46 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-17 21:46 Hugh Dickins
2012-02-17 22:29 ` Holger Macht
2012-02-17 22:42   ` Hugh Dickins
2012-02-17 23:01     ` Holger Macht
2012-02-17 23:49       ` Hugh Dickins
2012-02-18 11:14         ` Holger Macht
2012-02-18 13:05           ` Hillf Danton
2012-02-18 13:26             ` Holger Macht
2012-02-18 13:37               ` Hillf Danton
2012-02-18 14:04                 ` Holger Macht
2012-02-18 14:35                   ` Hillf Danton
2012-02-18 18:46                   ` Hugh Dickins [this message]
2012-02-18 19:57                     ` Holger Macht
2012-02-18 21:03                       ` Hugh Dickins
2012-02-18 21:50                         ` Holger Macht
2012-02-21 22:24                       ` Jeff Garzik
2012-02-21 22:30                         ` Holger Macht
2012-02-18  7:52       ` Hugh Dickins

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LSU.2.00.1202181034380.3512@eggly.anvils \
    --to=hughd@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=dhillf@gmail.com \
    --cc=holger@homac.de \
    --cc=jgarzik@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mjg@redhat.com \
    --cc=sfr@canb.auug.org.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®