hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/ipc/namespace.c
....@@ -42,7 +42,7 @@
4242 goto fail;
4343
4444 err = -ENOMEM;
45
- ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
45
+ ns = kzalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
4646 if (ns == NULL)
4747 goto fail_dec;
4848
....@@ -117,6 +117,10 @@
117117
118118 static void free_ipc_ns(struct ipc_namespace *ns)
119119 {
120
+ /* mq_put_mnt() waits for a grace period as kern_unmount()
121
+ * uses synchronize_rcu().
122
+ */
123
+ mq_put_mnt(ns);
120124 sem_exit_ns(ns);
121125 msg_exit_ns(ns);
122126 shm_exit_ns(ns);
....@@ -126,6 +130,21 @@
126130 ns_free_inum(&ns->ns);
127131 kfree(ns);
128132 }
133
+
134
+static LLIST_HEAD(free_ipc_list);
135
+static void free_ipc(struct work_struct *unused)
136
+{
137
+ struct llist_node *node = llist_del_all(&free_ipc_list);
138
+ struct ipc_namespace *n, *t;
139
+
140
+ llist_for_each_entry_safe(n, t, node, mnt_llist)
141
+ free_ipc_ns(n);
142
+}
143
+
144
+/*
145
+ * The work queue is used to avoid the cost of synchronize_rcu in kern_unmount.
146
+ */
147
+static DECLARE_WORK(free_ipc_work, free_ipc);
129148
130149 /*
131150 * put_ipc_ns - drop a reference to an ipc namespace.
....@@ -148,8 +167,9 @@
148167 if (refcount_dec_and_lock(&ns->count, &mq_lock)) {
149168 mq_clear_sbinfo(ns);
150169 spin_unlock(&mq_lock);
151
- mq_put_mnt(ns);
152
- free_ipc_ns(ns);
170
+
171
+ if (llist_add(&ns->mnt_llist, &free_ipc_list))
172
+ schedule_work(&free_ipc_work);
153173 }
154174 }
155175
....@@ -177,15 +197,14 @@
177197 return put_ipc_ns(to_ipc_ns(ns));
178198 }
179199
180
-static int ipcns_install(struct nsproxy *nsproxy, struct ns_common *new)
200
+static int ipcns_install(struct nsset *nsset, struct ns_common *new)
181201 {
202
+ struct nsproxy *nsproxy = nsset->nsproxy;
182203 struct ipc_namespace *ns = to_ipc_ns(new);
183204 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
184
- !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
205
+ !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
185206 return -EPERM;
186207
187
- /* Ditch state from the old ipc namespace */
188
- exit_sem(current);
189208 put_ipc_ns(nsproxy->ipc_ns);
190209 nsproxy->ipc_ns = get_ipc_ns(ns);
191210 return 0;