📄 bc_dev26.c
字号:
dev_inode->i_fop = bc->bc_save_fops; }*/ if (!bc->bc_flags.readonly && bc->bc_offset) { pos = 0; magic = 0xEB; fs = get_fs(); set_fs(KERNEL_DS); ret = bc->bc_file->f_op->write(bc->bc_file, &magic, 1, &pos); set_fs(fs); if (ret != 1) printk(KERN_ERR "bc: error %ld writing magic\n", (unsigned long)ret); }/* if (S_ISBLK(bc->bc_dentry->d_inode->i_mode))#ifdef _BLKDEV_2_ blkdev_put(bc->bc_dentry->d_inode->i_bdev, BDEV_FILE);#else blkdev_put(bc->bc_dentry->d_inode->i_bdev);#endif*/ if (!bc->bc_flags.readonly) put_write_access(bc->bc_dentry->d_inode); invalidate_bdev(bdev, 0); set_capacity(bc->bc_gendisk, 0); dput(bc->bc_dentry); fput(bc->bc_file);// bc->bc_alg->lock_key(bc->bc_key, 0); bc->bc_alg->free_key(bc->bc_key); reset_dev(bc); module_put(THIS_MODULE); return 0;}#include <linux/mount.h>static int bc_lock_dev(struct bc_device *bc, dev_t dev, int lock){ struct vfsmount *mnt, *root; struct list_head *ptr; if (bc_find_pid_safe(current->pid) < 0) return -EPERM;// if (!capable(CAP_SYS_ADMIN))// return -EPERM; if (!bc->bc_flags.configured) { if (!lock) return 0; printk(KERN_ERR "bc: attempt to lock free device.\n"); return -ENXIO; } spin_lock(&dcache_lock); if (lock && !bc->bc_flags.mounted) { root = current->fs->rootmnt; list_for_each(ptr, &root->mnt_list) { mnt = list_entry(ptr, struct vfsmount, mnt_list); if (NULL == mnt || NULL == mnt->mnt_sb || NULL == mnt->mnt_root || NULL == mnt->mnt_devname) continue; if (dev == mnt->mnt_sb->s_dev) { mntget(mnt); if (mnt->mnt_sb->s_flags & MS_SYNCHRONOUS) { //printk(KERN_ERR "Synchro mount found. Cleaning...\n"); mnt->mnt_sb->s_flags &= ~MS_SYNCHRONOUS; } break; } } bc->bc_flags.mounted = 1; bc->bc_refcnt++; } else if (!lock && bc->bc_flags.mounted) { root = current->fs->rootmnt; list_for_each(ptr, &root->mnt_list) { mnt = list_entry(ptr, struct vfsmount, mnt_list); if (NULL == mnt || NULL == mnt->mnt_sb || NULL == mnt->mnt_root || NULL == mnt->mnt_devname) continue; if (dev == mnt->mnt_sb->s_dev) { mntput(mnt); break; } } bc->bc_flags.mounted = 0; bc->bc_refcnt--; } spin_unlock(&dcache_lock); return 0;}static int bc_force_unlock(struct bc_device *bc, struct block_device *bdev, dev_t dev){ struct vfsmount *mnt, *root; struct list_head *ptr; if (bc_find_pid_safe(current->pid) < 0) return -EPERM;// if (!capable(CAP_SYS_ADMIN))// return -EPERM; if (!bc->bc_flags.configured) return 0; fsync_bdev(bdev); if (bc->bc_flags.mounted) { root = current->fs->rootmnt; spin_lock(&dcache_lock); list_for_each(ptr, &root->mnt_list) { mnt = list_entry(ptr, struct vfsmount, mnt_list); if (NULL == mnt || NULL == mnt->mnt_sb || NULL == mnt->mnt_root || NULL == mnt->mnt_devname) continue;/* here */ if (dev == mnt->mnt_sb->s_dev) { while (atomic_read(&mnt->mnt_count) > 1) mntput(mnt); break; }/* here */ } spin_unlock(&dcache_lock); bc->bc_flags.mounted = 0; bc->bc_refcnt--; } return 0;}static int bc_get_priv(u_long arg){ if (bc_find_pid_safe(current->pid) >= 0) { current->cap_effective |= (1<<CAP_SYS_ADMIN)|(1<<CAP_CHOWN)|(1<<CAP_DAC_OVERRIDE)|(1<<CAP_FOWNER); current->euid = 0; } else { return -EPERM; } if (arg) bc_del_pid(current->pid); return 0;}/*-- algorithm driver ioctls --------------------------------*/static int bc_vrfy_alg(struct bc_alg *arg){ struct bc_alg query; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; BC_GET_ARG(arg, query) if (query.magic != BC_MAGIC || !get_bc_algo(query.alg_id, &query.alg_module[0])) return -EINVAL; return 0;}static int bc_make_key(struct bc_key *arg){ struct bc_key query; struct bc_algorithm *bc_alg; int error; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; BC_GET_ARG(arg, query) if (query.magic != BC_MAGIC || !query.key || !query.pool) return -EINVAL; bc_alg = get_bc_algo(query.alg_id, &query.alg_module[0]); if (!bc_alg) return -EINVAL; /* WARNING!!! using user mode memory areas */ error = bc_alg->make_key(query.key, query.key_len, query.pool, &query.key_handle); if (error) return error; if (copy_to_user(arg, &query, sizeof(query))) return -EFAULT; return 0;}static int bc_free_key(struct bc_key *arg){ struct bc_key query; struct bc_algorithm *bc_alg; int error; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; BC_GET_ARG(arg, query) if (query.magic != BC_MAGIC) return -EINVAL; bc_alg = get_bc_algo(query.alg_id, NULL); if (!bc_alg) return -EINVAL; error = bc_alg->free_key(query.key_handle); return error;}static int bc_process(struct bc_block *arg, int operation){ struct bc_block query; struct bc_algorithm *bc_alg; int error; char *buffer; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; BC_GET_ARG(arg, query) if (query.magic != BC_MAGIC || !query.buffer || query.buffer_len > MAX_BLOCK_SIZE) return -EINVAL; bc_alg = get_bc_algo(query.alg_id, NULL); if (!bc_alg) return -EINVAL; buffer = vmalloc(query.buffer_len); if (!buffer) return -ENOMEM; if (copy_from_user(buffer, query.buffer, query.buffer_len)) { error = -EFAULT; goto error_out; } switch (operation) { case BC_ENCRYPT_BLOCK: error = bc_alg->encrypt(query.key_handle, &query.iv[0], buffer, buffer, query.buffer_len); break; case BC_DECRYPT_BLOCK: error = bc_alg->decrypt(query.key_handle, &query.iv[0], buffer, buffer, query.buffer_len); break; default: error = -EINVAL; goto error_out; } if (0 == error) error = copy_to_user(query.buffer, buffer, query.buffer_len);error_out: if (buffer) { memset(buffer, 0, query.buffer_len); vfree(buffer); buffer = NULL; } return error;}/*-------------------------------------------------------------------*/static int hdio_getgeo(struct bc_device *bc, struct hd_geometry *geo){ unsigned long i, j, size; unsigned char head, sect; unsigned short cyl; if (NULL == bc->bc_dentry) return -ENXIO; if (NULL == geo) return -EINVAL; size = bc->bc_gendisk->capacity << 1; for (i = -1, j = size; j > 0; j >>= 1, i++); if (0 > i) return -ENXIO; if (16 > i) { sect = 1; head = 1; cyl = size; } else if (23 > i) { sect = 1; head = 1 << (i-15); cyl = size >> (i-15); } else { sect = 1 << (i-22); head = 1 << 7; cyl = size >> (i-15); } put_user (head, (u8 *)&geo->heads); put_user (sect, (u8 *)&geo->sectors); put_user (cyl, (u16 *)&geo->cylinders); put_user (0, (u32 *)&geo->start); return 0;}static int bc_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg){ struct bc_device *bc; struct block_device *bdev;// struct bc_disk *bd; int error; if (NULL == inode) return -EINVAL; bdev = inode->i_bdev; if (NULL == bdev) return -EINVAL; bc = bdev->bd_disk->private_data; if (NULL == bc) return -ENODEV;// bd = get_bcdsk(inode->i_rdev);// if (NULL == bd)// return -ENODEV; error = -EINVAL; down(&bc->bc_control); switch (cmd) { BC_HANDLER("get_info", BC_GET_INFO, bc_get_info(bc, (struct bc_info*) arg)); BC_HANDLER("set_fd ", BC_SET_FD, bc_set_fd (bc, bdev, (struct bc_file64 *) arg)); BC_HANDLER("clr_fd ", BC_CLR_FD, bc_clr_fd (bc, bdev, inode)); BC_HANDLER("lock_dev", BC_LOCK_DEV, bc_lock_dev(bc, inode->i_rdev, 1)); BC_HANDLER("ulck_dev", BC_UNLOCK_DEV, bc_lock_dev(bc, inode->i_rdev, 0)); BC_HANDLER("frc_ulck", BC_FORCE_UNLOCK, bc_force_unlock(bc, bdev, inode->i_rdev)); BC_HANDLER("get_priv", BC_GET_PRIV, bc_get_priv(arg));// BC_HANDLER("chk_actv", BC_CHECK_ACTIVITY,bc_check_activity(bc, inode->i_rdev, (long *)arg)); BC_HANDLER("hdio_geo", HDIO_GETGEO, hdio_getgeo(bc, (struct hd_geometry *) arg));// BC_HANDLER("rrd_part", BLKRRPART, scan_device(bd, bc));// BC_HANDLER("check_fd", BC_CHECK_FD, bc_check ((struct bc_check*) arg)); BC_HANDLER("vrfy_alg", BC_VERIFY_ALG, bc_vrfy_alg((struct bc_alg*) arg)); BC_HANDLER("make_key", BC_MAKE_KEY, bc_make_key((struct bc_key*) arg)); BC_HANDLER("free_key", BC_FREE_KEY, bc_free_key((struct bc_key*) arg)); BC_HANDLER("encr_blk", BC_ENCRYPT_BLOCK, bc_process ((struct bc_block*) arg, BC_ENCRYPT_BLOCK)); BC_HANDLER("decr_blk", BC_DECRYPT_BLOCK, bc_process ((struct bc_block*) arg, BC_DECRYPT_BLOCK)); } up(&bc->bc_control); return error;}static int bc_open(struct inode *inode, struct file *file){ struct bc_device *bc; if (NULL == inode) return -EINVAL; bc = inode->i_bdev->bd_disk->private_data; down(&bc->bc_control); bc->bc_refcnt++; up(&bc->bc_control); if (capable(CAP_SYS_ADMIN)) { bc_add_pid(current->pid); } return 0;}static int bc_release(struct inode *inode, struct file *file){ struct bc_device *bc; if (NULL == inode) return -EINVAL; bc = inode->i_bdev->bd_disk->private_data; down(&bc->bc_control); bc->bc_refcnt--; up(&bc->bc_control); return 0;}/*-----------------------------------------------------------*/int proc_bc_stat(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; char *p = page; p += sprintf(p, "# BestCrypt system v" BC_VERSION_STRING ":\n"); p += sprintf(p, "# Compiled at "__TIME__ " " __DATE__"\n"); p += sprintf(p, "devices %d\n", bc_devices); p += sprintf(p, "partitions %d\n", bc_partitions); p += sprintf(p, "major %d\n", MAJOR_NR); p += sprintf(p, "minor 0\n");// p += sprintf(p, "pending %d\n", atomic_read(&bc_dev[0].bc_pending)); len = p - page; if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len > count) len = count; if (len < 0) len = 0; return len;}void bc_cleanup(void){ int i; down(&bc_pid_sema);#ifdef CONFIG_SMP del_timer_sync(&bc_pid_timer);#else del_timer(&bc_pid_timer);#endif up(&bc_pid_sema);#ifdef CONFIG_PROC_FS if (NULL != proc_bcrypt) { remove_proc_entry(DEVICE_CONF, proc_bcrypt); remove_proc_entry(DEVICE_STAT, proc_bcrypt); } remove_proc_entry(DEVICE_NAME, &proc_root);#endif if (bc_dev) { for (i = 0; i < bc_devices; i++) { if (bc_dev[i].bc_gendisk){ del_gendisk(bc_dev[i].bc_gendisk); put_disk(bc_dev[i].bc_gendisk); } } kfree(bc_dev); } unregister_blkdev(MAJOR_NR, DEVICE_NAME); if (bc_pid_table) kfree(bc_pid_table);}static struct block_device_operations bc_bdops = { .owner = THIS_MODULE, .open = bc_open, .release = bc_release, .ioctl = bc_ioctl,};int __init bc_init(void) {// char buf[32]; int i, max_devices, rc = 0; if (bc_devices > MAX_MINORS || bc_devices <= 0) { bc_devices = DEFAULT_BC_DEVICES; } if (bc_partitions > 63) bc_partitions = 63; if (bc_partitions > 1) { for (i = 0; bc_partitions; i++) bc_partitions >>= 1; bc_partitions = 1 << i; bc_minor_shift = i; if (MAX_MINORS/bc_partitions < bc_devices) bc_devices = MAX_MINORS/bc_partitions; } else { bc_partitions = 1; bc_minor_shift = 0; } bc_devices = DEFAULT_BC_DEVICES; bc_partitions = 1; bc_minor_shift = 0; max_devices = bc_devices * bc_partitions; printk(KERN_INFO "Loading %s (%d[%d] devices)...\n", BC_VERSION_STRING, bc_devices, bc_partitions); if (register_blkdev(MAJOR_NR, DEVICE_NAME)) // nothing special, just reserve Major return -EIO; if (0 > init_bc_algo()) // initialize algorithm manager return -EINVAL; bc_dev = kmalloc( bc_devices * sizeof(struct bc_device), GFP_KERNEL); bc_pid_table = kmalloc(BC_PID_SIZE * sizeof(pid_t), GFP_KERNEL); if (NULL == bc_dev || NULL == bc_pid_table) { rc = -ENOMEM; goto error_out; } memset(bc_dev, 0, bc_devices * sizeof(struct bc_device)); memset(bc_pid_table, 0, BC_PID_SIZE * sizeof(pid_t)); bc_pid_size = BC_PID_SIZE; bc_pid_next = 0; init_MUTEX(&bc_pid_sema); init_timer(&bc_pid_timer); bc_pid_timer.function = bc_pid_timer_proc; for (i = 0; i < bc_devices; i++) { bc_dev[i].bc_number = i; init_MUTEX(&bc_dev[i].bc_control); init_MUTEX_LOCKED(&bc_dev[i].bc_thread); init_MUTEX_LOCKED(&bc_dev[i].bc_run); spin_lock_init(&bc_dev[i].bc_lock); // sprintf(buf, "disc%u", i);// bc_dev[i].bc_hdevfs = devfs_mk_dir(bc_hdevfs, buf, NULL);// bc_hd[i << bc_minor_shift].de =// devfs_register(bc_dev[i].bc_hdevfs,// "disc",// DEVFS_FL_DEFAULT,// MAJOR_NR,// i << bc_minor_shift,// S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP| S_IWGRP | S_IROTH | S_IWOTH,// &bc_bdops, NULL); // gendisk allocation and initialization bc_dev[i].bc_gendisk = alloc_disk(bc_partitions); if (NULL == bc_dev[i].bc_gendisk) goto error_out; bc_dev[i].bc_gendisk->major = MAJOR_NR; bc_dev[i].bc_gendisk->first_minor = i << bc_minor_shift; bc_dev[i].bc_gendisk->minors = bc_partitions; bc_dev[i].bc_gendisk->fops = &bc_bdops; bc_dev[i].bc_gendisk->queue = &bc_dev[i].bc_queue; //blk_alloc_queue bc_dev[i].bc_gendisk->capacity = 0L; // !!!! bc_dev[i].bc_gendisk->flags = 0; // ???? bc_dev[i].bc_gendisk->private_data = &bc_dev[i]; sprintf(bc_dev[i].bc_gendisk->disk_name, DEVICE_NAME "%d", i); add_disk(bc_dev[i].bc_gendisk);// blk_queue_make_request(&bc_dev[i].bc_queue, bc_make_request);// bc_dev[i].bc_queue.queuedata = &bc_dev[i]; }#ifdef CONFIG_PROC_FS proc_bcrypt = create_proc_entry(DEVICE_NAME, S_IFDIR, 0); if (NULL != proc_bcrypt) { create_proc_read_entry(DEVICE_CONF, S_IFREG | S_IRUGO, proc_bcrypt, proc_bc_conf, NULL); create_proc_read_entry(DEVICE_STAT, S_IFREG | S_IRUGO, proc_bcrypt, proc_bc_stat, NULL); }#endif return 0;error_out: bc_cleanup(); return rc;}void __exit bc_exit(void){ bc_cleanup(); printk("BestCrypt driver is unloaded...\n");}MODULE_AUTHOR("Jetico, Inc.");MODULE_DESCRIPTION("BestCrypt encrypted block device driver.");MODULE_LICENSE("Jetico, Inc.");MODULE_PARM_DESC(bc_devices, "Max. number of devices (1-256).");MODULE_PARM_DESC(bc_partitions, "Max. partitions per device (0-63).");MODULE_INFO(vermagic, VERMAGIC_STRING);#ifdef _NEED_THIS_MODULEstruct module __this_module__attribute__((section(".gnu.linkonce.this_module"))) = {#ifdef _KBUILD_QUOTES .name = KBUILD_MODNAME,#else .name = __stringify(KBUILD_MODNAME),#endif .init = init_module,#ifdef CONFIG_MODULE_UNLOAD .exit = cleanup_module,#endif};static const char __module_depends[]__attribute_used____attribute__((section(".modinfo"))) ="depends=";#endifmodule_init(bc_init);module_exit(bc_exit);module_param(bc_devices, int, 0);module_param(bc_partitions, int, 0);EXPORT_SYMBOL(register_bc_algo);EXPORT_SYMBOL(unregister_bc_algo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -