📄 bc_dev24.c
字号:
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 (!bd->bd_flags.configured) return 0; fsync_dev(dev); if (bd->bd_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); bd->bd_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;}static int bc_check_activity(struct bc_device *bc, kdev_t dev, long *arg) { if (bc_find_pid_safe(current->pid) < 0) return -EPERM; if (NULL == arg) return -EINVAL; fsync_dev(dev); put_user(bc->bc_activity, arg); bc->bc_activity = 0; 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->key_handle, &query.key_handle, sizeof(KEY_HANDLE)))*/ 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 blkgetsize(struct bc_disk *bd, struct bc_device *bc, u32 *arg){ if (NULL == bc->bc_dentry) return -ENXIO; if (NULL == arg) return -EINVAL; put_user(bc_sizes[bd->bd_number] << 1, arg); return 0;}#ifdef BLKGETSIZE64static int blkgetsize64(struct bc_disk *bd, struct bc_device *bc, u64 *arg){ if (NULL == bc->bc_dentry) return -ENXIO; if (NULL == arg) return -EINVAL; put_user((u64)(bc_sizes[bd->bd_number] << 10), arg); return 0;}#endifstatic int hdio_getgeo(struct bc_disk *bd, 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_sizes[bd->bd_number] << 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 bc_disk *bd; int error; if (NULL == inode) return -EINVAL; bc = get_bcdev(inode->i_rdev); 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(bd, bc, (struct bc_info*) arg)); BC_HANDLER("set_fd ", BC_SET_FD, bc_set_fd (bd, bc, inode->i_rdev, inode, (struct bc_file64 *) arg)); BC_HANDLER("clr_fd ", BC_CLR_FD, bc_clr_fd (bd, bc, inode->i_rdev, inode)); BC_HANDLER("lock_dev", BC_LOCK_DEV, bc_lock_dev(bd, bc, inode->i_rdev, 1)); BC_HANDLER("ulck_dev", BC_UNLOCK_DEV, bc_lock_dev(bd, bc, inode->i_rdev, 0)); BC_HANDLER("frc_ulck", BC_FORCE_UNLOCK, bc_force_unlock(bd, bc, 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("blkgetsz", BLKGETSIZE, blkgetsize (bd, bc, (u32 *)arg));#ifdef BLKGETSIZE64 BC_HANDLER("blkgts64", BLKGETSIZE64, blkgetsize64(bd, bc, (u64 *)arg));#endif BC_HANDLER("hdio_geo", HDIO_GETGEO, hdio_getgeo(bd, 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;}/*====================================================================*//*-----------------------------------------------------------*/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;}/*-----------------------------------------------------------*/int init_module(void){ int i, max_devices, rc = 0; char buf[32]; 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 (devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &bc_bdops)) { return -EIO; } if (0 > init_bc_algo()) { return -EINVAL; } bc_dev = kmalloc( bc_devices * sizeof(struct bc_device), GFP_KERNEL); bc_dsk = kmalloc(max_devices * sizeof(struct bc_disk), GFP_KERNEL); bc_sizes = kmalloc(max_devices * sizeof(int), GFP_KERNEL); bc_blksizes = kmalloc(max_devices * sizeof(int), GFP_KERNEL);// fixed gendisk->hd_struct here. Many thanks to Andreas Rieke bc_hd = kmalloc(max_devices * sizeof(struct hd_struct), GFP_KERNEL); bc_pid_table = kmalloc(BC_PID_SIZE * sizeof(pid_t), GFP_KERNEL); if (NULL == bc_dev || NULL == bc_sizes || NULL == bc_blksizes || NULL == bc_pid_table || NULL == bc_hd) { rc = -ENOMEM; goto error_out; } memset(bc_dev, 0, bc_devices * sizeof(struct bc_device)); memset(bc_dsk, 0, max_devices * sizeof(struct bc_disk)); memset(bc_sizes, 0, max_devices * sizeof(int)); memset(bc_blksizes, 0, max_devices * sizeof(int)); memset(bc_hd, 0, max_devices * sizeof(struct hd_struct)); memset(&bc_gendisk, 0, sizeof(bc_gendisk)); 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; bc_hdevfs = devfs_mk_dir(NULL, DEVICE_NAME, NULL); for (i = 0; i < bc_devices; i++) { bc_dev[i].bc_number = i; 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); init_MUTEX(&bc_dev[i].bc_control); init_MUTEX_LOCKED(&bc_dev[i].bc_run); init_MUTEX_LOCKED(&bc_dev[i].bc_thread); spin_lock_init(&bc_dev[i].bc_lock); } for (i = 0; i < max_devices; i++) bc_dsk[i].bd_number = i; blk_size[MAJOR_NR] = bc_sizes; blksize_size[MAJOR_NR] = bc_blksizes; bc_gendisk.major = MAJOR_NR; bc_gendisk.major_name = DEVICE_NAME; bc_gendisk.minor_shift = bc_minor_shift; bc_gendisk.max_p = 1 << bc_minor_shift; bc_gendisk.part = bc_hd; bc_gendisk.sizes = bc_sizes; bc_gendisk.fops = &bc_bdops;#ifdef _GENDISK_OLD_ bc_gendisk.next = gendisk_head; gendisk_head = &bc_gendisk;#else add_gendisk(&bc_gendisk);#endif blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), bc_make_request);#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: if (bc_hd) kfree(bc_hd); if (bc_dev) kfree(bc_dev); if (bc_dsk) kfree(bc_dsk); if (bc_sizes) kfree(bc_sizes); if (bc_blksizes) kfree(bc_blksizes); return rc;}void cleanup_module(void){#ifdef _GENDISK_OLD_ struct gendisk **gdp;#endif 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 devfs_unregister(bc_hdevfs); devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME);#ifdef _GENDISK_OLD_ for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) if (*gdp == &bc_gendisk) break; if (!*gdp) printk(KERN_ERR "bc: entry in disk chain missing!\n"); else *gdp = (*gdp)->next;#else del_gendisk(&bc_gendisk);#endif if (bc_dev) kfree(bc_dev); if (bc_dsk) kfree(bc_dsk); if (bc_sizes) kfree(bc_sizes); if (bc_blksizes) kfree(bc_blksizes); if (bc_hd) kfree(bc_hd); if (bc_pid_table) kfree(bc_pid_table);}/*-- end of device registration stuff -----------------------*/char bc_dev24_c[]="$Id: bc_dev24.c,v 1.37 2006/03/07 05:40:24 nail Rel-1.6-3 $";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -