From: Gerrit Huizenga Part 1 of 5 patches to support Rule Based Classification Engine for CKRM. This patch provides the the basic rcfs interface for rbce. It just provides the interface with stub functions. Signed-Off-By: Hubertus Franke Signed-Off-By: Chandra Seetharaman Signed-Off-By: Shailabh Nagar Signed-Off-By: Vivek Kashyap Signed-Off-By: Gerrit Huizenga Signed-off-by: Andrew Morton --- include/linux/rbce.h | 28 ++ init/Kconfig | 12 + kernel/ckrm/Makefile | 1 kernel/ckrm/rbce/Makefile | 6 kernel/ckrm/rbce/rbce_fs.c | 365 +++++++++++++++++++++++++++++++++++++++ kernel/ckrm/rbce/rbce_internal.h | 59 ++++++ kernel/ckrm/rbce/rbce_main.c | 97 ++++++++++ 7 files changed, 568 insertions(+) diff -puN /dev/null include/linux/rbce.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/include/linux/rbce.h Wed Jul 13 14:44:13 2005 @@ -0,0 +1,28 @@ +/* Rule-based Classification Engine (RBCE) module + * + * Copyright (C) Hubertus Franke, IBM Corp. 2003 + * (C) Chandra Seetharaman, IBM Corp. 2003 + * + * Module for loading of classification policies and providing + * a user API for Class-based Kernel Resource Management (CKRM) + * + * Latest version, more details at http://ckrm.sf.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + */ + +#ifndef _LINUX_RBCE_H +#define _LINUX_RBCE_H + +#define RBCE_MOD_DESCR "Rule Based Classification Engine Module for CKRM" +#define RBCE_MOD_NAME "rbce" + +#endif /* _LINUX_RBCE_H */ diff -puN init/Kconfig~ckrm-rule-based-classification-engine-stub-rcfs-support init/Kconfig --- 25/init/Kconfig~ckrm-rule-based-classification-engine-stub-rcfs-support Wed Jul 13 14:44:13 2005 +++ 25-akpm/init/Kconfig Wed Jul 13 14:44:13 2005 @@ -203,6 +203,18 @@ config CKRM_RES_NUMTASKS Say N if unsure, Y to use the feature. + +config CKRM_RBCE + tristate "Vanilla Rule-based Classification Engine (RBCE)" + depends on CKRM && RCFS_FS + default m + help + Provides an optional module to support creation of rules for automatic + classification of kernel objects. Rules are created/deleted/modified + through an rcfs interface. RBCE is not required for CKRM. + + If unsure, say N. + endmenu config SYSCTL diff -puN kernel/ckrm/Makefile~ckrm-rule-based-classification-engine-stub-rcfs-support kernel/ckrm/Makefile --- 25/kernel/ckrm/Makefile~ckrm-rule-based-classification-engine-stub-rcfs-support Wed Jul 13 14:44:13 2005 +++ 25-akpm/kernel/ckrm/Makefile Wed Jul 13 14:44:13 2005 @@ -6,3 +6,4 @@ obj-y += ckrm_events.o ckrm.o ckrmutils. obj-$(CONFIG_CKRM_TYPE_TASKCLASS) += ckrm_tc.o ckrm_numtasks_stub.o obj-$(CONFIG_CKRM_TYPE_SOCKETCLASS) += ckrm_sockc.o obj-$(CONFIG_CKRM_RES_NUMTASKS) += ckrm_numtasks.o +obj-$(CONFIG_CKRM_RBCE) += rbce/ diff -puN /dev/null kernel/ckrm/rbce/Makefile --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/kernel/ckrm/rbce/Makefile Wed Jul 13 14:44:13 2005 @@ -0,0 +1,6 @@ +# +# Makefile for RBCE +# + +obj-$(CONFIG_CKRM_RBCE) += rbce.o +rbce-objs := rbce_fs.o rbce_main.o diff -puN /dev/null kernel/ckrm/rbce/rbce_fs.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/kernel/ckrm/rbce/rbce_fs.c Wed Jul 13 14:44:13 2005 @@ -0,0 +1,365 @@ +/* + * RCFS API for Rule-based Classification Engine (RBCE) + * + * Copyright (C) Hubertus Franke, IBM Corp. 2003 + * (C) Chandra Seetharaman, IBM Corp. 2003 + * (C) Vivek Kashyap, IBM Corp. 2004 + * + * Module for loading of classification policies and providing + * a user API for Class-based Kernel Resource Management (CKRM) + * + * Latest version, more details at http://ckrm.sf.net + * + * 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. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include +#include +#include "rbce_internal.h" + +#define CONFIG_CE_DIR "ce" +#define CONFIG_RULES_DIR "rules" +#define CONFIG_RBCE_STATE "rbce_state" +#define CONFIG_RBCE_TAG "rbce_tag" + +static int rbce_unlink(struct inode *, struct dentry *); + +static ssize_t +rbce_write(struct file *file, const char __user * buf, + size_t len, loff_t * ppos) +{ + char *line, *ptr; + int rc = 0, pid; + + line = kmalloc(len + 1, GFP_KERNEL); + if (!line) { + return -ENOMEM; + } + if (copy_from_user(line, buf, len)) { + kfree(line); + return -EFAULT; + } + line[len] = '\0'; + ptr = line; + while (*ptr) { + if (*ptr == '\n') { + *ptr = '\0'; + break; + } + ptr++; + } + if (!strcmp(file->f_dentry->d_name.name, CONFIG_RBCE_TAG)) { + pid = simple_strtol(line, &ptr, 0); + rc = rbce_set_tasktag(pid, ptr + 1); /* syntax "pid tag" */ + } else if (!strcmp(file->f_dentry->d_name.name, CONFIG_RBCE_STATE)) + rbce_enabled = line[0] - '0'; + else + rc = rbce_change_rule(file->f_dentry->d_name.name, line); + if (rc) + len = rc; + kfree(line); + return len; +} + +static int rbce_show(struct seq_file *seq, void *offset) +{ + struct file *file = (struct file *)seq->private; + char result[256]; + + memset(result, 0, 256); + if (!strcmp(file->f_dentry->d_name.name, CONFIG_RBCE_TAG)) + return -EPERM; + if (!strcmp(file->f_dentry->d_name.name, CONFIG_RBCE_STATE)) + seq_printf(seq, "%d\n", rbce_enabled); + else { + rbce_get_rule(file->f_dentry->d_name.name, result); + seq_printf(seq, "%s\n", result); + } + return 0; +} + +static int rbce_open(struct inode *inode, struct file *file) +{ + return single_open(file, rbce_show, file); +} + +static int rbce_close(struct inode *ino, struct file *file) +{ + const char *name = file->f_dentry->d_name.name; + + if (strcmp(name, CONFIG_RBCE_STATE) && + strcmp(name, CONFIG_RBCE_TAG) && + !rbce_rule_exists(name)) + rbce_unlink(file->f_dentry->d_parent->d_inode, file->f_dentry); + return single_release(ino, file); +} + +static struct file_operations rbce_file_operations; +static struct inode_operations rbce_file_inode_operations; +static struct inode_operations rbce_dir_inode_operations; + +static struct inode *rbce_get_inode(struct inode *dir, int mode, dev_t dev) +{ + struct inode *inode = new_inode(dir->i_sb); + + if (inode) { + inode->i_mode = mode; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_blksize = PAGE_CACHE_SIZE; + inode->i_blocks = 0; + inode->i_mapping->a_ops = dir->i_mapping->a_ops; + inode->i_mapping->backing_dev_info = + dir->i_mapping->backing_dev_info; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + switch (mode & S_IFMT) { + default: + init_special_inode(inode, mode, dev); + break; + case S_IFREG: + /* Treat as default assignment */ + inode->i_op = &rbce_file_inode_operations; + inode->i_fop = &rbce_file_operations; + break; + case S_IFDIR: + inode->i_op = &rbce_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + + /* directory inodes start off with i_nlink == 2 + (for "." entry) */ + inode->i_nlink++; + break; + } + } + return inode; +} + +/* + * File creation. Allocate an inode, and we're done.. + */ +static int +rbce_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ + struct inode *inode = rbce_get_inode(dir, mode, dev); + int error = -ENOSPC; + + if (inode) { + if (dir->i_mode & S_ISGID) { + inode->i_gid = dir->i_gid; + if (S_ISDIR(mode)) + inode->i_mode |= S_ISGID; + } + d_instantiate(dentry, inode); + dget(dentry); /* Extra count - pin the dentry in core */ + error = 0; + + } + return error; +} + +static int rbce_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + int rc; + + rc = rbce_delete_rule(dentry->d_name.name); + if (rc == 0) { + if (dir) + dir->i_ctime = dir->i_mtime = CURRENT_TIME; + inode->i_ctime = CURRENT_TIME; + inode->i_nlink--; + dput(dentry); + } + return rc; +} + +static int +rbce_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + int rc; + struct inode *inode = old_dentry->d_inode; + struct dentry *old_d = list_entry(old_dir->i_dentry.next, + struct dentry, d_alias); + struct dentry *new_d = list_entry(new_dir->i_dentry.next, + struct dentry, d_alias); + + /* Do not allow renaming any directory */ + if (S_ISDIR(old_dentry->d_inode->i_mode)) + return -EINVAL; + + /* Do not allow renaming files just under under /ce */ + if (!strcmp(old_d->d_name.name, CONFIG_CE_DIR)) + return -EINVAL; + + /* cannot move anything to /ce */ + if (!strcmp(new_d->d_name.name, CONFIG_CE_DIR)) + return -EINVAL; + + rc = rbce_rename_rule(old_dentry->d_name.name, new_dentry->d_name.name); + + if (!rc) + old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime = + new_dir->i_mtime = inode->i_ctime = CURRENT_TIME; + return rc; +} + +/* CE allows only the rules directory to be created */ +int rbce_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int retval = -EINVAL; + + struct dentry *pd = + list_entry(dir->i_dentry.next, struct dentry, d_alias); + + /* Allow only /rcfs/ce and ce/rules */ + if ((!strcmp(pd->d_name.name, CONFIG_CE_DIR) && + !strcmp(dentry->d_name.name, CONFIG_RULES_DIR)) || + (!strcmp(pd->d_name.name, "/") && + !strcmp(dentry->d_name.name, CONFIG_CE_DIR))) { + if (!strcmp(dentry->d_name.name, CONFIG_CE_DIR)) + try_module_get(THIS_MODULE); + retval = rbce_mknod(dir, dentry, mode | S_IFDIR, 0); + if (!retval) + dir->i_nlink++; + } + + return retval; +} + +/* CE doesn't allow deletion of directory */ +int rbce_rmdir(struct inode *dir, struct dentry *dentry) +{ + int rc; + rc = simple_rmdir(dir, dentry); + + if (!rc && !strcmp(dentry->d_name.name, CONFIG_CE_DIR)) + module_put(THIS_MODULE); + return rc; +} + +static int +rbce_create(struct inode *dir, struct dentry *dentry, + int mode, struct nameidata *nd) +{ + struct dentry *pd = + list_entry(dir->i_dentry.next, struct dentry, d_alias); + + /* No creation allowed under ce */ + if (!strcmp(pd->d_name.name, CONFIG_CE_DIR)) + return -EINVAL; + + return rbce_mknod(dir, dentry, mode | S_IFREG, 0); +} + +static int rbce_link(struct dentry *old_d, struct inode *dir, struct dentry *d) +{ + return -EINVAL; +} + +static int +rbce_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +{ + return -EINVAL; +} + +/******************************* Config files ********************/ + +#define RBCE_NR_CONFIG 5 +struct rcfs_magf rbce_config_files[RBCE_NR_CONFIG] = { + { + .name = CONFIG_CE_DIR, + .mode = RCFS_DEFAULT_DIR_MODE, + .i_op = &rbce_dir_inode_operations, + }, + { + .name = CONFIG_RBCE_TAG, + .mode = RCFS_DEFAULT_FILE_MODE, + .i_fop = &rbce_file_operations, + }, + { + .name = CONFIG_RBCE_STATE, + .mode = RCFS_DEFAULT_FILE_MODE, + .i_fop = &rbce_file_operations, + }, + { + .name = CONFIG_RULES_DIR, + .mode = (RCFS_DEFAULT_DIR_MODE | S_IWUSR), + .i_fop = &simple_dir_operations, + .i_op = &rbce_dir_inode_operations, + } +}; + +static struct dentry *ce_root_dentry; + +int rbce_create_config(void) +{ + int rc; + + /* Make root dentry */ + rc = rcfs_mkroot(rbce_config_files, RBCE_NR_CONFIG, &ce_root_dentry); + if ((!ce_root_dentry) || rc) + return rc; + + /* Create config files */ + if ((rc = rcfs_create_magic(ce_root_dentry, &rbce_config_files[1], + RBCE_NR_CONFIG - 1))) { + printk(KERN_ERR "Failed to create c/rbce config files." + " Deleting c/rbce root\n"); + rcfs_rmroot(ce_root_dentry); + return rc; + } + + return rc; +} + +int rbce_clear_config(void) +{ + int rc = 0; + if (ce_root_dentry) + rc = rcfs_rmroot(ce_root_dentry); + return rc; +} + +/******************************* File ops ********************/ + +static struct file_operations rbce_file_operations = { + .owner = THIS_MODULE, + .open = rbce_open, + .llseek = seq_lseek, + .read = seq_read, + .write = rbce_write, + .release = rbce_close, +}; + +static struct inode_operations rbce_file_inode_operations = { + .getattr = simple_getattr, +}; + +static struct inode_operations rbce_dir_inode_operations = { + .create = rbce_create, + .lookup = simple_lookup, + .link = rbce_link, + .unlink = rbce_unlink, + .symlink = rbce_symlink, + .mkdir = rbce_mkdir, + .rmdir = rbce_rmdir, + .mknod = rbce_mknod, + .rename = rbce_rename, + .getattr = simple_getattr, +}; + +struct rbce_eng_callback rbce_rcfs_ecbs = { + rbce_mkdir, + rbce_rmdir, + rbce_create_config, + rbce_clear_config +}; diff -puN /dev/null kernel/ckrm/rbce/rbce_internal.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/kernel/ckrm/rbce/rbce_internal.h Wed Jul 13 14:44:13 2005 @@ -0,0 +1,59 @@ +/* + * rbce internal header file. + * + * Copyright (C) Hubertus Franke, IBM Corp. 2003 + * (C) Chandra Seetharaman, IBM Corp. 2003 + * (C) Vivek Kashyap, IBM Corp. 2004 + * + * Module for loading of classification policies and providing + * a user API for Class-based Kernel Resource Management (CKRM) + * + * Latest version, more details at http://ckrm.sf.net + * + * 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. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ +#ifndef _RBCE_INTERNAL_H +#define _RBCE_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern int rbce_enabled; +extern struct rbce_eng_callback rbce_rcfs_ecbs; + +extern int rbce_mkdir(struct inode *, struct dentry *, int); +extern int rbce_rmdir(struct inode *, struct dentry *); +extern int rbce_create_config(void); +extern int rbce_clear_config(void); + +extern void rbce_get_rule(const char *, char *); +extern int rbce_rule_exists(const char *); +extern int rbce_change_rule(const char *, char *); +extern int rbce_delete_rule(const char *); +extern int rbce_set_tasktag(int, char *); +extern int rbce_rename_rule(const char *, const char *); + +#endif /* _RBCE_INTERNAL_H */ diff -puN /dev/null kernel/ckrm/rbce/rbce_main.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/kernel/ckrm/rbce/rbce_main.c Wed Jul 13 14:44:13 2005 @@ -0,0 +1,97 @@ +/* + * Rule Functionality and module initialization and destrution + * for Rule-based Classification Engine (RBCE) + * + * Copyright (C) Hubertus Franke, IBM Corp. 2003 + * (C) Chandra Seetharaman, IBM Corp. 2003 + * (C) Vivek Kashyap, IBM Corp. 2004 + * + * Module for loading of classification policies and providing + * a user API for Class-based Kernel Resource Management (CKRM) + * + * Latest version, more details at http://ckrm.sf.net + * + * 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. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include "rbce_internal.h" + +MODULE_DESCRIPTION(RBCE_MOD_DESCR); +MODULE_AUTHOR("Hubertus Franke, Chandra Seetharaman (IBM)"); +MODULE_LICENSE("GPL"); + +static char modname[] = RBCE_MOD_NAME; + +/* Stub routines for now */ +void rbce_get_rule(const char *a, char *b) +{ +} +int rbce_rule_exists(const char *a) +{ + return 0; +} +int rbce_change_rule(const char *a, char *b) +{ + return 1; +} +int rbce_delete_rule(const char *a) +{ + return 1; +} +int rbce_set_tasktag(int i, char *a) +{ + return 1; +} +int rbce_rename_rule(const char *a, const char *b) +{ + return 1; +} + +int rbce_enabled = 1; +/* ======================= Module definition Functions ====================== */ + +int init_rbce(void) +{ + int rc, line; + + printk(KERN_INFO "Installing \'%s\' module\n", modname); + + rc = rcfs_register_engine(&rbce_rcfs_ecbs); + line = __LINE__; + if (rc) + goto out; + + if (rcfs_mounted) { + rc = rbce_create_config(); + line = __LINE__; + if (!rc) + goto out; + } + + rcfs_unregister_engine(&rbce_rcfs_ecbs); +out: + printk(KERN_ERR "%s: error installing rc=%d line=%d\n", + __FUNCTION__, rc, line); + return rc; +} + +void exit_rbce(void) +{ + printk(KERN_INFO "Removing \'%s\' module\n", modname); + + if (rcfs_mounted) + rbce_clear_config(); + + rcfs_unregister_engine(&rbce_rcfs_ecbs); +} + +module_init(init_rbce); +module_exit(exit_rbce); _