1 /* RCFS API for Rule-based Classification Engine (RBCE) and
2 * Consolidated RBCE module code (combined)
4 * Copyright (C) Hubertus Franke, IBM Corp. 2003
5 * (C) Chandra Seetharaman, IBM Corp. 2003
6 * (C) Vivek Kashyap, IBM Corp. 2004
8 * Module for loading of classification policies and providing
9 * a user API for Class-based Kernel Resource Management (CKRM)
11 * Latest version, more details at http://ckrm.sf.net
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it would be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 #include <linux/init.h>
26 #include <linux/errno.h>
27 #include <linux/proc_fs.h>
28 #include <linux/ctype.h>
29 #include <linux/module.h>
30 #include <linux/seq_file.h>
31 #include <linux/pagemap.h>
32 #include <linux/highmem.h>
33 #include <linux/string.h>
34 #include <linux/smp_lock.h>
35 #include <linux/mount.h>
36 #include <linux/backing-dev.h>
37 #include <asm/uaccess.h>
38 #include <linux/rcfs.h>
40 extern int rbce_enabled;
41 extern void get_rule(const char *, char *);
42 extern int rule_exists(const char *);
43 extern int change_rule(const char *, char *);
44 extern int delete_rule(const char *);
45 //extern int reclassify_pid(int);
46 extern int set_tasktag(int, char *);
47 extern int rename_rule(const char *, const char *);
49 extern int rcfs_register_engine(rbce_eng_callback_t * rcbs);
50 extern int rcfs_unregister_engine(rbce_eng_callback_t * rcbs);
51 extern int rcfs_mkroot(struct rcfs_magf *, int, struct dentry **);
52 extern int rcfs_rmroot(struct dentry *);
54 static int rbce_unlink(struct inode *, struct dentry *);
58 rbce_write(struct file *file, const char __user * buf,
59 size_t len, loff_t * ppos)
64 line = (char *)kmalloc(len + 1, GFP_KERNEL);
68 if (copy_from_user(line, buf, len)) {
73 ptr = line + strlen(line) - 1;
77 if (!strcmp(file->f_dentry->d_name.name, "rbce_tag")) {
78 pid = simple_strtol(line, &ptr, 0);
79 rc = set_tasktag(pid, ptr + 1); // expected syntax "pid tag"
80 } else if (!strcmp(file->f_dentry->d_name.name, "rbce_state")) {
81 rbce_enabled = line[0] - '0';
82 } else if (!strcmp(file->f_dentry->d_name.name, "rbce_info")) {
85 rc = change_rule(file->f_dentry->d_name.name, line);
90 // printk("kernel read |%s|\n", line);
91 // printk("kernel read-2 |%s|\n", line+1000);
92 // printk prints only 1024 bytes once :)
98 static int rbce_show(struct seq_file *seq, void *offset)
100 struct file *file = (struct file *)seq->private;
103 memset(result, 0, 256);
104 if (!strcmp(file->f_dentry->d_name.name, "rbce_tag")) {
107 if (!strcmp(file->f_dentry->d_name.name, "rbce_state")) {
108 seq_printf(seq, "%d\n", rbce_enabled);
111 if (!strcmp(file->f_dentry->d_name.name, "rbce_info")) {
112 seq_printf(seq, info);
116 get_rule(file->f_dentry->d_name.name, result);
117 seq_printf(seq, "%s\n", result);
121 static int rbce_open(struct inode *inode, struct file *file)
123 //printk("mnt_mountpoint %s\n",
124 // file->f_vfsmnt->mnt_mountpoint->d_name.name);
125 //printk("mnt_root %s\n", file->f_vfsmnt->mnt_root->d_name.name);
126 return single_open(file, rbce_show, file);
129 static int rbce_close(struct inode *ino, struct file *file)
131 const char *name = file->f_dentry->d_name.name;
133 if (strcmp(name, "rbce_state") &&
134 strcmp(name, "rbce_tag") && strcmp(name, "rbce_info")) {
136 if (!rule_exists(name)) {
137 // need more stuff to happen in the vfs layer
138 rbce_unlink(file->f_dentry->d_parent->d_inode,
142 return single_release(ino, file);
145 #define RCFS_MAGIC 0x4feedbac
147 static struct file_operations rbce_file_operations;
148 static struct inode_operations rbce_file_inode_operations;
149 static struct inode_operations rbce_dir_inode_operations;
151 static struct inode *rbce_get_inode(struct inode *dir, int mode, dev_t dev)
153 struct inode *inode = new_inode(dir->i_sb);
156 inode->i_mode = mode;
157 inode->i_uid = current->fsuid;
158 inode->i_gid = current->fsgid;
159 inode->i_blksize = PAGE_CACHE_SIZE;
161 inode->i_mapping->a_ops = dir->i_mapping->a_ops;
162 inode->i_mapping->backing_dev_info =
163 dir->i_mapping->backing_dev_info;
164 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
165 switch (mode & S_IFMT) {
167 init_special_inode(inode, mode, dev);
170 /* Treat as default assignment */
171 inode->i_op = &rbce_file_inode_operations;
172 inode->i_fop = &rbce_file_operations;
175 inode->i_op = &rbce_dir_inode_operations;
176 inode->i_fop = &simple_dir_operations;
178 /* directory inodes start off with i_nlink == 2
188 * File creation. Allocate an inode, and we're done..
192 rbce_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
194 struct inode *inode = rbce_get_inode(dir, mode, dev);
198 if (dir->i_mode & S_ISGID) {
199 inode->i_gid = dir->i_gid;
201 inode->i_mode |= S_ISGID;
203 d_instantiate(dentry, inode);
204 dget(dentry); /* Extra count - pin the dentry in core */
211 static int rbce_unlink(struct inode *dir, struct dentry *dentry)
213 struct inode *inode = dentry->d_inode;
216 rc = delete_rule(dentry->d_name.name);
219 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
221 inode->i_ctime = CURRENT_TIME;
229 rbce_rename(struct inode *old_dir, struct dentry *old_dentry,
230 struct inode *new_dir, struct dentry *new_dentry)
233 struct inode *inode = old_dentry->d_inode;
234 struct dentry *old_d = list_entry(old_dir->i_dentry.next,
235 struct dentry, d_alias);
236 struct dentry *new_d = list_entry(new_dir->i_dentry.next,
237 struct dentry, d_alias);
239 // cannot rename any directory
240 if (S_ISDIR(old_dentry->d_inode->i_mode)) {
243 // cannot rename anything under /ce
244 if (!strcmp(old_d->d_name.name, "ce")) {
247 // cannot move anything to /ce
248 if (!strcmp(new_d->d_name.name, "ce")) {
252 rc = rename_rule(old_dentry->d_name.name, new_dentry->d_name.name);
255 old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
256 new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
261 // CE allows only the rules directory to be created
262 int rbce_mkdir(struct inode *dir, struct dentry *dentry, int mode)
264 int retval = -EINVAL;
267 list_entry(dir->i_dentry.next, struct dentry, d_alias);
269 // Allow only /rcfs/ce and ce/rules
270 if ((!strcmp(pd->d_name.name, "ce") &&
271 !strcmp(dentry->d_name.name, "rules")) ||
272 (!strcmp(pd->d_name.name, "/") &&
273 !strcmp(dentry->d_name.name, "ce"))) {
275 if (!strcmp(dentry->d_name.name, "ce")) {
276 try_module_get(THIS_MODULE);
278 retval = rbce_mknod(dir, dentry, mode | S_IFDIR, 0);
287 // CE doesn't allow deletion of directory
288 int rbce_rmdir(struct inode *dir, struct dentry *dentry)
291 // printk("removal of directory %s prohibited\n", dentry->d_name.name);
292 rc = simple_rmdir(dir, dentry);
294 if (!rc && !strcmp(dentry->d_name.name, "ce")) {
295 module_put(THIS_MODULE);
301 rbce_create(struct inode *dir, struct dentry *dentry,
302 int mode, struct nameidata *nd)
305 list_entry(dir->i_dentry.next, struct dentry, d_alias);
307 // Under /ce only "rbce_state", "rbce_tag" and "rbce_info" are allowed
308 if (!strcmp(pd->d_name.name, "ce")) {
309 if (strcmp(dentry->d_name.name, "rbce_state") &&
310 strcmp(dentry->d_name.name, "rbce_tag") &&
311 strcmp(dentry->d_name.name, "rbce_info")) {
316 return rbce_mknod(dir, dentry, mode | S_IFREG, 0);
319 static int rbce_link(struct dentry *old_d, struct inode *dir, struct dentry *d)
325 rbce_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
330 /******************************* Magic files ********************/
332 #define RBCE_NR_MAGF 5
333 struct rcfs_magf rbce_magf_files[RBCE_NR_MAGF] = {
336 .mode = RCFS_DEFAULT_DIR_MODE,
337 .i_op = &rbce_dir_inode_operations,
341 .mode = RCFS_DEFAULT_FILE_MODE,
342 .i_fop = &rbce_file_operations,
346 .mode = RCFS_DEFAULT_FILE_MODE,
347 .i_fop = &rbce_file_operations,
350 .name = "rbce_state",
351 .mode = RCFS_DEFAULT_FILE_MODE,
352 .i_fop = &rbce_file_operations,
356 .mode = (RCFS_DEFAULT_DIR_MODE | S_IWUSR),
357 .i_fop = &simple_dir_operations,
358 .i_op = &rbce_dir_inode_operations,
362 static struct dentry *ce_root_dentry;
364 int rbce_create_magic(void)
369 rc = rcfs_mkroot(rbce_magf_files, RBCE_NR_MAGF, &ce_root_dentry);
370 if ((!ce_root_dentry) || rc)
373 // Create magic files
374 if ((rc = rcfs_create_magic(ce_root_dentry, &rbce_magf_files[1],
375 RBCE_NR_MAGF - 1))) {
376 printk(KERN_ERR "Failed to create c/rbce magic files."
377 " Deleting c/rbce root\n");
378 rcfs_rmroot(ce_root_dentry);
385 int rbce_clear_magic(void)
389 rc = rcfs_rmroot(ce_root_dentry);
393 /******************************* File ops ********************/
395 static struct file_operations rbce_file_operations = {
396 .owner = THIS_MODULE,
401 .release = rbce_close,
404 static struct inode_operations rbce_file_inode_operations = {
405 .getattr = simple_getattr,
408 static struct inode_operations rbce_dir_inode_operations = {
409 .create = rbce_create,
410 .lookup = simple_lookup,
412 .unlink = rbce_unlink,
413 .symlink = rbce_symlink,
417 .rename = rbce_rename,
418 .getattr = simple_getattr,
422 static void rbce_put_super(struct super_block *sb)
424 module_put(THIS_MODULE);
425 printk(KERN_DEBUG "rbce_put_super called\n");
428 static struct super_operations rbce_ops = {
429 .statfs = simple_statfs,
430 .drop_inode = generic_delete_inode,
431 .put_super = rbce_put_super,
434 static int rbce_fill_super(struct super_block *sb, void *data, int silent)
439 sb->s_blocksize = PAGE_CACHE_SIZE;
440 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
441 sb->s_magic = RCFS_MAGIC;
442 sb->s_op = &rbce_ops;
443 inode = rbce_get_inode(sb, S_IFDIR | 0755, 0);
447 root = d_alloc_root(inode);
457 static struct super_block *rbce_get_sb(struct file_system_type *fs_type,
458 int flags, const char *dev_name,
461 struct super_block *sb =
462 get_sb_nodev(fs_type, flags, data, rbce_fill_super);
464 try_module_get(THIS_MODULE);
469 static struct file_system_type rbce_fs_type = {
471 .get_sb = rbce_get_sb,
472 .kill_sb = kill_litter_super,
476 __init init_rbce_fs(void)
478 return register_filesystem(&rbce_fs_type);
482 __exit exit_rbce_fs(void)
484 unregister_filesystem(&rbce_fs_type);
487 module_init(init_rbce_fs)
488 module_exit(exit_rbce_fs)
489 MODULE_LICENSE("GPL");