// SPDX-License-Identifier: GPL-2.0-only /* * Process number limiting controller for cgroups. * * Used to allow a cgroup hierarchy to stop any new processes from fork()ing * after a certain limit is reached. * * Since it is trivial to hit the task limit without hitting any kmemcg limits * in place, PIDs are a fundamental resource. As such, PID exhaustion must be * preventable in the scope of a cgroup hierarchy by allowing resource limiting * of the number of tasks in a cgroup. * * In order to use the `pids` controller, set the maximum number of tasks in * pids.max (this is not available in the root cgroup for obvious reasons). The * number of processes currently in the cgroup is given by pids.current. * Organisational operations are not blocked by cgroup policies, so it is * possible to have pids.current > pids.max. However, it is not possible to * violate a cgroup policy through fork(). fork() will return -EAGAIN if forking * would cause a cgroup policy to be violated. * * To set a cgroup to have no limit, set pids.max to "max". This is the default * for all new cgroups (N.B. that PID limits are hierarchical, so the most * stringent limit in the hierarchy is followed). * * pids.current tracks all child cgroup hierarchies, so parent/pids.current is * a superset of parent/child/pids.current. * * Copyright (C) 2015 Aleksa Sarai <[email protected]> */ #include <linux/kernel.h> #include <linux/threads.h> #include <linux/atomic.h> #include <linux/cgroup.h> #include <linux/slab.h> #include <linux/sched/task.h> #define PIDS_MAX … #define PIDS_MAX_STR … enum pidcg_event { … }; struct pids_cgroup { … }; static struct pids_cgroup *css_pids(struct cgroup_subsys_state *css) { … } static struct pids_cgroup *parent_pids(struct pids_cgroup *pids) { … } static struct cgroup_subsys_state * pids_css_alloc(struct cgroup_subsys_state *parent) { … } static void pids_css_free(struct cgroup_subsys_state *css) { … } static void pids_update_watermark(struct pids_cgroup *p, int64_t nr_pids) { … } /** * pids_cancel - uncharge the local pid count * @pids: the pid cgroup state * @num: the number of pids to cancel * * This function will WARN if the pid count goes under 0, because such a case is * a bug in the pids controller proper. */ static void pids_cancel(struct pids_cgroup *pids, int num) { … } /** * pids_uncharge - hierarchically uncharge the pid count * @pids: the pid cgroup state * @num: the number of pids to uncharge */ static void pids_uncharge(struct pids_cgroup *pids, int num) { … } /** * pids_charge - hierarchically charge the pid count * @pids: the pid cgroup state * @num: the number of pids to charge * * This function does *not* follow the pid limit set. It cannot fail and the new * pid count may exceed the limit. This is only used for reverting failed * attaches, where there is no other way out than violating the limit. */ static void pids_charge(struct pids_cgroup *pids, int num) { … } /** * pids_try_charge - hierarchically try to charge the pid count * @pids: the pid cgroup state * @num: the number of pids to charge * @fail: storage of pid cgroup causing the fail * * This function follows the set limit. It will fail if the charge would cause * the new value to exceed the hierarchical limit. Returns 0 if the charge * succeeded, otherwise -EAGAIN. */ static int pids_try_charge(struct pids_cgroup *pids, int num, struct pids_cgroup **fail) { … } static int pids_can_attach(struct cgroup_taskset *tset) { … } static void pids_cancel_attach(struct cgroup_taskset *tset) { … } static void pids_event(struct pids_cgroup *pids_forking, struct pids_cgroup *pids_over_limit) { … } /* * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies * on cgroup_threadgroup_change_begin() held by the copy_process(). */ static int pids_can_fork(struct task_struct *task, struct css_set *cset) { … } static void pids_cancel_fork(struct task_struct *task, struct css_set *cset) { … } static void pids_release(struct task_struct *task) { … } static ssize_t pids_max_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { … } static int pids_max_show(struct seq_file *sf, void *v) { … } static s64 pids_current_read(struct cgroup_subsys_state *css, struct cftype *cft) { … } static s64 pids_peak_read(struct cgroup_subsys_state *css, struct cftype *cft) { … } static int __pids_events_show(struct seq_file *sf, bool local) { … } static int pids_events_show(struct seq_file *sf, void *v) { … } static int pids_events_local_show(struct seq_file *sf, void *v) { … } static struct cftype pids_files[] = …; static struct cftype pids_files_legacy[] = …; struct cgroup_subsys pids_cgrp_subsys = …;