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

Commit 1f1503ba authored by Daniel De Graaf's avatar Daniel De Graaf Committed by Konrad Rzeszutek Wilk
Browse files

xen/gntdev: Fix sleep-inside-spinlock



BUG: sleeping function called from invalid context at /local/scratch/dariof/linux/kernel/mutex.c:271
in_atomic(): 1, irqs_disabled(): 0, pid: 3256, name: qemu-dm
1 lock held by qemu-dm/3256:
 #0:  (&(&priv->lock)->rlock){......}, at: [<ffffffff813223da>] gntdev_ioctl+0x2bd/0x4d5
Pid: 3256, comm: qemu-dm Tainted: G        W   3.1.0-rc8+ #5
Call Trace:
 [<ffffffff81054594>] __might_sleep+0x131/0x135
 [<ffffffff816bd64f>] mutex_lock_nested+0x25/0x45
 [<ffffffff8131c7c8>] free_xenballooned_pages+0x20/0xb1
 [<ffffffff8132194d>] gntdev_put_map+0xa8/0xdb
 [<ffffffff816be546>] ? _raw_spin_lock+0x71/0x7a
 [<ffffffff813223da>] ? gntdev_ioctl+0x2bd/0x4d5
 [<ffffffff8132243c>] gntdev_ioctl+0x31f/0x4d5
 [<ffffffff81007d62>] ? check_events+0x12/0x20
 [<ffffffff811433bc>] do_vfs_ioctl+0x488/0x4d7
 [<ffffffff81007d4f>] ? xen_restore_fl_direct_reloc+0x4/0x4
 [<ffffffff8109168b>] ? lock_release+0x21c/0x229
 [<ffffffff81135cdd>] ? rcu_read_unlock+0x21/0x32
 [<ffffffff81143452>] sys_ioctl+0x47/0x6a
 [<ffffffff816bfd82>] system_call_fastpath+0x16/0x1b

gntdev_put_map tries to acquire a mutex when freeing pages back to the
xenballoon pool, so it cannot be called with a spinlock held. In
gntdev_release, the spinlock is not needed as we are freeing the
structure later; in the ioctl, only the list manipulation needs to be
under the lock.

Reported-and-Tested-By: default avatarDario Faggioli <dario.faggioli@citrix.com>
Signed-off-by: default avatarDaniel De Graaf <dgdegra@tycho.nsa.gov>
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 0930bba6
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -492,13 +492,11 @@ static int gntdev_release(struct inode *inode, struct file *flip)

	pr_debug("priv %p\n", priv);

	spin_lock(&priv->lock);
	while (!list_empty(&priv->maps)) {
		map = list_entry(priv->maps.next, struct grant_map, next);
		list_del(&map->next);
		gntdev_put_map(map);
	}
	spin_unlock(&priv->lock);

	if (use_ptemod)
		mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -562,10 +560,11 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
	map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
	if (map) {
		list_del(&map->next);
		gntdev_put_map(map);
		err = 0;
	}
	spin_unlock(&priv->lock);
	if (map)
		gntdev_put_map(map);
	return err;
}