121 lines
		
	
	
	
		
			2.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
	
		
			2.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * net/core/netclassid_cgroup.c	Classid Cgroupfs Handling
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *		This program is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								 *		modify it under the terms of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 *		as published by the Free Software Foundation; either version
							 | 
						||
| 
								 | 
							
								 *		2 of the License, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Authors:	Thomas Graf <tgraf@suug.ch>
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <linux/module.h>
							 | 
						||
| 
								 | 
							
								#include <linux/slab.h>
							 | 
						||
| 
								 | 
							
								#include <linux/cgroup.h>
							 | 
						||
| 
								 | 
							
								#include <linux/fdtable.h>
							 | 
						||
| 
								 | 
							
								#include <net/cls_cgroup.h>
							 | 
						||
| 
								 | 
							
								#include <net/sock.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct cgroup_cls_state *task_cls_state(struct task_struct *p)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return css_cls_state(task_css(p, net_cls_subsys_id));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								EXPORT_SYMBOL_GPL(task_cls_state);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static struct cgroup_subsys_state *
							 | 
						||
| 
								 | 
							
								cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct cgroup_cls_state *cs;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									cs = kzalloc(sizeof(*cs), GFP_KERNEL);
							 | 
						||
| 
								 | 
							
									if (!cs)
							 | 
						||
| 
								 | 
							
										return ERR_PTR(-ENOMEM);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return &cs->css;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int cgrp_css_online(struct cgroup_subsys_state *css)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct cgroup_cls_state *cs = css_cls_state(css);
							 | 
						||
| 
								 | 
							
									struct cgroup_cls_state *parent = css_cls_state(css_parent(css));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (parent)
							 | 
						||
| 
								 | 
							
										cs->classid = parent->classid;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void cgrp_css_free(struct cgroup_subsys_state *css)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									kfree(css_cls_state(css));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int update_classid(const void *v, struct file *file, unsigned n)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int err;
							 | 
						||
| 
								 | 
							
									struct socket *sock = sock_from_file(file, &err);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (sock)
							 | 
						||
| 
								 | 
							
										sock->sk->sk_classid = (u32)(unsigned long)v;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void cgrp_attach(struct cgroup_subsys_state *css,
							 | 
						||
| 
								 | 
							
											struct cgroup_taskset *tset)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct cgroup_cls_state *cs = css_cls_state(css);
							 | 
						||
| 
								 | 
							
									void *v = (void *)(unsigned long)cs->classid;
							 | 
						||
| 
								 | 
							
									struct task_struct *p;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									cgroup_taskset_for_each(p, css, tset) {
							 | 
						||
| 
								 | 
							
										task_lock(p);
							 | 
						||
| 
								 | 
							
										iterate_fd(p->files, 0, update_classid, v);
							 | 
						||
| 
								 | 
							
										task_unlock(p);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return css_cls_state(css)->classid;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
							 | 
						||
| 
								 | 
							
											 u64 value)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									css_cls_state(css)->classid = (u32) value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static struct cftype ss_files[] = {
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										.name		= "classid",
							 | 
						||
| 
								 | 
							
										.read_u64	= read_classid,
							 | 
						||
| 
								 | 
							
										.write_u64	= write_classid,
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									{ }	/* terminate */
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct cgroup_subsys net_cls_subsys = {
							 | 
						||
| 
								 | 
							
									.name			= "net_cls",
							 | 
						||
| 
								 | 
							
									.css_alloc		= cgrp_css_alloc,
							 | 
						||
| 
								 | 
							
									.css_online		= cgrp_css_online,
							 | 
						||
| 
								 | 
							
									.css_free		= cgrp_css_free,
							 | 
						||
| 
								 | 
							
									.attach			= cgrp_attach,
							 | 
						||
| 
								 | 
							
									.subsys_id		= net_cls_subsys_id,
							 | 
						||
| 
								 | 
							
									.base_cftypes		= ss_files,
							 | 
						||
| 
								 | 
							
									.module			= THIS_MODULE,
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int __init init_netclassid_cgroup(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return cgroup_load_subsys(&net_cls_subsys);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								__initcall(init_netclassid_cgroup);
							 |