blob: 0642f91c4038d5b97b3820c3a16669583177fc0b [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Daniel Borkmannfe1217c2013-12-29 18:27:10 +01002/*
3 * net/core/netclassid_cgroup.c Classid Cgroupfs Handling
4 *
Daniel Borkmannfe1217c2013-12-29 18:27:10 +01005 * Authors: Thomas Graf <tgraf@suug.ch>
6 */
7
Daniel Borkmannfe1217c2013-12-29 18:27:10 +01008#include <linux/slab.h>
9#include <linux/cgroup.h>
10#include <linux/fdtable.h>
Ingo Molnarf719ff9b2017-02-06 10:57:33 +010011#include <linux/sched/task.h>
12
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010013#include <net/cls_cgroup.h>
14#include <net/sock.h>
15
16static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
17{
18 return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
19}
20
21struct cgroup_cls_state *task_cls_state(struct task_struct *p)
22{
Konstantin Khlebnikovcc9f4da2015-07-22 12:23:20 +030023 return css_cls_state(task_css_check(p, net_cls_cgrp_id,
24 rcu_read_lock_bh_held()));
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010025}
26EXPORT_SYMBOL_GPL(task_cls_state);
27
28static struct cgroup_subsys_state *
29cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
30{
31 struct cgroup_cls_state *cs;
32
33 cs = kzalloc(sizeof(*cs), GFP_KERNEL);
34 if (!cs)
35 return ERR_PTR(-ENOMEM);
36
37 return &cs->css;
38}
39
40static int cgrp_css_online(struct cgroup_subsys_state *css)
41{
42 struct cgroup_cls_state *cs = css_cls_state(css);
Tejun Heo5c9d5352014-05-16 13:22:48 -040043 struct cgroup_cls_state *parent = css_cls_state(css->parent);
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010044
45 if (parent)
46 cs->classid = parent->classid;
47
48 return 0;
49}
50
51static void cgrp_css_free(struct cgroup_subsys_state *css)
52{
53 kfree(css_cls_state(css));
54}
55
Nina Schiff3b137582015-11-20 12:31:39 -080056static int update_classid_sock(const void *v, struct file *file, unsigned n)
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010057{
58 int err;
59 struct socket *sock = sock_from_file(file, &err);
60
Tejun Heobd1060a2015-12-07 17:38:53 -050061 if (sock) {
62 spin_lock(&cgroup_sk_update_lock);
Tejun Heo2a56a1f2015-12-07 17:38:52 -050063 sock_cgroup_set_classid(&sock->sk->sk_cgrp_data,
64 (unsigned long)v);
Tejun Heobd1060a2015-12-07 17:38:53 -050065 spin_unlock(&cgroup_sk_update_lock);
66 }
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010067 return 0;
68}
69
Tejun Heo0b98f0c2015-12-07 10:09:03 -050070static void cgrp_attach(struct cgroup_taskset *tset)
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010071{
Tejun Heo0b98f0c2015-12-07 10:09:03 -050072 struct cgroup_subsys_state *css;
Tejun Heoa05d4fd2017-03-14 19:25:56 -040073 struct task_struct *p;
Tejun Heo0b98f0c2015-12-07 10:09:03 -050074
Tejun Heoa05d4fd2017-03-14 19:25:56 -040075 cgroup_taskset_for_each(p, css, tset) {
76 task_lock(p);
77 iterate_fd(p->files, 0, update_classid_sock,
78 (void *)(unsigned long)css_cls_state(css)->classid);
79 task_unlock(p);
80 }
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010081}
82
83static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
84{
85 return css_cls_state(css)->classid;
86}
87
88static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
89 u64 value)
90{
Nina Schiff3b137582015-11-20 12:31:39 -080091 struct cgroup_cls_state *cs = css_cls_state(css);
Tejun Heoa05d4fd2017-03-14 19:25:56 -040092 struct css_task_iter it;
93 struct task_struct *p;
Daniel Borkmannfe1217c2013-12-29 18:27:10 +010094
Tejun Heobd1060a2015-12-07 17:38:53 -050095 cgroup_sk_alloc_disable();
96
Nina Schiff3b137582015-11-20 12:31:39 -080097 cs->classid = (u32)value;
98
Tejun Heobc2fb7e2017-05-15 09:34:01 -040099 css_task_iter_start(css, 0, &it);
Tejun Heoa05d4fd2017-03-14 19:25:56 -0400100 while ((p = css_task_iter_next(&it))) {
101 task_lock(p);
102 iterate_fd(p->files, 0, update_classid_sock,
103 (void *)(unsigned long)cs->classid);
104 task_unlock(p);
Michal Hockoa90e90b2018-10-18 10:56:17 +0200105 cond_resched();
Tejun Heoa05d4fd2017-03-14 19:25:56 -0400106 }
107 css_task_iter_end(&it);
108
Daniel Borkmannfe1217c2013-12-29 18:27:10 +0100109 return 0;
110}
111
112static struct cftype ss_files[] = {
113 {
114 .name = "classid",
115 .read_u64 = read_classid,
116 .write_u64 = write_classid,
117 },
118 { } /* terminate */
119};
120
Tejun Heo073219e2014-02-08 10:36:58 -0500121struct cgroup_subsys net_cls_cgrp_subsys = {
Daniel Borkmannfe1217c2013-12-29 18:27:10 +0100122 .css_alloc = cgrp_css_alloc,
123 .css_online = cgrp_css_online,
124 .css_free = cgrp_css_free,
125 .attach = cgrp_attach,
Tejun Heo55779642014-07-15 11:05:09 -0400126 .legacy_cftypes = ss_files,
Daniel Borkmannfe1217c2013-12-29 18:27:10 +0100127};