File Index
Files and directories
Sign in
FILE

netclassid_cgroup.c

File preview with syntax highlighting.

linux-6.19.14/net/core/netclassid_cgroup.c C
  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
 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{
 23	return css_cls_state(task_css_check(p, net_cls_cgrp_id,
 24					    rcu_read_lock_held() ||
 25					    rcu_read_lock_bh_held() ||
 26					    rcu_read_lock_trace_held()));
 27}
 28EXPORT_SYMBOL_GPL(task_cls_state);
 29
 30static struct cgroup_subsys_state *
 31cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
 32{
 33	struct cgroup_cls_state *cs;
 34
 35	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
 36	if (!cs)
 37		return ERR_PTR(-ENOMEM);
 38
 39	return &cs->css;
 40}
 41
 42static int cgrp_css_online(struct cgroup_subsys_state *css)
 43{
 44	struct cgroup_cls_state *cs = css_cls_state(css);
 45	struct cgroup_cls_state *parent = css_cls_state(css->parent);
 46
 47	if (parent)
 48		cs->classid = parent->classid;
 49
 50	return 0;
 51}
 52
 53static void cgrp_css_free(struct cgroup_subsys_state *css)
 54{
 55	kfree(css_cls_state(css));
 56}
 57
 58/*
 59 * To avoid freezing of sockets creation for tasks with big number of threads
 60 * and opened sockets lets release file_lock every 1000 iterated descriptors.
 61 * New sockets will already have been created with new classid.
 62 */
 63
 64struct update_classid_context {
 65	u32 classid;
 66	unsigned int batch;
 67};
 68
 69#define UPDATE_CLASSID_BATCH 1000
 70
 71static int update_classid_sock(const void *v, struct file *file, unsigned int n)
 72{
 73	struct update_classid_context *ctx = (void *)v;
 74	struct socket *sock = sock_from_file(file);
 75
 76	if (sock)
 77		sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid);
 78	if (--ctx->batch == 0) {
 79		ctx->batch = UPDATE_CLASSID_BATCH;
 80		return n + 1;
 81	}
 82	return 0;
 83}
 84
 85static void update_classid_task(struct task_struct *p, u32 classid)
 86{
 87	struct update_classid_context ctx = {
 88		.classid = classid,
 89		.batch = UPDATE_CLASSID_BATCH
 90	};
 91	unsigned int fd = 0;
 92
 93	/* Only update the leader task, when many threads in this task,
 94	 * so it can avoid the useless traversal.
 95	 */
 96	if (p != p->group_leader)
 97		return;
 98
 99	do {
100		task_lock(p);
101		fd = iterate_fd(p->files, fd, update_classid_sock, &ctx);
102		task_unlock(p);
103		cond_resched();
104	} while (fd);
105}
106
107static void cgrp_attach(struct cgroup_taskset *tset)
108{
109	struct cgroup_subsys_state *css;
110	struct task_struct *p;
111
112	cgroup_taskset_for_each(p, css, tset) {
113		update_classid_task(p, css_cls_state(css)->classid);
114	}
115}
116
117static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
118{
119	return css_cls_state(css)->classid;
120}
121
122static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
123			 u64 value)
124{
125	struct cgroup_cls_state *cs = css_cls_state(css);
126	struct css_task_iter it;
127	struct task_struct *p;
128
129	cs->classid = (u32)value;
130
131	css_task_iter_start(css, 0, &it);
132	while ((p = css_task_iter_next(&it)))
133		update_classid_task(p, cs->classid);
134	css_task_iter_end(&it);
135
136	return 0;
137}
138
139static struct cftype ss_files[] = {
140	{
141		.name		= "classid",
142		.read_u64	= read_classid,
143		.write_u64	= write_classid,
144	},
145	{ }	/* terminate */
146};
147
148struct cgroup_subsys net_cls_cgrp_subsys = {
149	.css_alloc		= cgrp_css_alloc,
150	.css_online		= cgrp_css_online,
151	.css_free		= cgrp_css_free,
152	.attach			= cgrp_attach,
153	.legacy_cftypes		= ss_files,
154};
~/ Read-only file preview.