2 * This file is released under the GPL.
5 #include <linux/init.h>
6 #include <linux/errno.h>
7 #include <linux/proc_fs.h>
8 #include <linux/ctype.h>
9 #include <linux/module.h>
10 #include <linux/seq_file.h>
11 #include <linux/pagemap.h>
12 #include <linux/highmem.h>
13 #include <linux/string.h>
14 #include <linux/smp_lock.h>
15 #include <linux/mount.h>
16 #include <linux/backing-dev.h>
17 #include <asm/uaccess.h>
18 #include <linux/rcfs.h>
20 extern int rbce_enabled;
21 extern void get_rule(const char *, char *);
22 extern int rule_exists(const char *);
23 extern int change_rule(const char *, char *);
24 extern int delete_rule(const char *);
25 //extern int reclassify_pid(int);
26 extern int set_tasktag(int, char *);
27 extern int rename_rule(const char *, const char *);
29 extern int rcfs_register_engine(rbce_eng_callback_t * rcbs);
30 extern int rcfs_unregister_engine(rbce_eng_callback_t * rcbs);
31 extern int rcfs_mkroot(struct rcfs_magf *, int, struct dentry **);
32 extern int rcfs_rmroot(struct dentry *);
34 static int rbce_unlink(struct inode *, struct dentry *);
38 rbce_write(struct file *file, const char __user * buf,
39 size_t len, loff_t * ppos)
44 line = (char *)kmalloc(len + 1, GFP_KERNEL);
48 if (copy_from_user(line, buf, len)) {
53 ptr = line + strlen(line) - 1;
58 if (!strcmp(file->f_dentry->d_name.name, "rbce_reclassify")) {
59 pid = simple_strtol(line, NULL, 0);
60 rc = reclassify_pid(pid);
63 if (!strcmp(file->f_dentry->d_name.name, "rbce_tag")) {
64 pid = simple_strtol(line, &ptr, 0);
65 rc = set_tasktag(pid, ptr + 1); // expected syntax "pid tag"
66 } else if (!strcmp(file->f_dentry->d_name.name, "rbce_state")) {
67 rbce_enabled = line[0] - '0';
68 } else if (!strcmp(file->f_dentry->d_name.name, "rbce_info")) {
71 rc = change_rule(file->f_dentry->d_name.name, line);
76 // printk("kernel read |%s|\n", line);
77 // printk("kernel read-2 |%s|\n", line+1000);
78 // printk prints only 1024 bytes once :)
84 static int rbce_show(struct seq_file *seq, void *offset)
86 struct file *file = (struct file *)seq->private;
89 memset(result, 0, 256);
90 if (!strcmp(file->f_dentry->d_name.name, "rbce_reclassify") ||
91 !strcmp(file->f_dentry->d_name.name, "rbce_tag")) {
94 if (!strcmp(file->f_dentry->d_name.name, "rbce_state")) {
95 seq_printf(seq, "%d\n", rbce_enabled);
98 if (!strcmp(file->f_dentry->d_name.name, "rbce_info")) {
99 seq_printf(seq, info);
103 get_rule(file->f_dentry->d_name.name, result);
104 seq_printf(seq, "%s\n", result);
108 static int rbce_open(struct inode *inode, struct file *file)
110 //printk("mnt_mountpoint %s\n",
111 // file->f_vfsmnt->mnt_mountpoint->d_name.name);
112 //printk("mnt_root %s\n", file->f_vfsmnt->mnt_root->d_name.name);
113 return single_open(file, rbce_show, file);
116 static int rbce_close(struct inode *ino, struct file *file)
118 const char *name = file->f_dentry->d_name.name;
120 if (strcmp(name, "rbce_reclassify") &&
121 strcmp(name, "rbce_state") &&
122 strcmp(name, "rbce_tag") && strcmp(name, "rbce_info")) {
124 if (!rule_exists(name)) {
125 // need more stuff to happen in the vfs layer
126 rbce_unlink(file->f_dentry->d_parent->d_inode,
130 return single_release(ino, file);
133 #define RCFS_MAGIC 0x4feedbac
135 static struct file_operations rbce_file_operations;
136 static struct inode_operations rbce_file_inode_operations;
137 static struct inode_operations rbce_dir_inode_operations;
139 static struct inode *rbce_get_inode(struct inode *dir, int mode, dev_t dev)
141 struct inode *inode = new_inode(dir->i_sb);
144 inode->i_mode = mode;
145 inode->i_uid = current->fsuid;
146 inode->i_gid = current->fsgid;
147 inode->i_blksize = PAGE_CACHE_SIZE;
149 inode->i_mapping->a_ops = dir->i_mapping->a_ops;
150 inode->i_mapping->backing_dev_info =
151 dir->i_mapping->backing_dev_info;
152 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
153 switch (mode & S_IFMT) {
155 init_special_inode(inode, mode, dev);
158 /* Treat as default assignment */
159 inode->i_op = &rbce_file_inode_operations;
160 inode->i_fop = &rbce_file_operations;
163 inode->i_op = &rbce_dir_inode_operations;
164 inode->i_fop = &simple_dir_operations;
166 /* directory inodes start off with i_nlink == 2
176 * File creation. Allocate an inode, and we're done..
180 rbce_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
182 struct inode *inode = rbce_get_inode(dir, mode, dev);
186 if (dir->i_mode & S_ISGID) {
187 inode->i_gid = dir->i_gid;
189 inode->i_mode |= S_ISGID;
191 d_instantiate(dentry, inode);
192 dget(dentry); /* Extra count - pin the dentry in core */
199 static int rbce_unlink(struct inode *dir, struct dentry *dentry)
201 struct inode *inode = dentry->d_inode;
204 rc = delete_rule(dentry->d_name.name);
207 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
209 inode->i_ctime = CURRENT_TIME;
217 rbce_rename(struct inode *old_dir, struct dentry *old_dentry,
218 struct inode *new_dir, struct dentry *new_dentry)
221 struct inode *inode = old_dentry->d_inode;
222 struct dentry *old_d = list_entry(old_dir->i_dentry.next,
223 struct dentry, d_alias);
224 struct dentry *new_d = list_entry(new_dir->i_dentry.next,
225 struct dentry, d_alias);
227 // cannot rename any directory
228 if (S_ISDIR(old_dentry->d_inode->i_mode)) {
231 // cannot rename anything under /ce
232 if (!strcmp(old_d->d_name.name, "ce")) {
235 // cannot move anything to /ce
236 if (!strcmp(new_d->d_name.name, "ce")) {
240 rc = rename_rule(old_dentry->d_name.name, new_dentry->d_name.name);
243 old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
244 new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
249 // CE allows only the rules directory to be created
250 int rbce_mkdir(struct inode *dir, struct dentry *dentry, int mode)
252 int retval = -EINVAL;
255 list_entry(dir->i_dentry.next, struct dentry, d_alias);
257 // Allow only /rcfs/ce and ce/rules
258 if ((!strcmp(pd->d_name.name, "ce") &&
259 !strcmp(dentry->d_name.name, "rules")) ||
260 (!strcmp(pd->d_name.name, "/") &&
261 !strcmp(dentry->d_name.name, "ce"))) {
263 if (!strcmp(dentry->d_name.name, "ce")) {
264 try_module_get(THIS_MODULE);
266 retval = rbce_mknod(dir, dentry, mode | S_IFDIR, 0);
275 // CE doesn't allow deletion of directory
276 int rbce_rmdir(struct inode *dir, struct dentry *dentry)
279 // printk("removal of directory %s prohibited\n", dentry->d_name.name);
280 rc = simple_rmdir(dir, dentry);
282 if (!rc && !strcmp(dentry->d_name.name, "ce")) {
283 module_put(THIS_MODULE);
289 rbce_create(struct inode *dir, struct dentry *dentry,
290 int mode, struct nameidata *nd)
293 list_entry(dir->i_dentry.next, struct dentry, d_alias);
295 // Under /ce only "rbce_reclassify", "rbce_state", "rbce_tag" and
296 // "rbce_info" are allowed
297 if (!strcmp(pd->d_name.name, "ce")) {
298 if (strcmp(dentry->d_name.name, "rbce_reclassify") &&
299 strcmp(dentry->d_name.name, "rbce_state") &&
300 strcmp(dentry->d_name.name, "rbce_tag") &&
301 strcmp(dentry->d_name.name, "rbce_info")) {
306 return rbce_mknod(dir, dentry, mode | S_IFREG, 0);
309 static int rbce_link(struct dentry *old_d, struct inode *dir, struct dentry *d)
315 rbce_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
320 /******************************* Magic files ********************/
322 #define RBCE_NR_MAGF 6
323 struct rcfs_magf rbce_magf_files[RBCE_NR_MAGF] = {
326 .mode = RCFS_DEFAULT_DIR_MODE,
327 .i_op = &rbce_dir_inode_operations,
331 .mode = RCFS_DEFAULT_FILE_MODE,
332 .i_fop = &rbce_file_operations,
336 .mode = RCFS_DEFAULT_FILE_MODE,
337 .i_fop = &rbce_file_operations,
340 .name = "rbce_state",
341 .mode = RCFS_DEFAULT_FILE_MODE,
342 .i_fop = &rbce_file_operations,
345 .name = "rbce_reclassify",
346 .mode = RCFS_DEFAULT_FILE_MODE,
347 .i_fop = &rbce_file_operations,
351 .mode = (RCFS_DEFAULT_DIR_MODE | S_IWUSR),
352 .i_fop = &simple_dir_operations,
353 .i_op = &rbce_dir_inode_operations,
357 static struct dentry *ce_root_dentry;
359 int rbce_create_magic(void)
364 rc = rcfs_mkroot(rbce_magf_files, RBCE_NR_MAGF, &ce_root_dentry);
365 if ((!ce_root_dentry) || rc)
368 // Create magic files
369 if ((rc = rcfs_create_magic(ce_root_dentry, &rbce_magf_files[1],
370 RBCE_NR_MAGF - 1))) {
371 printk(KERN_ERR "Failed to create c/rbce magic files."
372 " Deleting c/rbce root\n");
373 rcfs_rmroot(ce_root_dentry);
380 int rbce_clear_magic(void)
384 rc = rcfs_rmroot(ce_root_dentry);
388 /******************************* File ops ********************/
390 static struct file_operations rbce_file_operations = {
391 .owner = THIS_MODULE,
396 .release = rbce_close,
399 static struct inode_operations rbce_file_inode_operations = {
400 .getattr = simple_getattr,
403 static struct inode_operations rbce_dir_inode_operations = {
404 .create = rbce_create,
405 .lookup = simple_lookup,
407 .unlink = rbce_unlink,
408 .symlink = rbce_symlink,
412 .rename = rbce_rename,
413 .getattr = simple_getattr,
417 static void rbce_put_super(struct super_block *sb)
419 module_put(THIS_MODULE);
420 printk("rbce_put_super called\n");
423 static struct super_operations rbce_ops = {
424 .statfs = simple_statfs,
425 .drop_inode = generic_delete_inode,
426 .put_super = rbce_put_super,
429 static int rbce_fill_super(struct super_block *sb, void *data, int silent)
434 sb->s_blocksize = PAGE_CACHE_SIZE;
435 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
436 sb->s_magic = RCFS_MAGIC;
437 sb->s_op = &rbce_ops;
438 inode = rbce_get_inode(sb, S_IFDIR | 0755, 0);
442 root = d_alloc_root(inode);
452 static struct super_block *rbce_get_sb(struct file_system_type *fs_type,
453 int flags, const char *dev_name,
456 struct super_block *sb =
457 get_sb_nodev(fs_type, flags, data, rbce_fill_super);
459 try_module_get(THIS_MODULE);
464 static struct file_system_type rbce_fs_type = {
466 .get_sb = rbce_get_sb,
467 .kill_sb = kill_litter_super,
471 __init init_rbce_fs(void)
473 return register_filesystem(&rbce_fs_type);
477 __exit exit_rbce_fs(void)
479 unregister_filesystem(&rbce_fs_type);
482 module_init(init_rbce_fs)
483 module_exit(exit_rbce_fs)
484 MODULE_LICENSE("GPL");