From 7aaa65476cbeec8e26dfb2fd6c01f9c642e8d5cd Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 27 Feb 2009 14:03:03 -0800 Subject: [PATCH] --- yaml --- r: 131839 b: refs/heads/master c: 5170836679185357dc1b7660bad13287b39e1e33 h: refs/heads/master i: 131837: 9f1f17e8ca779e37d320ca04d956cc2b42e351b0 131835: f15a427a23937006fb9b3600234e59814731bb34 131831: 041b968631a2d5076bee8dc700379b8b0fafe4ab 131823: 90bb2acb9da52983e8961fbed75991bb11d55ee1 131807: 75c9a8410052b64a76ccead2a459cd7f5666498a 131775: efc987ea0cffc99eb8fb0d9f5e0fd71706134f19 131711: 0beeec3a40a1aa1bfc678d666abf27b3c37cb5c1 131583: 6e8b1d1241e9ff2723db50bebb17dbd1dde73969 v: v3 --- [refs] | 2 +- trunk/include/linux/user_namespace.h | 1 + trunk/kernel/user_namespace.c | 21 +++++++++++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index 8b5a44416b23..6c802487a39a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8ca2f156b06bdcbfd1ab543355279246d05e2499 +refs/heads/master: 5170836679185357dc1b7660bad13287b39e1e33 diff --git a/trunk/include/linux/user_namespace.h b/trunk/include/linux/user_namespace.h index 315bcd375224..cc4f45361dbb 100644 --- a/trunk/include/linux/user_namespace.h +++ b/trunk/include/linux/user_namespace.h @@ -13,6 +13,7 @@ struct user_namespace { struct kref kref; struct hlist_head uidhash_table[UIDHASH_SZ]; struct user_struct *creator; + struct work_struct destroyer; }; extern struct user_namespace init_user_ns; diff --git a/trunk/kernel/user_namespace.c b/trunk/kernel/user_namespace.c index 79084311ee57..076c7c8215b0 100644 --- a/trunk/kernel/user_namespace.c +++ b/trunk/kernel/user_namespace.c @@ -60,12 +60,25 @@ int create_user_ns(struct cred *new) return 0; } -void free_user_ns(struct kref *kref) +/* + * Deferred destructor for a user namespace. This is required because + * free_user_ns() may be called with uidhash_lock held, but we need to call + * back to free_uid() which will want to take the lock again. + */ +static void free_user_ns_work(struct work_struct *work) { - struct user_namespace *ns; - - ns = container_of(kref, struct user_namespace, kref); + struct user_namespace *ns = + container_of(work, struct user_namespace, destroyer); free_uid(ns->creator); kfree(ns); } + +void free_user_ns(struct kref *kref) +{ + struct user_namespace *ns = + container_of(kref, struct user_namespace, kref); + + INIT_WORK(&ns->destroyer, free_user_ns_work); + schedule_work(&ns->destroyer); +} EXPORT_SYMBOL(free_user_ns);