Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Process number limiting controller for cgroups.
4 : : *
5 : : * Used to allow a cgroup hierarchy to stop any new processes from fork()ing
6 : : * after a certain limit is reached.
7 : : *
8 : : * Since it is trivial to hit the task limit without hitting any kmemcg limits
9 : : * in place, PIDs are a fundamental resource. As such, PID exhaustion must be
10 : : * preventable in the scope of a cgroup hierarchy by allowing resource limiting
11 : : * of the number of tasks in a cgroup.
12 : : *
13 : : * In order to use the `pids` controller, set the maximum number of tasks in
14 : : * pids.max (this is not available in the root cgroup for obvious reasons). The
15 : : * number of processes currently in the cgroup is given by pids.current.
16 : : * Organisational operations are not blocked by cgroup policies, so it is
17 : : * possible to have pids.current > pids.max. However, it is not possible to
18 : : * violate a cgroup policy through fork(). fork() will return -EAGAIN if forking
19 : : * would cause a cgroup policy to be violated.
20 : : *
21 : : * To set a cgroup to have no limit, set pids.max to "max". This is the default
22 : : * for all new cgroups (N.B. that PID limits are hierarchical, so the most
23 : : * stringent limit in the hierarchy is followed).
24 : : *
25 : : * pids.current tracks all child cgroup hierarchies, so parent/pids.current is
26 : : * a superset of parent/child/pids.current.
27 : : *
28 : : * Copyright (C) 2015 Aleksa Sarai <cyphar@cyphar.com>
29 : : */
30 : :
31 : : #include <linux/kernel.h>
32 : : #include <linux/threads.h>
33 : : #include <linux/atomic.h>
34 : : #include <linux/cgroup.h>
35 : : #include <linux/slab.h>
36 : :
37 : : #define PIDS_MAX (PID_MAX_LIMIT + 1ULL)
38 : : #define PIDS_MAX_STR "max"
39 : :
40 : : struct pids_cgroup {
41 : : struct cgroup_subsys_state css;
42 : :
43 : : /*
44 : : * Use 64-bit types so that we can safely represent "max" as
45 : : * %PIDS_MAX = (%PID_MAX_LIMIT + 1).
46 : : */
47 : : atomic64_t counter;
48 : : atomic64_t limit;
49 : :
50 : : /* Handle for "pids.events" */
51 : : struct cgroup_file events_file;
52 : :
53 : : /* Number of times fork failed because limit was hit. */
54 : : atomic64_t events_limit;
55 : : };
56 : :
57 : : static struct pids_cgroup *css_pids(struct cgroup_subsys_state *css)
58 : : {
59 : : return container_of(css, struct pids_cgroup, css);
60 : : }
61 : :
62 : : static struct pids_cgroup *parent_pids(struct pids_cgroup *pids)
63 : : {
64 : 1724752 : return css_pids(pids->css.parent);
65 : : }
66 : :
67 : : static struct cgroup_subsys_state *
68 : 25460 : pids_css_alloc(struct cgroup_subsys_state *parent)
69 : : {
70 : : struct pids_cgroup *pids;
71 : :
72 : 25460 : pids = kzalloc(sizeof(struct pids_cgroup), GFP_KERNEL);
73 [ + - ]: 25460 : if (!pids)
74 : : return ERR_PTR(-ENOMEM);
75 : :
76 : 25460 : atomic64_set(&pids->counter, 0);
77 : 25460 : atomic64_set(&pids->limit, PIDS_MAX);
78 : 25460 : atomic64_set(&pids->events_limit, 0);
79 : 25460 : return &pids->css;
80 : : }
81 : :
82 : 12124 : static void pids_css_free(struct cgroup_subsys_state *css)
83 : : {
84 : 12124 : kfree(css_pids(css));
85 : 12124 : }
86 : :
87 : : /**
88 : : * pids_cancel - uncharge the local pid count
89 : : * @pids: the pid cgroup state
90 : : * @num: the number of pids to cancel
91 : : *
92 : : * This function will WARN if the pid count goes under 0, because such a case is
93 : : * a bug in the pids controller proper.
94 : : */
95 : 809850 : static void pids_cancel(struct pids_cgroup *pids, int num)
96 : : {
97 : : /*
98 : : * A negative count (or overflow for that matter) is invalid,
99 : : * and indicates a bug in the `pids` controller proper.
100 : : */
101 [ - + # # ]: 809850 : WARN_ON_ONCE(atomic64_add_negative(-num, &pids->counter));
102 : 809850 : }
103 : :
104 : : /**
105 : : * pids_uncharge - hierarchically uncharge the pid count
106 : : * @pids: the pid cgroup state
107 : : * @num: the number of pids to uncharge
108 : : */
109 : : static void pids_uncharge(struct pids_cgroup *pids, int num)
110 : : {
111 : : struct pids_cgroup *p;
112 : :
113 [ + + # # : 1226560 : for (p = pids; parent_pids(p); p = parent_pids(p))
# # + + ]
114 : 809850 : pids_cancel(p, num);
115 : : }
116 : :
117 : : /**
118 : : * pids_charge - hierarchically charge the pid count
119 : : * @pids: the pid cgroup state
120 : : * @num: the number of pids to charge
121 : : *
122 : : * This function does *not* follow the pid limit set. It cannot fail and the new
123 : : * pid count may exceed the limit. This is only used for reverting failed
124 : : * attaches, where there is no other way out than violating the limit.
125 : : */
126 : 25060 : static void pids_charge(struct pids_cgroup *pids, int num)
127 : : {
128 : : struct pids_cgroup *p;
129 : :
130 [ + + ]: 103880 : for (p = pids; parent_pids(p); p = parent_pids(p))
131 : 53760 : atomic64_add(num, &p->counter);
132 : 25060 : }
133 : :
134 : : /**
135 : : * pids_try_charge - hierarchically try to charge the pid count
136 : : * @pids: the pid cgroup state
137 : : * @num: the number of pids to charge
138 : : *
139 : : * This function follows the set limit. It will fail if the charge would cause
140 : : * the new value to exceed the hierarchical limit. Returns 0 if the charge
141 : : * succeeded, otherwise -EAGAIN.
142 : : */
143 : 464268 : static int pids_try_charge(struct pids_cgroup *pids, int num)
144 : : {
145 : : struct pids_cgroup *p, *q;
146 : :
147 [ + + ]: 1789680 : for (p = pids; parent_pids(p); p = parent_pids(p)) {
148 : 861166 : int64_t new = atomic64_add_return(num, &p->counter);
149 : 861162 : int64_t limit = atomic64_read(&p->limit);
150 : :
151 : : /*
152 : : * Since new is capped to the maximum number of pid_t, if
153 : : * p->limit is %PIDS_MAX then we know that this test will never
154 : : * fail.
155 : : */
156 [ - + ]: 861144 : if (new > limit)
157 : : goto revert;
158 : : }
159 : :
160 : : return 0;
161 : :
162 : : revert:
163 [ # # ]: 0 : for (q = pids; q != p; q = parent_pids(q))
164 : 0 : pids_cancel(q, num);
165 : 0 : pids_cancel(p, num);
166 : :
167 : 0 : return -EAGAIN;
168 : : }
169 : :
170 : 24252 : static int pids_can_attach(struct cgroup_taskset *tset)
171 : : {
172 : : struct task_struct *task;
173 : : struct cgroup_subsys_state *dst_css;
174 : :
175 [ + + ]: 49312 : cgroup_taskset_for_each(task, dst_css, tset) {
176 : 25060 : struct pids_cgroup *pids = css_pids(dst_css);
177 : : struct cgroup_subsys_state *old_css;
178 : : struct pids_cgroup *old_pids;
179 : :
180 : : /*
181 : : * No need to pin @old_css between here and cancel_attach()
182 : : * because cgroup core protects it from being freed before
183 : : * the migration completes or fails.
184 : : */
185 : : old_css = task_css(task, pids_cgrp_id);
186 : : old_pids = css_pids(old_css);
187 : :
188 : 25060 : pids_charge(pids, 1);
189 : : pids_uncharge(old_pids, 1);
190 : : }
191 : :
192 : 24252 : return 0;
193 : : }
194 : :
195 : 0 : static void pids_cancel_attach(struct cgroup_taskset *tset)
196 : : {
197 : : struct task_struct *task;
198 : : struct cgroup_subsys_state *dst_css;
199 : :
200 [ # # ]: 0 : cgroup_taskset_for_each(task, dst_css, tset) {
201 : 0 : struct pids_cgroup *pids = css_pids(dst_css);
202 : : struct cgroup_subsys_state *old_css;
203 : : struct pids_cgroup *old_pids;
204 : :
205 : : old_css = task_css(task, pids_cgrp_id);
206 : : old_pids = css_pids(old_css);
207 : :
208 : 0 : pids_charge(old_pids, 1);
209 : : pids_uncharge(pids, 1);
210 : : }
211 : 0 : }
212 : :
213 : : /*
214 : : * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies
215 : : * on cgroup_threadgroup_change_begin() held by the copy_process().
216 : : */
217 : 464266 : static int pids_can_fork(struct task_struct *task)
218 : : {
219 : : struct cgroup_subsys_state *css;
220 : : struct pids_cgroup *pids;
221 : : int err;
222 : :
223 : 928532 : css = task_css_check(current, pids_cgrp_id, true);
224 : : pids = css_pids(css);
225 : 464266 : err = pids_try_charge(pids, 1);
226 [ - + ]: 464272 : if (err) {
227 : : /* Only log the first time events_limit is incremented. */
228 [ # # ]: 0 : if (atomic64_inc_return(&pids->events_limit) == 1) {
229 : 0 : pr_info("cgroup: fork rejected by pids controller in ");
230 : 0 : pr_cont_cgroup_path(css->cgroup);
231 : 0 : pr_cont("\n");
232 : : }
233 : 0 : cgroup_file_notify(&pids->events_file);
234 : : }
235 : 464272 : return err;
236 : : }
237 : :
238 : 0 : static void pids_cancel_fork(struct task_struct *task)
239 : : {
240 : : struct cgroup_subsys_state *css;
241 : : struct pids_cgroup *pids;
242 : :
243 : 0 : css = task_css_check(current, pids_cgrp_id, true);
244 : : pids = css_pids(css);
245 : : pids_uncharge(pids, 1);
246 : 0 : }
247 : :
248 : 391652 : static void pids_release(struct task_struct *task)
249 : : {
250 : : struct pids_cgroup *pids = css_pids(task_css(task, pids_cgrp_id));
251 : :
252 : : pids_uncharge(pids, 1);
253 : 391650 : }
254 : :
255 : 25460 : static ssize_t pids_max_write(struct kernfs_open_file *of, char *buf,
256 : : size_t nbytes, loff_t off)
257 : : {
258 : 25460 : struct cgroup_subsys_state *css = of_css(of);
259 : : struct pids_cgroup *pids = css_pids(css);
260 : : int64_t limit;
261 : : int err;
262 : :
263 : : buf = strstrip(buf);
264 [ + + ]: 25460 : if (!strcmp(buf, PIDS_MAX_STR)) {
265 : 4044 : limit = PIDS_MAX;
266 : 4044 : goto set_limit;
267 : : }
268 : :
269 : 21416 : err = kstrtoll(buf, 0, &limit);
270 [ + - ]: 21416 : if (err)
271 : : return err;
272 : :
273 [ + - ]: 21416 : if (limit < 0 || limit >= PIDS_MAX)
274 : : return -EINVAL;
275 : :
276 : : set_limit:
277 : : /*
278 : : * Limit updates don't need to be mutex'd, since it isn't
279 : : * critical that any racing fork()s follow the new limit.
280 : : */
281 : 25460 : atomic64_set(&pids->limit, limit);
282 : 25460 : return nbytes;
283 : : }
284 : :
285 : 0 : static int pids_max_show(struct seq_file *sf, void *v)
286 : : {
287 : : struct cgroup_subsys_state *css = seq_css(sf);
288 : : struct pids_cgroup *pids = css_pids(css);
289 : 0 : int64_t limit = atomic64_read(&pids->limit);
290 : :
291 [ # # ]: 0 : if (limit >= PIDS_MAX)
292 : 0 : seq_printf(sf, "%s\n", PIDS_MAX_STR);
293 : : else
294 : 0 : seq_printf(sf, "%lld\n", limit);
295 : :
296 : 0 : return 0;
297 : : }
298 : :
299 : 404 : static s64 pids_current_read(struct cgroup_subsys_state *css,
300 : : struct cftype *cft)
301 : : {
302 : : struct pids_cgroup *pids = css_pids(css);
303 : :
304 : 808 : return atomic64_read(&pids->counter);
305 : : }
306 : :
307 : 0 : static int pids_events_show(struct seq_file *sf, void *v)
308 : : {
309 : : struct pids_cgroup *pids = css_pids(seq_css(sf));
310 : :
311 : 0 : seq_printf(sf, "max %lld\n", (s64)atomic64_read(&pids->events_limit));
312 : 0 : return 0;
313 : : }
314 : :
315 : : static struct cftype pids_files[] = {
316 : : {
317 : : .name = "max",
318 : : .write = pids_max_write,
319 : : .seq_show = pids_max_show,
320 : : .flags = CFTYPE_NOT_ON_ROOT,
321 : : },
322 : : {
323 : : .name = "current",
324 : : .read_s64 = pids_current_read,
325 : : .flags = CFTYPE_NOT_ON_ROOT,
326 : : },
327 : : {
328 : : .name = "events",
329 : : .seq_show = pids_events_show,
330 : : .file_offset = offsetof(struct pids_cgroup, events_file),
331 : : .flags = CFTYPE_NOT_ON_ROOT,
332 : : },
333 : : { } /* terminate */
334 : : };
335 : :
336 : : struct cgroup_subsys pids_cgrp_subsys = {
337 : : .css_alloc = pids_css_alloc,
338 : : .css_free = pids_css_free,
339 : : .can_attach = pids_can_attach,
340 : : .cancel_attach = pids_cancel_attach,
341 : : .can_fork = pids_can_fork,
342 : : .cancel_fork = pids_cancel_fork,
343 : : .release = pids_release,
344 : : .legacy_cftypes = pids_files,
345 : : .dfl_cftypes = pids_files,
346 : : .threaded = true,
347 : : };
|