📄 bc_dev22.c
字号:
/*-- 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))) 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, long *arg) { if (!bc->bc_dentry) return -ENXIO; if (!arg) return -EINVAL; put_user(bc_sizes[bd->bd_number] << 1, arg); return 0;}static 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 (!inode) return -EINVAL; bc = get_bcdev(inode->i_rdev); if (NULL == bc) { error = save_fops.ioctl(inode, file, cmd, arg); if (max_loop) { if (save_blksize) memcpy(bc_sizes, save_blksize, (max_loop)*sizeof(int)); if (save_blksize_size) memcpy(bc_blksizes, save_blksize_size, (max_loop)*sizeof(int)); } return error; } bd = get_bcdsk(inode->i_rdev); 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, (struct bc_file64 *) arg)); BC_HANDLER("clr_fd ", BC_CLR_FD, bc_clr_fd (bd, bc)); 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, (long *)arg)); 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 %d\n", bc_start_minor); 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 max_devices, rc, error; struct file_operations *fops; struct inode fake_inode; bc_start_minor = 128; if ((bc_devices > MAX_MINORS-bc_start_minor) || (bc_devices <= 0)) bc_devices = DEFAULT_BC_DEVICES; if (bc_partitions > 1) { for (bc_minor_shift = 0; bc_partitions; bc_minor_shift++) bc_partitions >>= 1; bc_partitions = 1 << bc_minor_shift; while (bc_start_minor & (bc_partitions - 1)) { bc_partitions >>= 1; bc_minor_shift--; } if ((MAX_MINORS-bc_start_minor)/bc_partitions < bc_devices) bc_devices = (MAX_MINORS-bc_start_minor)/bc_partitions; } if (bc_partitions < 2) { 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 BestCrypt v%s (%d[%d] devices)...\n", BC_VERSION_STRING, bc_devices, bc_partitions); memset(&fake_inode, 0, sizeof(struct inode)); fake_inode.i_rdev = MKDEV(MAJOR_NR, bc_start_minor); fops = get_blkfops(MAJOR_NR); if (NULL == fops) { if (0 > register_blkdev(MAJOR_NR, DEVICE_NAME, &bc_fops)) { printk(KERN_ERR "bc: unable to get major number %d\n", MAJOR_NR); return -EIO; } } else { if (-ENODEV != fops->open(&fake_inode, NULL)) { fops->release(&fake_inode, NULL); printk(KERN_ERR "bc: already loaded\n"); return -EIO; } for (max_loop = 255; max_loop >= 0; max_loop--) { fake_inode.i_rdev = MKDEV(MAJOR_NR, max_loop); if (-ENODEV != fops->open(&fake_inode, NULL)) break; } if ((max_loop < 0) || (max_loop >= bc_start_minor)) { printk(KERN_ERR "bc: initialization error\n"); return -EIO; } max_loop++; memcpy(&save_fops, fops, sizeof(struct file_operations)); memcpy(fops, &bc_fops, sizeof(struct file_operations)); save_request_fn = BC_GET_REQUEST_FN(MAJOR_NR); save_blksize = blk_size[MAJOR_NR]; save_blksize_size = blksize_size[MAJOR_NR]; } bc_dev = kmalloc(bc_devices * sizeof(struct bc_device), GFP_KERNEL); bc_dsk = kmalloc(max_devices * sizeof(struct bc_disk), GFP_KERNEL); bc_buffers[0].ptr = vmalloc(BC_BUFFERS * BC_BUFFER_SIZE); bc_pid_table = kmalloc(BC_PID_SIZE * sizeof(pid_t), GFP_KERNEL); if (NULL == bc_dev || NULL == bc_dsk || NULL == bc_pid_table || NULL == bc_buffers[0].ptr) { error = -ENOMEM; goto error_out; } memset(bc_sizes, 0, sizeof(bc_sizes)); memset(bc_blksizes, 0, sizeof(bc_blksizes)); memset(bc_hd, 0, sizeof(bc_hd)); memset(bc_dev, 0, bc_devices * sizeof(struct bc_device)); memset(bc_dsk, 0, max_devices * sizeof(struct bc_disk)); memset(bc_pid_table, 0, BC_PID_SIZE * sizeof(pid_t)); bc_pid_size = BC_PID_SIZE; bc_pid_next = 0; bc_pid_sema = MUTEX; init_timer(&bc_pid_timer); bc_pid_timer.function = bc_pid_timer_proc; for (rc = 0; rc < bc_devices; rc++) { bc_dev[rc].bc_number = rc; bc_dev[rc].bc_control = MUTEX; } for (rc = 0; rc < max_devices; rc++) { bc_dsk[rc].bd_number = rc + bc_start_minor; } for (rc = 0; rc < BC_BUFFERS; rc++) { bc_buffers[rc].ptr = bc_buffers[0].ptr + rc * BC_BUFFER_SIZE; atomic_set(&bc_buffers[rc].count, 1); } if (0 > init_bc_algo()) { error = -EINVAL; goto error_out; }#ifdef CONFIG_PROC_FS proc_bcrypt = create_proc_entry("bcrypt", S_IFDIR, &proc_root); if (proc_bcrypt) { proc_tmp = create_proc_entry(DEVICE_CONF, S_IFREG | S_IRUGO, proc_bcrypt); if (proc_tmp) proc_tmp->read_proc = proc_bc_conf; proc_tmp = create_proc_entry(DEVICE_STAT, S_IFREG | S_IRUGO, proc_bcrypt); if (proc_tmp) proc_tmp->read_proc = proc_bc_stat; } #endif if (max_loop) { if (blk_size[MAJOR_NR]) memcpy(bc_sizes, blk_size[MAJOR_NR], (max_loop)*sizeof(int)); if (blksize_size[MAJOR_NR]) memcpy(bc_blksizes, blksize_size[MAJOR_NR], (max_loop)*sizeof(int)); } BC_GET_REQUEST_FN(MAJOR_NR) = do_bc_request; 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.max_nr = (MAX_MINORS - bc_start_minor) >> bc_minor_shift; bc_gendisk.init = NULL; bc_gendisk.part = bc_hd; bc_gendisk.sizes = bc_sizes; bc_gendisk.nr_real = 0; bc_gendisk.real_devices = NULL; bc_gendisk.next = gendisk_head; gendisk_head = &bc_gendisk; return 0; error_out: if (NULL == fops) { unregister_blkdev(MAJOR_NR, DEVICE_NAME); } else { memcpy(fops, &save_fops, sizeof(struct file_operations)); } if (bc_dev) kfree(bc_dev); if (bc_dsk) kfree(bc_dsk); if (bc_pid_table) kfree(bc_pid_table); if (bc_buffers[0].ptr) vfree(bc_buffers[0].ptr); bc_dev = NULL; bc_dsk = NULL; bc_buffers[0].ptr = NULL; return error;}void cleanup_module(void) { struct file_operations *fops; struct gendisk **gdp; struct inode fake_inode; down(&bc_pid_sema); del_timer(&bc_pid_timer); up(&bc_pid_sema); if (max_loop) { fops = get_blkfops(MAJOR_NR); memcpy(fops, &save_fops, sizeof(struct file_operations)); BC_GET_REQUEST_FN(MAJOR_NR) = save_request_fn; memcpy(save_blksize, blk_size[MAJOR_NR], max_loop*sizeof(int)); memcpy(save_blksize_size, blksize_size[MAJOR_NR], max_loop*sizeof(int)); blk_size[MAJOR_NR] = save_blksize; blksize_size[MAJOR_NR] = save_blksize_size; memset(&fake_inode, 0, sizeof(struct inode)); fake_inode.i_rdev = MKDEV(MAJOR_NR, max_loop-1); fops->release(&fake_inode, NULL); } else { if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0) printk(KERN_ERR "bc: cleanup failed.\n"); } 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;#ifdef CONFIG_PROC_FS if (proc_bcrypt) { remove_proc_entry(DEVICE_CONF, proc_bcrypt); remove_proc_entry(DEVICE_STAT, proc_bcrypt); } remove_proc_entry("bcrypt", &proc_root);#endif if (bc_dev) kfree(bc_dev); if (bc_dsk) kfree(bc_dsk); if (bc_pid_table) kfree(bc_pid_table); if (bc_buffers[0].ptr) vfree(bc_buffers[0].ptr); bc_dev = NULL; bc_dsk = NULL; bc_buffers[0].ptr = NULL;}/*-- end of device registration stuff -----------------------*/ char bc_dev22_c[]="$Id: bc_dev22.c,v 1.18 2006/03/07 05:40:24 nail Rel-1.6-5 $";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -