diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 49538b172483c4f519100e1617f42d0f897bfbaa..8d712dee41b777b8ee66da84cf4677504973ad7e 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -43,6 +43,7 @@ struct pid_namespace { struct work_struct proc_work; kgid_t pid_gid; int hide_pid; + int pid_max; int reboot; /* group exit code if this pidns was rebooted */ struct ns_common ns; } __randomize_layout; diff --git a/kernel/pid.c b/kernel/pid.c index b88fe5e494ccfd46e26fbe78e843c1fc2f7244f7..cc1ec35c902e4ab20d3223a52e9cae69f098dc3c 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -55,12 +55,10 @@ struct pid init_struct_pid = { }, } }; -int pid_max = PID_MAX_DEFAULT; - #define RESERVED_PIDS 300 -int pid_max_min = RESERVED_PIDS + 1; -int pid_max_max = PID_MAX_LIMIT; +static int pid_max_min = RESERVED_PIDS + 1; +static int pid_max_max = PID_MAX_LIMIT; /* * PID-map pages start out as NULL, they get allocated upon @@ -190,7 +188,8 @@ struct pid *alloc_pid(struct pid_namespace *ns) * a partially initialized PID (see below). */ nr = idr_alloc_cyclic(&tmp->idr, NULL, pid_min, - pid_max, GFP_ATOMIC); + task_active_pid_ns(current)->pid_max, + GFP_ATOMIC); spin_unlock_irq(&pidmap_lock); idr_preload_end(); @@ -451,8 +450,36 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) return idr_get_next(&ns->idr, &nr); } +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 = ¤t->nsproxy->pid_ns_for_children->pid_max; + + return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); +} + +static struct ctl_table pid_ctl_table[] = { + { + .procname = "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) { + int pid_max = init_pid_ns.pid_max; + /* Verify no one has done anything silly: */ BUILD_BUG_ON(PID_MAX_LIMIT >= PIDNS_ADDING); @@ -463,8 +490,12 @@ void __init pid_idr_init(void) PIDS_PER_CPU_MIN * num_possible_cpus()); pr_info("pid_max: default: %u minimum: %u\n", pid_max, pid_max_min); + init_pid_ns.pid_max = pid_max; + 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); } diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 2a2ac53d8b8bb845f25581b549a1ea4136564692..80d39dc961d77c71cc3a157c59ec169543e86d53 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -115,6 +115,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns ns->user_ns = get_user_ns(user_ns); ns->ucounts = ucounts; ns->pid_allocated = PIDNS_ADDING; + ns->pid_max = parent_pid_ns->pid_max; INIT_WORK(&ns->proc_work, proc_cleanup_work); return ns; @@ -289,7 +290,6 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write, return ret; } -extern int pid_max; static int zero = 0; static struct ctl_table pid_ns_ctl_table[] = { { @@ -298,7 +298,7 @@ static struct ctl_table pid_ns_ctl_table[] = { .mode = 0666, /* permissions are checked in the handler */ .proc_handler = pid_ns_ctl_handler, .extra1 = &zero, - .extra2 = &pid_max, + .extra2 = &init_pid_ns.pid_max, }, { } }; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 56054a6a7a89cc4cd268db4c48da474fc4bd76eb..405806e0650a97a307987083a824c62bc075cfd5 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -107,8 +107,6 @@ extern int core_uses_pid; extern char core_pattern[]; extern unsigned int core_pipe_limit; #endif -extern int pid_max; -extern int pid_max_min, pid_max_max; extern int percpu_pagelist_fraction; extern int latencytop_enabled; extern unsigned int sysctl_nr_open_min, sysctl_nr_open_max; @@ -794,15 +792,6 @@ static struct ctl_table kern_table[] = { .proc_handler = proc_dointvec, }, #endif - { - .procname = "pid_max", - .data = &pid_max, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &pid_max_min, - .extra2 = &pid_max_max, - }, { .procname = "panic_on_oops", .data = &panic_on_oops, diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c65cea71d1ee5e1d44fb8979bc1798000632650e..8a38b3b0dc071e9b66ab32b7af0924985184d384 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -499,7 +499,7 @@ int trace_pid_write(struct trace_pid_list *filtered_pids, if (!pid_list) return -ENOMEM; - pid_list->pid_max = READ_ONCE(pid_max); + pid_list->pid_max = READ_ONCE(init_pid_ns.pid_max); /* Only truncating will shrink pid_max */ if (filtered_pids && filtered_pids->pid_max > pid_list->pid_max)