|
|
1.1 ! root 1: /* ! 2: Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. ! 3: ! 4: Covered by TrueCrypt License 2.0 the full text of which is contained in the file ! 5: License.txt included in TrueCrypt binary and source code distribution archives. ! 6: */ ! 7: ! 8: #include <linux/bio.h> ! 9: #include <linux/ctype.h> ! 10: #include <linux/init.h> ! 11: #include <linux/module.h> ! 12: #include <linux/moduleparam.h> ! 13: #include <linux/version.h> ! 14: #include <linux/workqueue.h> ! 15: ! 16: #include "dm.h" ! 17: ! 18: #include "Tcdefs.h" ! 19: #include "Crypto.h" ! 20: #include "Tests.h" ! 21: #include "Dm-target.h" ! 22: ! 23: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ! 24: #error Linux kernel 2.6.5 or later required ! 25: #endif ! 26: ! 27: int trace_level = 0; ! 28: ! 29: #define MSG_PREFIX "truecrypt: " ! 30: #define error(fmt, args...) printk(KERN_ERR MSG_PREFIX fmt, ## args) ! 31: #define trace(level, fmt, args...) level <= trace_level && printk(KERN_DEBUG MSG_PREFIX fmt, ## args) ! 32: #define dbg(fmt, args...) printk(KERN_DEBUG MSG_PREFIX fmt, ## args) ! 33: ! 34: #define MIN_POOL_SIZE 16 ! 35: ! 36: struct target_ctx ! 37: { ! 38: struct dm_dev *dev; ! 39: sector_t start; ! 40: int ea; ! 41: u8 *ks; ! 42: u8 iv[DISK_IV_SIZE]; ! 43: char *volume_path; ! 44: mempool_t *bio_ctx_pool; ! 45: mempool_t *pg_pool; ! 46: sector_t read_only_start; ! 47: sector_t read_only_end; ! 48: u64 mtime; ! 49: u64 atime; ! 50: int flags; ! 51: }; ! 52: ! 53: struct bio_ctx ! 54: { ! 55: struct dm_target *target; ! 56: struct bio *orig_bio; ! 57: atomic_t ref_count; ! 58: u64 crypto_sector; ! 59: int error; ! 60: struct work_struct work; ! 61: }; ! 62: ! 63: static struct workqueue_struct *work_queue = NULL; ! 64: static kmem_cache_t *bio_ctx_cache = NULL; ! 65: ! 66: #define READ_ONLY(tc) (tc->flags & FLAG_READ_ONLY) ! 67: #define HID_VOL_PROT(tc) (tc->flags & FLAG_HIDDEN_VOLUME_PROTECTION) ! 68: ! 69: ! 70: static int hex2bin (char *hex_string, u8 *byte_buf, int max_length) ! 71: { ! 72: int i = 0, n; ! 73: char s[3]; ! 74: s[2] = 0; ! 75: ! 76: trace (3, "hex2bin (%p, %p, %d)\n", hex_string, byte_buf, max_length); ! 77: ! 78: while (i < max_length ! 79: && (s[0] = *hex_string++) ! 80: && (s[1] = *hex_string++)) ! 81: { ! 82: if (sscanf (s, "%x", &n) != 1) ! 83: return 0; ! 84: byte_buf[i++] = (u8) n; ! 85: } ! 86: ! 87: return i; ! 88: } ! 89: ! 90: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) ! 91: static void *mempool_alloc_pg (unsigned int gfp_mask, void *pool_data) ! 92: #else ! 93: static void *mempool_alloc_pg (int gfp_mask, void *pool_data) ! 94: #endif ! 95: { ! 96: trace (3, "mempool_alloc_pg (%d, %p)\n", gfp_mask, pool_data); ! 97: return alloc_page (gfp_mask); ! 98: } ! 99: ! 100: ! 101: static void mempool_free_pg (void *element, void *pool_data) ! 102: { ! 103: trace (3, "mempool_free_pg (%p, %p)\n", element, pool_data); ! 104: __free_page (element); ! 105: } ! 106: ! 107: ! 108: static int truecrypt_ctr (struct dm_target *ti, unsigned int argc, char **argv) ! 109: { ! 110: struct target_ctx *tc; ! 111: u8 *key = NULL; ! 112: int key_size; ! 113: int error = -EINVAL; ! 114: ! 115: trace (3, "truecrypt_ctr (%p, %d, %p)\n", ti, argc, argv); ! 116: ! 117: if (argc != 11) ! 118: { ! 119: ti->error = "truecrypt: Usage: <start_sector> <sector_count> truecrypt <EA> <key> <IV> <host_device> <sector_offset> <read_only_start> <read_only_end> <mtime> <atime> <flags> <volume_path>"; ! 120: return -EINVAL; ! 121: } ! 122: ! 123: tc = kmalloc (sizeof (*tc), GFP_KERNEL); ! 124: if (tc == NULL) ! 125: { ! 126: ti->error = "truecrypt: Cannot allocate target context"; ! 127: error = -ENOMEM; ! 128: goto err; ! 129: } ! 130: memset (tc, 0, sizeof (*tc)); ! 131: ! 132: tc->bio_ctx_pool = mempool_create (MIN_POOL_SIZE, mempool_alloc_slab, mempool_free_slab, bio_ctx_cache); ! 133: if (!tc->bio_ctx_pool) ! 134: { ! 135: ti->error = "truecrypt: Cannot create bio context memory pool"; ! 136: error = -ENOMEM; ! 137: goto err; ! 138: } ! 139: ! 140: tc->pg_pool = mempool_create (MIN_POOL_SIZE, mempool_alloc_pg, mempool_free_pg, NULL); ! 141: if (!tc->pg_pool) ! 142: { ! 143: ti->error = "truecrypt: Cannot create page memory pool"; ! 144: error = -ENOMEM; ! 145: goto err; ! 146: } ! 147: ! 148: if (sscanf (argv[ARG_SEC], SECTOR_FORMAT, &tc->start) != 1) ! 149: { ! 150: ti->error = "truecrypt: Invalid device sector"; ! 151: goto err; ! 152: } ! 153: ! 154: if (dm_get_device (ti, argv[ARG_DEV], tc->start, ti->len, dm_table_get_mode (ti->table), &tc->dev)) ! 155: { ! 156: ti->error = "truecrypt: Device lookup failed"; ! 157: goto err; ! 158: } ! 159: ! 160: // Encryption algorithm ! 161: tc->ea = 0; ! 162: if (sscanf (argv[ARG_EA], "%d", &tc->ea) != 1 ! 163: || tc->ea < EAGetFirst () ! 164: || tc->ea > EAGetCount ()) ! 165: { ! 166: ti->error = "truecrypt: Invalid encryption algorithm"; ! 167: goto err; ! 168: } ! 169: ! 170: // Key ! 171: key_size = EAGetKeySize (tc->ea); ! 172: key = kmalloc (key_size, GFP_KERNEL); ! 173: if (!key) ! 174: { ! 175: ti->error = "truecrypt: Cannot allocate key buffer"; ! 176: error = -ENOMEM; ! 177: goto err; ! 178: } ! 179: ! 180: if (hex2bin (argv[ARG_KEY], key, key_size) != key_size) ! 181: { ! 182: ti->error = "truecrypt: Invalid key"; ! 183: goto err; ! 184: } ! 185: ! 186: // Scheduled key ! 187: tc->ks = kmalloc (EAGetKeyScheduleSize (tc->ea), GFP_KERNEL); ! 188: if (tc->ks == NULL) ! 189: { ! 190: ti->error = "truecrypt: Cannot allocate scheduled key buffer"; ! 191: error = -ENOMEM; ! 192: goto err; ! 193: } ! 194: ! 195: trace (2, "EAInit (%d, %p, %p)\n", tc->ea, key, tc->ks); ! 196: EAInit (tc->ea, key, tc->ks); ! 197: kfree (key); ! 198: key = NULL; ! 199: ! 200: // IV ! 201: if (hex2bin (argv[ARG_IV], tc->iv, sizeof (tc->iv)) != sizeof (tc->iv)) ! 202: { ! 203: ti->error = "truecrypt: Invalid IV"; ! 204: goto err; ! 205: } ! 206: ! 207: // Read-only start sector ! 208: if (sscanf (argv[ARG_RO_START], SECTOR_FORMAT, &tc->read_only_start) != 1) ! 209: { ! 210: ti->error = "truecrypt: Invalid read-only start sector"; ! 211: goto err; ! 212: } ! 213: ! 214: // Read-only end sector ! 215: if (sscanf (argv[ARG_RO_END], SECTOR_FORMAT, &tc->read_only_end) != 1) ! 216: { ! 217: ti->error = "truecrypt: Invalid read-only end sector"; ! 218: goto err; ! 219: } ! 220: ! 221: // Modification time ! 222: if (sscanf (argv[ARG_MTIME], "%Ld", &tc->mtime) != 1) ! 223: { ! 224: ti->error = "truecrypt: Invalid modification time"; ! 225: goto err; ! 226: } ! 227: ! 228: // Access time ! 229: if (sscanf (argv[ARG_ATIME], "%Ld", &tc->atime) != 1) ! 230: { ! 231: ti->error = "truecrypt: Invalid access time"; ! 232: goto err; ! 233: } ! 234: ! 235: // Flags ! 236: if (sscanf (argv[ARG_FLAGS], "%d", &tc->flags) != 1) ! 237: { ! 238: ti->error = "truecrypt: Invalid flags"; ! 239: goto err; ! 240: } ! 241: ! 242: // Volume path ! 243: tc->volume_path = kmalloc (strlen (argv[ARG_VOL]) + 1, GFP_KERNEL); ! 244: if (tc->volume_path == NULL) ! 245: { ! 246: ti->error = "truecrypt: Cannot allocate volume path buffer"; ! 247: error = -ENOMEM; ! 248: goto err; ! 249: } ! 250: strcpy (tc->volume_path, argv[ARG_VOL]); ! 251: ! 252: ti->private = tc; ! 253: return 0; ! 254: ! 255: err: ! 256: trace (3, "truecrypt_ctr: error\n"); ! 257: ! 258: if (key) ! 259: kfree(key); ! 260: if (tc) ! 261: { ! 262: if (tc->ks) ! 263: kfree (tc->ks); ! 264: if (tc->volume_path) ! 265: kfree (tc->volume_path); ! 266: if (tc->bio_ctx_pool) ! 267: mempool_destroy (tc->bio_ctx_pool); ! 268: if (tc->pg_pool) ! 269: mempool_destroy (tc->pg_pool); ! 270: kfree (tc); ! 271: } ! 272: ! 273: return error; ! 274: } ! 275: ! 276: ! 277: static void truecrypt_dtr (struct dm_target *ti) ! 278: { ! 279: struct target_ctx *tc = (struct target_ctx *) ti->private; ! 280: ! 281: trace (3, "truecrypt_dtr (%p)\n", ti); ! 282: ! 283: dm_put_device(ti, tc->dev); ! 284: ! 285: mempool_destroy (tc->bio_ctx_pool); ! 286: kfree(tc->ks); ! 287: kfree(tc->volume_path); ! 288: kfree(tc); ! 289: } ! 290: ! 291: ! 292: // Checks if two regions overlap (borders are parts of regions) ! 293: static int RegionsOverlap (sector_t start1, sector_t end1, sector_t start2, sector_t end2) ! 294: { ! 295: return (start1 < start2) ? (end1 >= start2) : (start1 <= end2); ! 296: } ! 297: ! 298: ! 299: static void dereference_bio_ctx (struct bio_ctx *bc) ! 300: { ! 301: struct target_ctx *tc = (struct target_ctx *) bc->target->private; ! 302: trace (3, "dereference_bio_ctx (%p)\n", bc); ! 303: ! 304: if (!atomic_dec_and_test (&bc->ref_count)) ! 305: return; ! 306: ! 307: bio_endio (bc->orig_bio, bc->orig_bio->bi_size, bc->error); ! 308: trace (3, "dereference_bio_ctx: mempool_free (%p)\n", bc); ! 309: mempool_free (bc, tc->bio_ctx_pool); ! 310: } ! 311: ! 312: ! 313: static void work_process (void *data) ! 314: { ! 315: struct bio_ctx *bc = (struct bio_ctx *) data; ! 316: struct target_ctx *tc = (struct target_ctx *) bc->target->private; ! 317: struct bio_vec *bv; ! 318: sector_t sec_no = bc->crypto_sector; ! 319: int seg_no; ! 320: unsigned long flags; ! 321: ! 322: trace (3, "work_process (%p)\n", data); ! 323: ! 324: // Decrypt queued data ! 325: bio_for_each_segment (bv, bc->orig_bio, seg_no) ! 326: { ! 327: unsigned int secs = bv->bv_len / SECTOR_SIZE; ! 328: char *data = bvec_kmap_irq (bv, &flags); ! 329: ! 330: trace (2, "DecryptSectors (%Ld, %d)\n", sec_no, secs); ! 331: DecryptSectors ((unsigned __int32 *)data, sec_no, secs, tc->ks, tc->iv, tc->ea); ! 332: ! 333: sec_no += secs; ! 334: ! 335: flush_dcache_page (bv->bv_page); ! 336: bvec_kunmap_irq (data, &flags); ! 337: } ! 338: ! 339: dereference_bio_ctx (bc); ! 340: } ! 341: ! 342: ! 343: static int truecrypt_endio (struct bio *bio, unsigned int bytes_done, int error) ! 344: { ! 345: struct bio_ctx *bc = (struct bio_ctx *) bio->bi_private; ! 346: struct target_ctx *tc = (struct target_ctx *) bc->target->private; ! 347: struct bio_vec *bv; ! 348: int seg_no; ! 349: ! 350: trace (3, "truecrypt_endio (%p, %d, %d)\n", bio, bytes_done, error); ! 351: trace (1, "end: sc=" SECTOR_FORMAT " fl=%ld rw=%ld sz=%d ix=%hd vc=%hd dn=%d er=%d\n", ! 352: bio->bi_sector, bio->bi_flags, bio->bi_rw, bio->bi_size, bio->bi_idx, bio->bi_vcnt, bytes_done, error); ! 353: ! 354: if (error != 0) ! 355: bc->error = error; ! 356: ! 357: if (bio->bi_size) ! 358: { ! 359: trace (2, "Outstanding IO: %d\n", bio->bi_size); ! 360: return 1; ! 361: } ! 362: ! 363: if (bio_data_dir (bio) == READ) ! 364: { ! 365: bio_put (bio); ! 366: ! 367: // Queue decryption to leave completion interrupt ASAP ! 368: INIT_WORK (&bc->work, work_process, bc); ! 369: trace (3, "queue_work (%p)\n", work_queue); ! 370: queue_work (work_queue, &bc->work); ! 371: return error; ! 372: } ! 373: ! 374: // Free pages allocated for encryption ! 375: bio_for_each_segment (bv, bio, seg_no) ! 376: { ! 377: trace (3, "mempool_free (%p, %p)\n", bv->bv_page, tc->pg_pool); ! 378: mempool_free (bv->bv_page, tc->pg_pool); ! 379: } ! 380: ! 381: bio_put (bio); ! 382: dereference_bio_ctx (bc); ! 383: return error; ! 384: } ! 385: ! 386: ! 387: static int truecrypt_map (struct dm_target *ti, struct bio *bio, union map_info *map_context) ! 388: { ! 389: struct target_ctx *tc = (struct target_ctx *) ti->private; ! 390: struct bio_ctx *bc; ! 391: struct bio *bion; ! 392: struct bio_vec *bv; ! 393: int seg_no; ! 394: ! 395: trace (3, "truecrypt_map (%p, %p, %p)\n", ti, bio, map_context); ! 396: trace (1, "map: sc=" SECTOR_FORMAT " fl=%ld rw=%ld sz=%d ix=%hd vc=%hd\n", ! 397: bio->bi_sector, bio->bi_flags, bio->bi_rw, bio->bi_size, bio->bi_idx, bio->bi_vcnt); ! 398: ! 399: // Write protection ! 400: if (bio_data_dir (bio) == WRITE && READ_ONLY (tc)) ! 401: return -EPERM; ! 402: ! 403: // Validate segment sizes ! 404: bio_for_each_segment (bv, bio, seg_no) ! 405: { ! 406: if (bv->bv_len & (SECTOR_SIZE - 1)) ! 407: { ! 408: error ("unsupported segment size %d (%ld %d %hd %hd)\n", ! 409: bv->bv_len, bio->bi_rw, bio->bi_size, bio->bi_idx, bio->bi_vcnt); ! 410: return -EINVAL; ! 411: } ! 412: } ! 413: ! 414: // Bio context ! 415: bc = mempool_alloc (tc->bio_ctx_pool, GFP_NOIO); ! 416: if (!bc) ! 417: { ! 418: error ("bio context allocation failed\n"); ! 419: return -ENOMEM; ! 420: } ! 421: trace (3, "truecrypt_map: mempool_alloc bc: %p\n", bc); ! 422: ! 423: atomic_set (&bc->ref_count, 1); ! 424: bc->orig_bio = bio; ! 425: bc->error = 0; ! 426: bc->target = ti; ! 427: bc->crypto_sector = tc->start + (bio->bi_sector - ti->begin); ! 428: ! 429: // New bio for encrypted device ! 430: trace (3, "bio_alloc (%hd)\n", bio_segments (bio)); ! 431: bion = bio_alloc (GFP_NOIO, bio_segments (bio)); ! 432: if (!bion) ! 433: { ! 434: error ("bio allocation failed\n"); ! 435: bc->error = -ENOMEM; ! 436: dereference_bio_ctx (bc); ! 437: return 0; ! 438: } ! 439: ! 440: bion->bi_bdev = tc->dev->bdev; ! 441: bion->bi_end_io = truecrypt_endio; ! 442: bion->bi_idx = 0; ! 443: bion->bi_private = bc; ! 444: bion->bi_rw = bio->bi_rw; ! 445: bion->bi_sector = bc->crypto_sector; ! 446: bion->bi_size = bio->bi_size; ! 447: bion->bi_vcnt = bio_segments (bio); ! 448: ! 449: if (bio_data_dir (bio) == READ) ! 450: { ! 451: // Buffers of originating bio can be used for decryption ! 452: memcpy (bion->bi_io_vec, ! 453: bio_iovec (bio), ! 454: bion->bi_vcnt * sizeof (struct bio_vec)); ! 455: } ! 456: else ! 457: { ! 458: // Encrypt data to be written ! 459: unsigned long flags, copyFlags; ! 460: char *data, *copy; ! 461: long long sec_no = bc->crypto_sector; ! 462: ! 463: memset (bion->bi_io_vec, 0, sizeof (struct bio_vec) * bion->bi_vcnt); ! 464: ! 465: bio_for_each_segment (bv, bio, seg_no) ! 466: { ! 467: struct bio_vec *cbv = bio_iovec_idx (bion, seg_no); ! 468: unsigned int secs = bv->bv_len / SECTOR_SIZE; ! 469: ! 470: // Hidden volume protection ! 471: if (!READ_ONLY (tc) && HID_VOL_PROT (tc) ! 472: && RegionsOverlap (sec_no, sec_no + secs - 1, tc->read_only_start, tc->read_only_end)) ! 473: { ! 474: tc->flags |= FLAG_READ_ONLY | FLAG_PROTECTION_ACTIVATED; ! 475: } ! 476: ! 477: if (!READ_ONLY (tc)) ! 478: { ! 479: cbv->bv_page = mempool_alloc (tc->pg_pool, GFP_NOIO); ! 480: if (cbv->bv_page == NULL) ! 481: error ("page allocation failed during write\n"); ! 482: } ! 483: ! 484: if (READ_ONLY (tc) || cbv->bv_page == NULL) ! 485: { ! 486: // Write not permitted or no memory ! 487: bio_for_each_segment (cbv, bion, seg_no) ! 488: { ! 489: if (cbv->bv_page != NULL) ! 490: mempool_free (cbv->bv_page, tc->pg_pool); ! 491: } ! 492: ! 493: bio_put (bion); ! 494: bc->error = READ_ONLY (tc) ? -EPERM : -ENOMEM; ! 495: dereference_bio_ctx (bc); ! 496: return 0; ! 497: } ! 498: trace (3, "truecrypt_map: mempool_alloc pg: %p\n", cbv->bv_page); ! 499: ! 500: cbv->bv_offset = 0; ! 501: cbv->bv_len = bv->bv_len; ! 502: ! 503: data = bvec_kmap_irq (bv, &flags); ! 504: copy = bvec_kmap_irq (cbv, ©Flags); ! 505: ! 506: memcpy (copy, data, bv->bv_len); ! 507: ! 508: flush_dcache_page (bv->bv_page); ! 509: bvec_kunmap_irq (data, &flags); ! 510: ! 511: trace (2, "EncryptSectors (%Ld, %d)\n", sec_no, secs); ! 512: ! 513: EncryptSectors ((unsigned __int32 *)copy, sec_no, secs, tc->ks, tc->iv, tc->ea); ! 514: sec_no += secs; ! 515: ! 516: flush_dcache_page (cbv->bv_page); ! 517: bvec_kunmap_irq (copy, ©Flags); ! 518: } ! 519: } ! 520: ! 521: atomic_inc (&bc->ref_count); ! 522: ! 523: trace (3, "generic_make_request (rw=%ld sc=" SECTOR_FORMAT ")\n", bion->bi_rw, bion->bi_sector); ! 524: generic_make_request (bion); ! 525: ! 526: dereference_bio_ctx (bc); ! 527: return 0; ! 528: } ! 529: ! 530: ! 531: static int truecrypt_status (struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) ! 532: { ! 533: struct target_ctx *tc = (struct target_ctx *) ti->private; ! 534: ! 535: switch (type) ! 536: { ! 537: case STATUSTYPE_INFO: ! 538: result[0] = 0; ! 539: break; ! 540: ! 541: case STATUSTYPE_TABLE: ! 542: { ! 543: char name[32]; ! 544: format_dev_t (name, tc->dev->bdev->bd_dev); ! 545: snprintf (result, maxlen, "%d 0 0 %s " SECTOR_FORMAT " " SECTOR_FORMAT " " SECTOR_FORMAT " %Ld %Ld %d %s", ! 546: tc->ea, ! 547: name, ! 548: tc->start, ! 549: tc->read_only_start, ! 550: tc->read_only_end, ! 551: tc->mtime, ! 552: tc->atime, ! 553: tc->flags, ! 554: tc->volume_path); ! 555: } ! 556: break; ! 557: } ! 558: ! 559: return 0; ! 560: } ! 561: ! 562: ! 563: static struct target_type truecrypt_target = { ! 564: .name = "truecrypt", ! 565: .version= {VERSION_NUM1, VERSION_NUM2, VERSION_NUM3}, ! 566: .module = THIS_MODULE, ! 567: .ctr = truecrypt_ctr, ! 568: .dtr = truecrypt_dtr, ! 569: .map = truecrypt_map, ! 570: .status = truecrypt_status ! 571: }; ! 572: ! 573: ! 574: int __init dm_truecrypt_init(void) ! 575: { ! 576: int r; ! 577: trace (3, "dm_truecrypt_init (trace_level=%d)\n", trace_level); ! 578: ! 579: if (!AutoTestAlgorithms ()) ! 580: { ! 581: DMERR ("truecrypt: self-test of algorithms failed"); ! 582: return -ERANGE; ! 583: } ! 584: ! 585: work_queue = create_workqueue ("truecryptq"); ! 586: ! 587: if (!work_queue) ! 588: { ! 589: DMERR ("truecrypt: create_workqueue creation failed"); ! 590: goto err; ! 591: } ! 592: ! 593: bio_ctx_cache = kmem_cache_create ("truecrypt-bioctx", sizeof (struct bio_ctx), 0, 0, NULL, NULL); ! 594: if (!bio_ctx_cache) ! 595: { ! 596: DMERR ("truecrypt: kmem_cache_create failed"); ! 597: goto err; ! 598: } ! 599: ! 600: r = dm_register_target (&truecrypt_target); ! 601: if (r < 0) ! 602: { ! 603: DMERR ("truecrypt: register failed %d", r); ! 604: goto err; ! 605: } ! 606: ! 607: return r; ! 608: ! 609: err: ! 610: if (work_queue) ! 611: destroy_workqueue (work_queue); ! 612: if (bio_ctx_cache) ! 613: kmem_cache_destroy (bio_ctx_cache); ! 614: ! 615: return -ENOMEM; ! 616: } ! 617: ! 618: ! 619: void __exit dm_truecrypt_exit(void) ! 620: { ! 621: int r; ! 622: trace (3, "dm_truecrypt_exit ()\n"); ! 623: ! 624: r = dm_unregister_target (&truecrypt_target); ! 625: ! 626: if (r < 0) ! 627: DMERR ("truecrypt: unregister failed %d", r); ! 628: ! 629: destroy_workqueue (work_queue); ! 630: kmem_cache_destroy (bio_ctx_cache); ! 631: } ! 632: ! 633: ! 634: module_init(dm_truecrypt_init); ! 635: module_exit(dm_truecrypt_exit); ! 636: module_param_named(trace, trace_level, int, 0); ! 637: ! 638: MODULE_AUTHOR("TrueCrypt Foundation"); ! 639: MODULE_DESCRIPTION(DM_NAME " target for encryption and decryption of TrueCrypt volumes"); ! 640: MODULE_PARM_DESC(trace, "Trace level"); ! 641: MODULE_LICENSE("GPL and additional rights"); // Kernel thinks only GPL/BSD/MPL != closed-source code
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.