Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * net/core/netclassid_cgroup.c Classid Cgroupfs Handling
0004  *
0005  * Authors: Thomas Graf <tgraf@suug.ch>
0006  */
0007 
0008 #include <linux/slab.h>
0009 #include <linux/cgroup.h>
0010 #include <linux/fdtable.h>
0011 #include <linux/sched/task.h>
0012 
0013 #include <net/cls_cgroup.h>
0014 #include <net/sock.h>
0015 
0016 static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
0017 {
0018     return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
0019 }
0020 
0021 struct cgroup_cls_state *task_cls_state(struct task_struct *p)
0022 {
0023     return css_cls_state(task_css_check(p, net_cls_cgrp_id,
0024                         rcu_read_lock_bh_held()));
0025 }
0026 EXPORT_SYMBOL_GPL(task_cls_state);
0027 
0028 static struct cgroup_subsys_state *
0029 cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
0030 {
0031     struct cgroup_cls_state *cs;
0032 
0033     cs = kzalloc(sizeof(*cs), GFP_KERNEL);
0034     if (!cs)
0035         return ERR_PTR(-ENOMEM);
0036 
0037     return &cs->css;
0038 }
0039 
0040 static int cgrp_css_online(struct cgroup_subsys_state *css)
0041 {
0042     struct cgroup_cls_state *cs = css_cls_state(css);
0043     struct cgroup_cls_state *parent = css_cls_state(css->parent);
0044 
0045     if (parent)
0046         cs->classid = parent->classid;
0047 
0048     return 0;
0049 }
0050 
0051 static void cgrp_css_free(struct cgroup_subsys_state *css)
0052 {
0053     kfree(css_cls_state(css));
0054 }
0055 
0056 /*
0057  * To avoid freezing of sockets creation for tasks with big number of threads
0058  * and opened sockets lets release file_lock every 1000 iterated descriptors.
0059  * New sockets will already have been created with new classid.
0060  */
0061 
0062 struct update_classid_context {
0063     u32 classid;
0064     unsigned int batch;
0065 };
0066 
0067 #define UPDATE_CLASSID_BATCH 1000
0068 
0069 static int update_classid_sock(const void *v, struct file *file, unsigned n)
0070 {
0071     struct update_classid_context *ctx = (void *)v;
0072     struct socket *sock = sock_from_file(file);
0073 
0074     if (sock)
0075         sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid);
0076     if (--ctx->batch == 0) {
0077         ctx->batch = UPDATE_CLASSID_BATCH;
0078         return n + 1;
0079     }
0080     return 0;
0081 }
0082 
0083 static void update_classid_task(struct task_struct *p, u32 classid)
0084 {
0085     struct update_classid_context ctx = {
0086         .classid = classid,
0087         .batch = UPDATE_CLASSID_BATCH
0088     };
0089     unsigned int fd = 0;
0090 
0091     do {
0092         task_lock(p);
0093         fd = iterate_fd(p->files, fd, update_classid_sock, &ctx);
0094         task_unlock(p);
0095         cond_resched();
0096     } while (fd);
0097 }
0098 
0099 static void cgrp_attach(struct cgroup_taskset *tset)
0100 {
0101     struct cgroup_subsys_state *css;
0102     struct task_struct *p;
0103 
0104     cgroup_taskset_for_each(p, css, tset) {
0105         update_classid_task(p, css_cls_state(css)->classid);
0106     }
0107 }
0108 
0109 static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
0110 {
0111     return css_cls_state(css)->classid;
0112 }
0113 
0114 static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
0115              u64 value)
0116 {
0117     struct cgroup_cls_state *cs = css_cls_state(css);
0118     struct css_task_iter it;
0119     struct task_struct *p;
0120 
0121     cs->classid = (u32)value;
0122 
0123     css_task_iter_start(css, 0, &it);
0124     while ((p = css_task_iter_next(&it)))
0125         update_classid_task(p, cs->classid);
0126     css_task_iter_end(&it);
0127 
0128     return 0;
0129 }
0130 
0131 static struct cftype ss_files[] = {
0132     {
0133         .name       = "classid",
0134         .read_u64   = read_classid,
0135         .write_u64  = write_classid,
0136     },
0137     { } /* terminate */
0138 };
0139 
0140 struct cgroup_subsys net_cls_cgrp_subsys = {
0141     .css_alloc      = cgrp_css_alloc,
0142     .css_online     = cgrp_css_online,
0143     .css_free       = cgrp_css_free,
0144     .attach         = cgrp_attach,
0145     .legacy_cftypes     = ss_files,
0146 };