diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 7c7e627503d22..b89d8ab82702a 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -19,6 +19,7 @@ struct fs_pin; struct pid_namespace { struct idr idr; struct rcu_head rcu; + int pid_max; unsigned int pid_allocated; struct task_struct *child_reaper; struct kmem_cache *pid_cachep; diff --git a/kernel/pid.c b/kernel/pid.c index de13b4690aaf2..cd0982ac8d10b 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -186,12 +186,13 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid, for (i = ns->level; i >= 0; i--) { int tid = 0; + int ns_pid_max = min(pid_max, tmp->pid_max); if (set_tid_size) { tid = set_tid[ns->level - i]; retval = -EINVAL; - if (tid < 1 || tid >= pid_max) + if (tid < 1 || tid >= ns_pid_max) goto out_free; /* * Also fail if a PID != 1 is requested and @@ -231,7 +232,7 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid, * a partially initialized PID (see below). */ nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min, - pid_max, GFP_ATOMIC); + ns_pid_max, GFP_ATOMIC); } spin_unlock_irq(&pidmap_lock); idr_preload_end(); @@ -611,6 +612,33 @@ SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags) return fd; } + +static int proc_dointvec_pidmax(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct ctl_table tmp; + + tmp = *table; + tmp.data = &(task_active_pid_ns(current)->pid_max); + + return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); +} + +static struct ctl_table pid_ctl_table[] = { + { + .procname = "ns_pid_max", + .data = &init_pid_ns.pid_max, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = proc_dointvec_pidmax, + .extra1 = &pid_max_min, + .extra2 = &pid_max_max, + }, + { } +}; + +static struct ctl_path pid_kern_path[] = { { .procname = "kernel" }, { } }; + void __init pid_idr_init(void) { /* Verify no one has done anything silly: */ @@ -619,14 +647,16 @@ void __init pid_idr_init(void) /* bump default and minimum pid_max based on number of cpus */ pid_max = min(pid_max_max, max_t(int, pid_max, PIDS_PER_CPU_DEFAULT * num_possible_cpus())); + init_pid_ns.pid_max = pid_max_max; pid_max_min = max_t(int, pid_max_min, PIDS_PER_CPU_MIN * num_possible_cpus()); - pr_info("pid_max: default: %u minimum: %u\n", pid_max, pid_max_min); + pr_info("pid_max: default: %u, ns_pid_max: %d, minimum: %u\n", pid_max, init_pid_ns.pid_max, pid_max_min); idr_init(&init_pid_ns.idr); init_pid_ns.pid_cachep = KMEM_CACHE(pid, SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); + register_sysctl_paths(pid_kern_path, pid_ctl_table); } static struct file *__pidfd_fget(struct task_struct *task, int fd) diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index a46a3723bc662..8383d09b802d2 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -106,6 +106,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns refcount_set(&ns->ns.count, 1); ns->level = level; ns->parent = get_pid_ns(parent_pid_ns); + ns->pid_max = parent_pid_ns->pid_max; ns->user_ns = get_user_ns(user_ns); ns->ucounts = ucounts; ns->pid_allocated = PIDNS_ADDING;