ループバックデバイスのCRYPT2
crypt type=12として、write時++1/read時--1とするloop transferのlkmサンプルです。hogeloop_funcsのinitは、loop_register_transfer()、releaseはloop_unregister_transfer()でコールされ、initは暗号等必要な初期化処理また掛かる動的なメモリの取得等の処理を行う場合に、releaseは動的メモリの解放等の処理で使用することが想定されます。サンプルはreturn 0としています。不必要ならNULLとし定義する必要はありません。
#include <linux/module.h> #include <linux/loop.h> #define LO_HOGECRYPT 12 static int hogeloop_transfer(struct loop_device *lo, int cmd, struct page *raw_page, unsigned raw_off, struct page *loop_page, unsigned loop_off, int size, sector_t real_block) { char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off; char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off; char *in, *out; int i; if (cmd == READ) { in = raw_buf; out = loop_buf; } else { in = loop_buf; out = raw_buf; } for (i = 0; i < size; i++) { if (cmd == READ) { *out++ = *in++ - 1; } else { *out++ = *in++ + 1; } } kunmap_atomic(loop_buf, KM_USER1); kunmap_atomic(raw_buf, KM_USER0); return 0; } static int hogeloop_init(struct loop_device *lo, const struct loop_info64 *info) { return 0; } static int hogeloop_release(struct loop_device *lo) { return 0; } static struct loop_func_table hogeloop_funcs = { .number = LO_HOGECRYPT, .init = hogeloop_init, .transfer = hogeloop_transfer, .release = hogeloop_release, .owner = THIS_MODULE }; static int __init init_hogeloop(void) { int rc = loop_register_transfer(&hogeloop_funcs); if (rc) printk("hogeloop register failed\n"); return rc; } static void __exit exit_hogeloop(void) { if (loop_unregister_transfer(LO_HOGECRYPT)) printk("hogeloop unregister failed\n"); } module_init(init_hogeloop); module_exit(exit_hogeloop);サンプルをinsmodし、/dev/loop0にdiskをバインド、cryptをLO_HOGECRYPTとします。
[root@localhost lkm]# insmod hogeloop.ko [root@localhost lkm]# dd if=/dev/zero of=disk bs=1M count=1 [root@localhost lkm]# losetup /dev/loop0 disk [root@localhost lkm]# ./loopcrypt set /dev/loop0 [root@localhost lkm]# ./loopcrypt show /dev/loop0 lo_encrypt_type:12 lo_encrypt_key:hogediskに書き込まれたデータは元データ++となりますが、/dev/loop0は元データとして参照しています。
[root@localhost lkm]# echo 12345 > /dev/loop0 [root@localhost lkm]# cat /dev/loop0 12345 ddddddddddddddddddddddddddddddddddddddddddddddddddddddddd : [root@localhost lkm]# cat disk 23456 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee :
補足
crypt typeはlosetupの-Eオプションで設定できるらしいのですが、crypt名称もチェックしているのかlosetupコマンドで設定できませんでした。loopinfo.lo_encrypt_typeにtypeナンバーを設定すればいいだけの事ですので、オリジナルのloopcryptコマンドとして無理やり設定しています。なお、encrypt_keyをhogeとしていますが、サンプルでは使用していません。#include "stdio.h" #include <fcntl.h> #include <string.h> typedef unsigned short __kernel_old_dev_t; #define LO_NAME_SIZE 64 #define LO_KEY_SIZE 32 struct loop_info { int lo_number; /* ioctl r/o */ __kernel_old_dev_t lo_device; /* ioctl r/o */ unsigned long lo_inode; /* ioctl r/o */ __kernel_old_dev_t lo_rdevice; /* ioctl r/o */ int lo_offset; int lo_encrypt_type; int lo_encrypt_key_size; /* ioctl w/o */ int lo_flags; /* ioctl r/o */ char lo_name[LO_NAME_SIZE]; unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ unsigned long lo_init[2]; char reserved[4]; }; #define LOOP_SET_STATUS 0x4C02 #define LOOP_GET_STATUS 0x4C03 void show_crypt(); void set_crypt(); int get_cmd(char *cmd); void main(int argc, char *argv[]) { if (argc == 3 ) { switch (get_cmd(argv[1])) { case 0: show_crypt(argv[2]); break; case 1: set_crypt(argv[2]); break; default: printf("cmd err\n"); break; } } else { printf("param err\n"); } } int get_cmd(char *cmd) { int ans = -1; if (!strcmp(cmd, "show")) { ans = 0; } if (!strcmp(cmd, "set")) { ans = 1; } return ans; } void set_crypt() { struct loop_info loopinfo; int fd; if ((fd = open ("/dev/loop0", O_RDONLY)) < 0) { fprintf(stderr, "can't open device\n"); return; } if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) { fprintf(stderr, "can't get info\n"); close (fd); return; } loopinfo.lo_encrypt_type = 12; loopinfo.lo_encrypt_key_size = 4; strncpy(loopinfo.lo_encrypt_key, "hoge", 4); if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) { fprintf(stderr, "can't set info\n"); } close (fd); } void show_crypt() { struct loop_info loopinfo; int fd, i; if ((fd = open ("/dev/loop0", O_RDONLY)) < 0) { fprintf(stderr, "can't open device\n"); close (fd); return; } if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) { fprintf(stderr, "can't get info\n"); close (fd); return; } printf("lo_encrypt_type:%d\n", loopinfo.lo_encrypt_type); printf("lo_encrypt_key:"); for (i = 0; i < loopinfo.lo_encrypt_key_size; i++) { putchar(loopinfo.lo_encrypt_key[i]); } putchar('\n'); close (fd); }