···3536config SECURITY37 bool "Enable different security models"038 help39 This allows you to choose different security modules to be40 configured into your kernel.
···3536config SECURITY37 bool "Enable different security models"38+ depends on SYSFS39 help40 This allows you to choose different security modules to be41 configured into your kernel.
+1-1
security/Makefile
···11endif1213# Object file lists14-obj-$(CONFIG_SECURITY) += security.o dummy.o15# Must precede capability.o in order to stack properly.16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o17obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
···11endif1213# Object file lists14+obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o15# Must precede capability.o in order to stack properly.16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o17obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
···1+/*2+ * inode.c - securityfs3+ *4+ * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>5+ *6+ * This program is free software; you can redistribute it and/or7+ * modify it under the terms of the GNU General Public License version8+ * 2 as published by the Free Software Foundation.9+ *10+ * Based on fs/debugfs/inode.c which had the following copyright notice:11+ * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>12+ * Copyright (C) 2004 IBM Inc.13+ */14+15+/* #define DEBUG */16+#include <linux/config.h>17+#include <linux/module.h>18+#include <linux/fs.h>19+#include <linux/mount.h>20+#include <linux/pagemap.h>21+#include <linux/init.h>22+#include <linux/namei.h>23+#include <linux/security.h>24+25+#define SECURITYFS_MAGIC 0x7363667326+27+static struct vfsmount *mount;28+static int mount_count;29+30+/*31+ * TODO:32+ * I think I can get rid of these default_file_ops, but not quite sure...33+ */34+static ssize_t default_read_file(struct file *file, char __user *buf,35+ size_t count, loff_t *ppos)36+{37+ return 0;38+}39+40+static ssize_t default_write_file(struct file *file, const char __user *buf,41+ size_t count, loff_t *ppos)42+{43+ return count;44+}45+46+static int default_open(struct inode *inode, struct file *file)47+{48+ if (inode->u.generic_ip)49+ file->private_data = inode->u.generic_ip;50+51+ return 0;52+}53+54+static struct file_operations default_file_ops = {55+ .read = default_read_file,56+ .write = default_write_file,57+ .open = default_open,58+};59+60+static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)61+{62+ struct inode *inode = new_inode(sb);63+64+ if (inode) {65+ inode->i_mode = mode;66+ inode->i_uid = 0;67+ inode->i_gid = 0;68+ inode->i_blksize = PAGE_CACHE_SIZE;69+ inode->i_blocks = 0;70+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;71+ switch (mode & S_IFMT) {72+ default:73+ init_special_inode(inode, mode, dev);74+ break;75+ case S_IFREG:76+ inode->i_fop = &default_file_ops;77+ break;78+ case S_IFDIR:79+ inode->i_op = &simple_dir_inode_operations;80+ inode->i_fop = &simple_dir_operations;81+82+ /* directory inodes start off with i_nlink == 2 (for "." entry) */83+ inode->i_nlink++;84+ break;85+ }86+ }87+ return inode;88+}89+90+/* SMP-safe */91+static int mknod(struct inode *dir, struct dentry *dentry,92+ int mode, dev_t dev)93+{94+ struct inode *inode;95+ int error = -EPERM;96+97+ if (dentry->d_inode)98+ return -EEXIST;99+100+ inode = get_inode(dir->i_sb, mode, dev);101+ if (inode) {102+ d_instantiate(dentry, inode);103+ dget(dentry);104+ error = 0;105+ }106+ return error;107+}108+109+static int mkdir(struct inode *dir, struct dentry *dentry, int mode)110+{111+ int res;112+113+ mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;114+ res = mknod(dir, dentry, mode, 0);115+ if (!res)116+ dir->i_nlink++;117+ return res;118+}119+120+static int create(struct inode *dir, struct dentry *dentry, int mode)121+{122+ mode = (mode & S_IALLUGO) | S_IFREG;123+ return mknod(dir, dentry, mode, 0);124+}125+126+static inline int positive(struct dentry *dentry)127+{128+ return dentry->d_inode && !d_unhashed(dentry);129+}130+131+static int fill_super(struct super_block *sb, void *data, int silent)132+{133+ static struct tree_descr files[] = {{""}};134+135+ return simple_fill_super(sb, SECURITYFS_MAGIC, files);136+}137+138+static struct super_block *get_sb(struct file_system_type *fs_type,139+ int flags, const char *dev_name,140+ void *data)141+{142+ return get_sb_single(fs_type, flags, data, fill_super);143+}144+145+static struct file_system_type fs_type = {146+ .owner = THIS_MODULE,147+ .name = "securityfs",148+ .get_sb = get_sb,149+ .kill_sb = kill_litter_super,150+};151+152+static int create_by_name(const char *name, mode_t mode,153+ struct dentry *parent,154+ struct dentry **dentry)155+{156+ int error = 0;157+158+ *dentry = NULL;159+160+ /* If the parent is not specified, we create it in the root.161+ * We need the root dentry to do this, which is in the super162+ * block. A pointer to that is in the struct vfsmount that we163+ * have around.164+ */165+ if (!parent ) {166+ if (mount && mount->mnt_sb) {167+ parent = mount->mnt_sb->s_root;168+ }169+ }170+ if (!parent) {171+ pr_debug("securityfs: Ah! can not find a parent!\n");172+ return -EFAULT;173+ }174+175+ down(&parent->d_inode->i_sem);176+ *dentry = lookup_one_len(name, parent, strlen(name));177+ if (!IS_ERR(dentry)) {178+ if ((mode & S_IFMT) == S_IFDIR)179+ error = mkdir(parent->d_inode, *dentry, mode);180+ else181+ error = create(parent->d_inode, *dentry, mode);182+ } else183+ error = PTR_ERR(dentry);184+ up(&parent->d_inode->i_sem);185+186+ return error;187+}188+189+/**190+ * securityfs_create_file - create a file in the securityfs filesystem191+ *192+ * @name: a pointer to a string containing the name of the file to create.193+ * @mode: the permission that the file should have194+ * @parent: a pointer to the parent dentry for this file. This should be a195+ * directory dentry if set. If this paramater is NULL, then the196+ * file will be created in the root of the securityfs filesystem.197+ * @data: a pointer to something that the caller will want to get to later198+ * on. The inode.u.generic_ip pointer will point to this value on199+ * the open() call.200+ * @fops: a pointer to a struct file_operations that should be used for201+ * this file.202+ *203+ * This is the basic "create a file" function for securityfs. It allows for a204+ * wide range of flexibility in createing a file, or a directory (if you205+ * want to create a directory, the securityfs_create_dir() function is206+ * recommended to be used instead.)207+ *208+ * This function will return a pointer to a dentry if it succeeds. This209+ * pointer must be passed to the securityfs_remove() function when the file is210+ * to be removed (no automatic cleanup happens if your module is unloaded,211+ * you are responsible here.) If an error occurs, NULL will be returned.212+ *213+ * If securityfs is not enabled in the kernel, the value -ENODEV will be214+ * returned. It is not wise to check for this value, but rather, check for215+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling216+ * code.217+ */218+struct dentry *securityfs_create_file(const char *name, mode_t mode,219+ struct dentry *parent, void *data,220+ struct file_operations *fops)221+{222+ struct dentry *dentry = NULL;223+ int error;224+225+ pr_debug("securityfs: creating file '%s'\n",name);226+227+ error = simple_pin_fs("securityfs", &mount, &mount_count);228+ if (error) {229+ dentry = ERR_PTR(error);230+ goto exit;231+ }232+233+ error = create_by_name(name, mode, parent, &dentry);234+ if (error) {235+ dentry = ERR_PTR(error);236+ simple_release_fs(&mount, &mount_count);237+ goto exit;238+ }239+240+ if (dentry->d_inode) {241+ if (fops)242+ dentry->d_inode->i_fop = fops;243+ if (data)244+ dentry->d_inode->u.generic_ip = data;245+ }246+exit:247+ return dentry;248+}249+EXPORT_SYMBOL_GPL(securityfs_create_file);250+251+/**252+ * securityfs_create_dir - create a directory in the securityfs filesystem253+ *254+ * @name: a pointer to a string containing the name of the directory to255+ * create.256+ * @parent: a pointer to the parent dentry for this file. This should be a257+ * directory dentry if set. If this paramater is NULL, then the258+ * directory will be created in the root of the securityfs filesystem.259+ *260+ * This function creates a directory in securityfs with the given name.261+ *262+ * This function will return a pointer to a dentry if it succeeds. This263+ * pointer must be passed to the securityfs_remove() function when the file is264+ * to be removed (no automatic cleanup happens if your module is unloaded,265+ * you are responsible here.) If an error occurs, NULL will be returned.266+ *267+ * If securityfs is not enabled in the kernel, the value -ENODEV will be268+ * returned. It is not wise to check for this value, but rather, check for269+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling270+ * code.271+ */272+struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)273+{274+ return securityfs_create_file(name,275+ S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,276+ parent, NULL, NULL);277+}278+EXPORT_SYMBOL_GPL(securityfs_create_dir);279+280+/**281+ * securityfs_remove - removes a file or directory from the securityfs filesystem282+ *283+ * @dentry: a pointer to a the dentry of the file or directory to be284+ * removed.285+ *286+ * This function removes a file or directory in securityfs that was previously287+ * created with a call to another securityfs function (like288+ * securityfs_create_file() or variants thereof.)289+ *290+ * This function is required to be called in order for the file to be291+ * removed, no automatic cleanup of files will happen when a module is292+ * removed, you are responsible here.293+ */294+void securityfs_remove(struct dentry *dentry)295+{296+ struct dentry *parent;297+298+ if (!dentry)299+ return;300+301+ parent = dentry->d_parent;302+ if (!parent || !parent->d_inode)303+ return;304+305+ down(&parent->d_inode->i_sem);306+ if (positive(dentry)) {307+ if (dentry->d_inode) {308+ if (S_ISDIR(dentry->d_inode->i_mode))309+ simple_rmdir(parent->d_inode, dentry);310+ else311+ simple_unlink(parent->d_inode, dentry);312+ dput(dentry);313+ }314+ }315+ up(&parent->d_inode->i_sem);316+ simple_release_fs(&mount, &mount_count);317+}318+EXPORT_SYMBOL_GPL(securityfs_remove);319+320+static decl_subsys(security, NULL, NULL);321+322+static int __init securityfs_init(void)323+{324+ int retval;325+326+ kset_set_kset_s(&security_subsys, kernel_subsys);327+ retval = subsystem_register(&security_subsys);328+ if (retval)329+ return retval;330+331+ retval = register_filesystem(&fs_type);332+ if (retval)333+ subsystem_unregister(&security_subsys);334+ return retval;335+}336+337+static void __exit securityfs_exit(void)338+{339+ simple_release_fs(&mount, &mount_count);340+ unregister_filesystem(&fs_type);341+ subsystem_unregister(&security_subsys);342+}343+344+core_initcall(securityfs_init);345+module_exit(securityfs_exit);346+MODULE_LICENSE("GPL");347+
+70-158
security/seclvl.c
···119 } while (0)120121/**122- * kobject stuff123- */124-125-struct subsystem seclvl_subsys;126-127-struct seclvl_obj {128- char *name;129- struct list_head slot_list;130- struct kobject kobj;131-};132-133-/**134- * There is a seclvl_attribute struct for each file in sysfs.135- *136- * In our case, we have one of these structs for "passwd" and another137- * for "seclvl".138- */139-struct seclvl_attribute {140- struct attribute attr;141- ssize_t(*show) (struct seclvl_obj *, char *);142- ssize_t(*store) (struct seclvl_obj *, const char *, size_t);143-};144-145-/**146- * When this function is called, one of the files in sysfs is being147- * written to. attribute->store is a function pointer to whatever the148- * struct seclvl_attribute store function pointer points to. It is149- * unique for "passwd" and "seclvl".150- */151-static ssize_t152-seclvl_attr_store(struct kobject *kobj,153- struct attribute *attr, const char *buf, size_t len)154-{155- struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);156- struct seclvl_attribute *attribute =157- container_of(attr, struct seclvl_attribute, attr);158- return attribute->store ? attribute->store(obj, buf, len) : -EIO;159-}160-161-static ssize_t162-seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)163-{164- struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);165- struct seclvl_attribute *attribute =166- container_of(attr, struct seclvl_attribute, attr);167- return attribute->show ? attribute->show(obj, buf) : -EIO;168-}169-170-/**171- * Callback function pointers for show and store172- */173-static struct sysfs_ops seclvlfs_sysfs_ops = {174- .show = seclvl_attr_show,175- .store = seclvl_attr_store,176-};177-178-static struct kobj_type seclvl_ktype = {179- .sysfs_ops = &seclvlfs_sysfs_ops180-};181-182-decl_subsys(seclvl, &seclvl_ktype, NULL);183-184-/**185 * The actual security level. Ranges between -1 and 2 inclusive.186 */187static int seclvl;···150}151152/**153- * Called whenever the user reads the sysfs handle to this kernel154- * object155- */156-static ssize_t seclvl_read_file(struct seclvl_obj *obj, char *buff)157-{158- return snprintf(buff, PAGE_SIZE, "%d\n", seclvl);159-}160-161-/**162 * security level advancement rules:163 * Valid levels are -1 through 2, inclusive.164 * From -1, stuck. [ in case compiled into kernel ]165 * From 0 or above, can only increment.166 */167-static int do_seclvl_advance(int newlvl)168{169- if (newlvl <= seclvl) {170- seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "171- "[%d]\n", newlvl);172- return -EINVAL;173- }00174 if (newlvl > 2) {175 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "176 "[%d]\n", newlvl);177- return -EINVAL;178 }179 if (seclvl == -1) {180 seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "181 "seclvl [%d]\n", seclvl);182- return -EPERM;183 }184- seclvl = newlvl;185- return 0;186}187188-/**189- * Called whenever the user writes to the sysfs handle to this kernel190- * object (seclvl/seclvl). It expects a single-digit number.191- */192-static ssize_t193-seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count)194{195- unsigned long val;196- if (count > 2 || (count == 2 && buff[1] != '\n')) {197- seclvl_printk(1, KERN_WARNING, "Invalid value passed to "198- "seclvl: [%s]\n", buff);199- return -EINVAL;200- }201- val = buff[0] - 48;202- if (seclvl_sanity(val)) {203- seclvl_printk(1, KERN_WARNING, "Illegal secure level "204- "requested: [%d]\n", (int)val);205- return -EPERM;206- }207- if (do_seclvl_advance(val)) {208- seclvl_printk(0, KERN_ERR, "Failure advancing security level "209- "to %lu\n", val);210- }211- return count;212}213214-/* Generate sysfs_attr_seclvl */215-static struct seclvl_attribute sysfs_attr_seclvl =216-__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file,217- seclvl_write_file);218219static unsigned char hashedPassword[SHA1_DIGEST_SIZE];220-221-/**222- * Called whenever the user reads the sysfs passwd handle.223- */224-static ssize_t seclvl_read_passwd(struct seclvl_obj *obj, char *buff)225-{226- /* So just how good *is* your password? :-) */227- char tmp[3];228- int i = 0;229- buff[0] = '\0';230- if (hideHash) {231- /* Security through obscurity */232- return 0;233- }234- while (i < SHA1_DIGEST_SIZE) {235- snprintf(tmp, 3, "%02x", hashedPassword[i]);236- strncat(buff, tmp, 2);237- i++;238- }239- strcat(buff, "\n");240- return ((SHA1_DIGEST_SIZE * 2) + 1);241-}242243/**244 * Converts a block of plaintext of into its SHA1 hashed value.···231 * object. It hashes the password and compares the hashed results.232 */233static ssize_t234-seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)0235{236 int i;237 unsigned char tmp[SHA1_DIGEST_SIZE];0238 int rc;239 int len;0240 if (!*passwd && !*sha1_passwd) {241 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "242 "seclvl module, but neither a plain text "···250 "maintainer about this event.\n");251 return -EINVAL;252 }253- len = strlen(buff);0000000000000254 /* ``echo "secret" > seclvl/passwd'' includes a newline */255- if (buff[len - 1] == '\n') {256 len--;257 }258 /* Hash the password, then compare the hashed values */259- if ((rc = plaintext_to_sha1(tmp, buff, len))) {260 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "261 "[%d]\n", rc);262 return rc;···282 seclvl_printk(0, KERN_INFO,283 "Password accepted; seclvl reduced to 0.\n");284 seclvl = 0;285- return count;0000286}287288-/* Generate sysfs_attr_passwd */289-static struct seclvl_attribute sysfs_attr_passwd =290-__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd,291- seclvl_write_passwd);292293/**294 * Explicitely disallow ptrace'ing the init process.···550}551552/**553- * Sysfs registrations554 */555-static int doSysfsRegistrations(void)00556{557- int rc = 0;558- if ((rc = subsystem_register(&seclvl_subsys))) {559- seclvl_printk(0, KERN_WARNING,560- "Error [%d] registering seclvl subsystem\n", rc);561- return rc;562- }563- sysfs_create_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);0564 if (*passwd || *sha1_passwd) {565- sysfs_create_file(&seclvl_subsys.kset.kobj,566- &sysfs_attr_passwd.attr);00567 }568 return 0;0000000569}570571/**···592 rc = -EINVAL;593 goto exit;594 }595- sysfs_attr_seclvl.attr.owner = THIS_MODULE;596- sysfs_attr_passwd.attr.owner = THIS_MODULE;597 if (initlvl < -1 || initlvl > 2) {598 seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "599 "[%d].\n", initlvl);···619 } /* if primary module registered */620 secondary = 1;621 } /* if we registered ourselves with the security framework */622- if ((rc = doSysfsRegistrations())) {623 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");624 goto exit;625 }···637 */638static void __exit seclvl_exit(void)639{640- sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);641 if (*passwd || *sha1_passwd) {642- sysfs_remove_file(&seclvl_subsys.kset.kobj,643- &sysfs_attr_passwd.attr);644 }645- subsystem_unregister(&seclvl_subsys);646 if (secondary == 1) {647 mod_unreg_security(MY_NAME, &seclvl_ops);648 } else if (unregister_security(&seclvl_ops)) {
···119 } while (0)120121/**000000000000000000000000000000000000000000000000000000000000000122 * The actual security level. Ranges between -1 and 2 inclusive.123 */124static int seclvl;···213}214215/**000000000216 * security level advancement rules:217 * Valid levels are -1 through 2, inclusive.218 * From -1, stuck. [ in case compiled into kernel ]219 * From 0 or above, can only increment.220 */221+static void do_seclvl_advance(void *data, u64 val)222{223+ int ret;224+ int newlvl = (int)val;225+226+ ret = seclvl_sanity(newlvl);227+ if (ret)228+ return;229+230 if (newlvl > 2) {231 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "232 "[%d]\n", newlvl);233+ return;234 }235 if (seclvl == -1) {236 seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "237 "seclvl [%d]\n", seclvl);238+ return;239 }240+ seclvl = newlvl; /* would it be more "correct" to set *data? */241+ return;242}243244+static u64 seclvl_int_get(void *data)00000245{246+ return *(int *)data;0000000000000000247}248249+DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n");000250251static unsigned char hashedPassword[SHA1_DIGEST_SIZE];0000000000000000000000252253/**254 * Converts a block of plaintext of into its SHA1 hashed value.···347 * object. It hashes the password and compares the hashed results.348 */349static ssize_t350+passwd_write_file(struct file * file, const char __user * buf,351+ size_t count, loff_t *ppos)352{353 int i;354 unsigned char tmp[SHA1_DIGEST_SIZE];355+ char *page;356 int rc;357 int len;358+359 if (!*passwd && !*sha1_passwd) {360 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "361 "seclvl module, but neither a plain text "···363 "maintainer about this event.\n");364 return -EINVAL;365 }366+367+ if (count < 0 || count >= PAGE_SIZE)368+ return -ENOMEM;369+ if (*ppos != 0) {370+ return -EINVAL;371+ }372+ page = (char *)get_zeroed_page(GFP_KERNEL);373+ if (!page)374+ return -ENOMEM;375+ len = -EFAULT;376+ if (copy_from_user(page, buf, count))377+ goto out;378+379+ len = strlen(page);380 /* ``echo "secret" > seclvl/passwd'' includes a newline */381+ if (page[len - 1] == '\n') {382 len--;383 }384 /* Hash the password, then compare the hashed values */385+ if ((rc = plaintext_to_sha1(tmp, page, len))) {386 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "387 "[%d]\n", rc);388 return rc;···382 seclvl_printk(0, KERN_INFO,383 "Password accepted; seclvl reduced to 0.\n");384 seclvl = 0;385+ len = count;386+387+out:388+ free_page((unsigned long)page);389+ return len;390}391392+static struct file_operations passwd_file_ops = {393+ .write = passwd_write_file,394+};0395396/**397 * Explicitely disallow ptrace'ing the init process.···647}648649/**650+ * securityfs registrations651 */652+struct dentry *dir_ino, *seclvl_ino, *passwd_ino;653+654+static int seclvlfs_register(void)655{656+ dir_ino = securityfs_create_dir("seclvl", NULL);657+ if (!dir_ino)658+ return -EFAULT;659+660+ seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,661+ dir_ino, &seclvl, &seclvl_file_ops);662+ if (!seclvl_ino)663+ goto out_deldir;664 if (*passwd || *sha1_passwd) {665+ passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,666+ dir_ino, NULL, &passwd_file_ops);667+ if (!passwd_ino)668+ goto out_delf;669 }670 return 0;671+672+out_deldir:673+ securityfs_remove(dir_ino);674+out_delf:675+ securityfs_remove(seclvl_ino);676+677+ return -EFAULT;678}679680/**···677 rc = -EINVAL;678 goto exit;679 }00680 if (initlvl < -1 || initlvl > 2) {681 seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "682 "[%d].\n", initlvl);···706 } /* if primary module registered */707 secondary = 1;708 } /* if we registered ourselves with the security framework */709+ if ((rc = seclvlfs_register())) {710 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");711 goto exit;712 }···724 */725static void __exit seclvl_exit(void)726{727+ securityfs_remove(seclvl_ino);728 if (*passwd || *sha1_passwd) {729+ securityfs_remove(passwd_ino);0730 }731+ securityfs_remove(dir_ino);732 if (secondary == 1) {733 mod_unreg_security(MY_NAME, &seclvl_ops);734 } else if (unregister_security(&seclvl_ops)) {