Skip to content

Commit

Permalink
media: v4l2-async: Don't use dynamic static allocation
Browse files Browse the repository at this point in the history
commit 24e9a47 upstream.

Dynamic static allocation is evil, as Kernel stack is too low, and
compilation complains about it on some archs:
	drivers/media/v4l2-core/v4l2-async.c:238:1: warning: 'v4l2_async_notifier_unregister' uses dynamic stack allocation [enabled by default]
Instead, let's enforce a limit for the buffer.
In this specific case, there's a hard limit imposed by V4L2_MAX_SUBDEVS,
with is currently 128. That means that the buffer size can be up to
128x8 = 1024 bytes (on a 64bits kernel), with is too big for stack.
Worse than that, someone could increase it and cause real troubles.
So, let's use dynamically allocated data, instead.

Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Mauro Carvalho Chehab authored and Greg Kroah-Hartman committed Dec 4, 2013
1 parent 282e059 commit e715159
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions drivers/media/v4l2-core/v4l2-async.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,30 +189,53 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
struct v4l2_subdev *sd, *tmp;
unsigned int notif_n_subdev = notifier->num_subdevs;
unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS);
struct device *dev[n_subdev];
struct device **dev;
int i = 0;

if (!notifier->v4l2_dev)
return;

dev = kmalloc(n_subdev * sizeof(*dev), GFP_KERNEL);
if (!dev) {
dev_err(notifier->v4l2_dev->dev,
"Failed to allocate device cache!\n");
}

mutex_lock(&list_lock);

list_del(&notifier->list);

list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
dev[i] = get_device(sd->dev);
struct device *d;

d = get_device(sd->dev);

v4l2_async_cleanup(sd);

/* If we handled USB devices, we'd have to lock the parent too */
device_release_driver(dev[i++]);
device_release_driver(d);

if (notifier->unbind)
notifier->unbind(notifier, sd, sd->asd);

/*
* Store device at the device cache, in order to call
* put_device() on the final step
*/
if (dev)
dev[i++] = d;
else
put_device(d);
}

mutex_unlock(&list_lock);

/*
* Call device_attach() to reprobe devices
*
* NOTE: If dev allocation fails, i is 0, and the whole loop won't be
* executed.
*/
while (i--) {
struct device *d = dev[i];

Expand All @@ -228,6 +251,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
}
put_device(d);
}
kfree(dev);

notifier->v4l2_dev = NULL;

Expand Down

0 comments on commit e715159

Please sign in to comment.