Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975// SPDX-License-Identifier: GPL-2.0-only/* * Generic pidhash and scalable, time-bounded PID allocator * * (C) 2002-2003 Nadia Yvette Chambers, IBM * (C) 2004 Nadia Yvette Chambers, Oracle * (C) 2002-2004 Ingo Molnar, Red Hat * * pid-structures are backing objects for tasks sharing a given ID to chain * against. There is very little to them aside from hashing them and * parking tasks using given ID's on a list. * * The hash is always changed with the tasklist_lock write-acquired, * and the hash is only accessed with the tasklist_lock at least * read-acquired, so there's no additional SMP locking needed here. * * We have a list of bitmap pages, which bitmaps represent the PID space. * Allocating and freeing PIDs is completely lockless. The worst-case * allocation scenario when all but one out of 1 million PIDs possible are * allocated already: the scanning of 32 list entries and at most PAGE_SIZE * bytes. The typical fastpath is a single successful setbit. Freeing is O(1). * * Pid namespaces: * (C) 2007 Pavel Emelyanov <xemul@openvz.org>, OpenVZ, SWsoft Inc. * (C) 2007 Sukadev Bhattiprolu <sukadev@us.ibm.com>, IBM * Many thanks to Oleg Nesterov for comments and help * */
#include <linux/mm.h>#include <linux/export.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/rculist.h>#include <linux/memblock.h>#include <linux/pid_namespace.h>#include <linux/init_task.h>#include <linux/syscalls.h>#include <linux/proc_ns.h>#include <linux/refcount.h>#include <linux/anon_inodes.h>#include <linux/sched/signal.h>#include <linux/sched/task.h>#include <linux/idr.h>#include <linux/pidfs.h>#include <net/sock.h>#include <uapi/linux/pidfd.h>
struct pid init_struct_pid = { .count = REFCOUNT_INIT(1), .tasks = { { .first = NULL }, { .first = NULL }, { .first = NULL }, }, .level = 0, .numbers = { { .nr = 0, .ns = &init_pid_ns, }, }};
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 * first use and are never deallocated. This way a low pid_max * value does not cause lots of bitmaps to be allocated, but * the scheme scales to up to 4 million PIDs, runtime. */struct pid_namespace init_pid_ns = { .ns = NS_COMMON_INIT(init_pid_ns), .idr = IDR_INIT(init_pid_ns.idr), .pid_allocated = PIDNS_ADDING, .level = 0, .child_reaper = &init_task, .user_ns = &init_user_ns, .pid_max = PID_MAX_DEFAULT,#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) .memfd_noexec_scope = MEMFD_NOEXEC_SCOPE_EXEC,#endif};EXPORT_SYMBOL_GPL(init_pid_ns);
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
void put_pid(struct pid *pid){ struct pid_namespace *ns;
if (!pid) return;
ns = pid->numbers[pid->level].ns; if (refcount_dec_and_test(&pid->count)) { pidfs_free_pid(pid); kmem_cache_free(ns->pid_cachep, pid); put_pid_ns(ns); }}EXPORT_SYMBOL_GPL(put_pid);
static void delayed_put_pid(struct rcu_head *rhp){ struct pid *pid = container_of(rhp, struct pid, rcu); put_pid(pid);}
void free_pid(struct pid *pid){ int i; struct pid_namespace *active_ns;
lockdep_assert_not_held(&tasklist_lock);
active_ns = pid->numbers[pid->level].ns; ns_ref_active_put(active_ns);
spin_lock(&pidmap_lock); for (i = 0; i <= pid->level; i++) { struct upid *upid = pid->numbers + i; struct pid_namespace *ns = upid->ns; switch (--ns->pid_allocated) { case 2: case 1: /* When all that is left in the pid namespace * is the reaper wake up the reaper. The reaper * may be sleeping in zap_pid_ns_processes(). */ wake_up_process(READ_ONCE(ns->child_reaper)); break; case PIDNS_ADDING: /* Only possible if the 1st fork fails */ WARN_ON(READ_ONCE(ns->child_reaper)); break; }
idr_remove(&ns->idr, upid->nr); } spin_unlock(&pidmap_lock);
pidfs_remove_pid(pid); call_rcu(&pid->rcu, delayed_put_pid);}
void free_pids(struct pid **pids){ int tmp;
/* * This can batch pidmap_lock. */ for (tmp = PIDTYPE_MAX; --tmp >= 0; ) if (pids[tmp]) free_pid(pids[tmp]);}
struct pid *alloc_pid(struct pid_namespace *ns, pid_t *arg_set_tid, size_t arg_set_tid_size){ int set_tid[MAX_PID_NS_LEVEL + 1] = {}; int pid_max[MAX_PID_NS_LEVEL + 1] = {}; struct pid *pid; enum pid_type type; int i, nr; struct pid_namespace *tmp; struct upid *upid; int retval = -ENOMEM; bool retried_preload;
/* * arg_set_tid_size contains the size of the arg_set_tid array. Starting at * the most nested currently active PID namespace it tells alloc_pid() * which PID to set for a process in that most nested PID namespace * up to arg_set_tid_size PID namespaces. It does not have to set the PID * for a process in all nested PID namespaces but arg_set_tid_size must * never be greater than the current ns->level + 1. */ if (arg_set_tid_size > ns->level + 1) return ERR_PTR(-EINVAL);
/* * Prep before we take locks: * * 1. allocate and fill in pid struct */ pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); if (!pid) return ERR_PTR(retval);
get_pid_ns(ns); pid->level = ns->level; refcount_set(&pid->count, 1); spin_lock_init(&pid->lock); for (type = 0; type < PIDTYPE_MAX; ++type) INIT_HLIST_HEAD(&pid->tasks[type]); init_waitqueue_head(&pid->wait_pidfd); INIT_HLIST_HEAD(&pid->inodes); pidfs_prepare_pid(pid);
/* * 2. perm check checkpoint_restore_ns_capable() * * This stores found pid_max to make sure the used value is the same should * later code need it. */ for (tmp = ns, i = ns->level; i >= 0; i--) { pid_max[ns->level - i] = READ_ONCE(tmp->pid_max);
if (arg_set_tid_size) { int tid = set_tid[ns->level - i] = arg_set_tid[ns->level - i];
retval = -EINVAL; if (tid < 1 || tid >= pid_max[ns->level - i]) goto out_abort; retval = -EPERM; if (!checkpoint_restore_ns_capable(tmp->user_ns)) goto out_abort; arg_set_tid_size--; }
tmp = tmp->parent; }
/* * Prep is done, id allocation goes here: */ retried_preload = false; idr_preload(GFP_KERNEL); spin_lock(&pidmap_lock); /* For the case when the previous attempt to create init failed */ if (ns->pid_allocated == PIDNS_ADDING) idr_set_cursor(&ns->idr, 0);
for (tmp = ns, i = ns->level; i >= 0;) { int tid = set_tid[ns->level - i];
if (tid) { nr = idr_alloc(&tmp->idr, NULL, tid, tid + 1, GFP_ATOMIC); /* * If ENOSPC is returned it means that the PID is * alreay in use. Return EEXIST in that case. */ if (nr == -ENOSPC)
nr = -EEXIST; } else { int pid_min = 1; /* * init really needs pid 1, but after reaching the * maximum wrap back to RESERVED_PIDS */ if (idr_get_cursor(&tmp->idr) > RESERVED_PIDS) pid_min = RESERVED_PIDS;
/* * 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[ns->level - i], GFP_ATOMIC); if (nr == -ENOSPC) nr = -EAGAIN; }
if (unlikely(nr < 0)) { /* * Preload more memory if idr_alloc{,cyclic} failed with -ENOMEM. * * The IDR API only allows us to preload memory for one call, while we may end * up doing several under pidmap_lock with GFP_ATOMIC. The situation may be * salvageable with GFP_KERNEL. But make sure to not loop indefinitely if preload * did not help (the routine unfortunately returns void, so we have no idea * if it got anywhere). * * The lock can be safely dropped and picked up as historically pid allocation * for different namespaces was *not* atomic -- we try to hold on to it the * entire time only for performance reasons. */ if (nr == -ENOMEM && !retried_preload) { spin_unlock(&pidmap_lock); idr_preload_end(); retried_preload = true; idr_preload(GFP_KERNEL); spin_lock(&pidmap_lock); continue; } retval = nr; goto out_free; }
pid->numbers[i].nr = nr; pid->numbers[i].ns = tmp; i--; retried_preload = false;
/* * PID 1 (init) must be created first. */ if (!READ_ONCE(tmp->child_reaper) && nr != 1) { retval = -EINVAL; goto out_free; }
tmp = tmp->parent; }
/* * ENOMEM is not the most obvious choice especially for the case * where the child subreaper has already exited and the pid * namespace denies the creation of any new processes. But ENOMEM * is what we have exposed to userspace for a long time and it is * documented behavior for pid namespaces. So we can't easily * change it even if there were an error code better suited. * * This can't be done earlier because we need to preserve other * error conditions. * * We need this even if copy_process() does the same check. If two * or more tasks from parent namespace try to inject a child into a * dead namespace, one of free_pid() calls from the copy_process() * error path may try to wakeup the possibly freed ns->child_reaper. */ retval = -ENOMEM; if (unlikely(!(ns->pid_allocated & PIDNS_ADDING))) goto out_free; for (upid = pid->numbers + ns->level; upid >= pid->numbers; --upid) { /* Make the PID visible to find_pid_ns. */ idr_replace(&upid->ns->idr, pid, upid->nr); upid->ns->pid_allocated++; } spin_unlock(&pidmap_lock); idr_preload_end(); ns_ref_active_get(ns);
retval = pidfs_add_pid(pid); if (unlikely(retval)) { free_pid(pid); pid = ERR_PTR(-ENOMEM); }
return pid;
out_free: while (++i <= ns->level) { upid = pid->numbers + i; idr_remove(&upid->ns->idr, upid->nr); }
spin_unlock(&pidmap_lock); idr_preload_end();
out_abort: put_pid_ns(ns); kmem_cache_free(ns->pid_cachep, pid); return ERR_PTR(retval);}
void disable_pid_allocation(struct pid_namespace *ns){ spin_lock(&pidmap_lock); ns->pid_allocated &= ~PIDNS_ADDING; spin_unlock(&pidmap_lock);}
struct pid *find_pid_ns(int nr, struct pid_namespace *ns){ return idr_find(&ns->idr, nr);}EXPORT_SYMBOL_GPL(find_pid_ns);
struct pid *find_vpid(int nr){ return find_pid_ns(nr, task_active_pid_ns(current));}EXPORT_SYMBOL_GPL(find_vpid);
static struct pid **task_pid_ptr(struct task_struct *task, enum pid_type type){ return (type == PIDTYPE_PID) ? &task->thread_pid : &task->signal->pids[type];}
/* * attach_pid() must be called with the tasklist_lock write-held. */void attach_pid(struct task_struct *task, enum pid_type type){ struct pid *pid;
lockdep_assert_held_write(&tasklist_lock);
pid = *task_pid_ptr(task, type); hlist_add_head_rcu(&task->pid_links[type], &pid->tasks[type]);}
static void __change_pid(struct pid **pids, struct task_struct *task, enum pid_type type, struct pid *new){ struct pid **pid_ptr, *pid; int tmp;
lockdep_assert_held_write(&tasklist_lock);
pid_ptr = task_pid_ptr(task, type); pid = *pid_ptr;
hlist_del_rcu(&task->pid_links[type]); *pid_ptr = new;
for (tmp = PIDTYPE_MAX; --tmp >= 0; ) if (pid_has_task(pid, tmp)) return;
WARN_ON(pids[type]); pids[type] = pid;}
void detach_pid(struct pid **pids, struct task_struct *task, enum pid_type type){ __change_pid(pids, task, type, NULL);}
void change_pid(struct pid **pids, struct task_struct *task, enum pid_type type, struct pid *pid){ __change_pid(pids, task, type, pid); attach_pid(task, type);}
void exchange_tids(struct task_struct *left, struct task_struct *right){ struct pid *pid1 = left->thread_pid; struct pid *pid2 = right->thread_pid; struct hlist_head *head1 = &pid1->tasks[PIDTYPE_PID]; struct hlist_head *head2 = &pid2->tasks[PIDTYPE_PID];
lockdep_assert_held_write(&tasklist_lock);
/* Swap the single entry tid lists */ hlists_swap_heads_rcu(head1, head2);
/* Swap the per task_struct pid */ rcu_assign_pointer(left->thread_pid, pid2); rcu_assign_pointer(right->thread_pid, pid1);
/* Swap the cached value */ WRITE_ONCE(left->pid, pid_nr(pid2)); WRITE_ONCE(right->pid, pid_nr(pid1));}
/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */void transfer_pid(struct task_struct *old, struct task_struct *new, enum pid_type type){ WARN_ON_ONCE(type == PIDTYPE_PID); lockdep_assert_held_write(&tasklist_lock); hlist_replace_rcu(&old->pid_links[type], &new->pid_links[type]);}
struct task_struct *pid_task(struct pid *pid, enum pid_type type){ struct task_struct *result = NULL; if (pid) { struct hlist_node *first; first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]), lockdep_tasklist_lock_is_held()); if (first) result = hlist_entry(first, struct task_struct, pid_links[(type)]); } return result;}EXPORT_SYMBOL(pid_task);
/* * Must be called under rcu_read_lock(). */struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns){ RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "find_task_by_pid_ns() needs rcu_read_lock() protection"); return pid_task(find_pid_ns(nr, ns), PIDTYPE_PID);}
struct task_struct *find_task_by_vpid(pid_t vnr){ return find_task_by_pid_ns(vnr, task_active_pid_ns(current));}
struct task_struct *find_get_task_by_vpid(pid_t nr){ struct task_struct *task;
rcu_read_lock(); task = find_task_by_vpid(nr); if (task) get_task_struct(task); rcu_read_unlock();
return task;}
struct pid *get_task_pid(struct task_struct *task, enum pid_type type){ struct pid *pid; rcu_read_lock(); pid = get_pid(rcu_dereference(*task_pid_ptr(task, type))); rcu_read_unlock(); return pid;}EXPORT_SYMBOL_GPL(get_task_pid);
struct task_struct *get_pid_task(struct pid *pid, enum pid_type type){ struct task_struct *result; rcu_read_lock(); result = pid_task(pid, type); if (result) get_task_struct(result); rcu_read_unlock(); return result;}EXPORT_SYMBOL_GPL(get_pid_task);
struct pid *find_get_pid(pid_t nr){ struct pid *pid;
rcu_read_lock(); pid = get_pid(find_vpid(nr)); rcu_read_unlock();
return pid;}EXPORT_SYMBOL_GPL(find_get_pid);
pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns){ struct upid *upid; pid_t nr = 0;
if (pid && ns && ns->level <= pid->level) { upid = &pid->numbers[ns->level]; if (upid->ns == ns) nr = upid->nr; } return nr;}EXPORT_SYMBOL_GPL(pid_nr_ns);
pid_t pid_vnr(struct pid *pid){ return pid_nr_ns(pid, task_active_pid_ns(current));}EXPORT_SYMBOL_GPL(pid_vnr);
pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, struct pid_namespace *ns){ pid_t nr = 0;
rcu_read_lock(); if (!ns) ns = task_active_pid_ns(current); nr = pid_nr_ns(rcu_dereference(*task_pid_ptr(task, type)), ns); rcu_read_unlock();
return nr;}EXPORT_SYMBOL(__task_pid_nr_ns);
struct pid_namespace *task_active_pid_ns(struct task_struct *tsk){ return ns_of_pid(task_pid(tsk));}EXPORT_SYMBOL_GPL(task_active_pid_ns);
/* * Used by proc to find the first pid that is greater than or equal to nr. * * If there is a pid at nr this function is exactly the same as find_pid_ns. */struct pid *find_ge_pid(int nr, struct pid_namespace *ns){ return idr_get_next(&ns->idr, &nr);}EXPORT_SYMBOL_GPL(find_ge_pid);
struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags){ CLASS(fd, f)(fd); struct pid *pid;
if (fd_empty(f)) return ERR_PTR(-EBADF);
pid = pidfd_pid(fd_file(f)); if (!IS_ERR(pid)) { get_pid(pid); *flags = fd_file(f)->f_flags; } return pid;}
/** * pidfd_get_task() - Get the task associated with a pidfd * * @pidfd: pidfd for which to get the task * @flags: flags associated with this pidfd * * Return the task associated with @pidfd. The function takes a reference on * the returned task. The caller is responsible for releasing that reference. * * Return: On success, the task_struct associated with the pidfd. * On error, a negative errno number will be returned. */struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags){ unsigned int f_flags = 0; struct pid *pid; struct task_struct *task; enum pid_type type;
switch (pidfd) { case PIDFD_SELF_THREAD: type = PIDTYPE_PID; pid = get_task_pid(current, type); break; case PIDFD_SELF_THREAD_GROUP: type = PIDTYPE_TGID; pid = get_task_pid(current, type); break; default: pid = pidfd_get_pid(pidfd, &f_flags); if (IS_ERR(pid)) return ERR_CAST(pid); type = PIDTYPE_TGID; break; }
task = get_pid_task(pid, type); put_pid(pid); if (!task) return ERR_PTR(-ESRCH);
*flags = f_flags; return task;}
/** * pidfd_create() - Create a new pid file descriptor. * * @pid: struct pid that the pidfd will reference * @flags: flags to pass * * This creates a new pid file descriptor with the O_CLOEXEC flag set. * * Note, that this function can only be called after the fd table has * been unshared to avoid leaking the pidfd to the new process. * * This symbol should not be explicitly exported to loadable modules. * * Return: On success, a cloexec pidfd is returned. * On error, a negative errno number will be returned. */static int pidfd_create(struct pid *pid, unsigned int flags){ int pidfd; struct file *pidfd_file;
pidfd = pidfd_prepare(pid, flags, &pidfd_file); if (pidfd < 0) return pidfd;
fd_install(pidfd, pidfd_file); return pidfd;}
/** * sys_pidfd_open() - Open new pid file descriptor. * * @pid: pid for which to retrieve a pidfd * @flags: flags to pass * * This creates a new pid file descriptor with the O_CLOEXEC flag set for * the task identified by @pid. Without PIDFD_THREAD flag the target task * must be a thread-group leader. * * Return: On success, a cloexec pidfd is returned. * On error, a negative errno number will be returned. */SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags){ int fd; struct pid *p;
if (flags & ~(PIDFD_NONBLOCK | PIDFD_THREAD)) return -EINVAL;
if (pid <= 0) return -EINVAL;
p = find_get_pid(pid); if (!p) return -ESRCH;
fd = pidfd_create(p, flags);
put_pid(p); return fd;}
#ifdef CONFIG_SYSCTLstatic struct ctl_table_set *pid_table_root_lookup(struct ctl_table_root *root){ return &task_active_pid_ns(current)->set;}
static int set_is_seen(struct ctl_table_set *set){ return &task_active_pid_ns(current)->set == set;}
static int pid_table_root_permissions(struct ctl_table_header *head, const struct ctl_table *table){ struct pid_namespace *pidns = container_of(head->set, struct pid_namespace, set); int mode = table->mode;
if (ns_capable_noaudit(pidns->user_ns, CAP_SYS_ADMIN) || uid_eq(current_euid(), make_kuid(pidns->user_ns, 0))) mode = (mode & S_IRWXU) >> 6; else if (in_egroup_p(make_kgid(pidns->user_ns, 0))) mode = (mode & S_IRWXG) >> 3; else mode = mode & S_IROTH; return (mode << 6) | (mode << 3) | mode;}
static void pid_table_root_set_ownership(struct ctl_table_header *head, kuid_t *uid, kgid_t *gid){ struct pid_namespace *pidns = container_of(head->set, struct pid_namespace, set); kuid_t ns_root_uid; kgid_t ns_root_gid;
ns_root_uid = make_kuid(pidns->user_ns, 0); if (uid_valid(ns_root_uid)) *uid = ns_root_uid;
ns_root_gid = make_kgid(pidns->user_ns, 0); if (gid_valid(ns_root_gid)) *gid = ns_root_gid;}
static struct ctl_table_root pid_table_root = { .lookup = pid_table_root_lookup, .permissions = pid_table_root_permissions, .set_ownership = pid_table_root_set_ownership,};
static int proc_do_cad_pid(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos){ struct pid *new_pid; pid_t tmp_pid; int r; struct ctl_table tmp_table = *table;
tmp_pid = pid_vnr(cad_pid); tmp_table.data = &tmp_pid;
r = proc_dointvec(&tmp_table, write, buffer, lenp, ppos); if (r || !write) return r;
new_pid = find_get_pid(tmp_pid); if (!new_pid) return -ESRCH;
put_pid(xchg(&cad_pid, new_pid)); return 0;}
static const struct ctl_table pid_table[] = { { .procname = "pid_max", .data = &init_pid_ns.pid_max, .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, .extra1 = &pid_max_min, .extra2 = &pid_max_max, },#ifdef CONFIG_PROC_SYSCTL { .procname = "cad_pid", .maxlen = sizeof(int), .mode = 0600, .proc_handler = proc_do_cad_pid, },#endif};#endif
int register_pidns_sysctls(struct pid_namespace *pidns){#ifdef CONFIG_SYSCTL struct ctl_table *tbl;
setup_sysctl_set(&pidns->set, &pid_table_root, set_is_seen);
tbl = kmemdup(pid_table, sizeof(pid_table), GFP_KERNEL); if (!tbl) return -ENOMEM; tbl->data = &pidns->pid_max; pidns->pid_max = min(pid_max_max, max_t(int, pidns->pid_max, PIDS_PER_CPU_DEFAULT * num_possible_cpus()));
pidns->sysctls = __register_sysctl_table(&pidns->set, "kernel", tbl, ARRAY_SIZE(pid_table)); if (!pidns->sysctls) { kfree(tbl); retire_sysctl_set(&pidns->set); return -ENOMEM; }#endif return 0;}
void unregister_pidns_sysctls(struct pid_namespace *pidns){#ifdef CONFIG_SYSCTL const struct ctl_table *tbl;
tbl = pidns->sysctls->ctl_table_arg; unregister_sysctl_table(pidns->sysctls); retire_sysctl_set(&pidns->set); kfree(tbl);#endif}
void __init pid_idr_init(void){ /* Verify no one has done anything silly: */ BUILD_BUG_ON(PID_MAX_LIMIT >= PIDNS_ADDING);
/* bump default and minimum pid_max based on number of cpus */ init_pid_ns.pid_max = min(pid_max_max, max_t(int, init_pid_ns.pid_max, PIDS_PER_CPU_DEFAULT * num_possible_cpus())); 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", init_pid_ns.pid_max, pid_max_min);
idr_init(&init_pid_ns.idr);
init_pid_ns.pid_cachep = kmem_cache_create("pid", struct_size_t(struct pid, numbers, 1), __alignof__(struct pid), SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT, NULL);}
static __init int pid_namespace_sysctl_init(void){#ifdef CONFIG_SYSCTL /* "kernel" directory will have already been initialized. */ BUG_ON(register_pidns_sysctls(&init_pid_ns));#endif return 0;}subsys_initcall(pid_namespace_sysctl_init);
static struct file *__pidfd_fget(struct task_struct *task, int fd){ struct file *file; int ret;
ret = down_read_killable(&task->signal->exec_update_lock); if (ret) return ERR_PTR(ret);
if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS)) file = ERR_PTR(-EPERM); else if (task->flags & PF_EXITING) file = ERR_PTR(-ESRCH); else file = fget_task(task, fd);
up_read(&task->signal->exec_update_lock);
if (!file) { /* * It is possible that the target thread is exiting; it can be * either: * 1. before exit_signals(), which gives a real fd * 2. before exit_files() takes the task_lock() gives a real fd * 3. after exit_files() releases task_lock(), ->files is NULL; * this has PF_EXITING, since it was set in exit_signals(), * __pidfd_fget() returns EBADF. * In case 3 we get EBADF, but that really means ESRCH, since * the task is currently exiting and has freed its files * struct, so we fix it up. */ if (task->flags & PF_EXITING) file = ERR_PTR(-ESRCH); else file = ERR_PTR(-EBADF); }
return file;}
static int pidfd_getfd(struct pid *pid, int fd){ struct task_struct *task; struct file *file; int ret;
task = get_pid_task(pid, PIDTYPE_PID); if (!task) return -ESRCH;
file = __pidfd_fget(task, fd); put_task_struct(task); if (IS_ERR(file)) return PTR_ERR(file);
ret = receive_fd(file, NULL, O_CLOEXEC); fput(file);
return ret;}
/** * sys_pidfd_getfd() - Get a file descriptor from another process * * @pidfd: the pidfd file descriptor of the process * @fd: the file descriptor number to get * @flags: flags on how to get the fd (reserved) * * This syscall gets a copy of a file descriptor from another process * based on the pidfd, and file descriptor number. It requires that * the calling process has the ability to ptrace the process represented * by the pidfd. The process which is having its file descriptor copied * is otherwise unaffected. * * Return: On success, a cloexec file descriptor is returned. * On error, a negative errno number will be returned. */SYSCALL_DEFINE3(pidfd_getfd, int, pidfd, int, fd, unsigned int, flags){ struct pid *pid;
/* flags is currently unused - make sure it's unset */ if (flags) return -EINVAL;
CLASS(fd, f)(pidfd); if (fd_empty(f)) return -EBADF;
pid = pidfd_pid(fd_file(f)); if (IS_ERR(pid)) return PTR_ERR(pid);
return pidfd_getfd(pid, fd);}