for (i = ns->level; i >= 0; i--) {
int tid = 0;
+ bool pid_noncyclic = 0;
+#ifdef CONFIG_IA32_EMULATION
+ pid_noncyclic = READ_ONCE(tmp->pid_noncyclic);
+#endif
if (set_tid_size) {
tid = set_tid[ns->level - i];
* Store a null pointer so find_pid_ns does not find
* a partially initialized PID (see below).
*/
- nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
- pid_max, GFP_ATOMIC);
+ if (likely(!pid_noncyclic))
+ nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min,
+ pid_max, GFP_ATOMIC);
+ else
+ nr = idr_alloc(&tmp->idr, NULL, pid_min,
+ pid_max, GFP_ATOMIC);
}
spin_unlock_irq(&pidmap_lock);
idr_preload_end();
ns->pid_allocated = PIDNS_ADDING;
#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE)
ns->memfd_noexec_scope = pidns_memfd_noexec_scope(parent_pid_ns);
+#endif
+#ifdef CONFIG_IA32_EMULATION
+ ns->pid_noncyclic = READ_ONCE(parent_pid_ns->pid_noncyclic);
#endif
return ns;
return;
}
-#ifdef CONFIG_CHECKPOINT_RESTORE
+#if defined(CONFIG_CHECKPOINT_RESTORE) || defined(CONFIG_IA32_EMULATION)
static int pid_ns_ctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (write && !checkpoint_restore_ns_capable(pid_ns->user_ns))
return -EPERM;
- next = idr_get_cursor(&pid_ns->idr) - 1;
+ next = -1;
+#ifdef CONFIG_IA32_EMULATION
+ if (!pid_ns->pid_noncyclic)
+#endif
+ next += idr_get_cursor(&pid_ns->idr);
tmp.data = &next;
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
- if (!ret && write)
- idr_set_cursor(&pid_ns->idr, next + 1);
+ if (!ret && write) {
+ if (next > -1)
+ idr_set_cursor(&pid_ns->idr, next + 1);
+ else if (!IS_ENABLED(CONFIG_IA32_EMULATION))
+ ret = -EINVAL;
+#ifdef CONFIG_IA32_EMULATION
+ WRITE_ONCE(pid_ns->pid_noncyclic, next == -1);
+#endif
+ }
return ret;
}
.maxlen = sizeof(int),
.mode = 0666, /* permissions are checked in the handler */
.proc_handler = pid_ns_ctl_handler,
- .extra1 = SYSCTL_ZERO,
+ .extra1 = SYSCTL_NEG_ONE,
.extra2 = &pid_max,
},
};
-#endif /* CONFIG_CHECKPOINT_RESTORE */
+#endif /* CONFIG_CHECKPOINT_RESTORE || CONFIG_IA32_EMULATION */
int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
{
{
pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC | SLAB_ACCOUNT);
-#ifdef CONFIG_CHECKPOINT_RESTORE
+#if defined(CONFIG_CHECKPOINT_RESTORE) || defined(CONFIG_IA32_EMULATION)
register_sysctl_init("kernel", pid_ns_ctl_table);
#endif