0001
0002
0003
0004
0005
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
0058
0059
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 { }
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 };