diff -Naur linux-2.5.70/security/tpe.c linux-2.5.70-tpe/security/tpe.c --- linux-2.5.70/security/tpe.c 2003-06-10 12:26:16.000000000 -0700 +++ linux-2.5.70-tpe/security/tpe.c 2003-06-10 11:10:45.000000000 -0700 @@ -61,399 +61,58 @@ #include #include #include +#include #include "tpe.h" -/* Beginning of my implementation of Greg Kroah-Hartman's - * pseudofs approach for tpefs. - */ - -#define dbg(fmt, arg...) \ -do { if (1) printk(KERN_DEBUG "%s: " fmt , "tpe" , ## arg); } while (0) - -#define TPEFS_MAGIC 0x84295178 -static struct super_operations tpefs_ops; -static struct file_operations default_file_operations; -static struct inode_operations tpefs_dir_inode_operations; -static struct vfsmount *tpefs_mount; -static int tpefs_mount_count; -static spinlock_t tpe_mount_lock; -static spinlock_t tpe_list_lock; -static int secondary; - -struct tpe_dents { - struct dentry *d; - struct tpe_dents *next; -}; - -struct dentry *trustedlistadd_dentry = NULL; -struct dentry *trustedlistdel_dentry = NULL; - -struct tpe_dents * tpe_dents = NULL; - -static struct inode *tpefs_get_inode (struct super_block *sb, int mode, -dev_t dev) -{ - struct inode *inode = new_inode(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_rdev = NODEV; - 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: - inode->i_fop = &default_file_operations; - break; - case S_IFDIR: - inode->i_op = &tpefs_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - inode->i_nlink++; - break; - } - } - return inode; -} - -static int tpefs_mknod(struct inode *dir, struct dentry *dentry, -int mode, dev_t dev) -{ - struct inode *inode = tpefs_get_inode(dir->i_sb, mode, dev); - int error = -ENOSPC; - - if (inode) { - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - return error; -} +/* Beginning of a sysfs subsystem for tpe */ -static int tpefs_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - return tpefs_mknod(dir, dentry, mode | S_IFDIR, 0); -} - -static int tpefs_create (struct inode *dir, struct dentry *dentry, int mode) -{ - return tpefs_mknod(dir, dentry, mode | S_IFREG, 0); -} - -static inline int tpefs_positive (struct dentry *dentry) -{ - return dentry->d_inode && !d_unhashed(dentry); -} - -static int tpefs_empty (struct dentry *dentry) -{ - struct list_head *list; - spin_lock(&dcache_lock); - list_for_each(list, &dentry->d_subdirs) { - struct dentry *de = list_entry(list, struct dentry, d_child); - if (tpefs_positive(de)) { - spin_unlock(&dcache_lock); - return 0; - } - } - spin_unlock(&dcache_lock); - return 1; -} - -static int tpefs_unlink(struct inode *dir, struct dentry *dentry) -{ - int error = -ENOTEMPTY; - if (tpefs_empty(dentry)) { - struct inode *inode = dentry->d_inode; - inode->i_nlink--; - dput(dentry); - error = 0; - } - return error; -} - -#define tpefs_rmdir tpefs_unlink - -static ssize_t default_read_file (struct file *file, char *buf, size_t count, -loff_t *ppos) -{ - return 0; -} +static int secondary; +static spinlock_t tpe_acl_lock; -static ssize_t default_write_file (struct file *file, const char *buf, -size_t count, loff_t *ppos) -{ - return count; -} +static struct subsystem tpefs_subsys; -static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) -{ - loff_t retval = -EINVAL; +struct tpe_list { + char *name; - switch(orig) { - case 0: - if (offset > 0) { - file->f_pos = offset; - retval = file->f_pos; - } - break; - case 1: - if ((offset + file->f_pos) > 0) { - file->f_pos += offset; - retval = file->f_pos; - } - break; - default: - break; - } - return retval; -} - -static int default_open (struct inode *inode, struct file *filp) -{ - if (inode->u.generic_ip) { - filp->private_data = inode->u.generic_ip; - } - return 0; -} - -static struct file_operations default_file_operations = { - read: default_read_file, - write: default_write_file, - open: default_open, - llseek: default_file_lseek, -}; - -static ssize_t trustedlistadd_read_file(struct file *file, char *buf, -size_t count, loff_t *offset); -static ssize_t trustedlistadd_write_file(struct file *file, const char *ubuff, -size_t count, loff_t *offset); - -static struct file_operations trustedlistadd_file_operations = { - read: trustedlistadd_read_file, - write: trustedlistadd_write_file, - open: default_open, - llseek: default_file_lseek, + struct list_head slot_list; + struct kobject kobj; }; - -static ssize_t trustedlistdel_write_file(struct file *file, const char *ubuff, -size_t count, loff_t *offset); - -static struct file_operations trustedlistdel_file_operations = { - read: default_read_file, - write: trustedlistdel_write_file, - open: default_open, - llseek: default_file_lseek, -}; - -static struct inode_operations tpefs_dir_inode_operations = { - create: tpefs_create, - lookup: simple_lookup, - unlink: tpefs_unlink, - mkdir: tpefs_mkdir, - rmdir: tpefs_rmdir, - mknod: tpefs_mknod, -}; - -static struct super_operations tpefs_ops = { - statfs: simple_statfs, - drop_inode: generic_delete_inode, -}; - -static int tpefs_fill_super (struct super_block *sb, void *data, int silent) -{ - struct inode *inode; - struct dentry *root; - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = TPEFS_MAGIC; - sb->s_op = &tpefs_ops; - inode = tpefs_get_inode(sb, S_IFDIR | 0755, 0); - - if (!inode) { - dbg("%s: could not get inode!\n",__FUNCTION__); - return -ENOMEM; - } - - root = d_alloc_root(inode); - if (!root) { - dbg("%s: could not get root dentry!\n",__FUNCTION__); - iput(inode); - return -ENOMEM; - } - sb->s_root = root; - return 0; -} - -static struct super_block *tpefs_get_sb(struct file_system_type *fs_type, -int flags, char *dev_name, void *data) -{ - return get_sb_single(fs_type, flags, data, tpefs_fill_super); -} - -static struct file_system_type tpefs_fs_type = { -.owner = THIS_MODULE, -.name = "tpefs", -.get_sb = tpefs_get_sb, -.kill_sb = kill_litter_super, +struct tpefs_attribute { + struct attribute attr; + ssize_t (*show)(struct tpe_list *, char *); + ssize_t (*store)(struct tpe_list *, const char *, size_t); }; -static int mount_internal (void) -{ - struct vfsmount *mnt; - - printk(KERN_INFO "mount_internal, tpefs_mount_count is %d\n", - tpefs_mount_count); - spin_lock (&tpe_mount_lock); - if (tpefs_mount) { - mntget(tpefs_mount); - ++tpefs_mount_count; - spin_unlock (&tpe_mount_lock); - goto go_ahead; - } - - spin_unlock (&tpe_mount_lock); - mnt = kern_mount (&tpefs_fs_type); - if (IS_ERR(mnt)) { - printk(KERN_INFO "could not mount the fs...erroring out!\n"); - return -ENODEV; - } - spin_lock (&tpe_mount_lock); - if (!tpefs_mount) { - tpefs_mount = mnt; - ++tpefs_mount_count; - spin_unlock (&tpe_mount_lock); - goto go_ahead; - } - - mntget(tpefs_mount); - ++tpefs_mount_count; - spin_unlock (&tpe_mount_lock); - mntput(mnt); - -go_ahead: - printk(KERN_INFO "tpefs_mount_count = %d\n", tpefs_mount_count); - return 0; -} - -static void remove_mount (void) +static ssize_t tpefs_attr_show(struct kobject *kobj, struct attribute *attr, +char *buf) { - struct vfsmount *mnt; - - spin_lock (&tpe_mount_lock); - mnt = tpefs_mount; - --tpefs_mount_count; - if (!tpefs_mount_count) { - tpefs_mount = NULL; - } - - spin_unlock (&tpe_mount_lock); - mntput(mnt); - dbg("tpefs_mount_count = %d\n", tpefs_mount_count); + struct tpe_list *list = container_of(kobj, struct tpe_list, kobj); + struct tpefs_attribute *attribute = container_of(attr, struct + tpefs_attribute, attr); + return attribute->show ? attribute->show(list, buf) : 0; } -static int tpefs_create_by_name (const char *name, mode_t mode, - struct dentry *parent, struct dentry **dentry) +static ssize_t tpefs_attr_store(struct kobject *kobj, struct attribute *attr, +const char *buf, size_t len) { - struct dentry *d = NULL; - struct qstr qstr; - int error; - - if (tpefs_mount && tpefs_mount->mnt_sb) { - parent = tpefs_mount->mnt_sb->s_root; - } - - if (!parent) { - printk(KERN_INFO "Ah! can not find a parent!\n"); - return -EFAULT; - } - - *dentry = NULL; - qstr.name = name; - qstr.len = strlen(name); - qstr.hash = full_name_hash(name,qstr.len); - - parent = dget(parent); - - down(&parent->d_inode->i_sem); - - d = lookup_hash(&qstr,parent); - - error = PTR_ERR(d); - if (!IS_ERR(d)) { - switch(mode & S_IFMT) { - case 0: - case S_IFREG: - error = vfs_create(parent->d_inode,d,mode); - break; - case S_IFDIR: - error = vfs_mkdir(parent->d_inode,d,mode); - break; - default: - printk(KERN_INFO "cannot create special files\n"); - } - *dentry = d; - } - up(&parent->d_inode->i_sem); - - dput(parent); - return error; + struct tpe_list *list = container_of(kobj, struct tpe_list, kobj); + struct tpefs_attribute *attribute = container_of(attr, struct + tpefs_attribute, attr); + return attribute->store ? attribute->store(list, buf, len) : 0; } -static struct dentry *fs_create_file (const char * name, mode_t mode, - struct dentry *parent, void *data, - struct file_operations *fops) -{ - struct dentry *dentry; - int error; - - printk(KERN_INFO "creating file '%s'\n",name); - - error = tpefs_create_by_name(name,mode,parent,&dentry); - if (error) { - dentry = NULL; - } else { - if (dentry->d_inode) { - if (data) { - dentry->d_inode->u.generic_ip = data; - } - if (fops) { - dentry->d_inode->i_fop = fops; - } - } - } - - return dentry; -} +static struct sysfs_ops tpefs_sysfs_ops = { + .show = tpefs_attr_show, + .store = tpefs_attr_store, +}; -static void fs_remove_file (struct dentry *dentry) -{ - struct dentry *parent = dentry->d_parent; +static struct kobj_type tpefs_ktype = { + .sysfs_ops = &tpefs_sysfs_ops +}; - if (!parent || !parent->d_inode) { - return; - } - - down(&parent->d_inode->i_sem); - if (tpefs_positive(dentry)) { - if (dentry->d_inode) { - if (S_ISDIR(dentry->d_inode->i_mode)) { - vfs_rmdir(parent->d_inode,dentry); - } else { - vfs_unlink(parent->d_inode,dentry); - } - } - - dput(dentry); - } - up(&parent->d_inode->i_sem); -} +static decl_subsys(tpefs, &tpefs_ktype, NULL); #if defined(CONFIG_SECURITY_TPE_MODULE) #define MY_NAME THIS_MODULE->name @@ -461,30 +120,16 @@ #define MY_NAME "tpe" #endif -static ssize_t trustedlistadd_read_file (struct file *file, char *buf, -size_t count, loff_t *offset) +static ssize_t trustedlistadd_read_file (struct tpe_list *list, char *buf) { - int retval; int i; - int len; - int pagelen; - unsigned char *page; - char buffer[400]; - - if (*offset < 0) { - return -EINVAL; - } - if (count <= 0) { - return 0; - } - if (*offset != 0) { - return 0; - } + int retval = 0; + char *user = NULL; + char buffer[400]; - page = (unsigned char *)__get_free_page(GFP_KERNEL); - if (!page) { - return -ENOMEM; - } + user = (char *)__get_free_page(GFP_KERNEL); + if (!user) + return -ENOMEM; if (tpe_acl == NULL) { printk(KERN_INFO "empty acl list\n"); @@ -493,102 +138,69 @@ buffer[0] = '\0'; printk(KERN_INFO "%d trusted user(s): \n", tpe_acl_candidates); + spin_lock(&tpe_acl_lock); for (i=0; i < tpe_acl_candidates; i++) { printk(KERN_INFO "%d ", tpe_acl[i]); - len += sprintf(page, "%d\n", tpe_acl[i]); - strcat(buffer, page); + retval = sprintf(user, "%d\n", tpe_acl[i]); + strcat(buffer, user); } printk(KERN_INFO "\n"); + spin_unlock (&tpe_acl_lock); - pagelen = sizeof(buffer); - printk(KERN_INFO "%d buffer size\n", pagelen); - - len = (sizeof(int) * (tpe_acl_candidates - 1)) + sizeof(short); - if (copy_to_user(buf, buffer, len)) { - printk(KERN_INFO "Problem with copy_to_user\n"); - retval = -EFAULT; - goto exit; - } - *offset += len; - retval = len; - -exit: - free_page((unsigned long)page); - return retval; + retval = snprintf(buf, 4096, "%s\n", buffer); + + return retval; } -static ssize_t trustedlistadd_write_file (struct file *file, const char *ubuff, -size_t count, loff_t *offset) +static ssize_t trustedlistadd_write_file (struct tpe_list *list, const char *buf, +size_t count) { - char *buf; - int retval = 0; + int retval; unsigned long add_candidate; - if (*offset < 0) { - return -EINVAL; - } - if (count <= 0) { - return 0; - } - if (*offset != 0) { - return 0; - } - - buf = kmalloc(count + 1, GFP_KERNEL); - if (!buf) { - return -ENOMEM; - } - memset(buf, 0x00, count + 1); - - if (copy_from_user ((void *)buf, (void *)ubuff, count)) { - retval = -EFAULT; - } - add_candidate = simple_strtoul(buf, NULL, 10); - dbg ("add_candidate = %d\n", (int)add_candidate); printk(KERN_INFO "value of add_candidate is %d.\n", (int)add_candidate); + spin_lock(&tpe_acl_lock); retval = tpe_add(add_candidate); - return retval; + if (retval) { + return retval; + } + spin_unlock (&tpe_acl_lock); + return count; } + +struct tpefs_attribute tpefs_listadd_attr = { + .attr = {.name = "add", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .show = trustedlistadd_read_file, + .store = trustedlistadd_write_file +}; -static ssize_t trustedlistdel_write_file (struct file *file, const char *ubuff, -size_t count, loff_t *offset) +static ssize_t trustedlistdel_write_file (struct tpe_list *list, const char *buf, +size_t count) { - char *buf; - int retval = 0; + int retval; unsigned long rem_candidate; - if (*offset < 0) { - return -EINVAL; - } - if (count <= 0) { - return 0; - } - if (*offset != 0) { - return 0; - } - - buf = kmalloc (count + 1, GFP_KERNEL); - if (!buf) { - return -ENOMEM; - } - memset(buf, 0x00, count + 1); - - if (copy_from_user ((void *)buf, (void *)ubuff, count)) { - retval = -EFAULT; - } - rem_candidate = simple_strtoul(buf, NULL, 10); - dbg ("rem_candidate = %d\n", (int)rem_candidate); printk(KERN_INFO "value of rem_candidate is %d.\n", (int)rem_candidate); + spin_lock(&tpe_acl_lock); retval = tpe_remove(rem_candidate); - return retval; + if (retval) { + return retval; + } + spin_unlock (&tpe_acl_lock); + return count; } +struct tpefs_attribute tpefs_listdel_attr = { + .attr = {.name = "del", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .store = trustedlistdel_write_file +}; + /* Module code */ static int tpe_bprm_set_security (struct linux_binprm *bprm) @@ -610,7 +222,7 @@ static int __init tpe_module_init (void) { - int retval, mntret; + int retval; /* register ourselves with the security framework */ if (register_security (&tpe_security_ops)) { printk (KERN_INFO @@ -623,43 +235,19 @@ } secondary = 1; } - /* register tpe filesystem */ - spin_lock_init(&tpe_mount_lock); - spin_lock_init(&tpe_list_lock); + spin_lock_init(&tpe_acl_lock); - printk(KERN_INFO "registering filesystem.\n"); - retval = register_filesystem(&tpefs_fs_type); + /* register tpe subsystem */ + printk(KERN_INFO "registering tpe subsystem.\n"); + retval = subsystem_register(&tpefs_subsys); if (retval) { - printk(KERN_INFO "register_filesystem failed with %d\n", retval); + printk(KERN_INFO "subsystem_register failed with %d\n", retval); return retval; } - /* Routine to get Kernel to mount tpefs internally */ - mntret = mount_internal(); - if (mntret) { - printk(KERN_INFO "failed to get fsmount error %d\n", retval); - } - - /* create a file user can read and write to */ - - trustedlistadd_dentry = fs_create_file("trustedlistadd", - S_IFREG | S_IRUGO | S_IWUSR, - NULL, NULL, - &trustedlistadd_file_operations); - - trustedlistdel_dentry = fs_create_file("trustedlistdel", - S_IFREG | S_IRUGO | S_IWUSR, - NULL, NULL, - &trustedlistdel_file_operations); - tpe_dents = (struct tpe_dents *)kmalloc(sizeof(struct tpe_dents), - GFP_KERNEL); - tpe_dents->d = trustedlistadd_dentry; - tpe_dents->next = (struct tpe_dents *)kmalloc(sizeof(struct tpe_dents), - GFP_KERNEL); - - tpe_dents->next->d = trustedlistdel_dentry; - tpe_dents->next->next = NULL; + sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_attr.attr); + sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_attr.attr); printk(KERN_INFO "tpe LSM initialized\n"); tpe_init(); @@ -676,17 +264,16 @@ "with primary module.\n"); return; } - fs_remove_file(trustedlistdel_dentry); - fs_remove_file(trustedlistadd_dentry); - remove_mount(); - /* unregister tpe filesystem */ - unregister_filesystem(&tpefs_fs_type); + sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_attr.attr); + sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_attr.attr); + subsystem_unregister(&tpefs_subsys); if (unregister_security (&tpe_security_ops)) { printk (KERN_INFO "Failure unregistering tpe module with the kernel\n"); } + printk(KERN_INFO "tpe LSM removed\n"); } diff -Naur linux-2.5.70/security/tpe.h linux-2.5.70-tpe/security/tpe.h --- linux-2.5.70/security/tpe.h 2003-06-10 12:26:16.000000000 -0700 +++ linux-2.5.70-tpe/security/tpe.h 2003-06-10 10:34:59.000000000 -0700 @@ -197,7 +197,7 @@ int i; for (i = 0; i < tpe_acl_candidates; i++) { if (candidate == tpe_acl[i]) { - return ACK; + return i; } } return NACK;