Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * net/core/netclassid_cgroup.c Classid Cgroupfs Handling
4 : : *
5 : : * Authors: Thomas Graf <tgraf@suug.ch>
6 : : */
7 : :
8 : : #include <linux/slab.h>
9 : : #include <linux/cgroup.h>
10 : : #include <linux/fdtable.h>
11 : : #include <linux/sched/task.h>
12 : :
13 : : #include <net/cls_cgroup.h>
14 : : #include <net/sock.h>
15 : :
16 : : static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
17 : : {
18 [ # # # # : 414 : return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
# # # # +
- - + #
# ]
19 : : }
20 : :
21 : 0 : struct cgroup_cls_state *task_cls_state(struct task_struct *p)
22 : : {
23 : 0 : return css_cls_state(task_css_check(p, net_cls_cgrp_id,
24 : : rcu_read_lock_bh_held()));
25 : : }
26 : : EXPORT_SYMBOL_GPL(task_cls_state);
27 : :
28 : : static struct cgroup_subsys_state *
29 : 207 : cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
30 : : {
31 : : struct cgroup_cls_state *cs;
32 : :
33 : 207 : cs = kzalloc(sizeof(*cs), GFP_KERNEL);
34 [ + - ]: 207 : if (!cs)
35 : : return ERR_PTR(-ENOMEM);
36 : :
37 : 207 : return &cs->css;
38 : : }
39 : :
40 : 207 : static int cgrp_css_online(struct cgroup_subsys_state *css)
41 : : {
42 : : struct cgroup_cls_state *cs = css_cls_state(css);
43 : 207 : struct cgroup_cls_state *parent = css_cls_state(css->parent);
44 : :
45 [ - + ]: 207 : if (parent)
46 : 0 : cs->classid = parent->classid;
47 : :
48 : 207 : return 0;
49 : : }
50 : :
51 : 0 : static void cgrp_css_free(struct cgroup_subsys_state *css)
52 : : {
53 : 0 : kfree(css_cls_state(css));
54 : 0 : }
55 : :
56 : : /*
57 : : * To avoid freezing of sockets creation for tasks with big number of threads
58 : : * and opened sockets lets release file_lock every 1000 iterated descriptors.
59 : : * New sockets will already have been created with new classid.
60 : : */
61 : :
62 : : struct update_classid_context {
63 : : u32 classid;
64 : : unsigned int batch;
65 : : };
66 : :
67 : : #define UPDATE_CLASSID_BATCH 1000
68 : :
69 : 0 : static int update_classid_sock(const void *v, struct file *file, unsigned n)
70 : : {
71 : : int err;
72 : : struct update_classid_context *ctx = (void *)v;
73 : 0 : struct socket *sock = sock_from_file(file, &err);
74 : :
75 [ # # ]: 0 : if (sock) {
76 : : spin_lock(&cgroup_sk_update_lock);
77 : 0 : sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid);
78 : : spin_unlock(&cgroup_sk_update_lock);
79 : : }
80 [ # # ]: 0 : if (--ctx->batch == 0) {
81 : 0 : ctx->batch = UPDATE_CLASSID_BATCH;
82 : 0 : return n + 1;
83 : : }
84 : : return 0;
85 : : }
86 : :
87 : 0 : static void update_classid_task(struct task_struct *p, u32 classid)
88 : : {
89 : 0 : struct update_classid_context ctx = {
90 : : .classid = classid,
91 : : .batch = UPDATE_CLASSID_BATCH
92 : : };
93 : : unsigned int fd = 0;
94 : :
95 : : do {
96 : : task_lock(p);
97 : 0 : fd = iterate_fd(p->files, fd, update_classid_sock, &ctx);
98 : : task_unlock(p);
99 : 0 : cond_resched();
100 [ # # ]: 0 : } while (fd);
101 : 0 : }
102 : :
103 : 0 : static void cgrp_attach(struct cgroup_taskset *tset)
104 : : {
105 : : struct cgroup_subsys_state *css;
106 : : struct task_struct *p;
107 : :
108 [ # # ]: 0 : cgroup_taskset_for_each(p, css, tset) {
109 : 0 : update_classid_task(p, css_cls_state(css)->classid);
110 : : }
111 : 0 : }
112 : :
113 : 0 : static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
114 : : {
115 : 0 : return css_cls_state(css)->classid;
116 : : }
117 : :
118 : 0 : static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
119 : : u64 value)
120 : : {
121 : : struct cgroup_cls_state *cs = css_cls_state(css);
122 : : struct css_task_iter it;
123 : : struct task_struct *p;
124 : :
125 : 0 : cgroup_sk_alloc_disable();
126 : :
127 : 0 : cs->classid = (u32)value;
128 : :
129 : 0 : css_task_iter_start(css, 0, &it);
130 [ # # ]: 0 : while ((p = css_task_iter_next(&it)))
131 : 0 : update_classid_task(p, cs->classid);
132 : 0 : css_task_iter_end(&it);
133 : :
134 : 0 : return 0;
135 : : }
136 : :
137 : : static struct cftype ss_files[] = {
138 : : {
139 : : .name = "classid",
140 : : .read_u64 = read_classid,
141 : : .write_u64 = write_classid,
142 : : },
143 : : { } /* terminate */
144 : : };
145 : :
146 : : struct cgroup_subsys net_cls_cgrp_subsys = {
147 : : .css_alloc = cgrp_css_alloc,
148 : : .css_online = cgrp_css_online,
149 : : .css_free = cgrp_css_free,
150 : : .attach = cgrp_attach,
151 : : .legacy_cftypes = ss_files,
152 : : };
|