X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=kernel%2Fuser_namespace.c;h=076c7c8215b0e15289130fa5339bfc26dced7514;hb=a2a735ad666a04306a708b5a0109cc1fe113f569;hp=79084311ee5779a1e12b411ff37a5f04da08e360;hpb=18b6e0414e42d95183f07d8177e3ff0241abd825;p=safe%2Fjmp%2Flinux-2.6 diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 7908431..076c7c8 100644 --- a/kernel/user_namespace.c +++ b/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);