0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <linux/kernel.h>
0032 #include <linux/threads.h>
0033 #include <linux/atomic.h>
0034 #include <linux/cgroup.h>
0035 #include <linux/slab.h>
0036 #include <linux/sched/task.h>
0037
0038 #define PIDS_MAX (PID_MAX_LIMIT + 1ULL)
0039 #define PIDS_MAX_STR "max"
0040
0041 struct pids_cgroup {
0042 struct cgroup_subsys_state css;
0043
0044
0045
0046
0047
0048 atomic64_t counter;
0049 atomic64_t limit;
0050
0051
0052 struct cgroup_file events_file;
0053
0054
0055 atomic64_t events_limit;
0056 };
0057
0058 static struct pids_cgroup *css_pids(struct cgroup_subsys_state *css)
0059 {
0060 return container_of(css, struct pids_cgroup, css);
0061 }
0062
0063 static struct pids_cgroup *parent_pids(struct pids_cgroup *pids)
0064 {
0065 return css_pids(pids->css.parent);
0066 }
0067
0068 static struct cgroup_subsys_state *
0069 pids_css_alloc(struct cgroup_subsys_state *parent)
0070 {
0071 struct pids_cgroup *pids;
0072
0073 pids = kzalloc(sizeof(struct pids_cgroup), GFP_KERNEL);
0074 if (!pids)
0075 return ERR_PTR(-ENOMEM);
0076
0077 atomic64_set(&pids->counter, 0);
0078 atomic64_set(&pids->limit, PIDS_MAX);
0079 atomic64_set(&pids->events_limit, 0);
0080 return &pids->css;
0081 }
0082
0083 static void pids_css_free(struct cgroup_subsys_state *css)
0084 {
0085 kfree(css_pids(css));
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static void pids_cancel(struct pids_cgroup *pids, int num)
0097 {
0098
0099
0100
0101
0102 WARN_ON_ONCE(atomic64_add_negative(-num, &pids->counter));
0103 }
0104
0105
0106
0107
0108
0109
0110 static void pids_uncharge(struct pids_cgroup *pids, int num)
0111 {
0112 struct pids_cgroup *p;
0113
0114 for (p = pids; parent_pids(p); p = parent_pids(p))
0115 pids_cancel(p, num);
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 static void pids_charge(struct pids_cgroup *pids, int num)
0128 {
0129 struct pids_cgroup *p;
0130
0131 for (p = pids; parent_pids(p); p = parent_pids(p))
0132 atomic64_add(num, &p->counter);
0133 }
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 static int pids_try_charge(struct pids_cgroup *pids, int num)
0145 {
0146 struct pids_cgroup *p, *q;
0147
0148 for (p = pids; parent_pids(p); p = parent_pids(p)) {
0149 int64_t new = atomic64_add_return(num, &p->counter);
0150 int64_t limit = atomic64_read(&p->limit);
0151
0152
0153
0154
0155
0156
0157 if (new > limit)
0158 goto revert;
0159 }
0160
0161 return 0;
0162
0163 revert:
0164 for (q = pids; q != p; q = parent_pids(q))
0165 pids_cancel(q, num);
0166 pids_cancel(p, num);
0167
0168 return -EAGAIN;
0169 }
0170
0171 static int pids_can_attach(struct cgroup_taskset *tset)
0172 {
0173 struct task_struct *task;
0174 struct cgroup_subsys_state *dst_css;
0175
0176 cgroup_taskset_for_each(task, dst_css, tset) {
0177 struct pids_cgroup *pids = css_pids(dst_css);
0178 struct cgroup_subsys_state *old_css;
0179 struct pids_cgroup *old_pids;
0180
0181
0182
0183
0184
0185
0186 old_css = task_css(task, pids_cgrp_id);
0187 old_pids = css_pids(old_css);
0188
0189 pids_charge(pids, 1);
0190 pids_uncharge(old_pids, 1);
0191 }
0192
0193 return 0;
0194 }
0195
0196 static void pids_cancel_attach(struct cgroup_taskset *tset)
0197 {
0198 struct task_struct *task;
0199 struct cgroup_subsys_state *dst_css;
0200
0201 cgroup_taskset_for_each(task, dst_css, tset) {
0202 struct pids_cgroup *pids = css_pids(dst_css);
0203 struct cgroup_subsys_state *old_css;
0204 struct pids_cgroup *old_pids;
0205
0206 old_css = task_css(task, pids_cgrp_id);
0207 old_pids = css_pids(old_css);
0208
0209 pids_charge(old_pids, 1);
0210 pids_uncharge(pids, 1);
0211 }
0212 }
0213
0214
0215
0216
0217
0218 static int pids_can_fork(struct task_struct *task, struct css_set *cset)
0219 {
0220 struct cgroup_subsys_state *css;
0221 struct pids_cgroup *pids;
0222 int err;
0223
0224 if (cset)
0225 css = cset->subsys[pids_cgrp_id];
0226 else
0227 css = task_css_check(current, pids_cgrp_id, true);
0228 pids = css_pids(css);
0229 err = pids_try_charge(pids, 1);
0230 if (err) {
0231
0232 if (atomic64_inc_return(&pids->events_limit) == 1) {
0233 pr_info("cgroup: fork rejected by pids controller in ");
0234 pr_cont_cgroup_path(css->cgroup);
0235 pr_cont("\n");
0236 }
0237 cgroup_file_notify(&pids->events_file);
0238 }
0239 return err;
0240 }
0241
0242 static void pids_cancel_fork(struct task_struct *task, struct css_set *cset)
0243 {
0244 struct cgroup_subsys_state *css;
0245 struct pids_cgroup *pids;
0246
0247 if (cset)
0248 css = cset->subsys[pids_cgrp_id];
0249 else
0250 css = task_css_check(current, pids_cgrp_id, true);
0251 pids = css_pids(css);
0252 pids_uncharge(pids, 1);
0253 }
0254
0255 static void pids_release(struct task_struct *task)
0256 {
0257 struct pids_cgroup *pids = css_pids(task_css(task, pids_cgrp_id));
0258
0259 pids_uncharge(pids, 1);
0260 }
0261
0262 static ssize_t pids_max_write(struct kernfs_open_file *of, char *buf,
0263 size_t nbytes, loff_t off)
0264 {
0265 struct cgroup_subsys_state *css = of_css(of);
0266 struct pids_cgroup *pids = css_pids(css);
0267 int64_t limit;
0268 int err;
0269
0270 buf = strstrip(buf);
0271 if (!strcmp(buf, PIDS_MAX_STR)) {
0272 limit = PIDS_MAX;
0273 goto set_limit;
0274 }
0275
0276 err = kstrtoll(buf, 0, &limit);
0277 if (err)
0278 return err;
0279
0280 if (limit < 0 || limit >= PIDS_MAX)
0281 return -EINVAL;
0282
0283 set_limit:
0284
0285
0286
0287
0288 atomic64_set(&pids->limit, limit);
0289 return nbytes;
0290 }
0291
0292 static int pids_max_show(struct seq_file *sf, void *v)
0293 {
0294 struct cgroup_subsys_state *css = seq_css(sf);
0295 struct pids_cgroup *pids = css_pids(css);
0296 int64_t limit = atomic64_read(&pids->limit);
0297
0298 if (limit >= PIDS_MAX)
0299 seq_printf(sf, "%s\n", PIDS_MAX_STR);
0300 else
0301 seq_printf(sf, "%lld\n", limit);
0302
0303 return 0;
0304 }
0305
0306 static s64 pids_current_read(struct cgroup_subsys_state *css,
0307 struct cftype *cft)
0308 {
0309 struct pids_cgroup *pids = css_pids(css);
0310
0311 return atomic64_read(&pids->counter);
0312 }
0313
0314 static int pids_events_show(struct seq_file *sf, void *v)
0315 {
0316 struct pids_cgroup *pids = css_pids(seq_css(sf));
0317
0318 seq_printf(sf, "max %lld\n", (s64)atomic64_read(&pids->events_limit));
0319 return 0;
0320 }
0321
0322 static struct cftype pids_files[] = {
0323 {
0324 .name = "max",
0325 .write = pids_max_write,
0326 .seq_show = pids_max_show,
0327 .flags = CFTYPE_NOT_ON_ROOT,
0328 },
0329 {
0330 .name = "current",
0331 .read_s64 = pids_current_read,
0332 .flags = CFTYPE_NOT_ON_ROOT,
0333 },
0334 {
0335 .name = "events",
0336 .seq_show = pids_events_show,
0337 .file_offset = offsetof(struct pids_cgroup, events_file),
0338 .flags = CFTYPE_NOT_ON_ROOT,
0339 },
0340 { }
0341 };
0342
0343 struct cgroup_subsys pids_cgrp_subsys = {
0344 .css_alloc = pids_css_alloc,
0345 .css_free = pids_css_free,
0346 .can_attach = pids_can_attach,
0347 .cancel_attach = pids_cancel_attach,
0348 .can_fork = pids_can_fork,
0349 .cancel_fork = pids_cancel_fork,
0350 .release = pids_release,
0351 .legacy_cftypes = pids_files,
0352 .dfl_cftypes = pids_files,
0353 .threaded = true,
0354 };