Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bd91249 authored by Palmer Dabbelt's avatar Palmer Dabbelt
Browse files

ANDROID: dm-user: Fix the list walk-and-delete code



This needs list_for_each_safe, without which we have a use-after-free
bug when updating the next pointer.

Fixes: 83bf345abc0b ("ANDROID: dm: dm-user: New target that proxies BIOs to userspace")
Suggested-by: default avatarAkilesh Kailash <akailash@google.com>
Signed-off-by: default avatarPalmer Dabbelt <palmerdabbelt@google.com>
Change-Id: I510ac12e2206a836ae6659bd7d96c0542960b26a
(cherry picked from commit 35f9e6bee13168655141057f8187b8b34c7543d9)
parent ea0aa597
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -507,11 +507,11 @@ static struct message *msg_get_to_user(struct target *t)
static struct message *msg_get_from_user(struct channel *c, u64 seq)
{
	struct message *m;
	struct list_head *cur;
	struct list_head *cur, *tmp;

	lockdep_assert_held(&c->lock);

	list_for_each (cur, &c->from_user) {
	list_for_each_safe (cur, tmp, &c->from_user) {
		m = list_entry(cur, struct message, from_user);
		if (m->msg.seq == seq) {
			list_del(&m->from_user);
@@ -544,14 +544,14 @@ static int target_poll(struct target *t)
static void target_release(struct kref *ref)
{
	struct target *t = container_of(ref, struct target, references);
	struct list_head *cur;
	struct list_head *cur, *tmp;

	/*
	 * There may be outstanding BIOs that have not yet been given to
	 * userspace.  At this point there's nothing we can do about them, as
	 * there are and will never be any channels.
	 */
	list_for_each (cur, &t->to_user) {
	list_for_each_safe (cur, tmp, &t->to_user) {
		message_kill(list_entry(cur, struct message, to_user),
			     &t->message_pool);
	}
@@ -595,7 +595,7 @@ static struct channel *channel_alloc(struct target *t)

static void channel_free(struct channel *c)
{
	struct list_head *cur;
	struct list_head *cur, *tmp;

	lockdep_assert_held(&c->lock);

@@ -616,7 +616,7 @@ static void channel_free(struct channel *c)
		message_kill(c->cur_to_user, &c->target->message_pool);
	if (c->cur_from_user != &c->scratch_message_from_user)
		message_kill(c->cur_from_user, &c->target->message_pool);
	list_for_each (cur, &c->from_user)
	list_for_each_safe (cur, tmp, &c->from_user)
		message_kill(list_entry(cur, struct message, from_user),
			     &c->target->message_pool);