Merge master.kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6

+424 -159
+5
include/linux/security.h
··· 1907 extern int unregister_security (struct security_operations *ops); 1908 extern int mod_reg_security (const char *name, struct security_operations *ops); 1909 extern int mod_unreg_security (const char *name, struct security_operations *ops); 1910 1911 1912 #else /* CONFIG_SECURITY */
··· 1907 extern int unregister_security (struct security_operations *ops); 1908 extern int mod_reg_security (const char *name, struct security_operations *ops); 1909 extern int mod_unreg_security (const char *name, struct security_operations *ops); 1910 + extern struct dentry *securityfs_create_file(const char *name, mode_t mode, 1911 + struct dentry *parent, void *data, 1912 + struct file_operations *fops); 1913 + extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent); 1914 + extern void securityfs_remove(struct dentry *dentry); 1915 1916 1917 #else /* CONFIG_SECURITY */
+1
security/Kconfig
··· 35 36 config SECURITY 37 bool "Enable different security models" 38 help 39 This allows you to choose different security modules to be 40 configured into your kernel.
··· 35 36 config SECURITY 37 bool "Enable different security models" 38 + depends on SYSFS 39 help 40 This allows you to choose different security modules to be 41 configured into your kernel.
+1 -1
security/Makefile
··· 11 endif 12 13 # Object file lists 14 - obj-$(CONFIG_SECURITY) += security.o dummy.o 15 # Must precede capability.o in order to stack properly. 16 obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o 17 obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
··· 11 endif 12 13 # Object file lists 14 + obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o 15 # Must precede capability.o in order to stack properly. 16 obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o 17 obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
+347
security/inode.c
···
··· 1 + /* 2 + * inode.c - securityfs 3 + * 4 + * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de> 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License version 8 + * 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 0x73636673 26 + 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 super 162 + * block. A pointer to that is in the struct vfsmount that we 163 + * 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 + else 181 + error = create(parent->d_inode, *dentry, mode); 182 + } else 183 + 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 filesystem 191 + * 192 + * @name: a pointer to a string containing the name of the file to create. 193 + * @mode: the permission that the file should have 194 + * @parent: a pointer to the parent dentry for this file. This should be a 195 + * directory dentry if set. If this paramater is NULL, then the 196 + * 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 later 198 + * on. The inode.u.generic_ip pointer will point to this value on 199 + * the open() call. 200 + * @fops: a pointer to a struct file_operations that should be used for 201 + * this file. 202 + * 203 + * This is the basic "create a file" function for securityfs. It allows for a 204 + * wide range of flexibility in createing a file, or a directory (if you 205 + * want to create a directory, the securityfs_create_dir() function is 206 + * recommended to be used instead.) 207 + * 208 + * This function will return a pointer to a dentry if it succeeds. This 209 + * pointer must be passed to the securityfs_remove() function when the file is 210 + * 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 be 214 + * returned. It is not wise to check for this value, but rather, check for 215 + * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 216 + * 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 filesystem 253 + * 254 + * @name: a pointer to a string containing the name of the directory to 255 + * create. 256 + * @parent: a pointer to the parent dentry for this file. This should be a 257 + * directory dentry if set. If this paramater is NULL, then the 258 + * 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. This 263 + * pointer must be passed to the securityfs_remove() function when the file is 264 + * 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 be 268 + * returned. It is not wise to check for this value, but rather, check for 269 + * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 270 + * 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 filesystem 282 + * 283 + * @dentry: a pointer to a the dentry of the file or directory to be 284 + * removed. 285 + * 286 + * This function removes a file or directory in securityfs that was previously 287 + * created with a call to another securityfs function (like 288 + * securityfs_create_file() or variants thereof.) 289 + * 290 + * This function is required to be called in order for the file to be 291 + * removed, no automatic cleanup of files will happen when a module is 292 + * 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 + else 311 + 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) 120 121 /** 122 - * kobject stuff 123 - */ 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 another 137 - * 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 being 147 - * written to. attribute->store is a function pointer to whatever the 148 - * struct seclvl_attribute store function pointer points to. It is 149 - * unique for "passwd" and "seclvl". 150 - */ 151 - static ssize_t 152 - 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_t 162 - 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 store 172 - */ 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_ops 180 - }; 181 - 182 - decl_subsys(seclvl, &seclvl_ktype, NULL); 183 - 184 - /** 185 * The actual security level. Ranges between -1 and 2 inclusive. 186 */ 187 static int seclvl; ··· 150 } 151 152 /** 153 - * Called whenever the user reads the sysfs handle to this kernel 154 - * object 155 - */ 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 - } 174 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 } 187 188 - /** 189 - * Called whenever the user writes to the sysfs handle to this kernel 190 - * object (seclvl/seclvl). It expects a single-digit number. 191 - */ 192 - static ssize_t 193 - 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 } 213 214 - /* 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); 218 219 static 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 - } 242 243 /** 244 * Converts a block of plaintext of into its SHA1 hashed value. ··· 231 * object. It hashes the password and compares the hashed results. 232 */ 233 static ssize_t 234 - seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count) 235 { 236 int i; 237 unsigned char tmp[SHA1_DIGEST_SIZE]; 238 int rc; 239 int len; 240 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); 254 /* ``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; 286 } 287 288 - /* 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); 292 293 /** 294 * Explicitely disallow ptrace'ing the init process. ··· 550 } 551 552 /** 553 - * Sysfs registrations 554 */ 555 - static int doSysfsRegistrations(void) 556 { 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); 564 if (*passwd || *sha1_passwd) { 565 - sysfs_create_file(&seclvl_subsys.kset.kobj, 566 - &sysfs_attr_passwd.attr); 567 } 568 return 0; 569 } 570 571 /** ··· 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 */ 638 static 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) 120 121 /** 122 * The actual security level. Ranges between -1 and 2 inclusive. 123 */ 124 static int seclvl; ··· 213 } 214 215 /** 216 * 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 } 243 244 + static u64 seclvl_int_get(void *data) 245 { 246 + return *(int *)data; 247 } 248 249 + DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n"); 250 251 static unsigned char hashedPassword[SHA1_DIGEST_SIZE]; 252 253 /** 254 * Converts a block of plaintext of into its SHA1 hashed value. ··· 347 * object. It hashes the password and compares the hashed results. 348 */ 349 static ssize_t 350 + 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 } 391 392 + static struct file_operations passwd_file_ops = { 393 + .write = passwd_write_file, 394 + }; 395 396 /** 397 * Explicitely disallow ptrace'ing the init process. ··· 647 } 648 649 /** 650 + * securityfs registrations 651 */ 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 } 679 680 /** ··· 677 rc = -EINVAL; 678 goto exit; 679 } 680 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 */ 725 static void __exit seclvl_exit(void) 726 { 727 + securityfs_remove(seclvl_ino); 728 if (*passwd || *sha1_passwd) { 729 + securityfs_remove(passwd_ino); 730 } 731 + securityfs_remove(dir_ino); 732 if (secondary == 1) { 733 mod_unreg_security(MY_NAME, &seclvl_ops); 734 } else if (unregister_security(&seclvl_ops)) {