|
@@ -29,6 +29,7 @@ static DEFINE_MUTEX(userns_state_mutex);
|
|
static bool new_idmap_permitted(const struct file *file,
|
|
static bool new_idmap_permitted(const struct file *file,
|
|
struct user_namespace *ns, int cap_setid,
|
|
struct user_namespace *ns, int cap_setid,
|
|
struct uid_gid_map *map);
|
|
struct uid_gid_map *map);
|
|
|
|
+static void free_user_ns(struct work_struct *work);
|
|
|
|
|
|
static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
|
|
static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
|
|
{
|
|
{
|
|
@@ -101,6 +102,7 @@ int create_user_ns(struct cred *new)
|
|
ns->level = parent_ns->level + 1;
|
|
ns->level = parent_ns->level + 1;
|
|
ns->owner = owner;
|
|
ns->owner = owner;
|
|
ns->group = group;
|
|
ns->group = group;
|
|
|
|
+ INIT_WORK(&ns->work, free_user_ns);
|
|
|
|
|
|
/* Inherit USERNS_SETGROUPS_ALLOWED from our parent */
|
|
/* Inherit USERNS_SETGROUPS_ALLOWED from our parent */
|
|
mutex_lock(&userns_state_mutex);
|
|
mutex_lock(&userns_state_mutex);
|
|
@@ -135,9 +137,10 @@ int unshare_userns(unsigned long unshare_flags, struct cred **new_cred)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-void free_user_ns(struct user_namespace *ns)
|
|
|
|
|
|
+static void free_user_ns(struct work_struct *work)
|
|
{
|
|
{
|
|
- struct user_namespace *parent;
|
|
|
|
|
|
+ struct user_namespace *parent, *ns =
|
|
|
|
+ container_of(work, struct user_namespace, work);
|
|
|
|
|
|
do {
|
|
do {
|
|
parent = ns->parent;
|
|
parent = ns->parent;
|
|
@@ -149,7 +152,12 @@ void free_user_ns(struct user_namespace *ns)
|
|
ns = parent;
|
|
ns = parent;
|
|
} while (atomic_dec_and_test(&parent->count));
|
|
} while (atomic_dec_and_test(&parent->count));
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL(free_user_ns);
|
|
|
|
|
|
+
|
|
|
|
+void __put_user_ns(struct user_namespace *ns)
|
|
|
|
+{
|
|
|
|
+ schedule_work(&ns->work);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(__put_user_ns);
|
|
|
|
|
|
static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
|
|
static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
|
|
{
|
|
{
|