Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12-rc6 747 lines 20 kB view raw
1/** 2 * BSD Secure Levels LSM 3 * 4 * Maintainers: 5 * Michael A. Halcrow <mike@halcrow.us> 6 * Serge Hallyn <hallyn@cs.wm.edu> 7 * 8 * Copyright (c) 2001 WireX Communications, Inc <chris@wirex.com> 9 * Copyright (c) 2001 Greg Kroah-Hartman <greg@kroah.com> 10 * Copyright (c) 2002 International Business Machines <robb@austin.ibm.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 */ 17 18#include <linux/config.h> 19#include <linux/module.h> 20#include <linux/moduleparam.h> 21#include <linux/kernel.h> 22#include <linux/init.h> 23#include <linux/security.h> 24#include <linux/netlink.h> 25#include <linux/fs.h> 26#include <linux/namei.h> 27#include <linux/mount.h> 28#include <linux/capability.h> 29#include <linux/time.h> 30#include <linux/proc_fs.h> 31#include <linux/kobject.h> 32#include <linux/crypto.h> 33#include <asm/scatterlist.h> 34#include <linux/gfp.h> 35#include <linux/sysfs.h> 36 37#define SHA1_DIGEST_SIZE 20 38 39/** 40 * Module parameter that defines the initial secure level. 41 * 42 * When built as a module, it defaults to seclvl 1, which is the 43 * behavior of BSD secure levels. Note that this default behavior 44 * wrecks havoc on a machine when the seclvl module is compiled into 45 * the kernel. In that case, we default to seclvl 0. 46 */ 47#ifdef CONFIG_SECURITY_SECLVL_MODULE 48static int initlvl = 1; 49#else 50static int initlvl; 51#endif 52module_param(initlvl, int, 0); 53MODULE_PARM_DESC(initlvl, "Initial secure level (defaults to 1)"); 54 55/* Module parameter that defines the verbosity level */ 56static int verbosity; 57module_param(verbosity, int, 0); 58MODULE_PARM_DESC(verbosity, "Initial verbosity level (0 or 1; defaults to " 59 "0, which is Quiet)"); 60 61/** 62 * Optional password which can be passed in to bring seclvl to 0 63 * (i.e., for halt/reboot). Defaults to NULL (the passwd attribute 64 * file will not be registered in sysfs). 65 * 66 * This gets converted to its SHA1 hash when stored. It's probably 67 * not a good idea to use this parameter when loading seclvl from a 68 * script; use sha1_passwd instead. 69 */ 70 71#define MAX_PASSWD_SIZE 32 72static char passwd[MAX_PASSWD_SIZE]; 73module_param_string(passwd, passwd, sizeof(passwd), 0); 74MODULE_PARM_DESC(passwd, 75 "Plaintext of password that sets seclvl=0 when written to " 76 "(sysfs mount point)/seclvl/passwd\n"); 77 78/** 79 * SHA1 hashed version of the optional password which can be passed in 80 * to bring seclvl to 0 (i.e., for halt/reboot). Must be in 81 * hexadecimal format (40 characters). Defaults to NULL (the passwd 82 * attribute file will not be registered in sysfs). 83 * 84 * Use the sha1sum utility to generate the SHA1 hash of a password: 85 * 86 * echo -n "secret" | sha1sum 87 */ 88#define MAX_SHA1_PASSWD 41 89static char sha1_passwd[MAX_SHA1_PASSWD]; 90module_param_string(sha1_passwd, sha1_passwd, sizeof(sha1_passwd), 0); 91MODULE_PARM_DESC(sha1_passwd, 92 "SHA1 hash (40 hexadecimal characters) of password that " 93 "sets seclvl=0 when plaintext password is written to " 94 "(sysfs mount point)/seclvl/passwd\n"); 95 96static int hideHash = 1; 97module_param(hideHash, int, 0); 98MODULE_PARM_DESC(hideHash, "When set to 0, reading seclvl/passwd from sysfs " 99 "will return the SHA1-hashed value of the password that " 100 "lowers the secure level to 0.\n"); 101 102#define MY_NAME "seclvl" 103 104/** 105 * This time-limits log writes to one per second. 106 */ 107#define seclvl_printk(verb, type, fmt, arg...) \ 108 do { \ 109 if (verbosity >= verb) { \ 110 static unsigned long _prior; \ 111 unsigned long _now = jiffies; \ 112 if ((_now - _prior) > HZ) { \ 113 printk(type "%s: %s: " fmt, \ 114 MY_NAME, __FUNCTION__ , \ 115 ## arg); \ 116 _prior = _now; \ 117 } \ 118 } \ 119 } while (0) 120 121/** 122 * kobject stuff 123 */ 124 125struct subsystem seclvl_subsys; 126 127struct 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 */ 139struct 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 */ 151static ssize_t 152seclvl_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) : 0); 159} 160 161static ssize_t 162seclvl_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) : 0); 168} 169 170/** 171 * Callback function pointers for show and store 172 */ 173static struct sysfs_ops seclvlfs_sysfs_ops = { 174 .show = seclvl_attr_show, 175 .store = seclvl_attr_store, 176}; 177 178static struct kobj_type seclvl_ktype = { 179 .sysfs_ops = &seclvlfs_sysfs_ops 180}; 181 182decl_subsys(seclvl, &seclvl_ktype, NULL); 183 184/** 185 * The actual security level. Ranges between -1 and 2 inclusive. 186 */ 187static int seclvl; 188 189/** 190 * flag to keep track of how we were registered 191 */ 192static int secondary; 193 194/** 195 * Verifies that the requested secure level is valid, given the current 196 * secure level. 197 */ 198static int seclvl_sanity(int reqlvl) 199{ 200 if ((reqlvl < -1) || (reqlvl > 2)) { 201 seclvl_printk(1, KERN_WARNING, "Attempt to set seclvl out of " 202 "range: [%d]\n", reqlvl); 203 return -EINVAL; 204 } 205 if ((seclvl == 0) && (reqlvl == -1)) 206 return 0; 207 if (reqlvl < seclvl) { 208 seclvl_printk(1, KERN_WARNING, "Attempt to lower seclvl to " 209 "[%d]\n", reqlvl); 210 return -EPERM; 211 } 212 return 0; 213} 214 215/** 216 * Called whenever the user reads the sysfs handle to this kernel 217 * object 218 */ 219static ssize_t seclvl_read_file(struct seclvl_obj *obj, char *buff) 220{ 221 return snprintf(buff, PAGE_SIZE, "%d\n", seclvl); 222} 223 224/** 225 * security level advancement rules: 226 * Valid levels are -1 through 2, inclusive. 227 * From -1, stuck. [ in case compiled into kernel ] 228 * From 0 or above, can only increment. 229 */ 230static int do_seclvl_advance(int newlvl) 231{ 232 if (newlvl <= seclvl) { 233 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl " 234 "[%d]\n", newlvl); 235 return -EINVAL; 236 } 237 if (newlvl > 2) { 238 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl " 239 "[%d]\n", newlvl); 240 return -EINVAL; 241 } 242 if (seclvl == -1) { 243 seclvl_printk(1, KERN_WARNING, "Not allowed to advance to " 244 "seclvl [%d]\n", seclvl); 245 return -EPERM; 246 } 247 seclvl = newlvl; 248 return 0; 249} 250 251/** 252 * Called whenever the user writes to the sysfs handle to this kernel 253 * object (seclvl/seclvl). It expects a single-digit number. 254 */ 255static ssize_t 256seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count) 257{ 258 unsigned long val; 259 if (count > 2 || (count == 2 && buff[1] != '\n')) { 260 seclvl_printk(1, KERN_WARNING, "Invalid value passed to " 261 "seclvl: [%s]\n", buff); 262 return -EINVAL; 263 } 264 val = buff[0] - 48; 265 if (seclvl_sanity(val)) { 266 seclvl_printk(1, KERN_WARNING, "Illegal secure level " 267 "requested: [%d]\n", (int)val); 268 return -EPERM; 269 } 270 if (do_seclvl_advance(val)) { 271 seclvl_printk(0, KERN_ERR, "Failure advancing security level " 272 "to %lu\n", val); 273 } 274 return count; 275} 276 277/* Generate sysfs_attr_seclvl */ 278static struct seclvl_attribute sysfs_attr_seclvl = 279__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file, 280 seclvl_write_file); 281 282static unsigned char hashedPassword[SHA1_DIGEST_SIZE]; 283 284/** 285 * Called whenever the user reads the sysfs passwd handle. 286 */ 287static ssize_t seclvl_read_passwd(struct seclvl_obj *obj, char *buff) 288{ 289 /* So just how good *is* your password? :-) */ 290 char tmp[3]; 291 int i = 0; 292 buff[0] = '\0'; 293 if (hideHash) { 294 /* Security through obscurity */ 295 return 0; 296 } 297 while (i < SHA1_DIGEST_SIZE) { 298 snprintf(tmp, 3, "%02x", hashedPassword[i]); 299 strncat(buff, tmp, 2); 300 i++; 301 } 302 strcat(buff, "\n"); 303 return ((SHA1_DIGEST_SIZE * 2) + 1); 304} 305 306/** 307 * Converts a block of plaintext of into its SHA1 hashed value. 308 * 309 * It would be nice if crypto had a wrapper to do this for us linear 310 * people... 311 */ 312static int 313plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len) 314{ 315 char *pgVirtAddr; 316 struct crypto_tfm *tfm; 317 struct scatterlist sg[1]; 318 if (len > PAGE_SIZE) { 319 seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d " 320 "characters). Largest possible is %lu " 321 "bytes.\n", len, PAGE_SIZE); 322 return -ENOMEM; 323 } 324 tfm = crypto_alloc_tfm("sha1", 0); 325 if (tfm == NULL) { 326 seclvl_printk(0, KERN_ERR, 327 "Failed to load transform for SHA1\n"); 328 return -ENOSYS; 329 } 330 // Just get a new page; don't play around with page boundaries 331 // and scatterlists. 332 pgVirtAddr = (char *)__get_free_page(GFP_KERNEL); 333 sg[0].page = virt_to_page(pgVirtAddr); 334 sg[0].offset = 0; 335 sg[0].length = len; 336 strncpy(pgVirtAddr, plaintext, len); 337 crypto_digest_init(tfm); 338 crypto_digest_update(tfm, sg, 1); 339 crypto_digest_final(tfm, hash); 340 crypto_free_tfm(tfm); 341 free_page((unsigned long)pgVirtAddr); 342 return 0; 343} 344 345/** 346 * Called whenever the user writes to the sysfs passwd handle to this kernel 347 * object. It hashes the password and compares the hashed results. 348 */ 349static ssize_t 350seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count) 351{ 352 int i; 353 unsigned char tmp[SHA1_DIGEST_SIZE]; 354 int rc; 355 int len; 356 if (!*passwd && !*sha1_passwd) { 357 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the " 358 "seclvl module, but neither a plain text " 359 "password nor a SHA1 hashed password was " 360 "passed in as a module parameter! This is a " 361 "bug, since it should not be possible to be in " 362 "this part of the module; please tell a " 363 "maintainer about this event.\n"); 364 return -EINVAL; 365 } 366 len = strlen(buff); 367 /* ``echo "secret" > seclvl/passwd'' includes a newline */ 368 if (buff[len - 1] == '\n') { 369 len--; 370 } 371 /* Hash the password, then compare the hashed values */ 372 if ((rc = plaintext_to_sha1(tmp, buff, len))) { 373 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " 374 "[%d]\n", rc); 375 return rc; 376 } 377 for (i = 0; i < SHA1_DIGEST_SIZE; i++) { 378 if (hashedPassword[i] != tmp[i]) { 379 return -EPERM; 380 } 381 } 382 seclvl_printk(0, KERN_INFO, 383 "Password accepted; seclvl reduced to 0.\n"); 384 seclvl = 0; 385 return count; 386} 387 388/* Generate sysfs_attr_passwd */ 389static struct seclvl_attribute sysfs_attr_passwd = 390__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd, 391 seclvl_write_passwd); 392 393/** 394 * Explicitely disallow ptrace'ing the init process. 395 */ 396static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child) 397{ 398 if (seclvl >= 0) { 399 if (child->pid == 1) { 400 seclvl_printk(1, KERN_WARNING, "Attempt to ptrace " 401 "the init process dissallowed in " 402 "secure level %d\n", seclvl); 403 return -EPERM; 404 } 405 } 406 return 0; 407} 408 409/** 410 * Capability checks for seclvl. The majority of the policy 411 * enforcement for seclvl takes place here. 412 */ 413static int seclvl_capable(struct task_struct *tsk, int cap) 414{ 415 /* init can do anything it wants */ 416 if (tsk->pid == 1) 417 return 0; 418 419 switch (seclvl) { 420 case 2: 421 /* fall through */ 422 case 1: 423 if (cap == CAP_LINUX_IMMUTABLE) { 424 seclvl_printk(1, KERN_WARNING, "Attempt to modify " 425 "the IMMUTABLE and/or APPEND extended " 426 "attribute on a file with the IMMUTABLE " 427 "and/or APPEND extended attribute set " 428 "denied in seclvl [%d]\n", seclvl); 429 return -EPERM; 430 } else if (cap == CAP_SYS_RAWIO) { // Somewhat broad... 431 seclvl_printk(1, KERN_WARNING, "Attempt to perform " 432 "raw I/O while in secure level [%d] " 433 "denied\n", seclvl); 434 return -EPERM; 435 } else if (cap == CAP_NET_ADMIN) { 436 seclvl_printk(1, KERN_WARNING, "Attempt to perform " 437 "network administrative task while " 438 "in secure level [%d] denied\n", seclvl); 439 return -EPERM; 440 } else if (cap == CAP_SETUID) { 441 seclvl_printk(1, KERN_WARNING, "Attempt to setuid " 442 "while in secure level [%d] denied\n", 443 seclvl); 444 return -EPERM; 445 } else if (cap == CAP_SETGID) { 446 seclvl_printk(1, KERN_WARNING, "Attempt to setgid " 447 "while in secure level [%d] denied\n", 448 seclvl); 449 } else if (cap == CAP_SYS_MODULE) { 450 seclvl_printk(1, KERN_WARNING, "Attempt to perform " 451 "a module operation while in secure " 452 "level [%d] denied\n", seclvl); 453 return -EPERM; 454 } 455 break; 456 default: 457 break; 458 } 459 /* from dummy.c */ 460 if (cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0) 461 return 0; /* capability granted */ 462 seclvl_printk(1, KERN_WARNING, "Capability denied\n"); 463 return -EPERM; /* capability denied */ 464} 465 466/** 467 * Disallow reversing the clock in seclvl > 1 468 */ 469static int seclvl_settime(struct timespec *tv, struct timezone *tz) 470{ 471 struct timespec now; 472 if (seclvl > 1) { 473 now = current_kernel_time(); 474 if (tv->tv_sec < now.tv_sec || 475 (tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) { 476 seclvl_printk(1, KERN_WARNING, "Attempt to decrement " 477 "time in secure level %d denied: " 478 "current->pid = [%d], " 479 "current->group_leader->pid = [%d]\n", 480 seclvl, current->pid, 481 current->group_leader->pid); 482 return -EPERM; 483 } /* if attempt to decrement time */ 484 } /* if seclvl > 1 */ 485 return 0; 486} 487 488/* claim the blockdev to exclude mounters, release on file close */ 489static int seclvl_bd_claim(struct inode *inode) 490{ 491 int holder; 492 struct block_device *bdev = NULL; 493 dev_t dev = inode->i_rdev; 494 bdev = open_by_devnum(dev, FMODE_WRITE); 495 if (bdev) { 496 if (bd_claim(bdev, &holder)) { 497 blkdev_put(bdev); 498 return -EPERM; 499 } 500 /* claimed, mark it to release on close */ 501 inode->i_security = current; 502 } 503 return 0; 504} 505 506/* release the blockdev if you claimed it */ 507static void seclvl_bd_release(struct inode *inode) 508{ 509 if (inode && S_ISBLK(inode->i_mode) && inode->i_security == current) { 510 struct block_device *bdev = inode->i_bdev; 511 if (bdev) { 512 bd_release(bdev); 513 blkdev_put(bdev); 514 inode->i_security = NULL; 515 } 516 } 517} 518 519/** 520 * Security for writes to block devices is regulated by this seclvl 521 * function. Deny all writes to block devices in seclvl 2. In 522 * seclvl 1, we only deny writes to *mounted* block devices. 523 */ 524static int 525seclvl_inode_permission(struct inode *inode, int mask, struct nameidata *nd) 526{ 527 if (current->pid != 1 && S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) { 528 switch (seclvl) { 529 case 2: 530 seclvl_printk(1, KERN_WARNING, "Write to block device " 531 "denied in secure level [%d]\n", seclvl); 532 return -EPERM; 533 case 1: 534 if (seclvl_bd_claim(inode)) { 535 seclvl_printk(1, KERN_WARNING, 536 "Write to mounted block device " 537 "denied in secure level [%d]\n", 538 seclvl); 539 return -EPERM; 540 } 541 } 542 } 543 return 0; 544} 545 546/** 547 * The SUID and SGID bits cannot be set in seclvl >= 1 548 */ 549static int seclvl_inode_setattr(struct dentry *dentry, struct iattr *iattr) 550{ 551 if (seclvl > 0) { 552 if (iattr->ia_valid & ATTR_MODE) 553 if (iattr->ia_mode & S_ISUID || 554 iattr->ia_mode & S_ISGID) { 555 seclvl_printk(1, KERN_WARNING, "Attempt to " 556 "modify SUID or SGID bit " 557 "denied in seclvl [%d]\n", 558 seclvl); 559 return -EPERM; 560 } 561 } 562 return 0; 563} 564 565/* release busied block devices */ 566static void seclvl_file_free_security(struct file *filp) 567{ 568 struct dentry *dentry = filp->f_dentry; 569 struct inode *inode = NULL; 570 571 if (dentry) { 572 inode = dentry->d_inode; 573 seclvl_bd_release(inode); 574 } 575} 576 577/** 578 * Cannot unmount in secure level 2 579 */ 580static int seclvl_umount(struct vfsmount *mnt, int flags) 581{ 582 if (current->pid == 1) { 583 return 0; 584 } 585 if (seclvl == 2) { 586 seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure " 587 "level %d\n", seclvl); 588 return -EPERM; 589 } 590 return 0; 591} 592 593static struct security_operations seclvl_ops = { 594 .ptrace = seclvl_ptrace, 595 .capable = seclvl_capable, 596 .inode_permission = seclvl_inode_permission, 597 .inode_setattr = seclvl_inode_setattr, 598 .file_free_security = seclvl_file_free_security, 599 .settime = seclvl_settime, 600 .sb_umount = seclvl_umount, 601}; 602 603/** 604 * Process the password-related module parameters 605 */ 606static int processPassword(void) 607{ 608 int rc = 0; 609 hashedPassword[0] = '\0'; 610 if (*passwd) { 611 if (*sha1_passwd) { 612 seclvl_printk(0, KERN_ERR, "Error: Both " 613 "passwd and sha1_passwd " 614 "were set, but they are mutually " 615 "exclusive.\n"); 616 return -EINVAL; 617 } 618 if ((rc = plaintext_to_sha1(hashedPassword, passwd, 619 strlen(passwd)))) { 620 seclvl_printk(0, KERN_ERR, "Error: SHA1 support not " 621 "in kernel\n"); 622 return rc; 623 } 624 /* All static data goes to the BSS, which zero's the 625 * plaintext password out for us. */ 626 } else if (*sha1_passwd) { // Base 16 627 int i; 628 i = strlen(sha1_passwd); 629 if (i != (SHA1_DIGEST_SIZE * 2)) { 630 seclvl_printk(0, KERN_ERR, "Received [%d] bytes; " 631 "expected [%d] for the hexadecimal " 632 "representation of the SHA1 hash of " 633 "the password.\n", 634 i, (SHA1_DIGEST_SIZE * 2)); 635 return -EINVAL; 636 } 637 while ((i -= 2) + 2) { 638 unsigned char tmp; 639 tmp = sha1_passwd[i + 2]; 640 sha1_passwd[i + 2] = '\0'; 641 hashedPassword[i / 2] = (unsigned char) 642 simple_strtol(&sha1_passwd[i], NULL, 16); 643 sha1_passwd[i + 2] = tmp; 644 } 645 } 646 return 0; 647} 648 649/** 650 * Sysfs registrations 651 */ 652static int doSysfsRegistrations(void) 653{ 654 int rc = 0; 655 if ((rc = subsystem_register(&seclvl_subsys))) { 656 seclvl_printk(0, KERN_WARNING, 657 "Error [%d] registering seclvl subsystem\n", rc); 658 return rc; 659 } 660 sysfs_create_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr); 661 if (*passwd || *sha1_passwd) { 662 sysfs_create_file(&seclvl_subsys.kset.kobj, 663 &sysfs_attr_passwd.attr); 664 } 665 return 0; 666} 667 668/** 669 * Initialize the seclvl module. 670 */ 671static int __init seclvl_init(void) 672{ 673 int rc = 0; 674 if (verbosity < 0 || verbosity > 1) { 675 printk(KERN_ERR "Error: bad verbosity [%d]; only 0 or 1 " 676 "are valid values\n", verbosity); 677 rc = -EINVAL; 678 goto exit; 679 } 680 sysfs_attr_seclvl.attr.owner = THIS_MODULE; 681 sysfs_attr_passwd.attr.owner = THIS_MODULE; 682 if (initlvl < -1 || initlvl > 2) { 683 seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel " 684 "[%d].\n", initlvl); 685 rc = -EINVAL; 686 goto exit; 687 } 688 seclvl = initlvl; 689 if ((rc = processPassword())) { 690 seclvl_printk(0, KERN_ERR, "Error processing the password " 691 "module parameter(s): rc = [%d]\n", rc); 692 goto exit; 693 } 694 /* register ourselves with the security framework */ 695 if (register_security(&seclvl_ops)) { 696 seclvl_printk(0, KERN_ERR, 697 "seclvl: Failure registering with the " 698 "kernel.\n"); 699 /* try registering with primary module */ 700 rc = mod_reg_security(MY_NAME, &seclvl_ops); 701 if (rc) { 702 seclvl_printk(0, KERN_ERR, "seclvl: Failure " 703 "registering with primary security " 704 "module.\n"); 705 goto exit; 706 } /* if primary module registered */ 707 secondary = 1; 708 } /* if we registered ourselves with the security framework */ 709 if ((rc = doSysfsRegistrations())) { 710 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n"); 711 goto exit; 712 } 713 seclvl_printk(0, KERN_INFO, "seclvl: Successfully initialized.\n"); 714 exit: 715 if (rc) { 716 printk(KERN_ERR "seclvl: Error during initialization: rc = " 717 "[%d]\n", rc); 718 } 719 return rc; 720} 721 722/** 723 * Remove the seclvl module. 724 */ 725static void __exit seclvl_exit(void) 726{ 727 sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr); 728 if (*passwd || *sha1_passwd) { 729 sysfs_remove_file(&seclvl_subsys.kset.kobj, 730 &sysfs_attr_passwd.attr); 731 } 732 subsystem_unregister(&seclvl_subsys); 733 if (secondary == 1) { 734 mod_unreg_security(MY_NAME, &seclvl_ops); 735 } else if (unregister_security(&seclvl_ops)) { 736 seclvl_printk(0, KERN_INFO, 737 "seclvl: Failure unregistering with the " 738 "kernel\n"); 739 } 740} 741 742module_init(seclvl_init); 743module_exit(seclvl_exit); 744 745MODULE_AUTHOR("Michael A. Halcrow <mike@halcrow.us>"); 746MODULE_DESCRIPTION("LSM implementation of the BSD Secure Levels"); 747MODULE_LICENSE("GPL");