Skip to content

Commit

Permalink
ANDROID: Add ns_pid_max for each pid namespace
Browse files Browse the repository at this point in the history
Android bionic has limitation for thread id(<65536),
add a new node /proc/sys/kernel/ns_pid_max for each
pid namespace, android container can use this new node
to limit max process/thread id for android.

We still use kernel original /proc/sys/kernel/pid_max
node to config global level max pid, the valid pid per
namespace is min(pid_max, ns_pid_max).

Signed-off-by: Hongcheng Xie <[email protected]>
  • Loading branch information
hongcheng-xie authored and JeevakaPrabu committed Nov 14, 2022
1 parent 69c4d40 commit 892ce93
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/linux/pid_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
36 changes: 33 additions & 3 deletions kernel/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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: */
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions kernel/pid_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 892ce93

Please sign in to comment.