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 : 3 : 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 : 3 : cgrp_css_alloc(struct cgroup_subsys_state *parent_css) 30 : : { 31 : : struct cgroup_cls_state *cs; 32 : : 33 : 3 : cs = kzalloc(sizeof(*cs), GFP_KERNEL); 34 : 3 : if (!cs) 35 : : return ERR_PTR(-ENOMEM); 36 : : 37 : 3 : return &cs->css; 38 : : } 39 : : 40 : 3 : static int cgrp_css_online(struct cgroup_subsys_state *css) 41 : : { 42 : : struct cgroup_cls_state *cs = css_cls_state(css); 43 : 3 : struct cgroup_cls_state *parent = css_cls_state(css->parent); 44 : : 45 : 3 : if (parent) 46 : 0 : cs->classid = parent->classid; 47 : : 48 : 3 : 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 : : };