Crypto/cryptoloop(?) bug in 2.6.1
[Note: I am not subscribed to the LKML--please CC any replies.]
While trying unsuccessfully to get encrypted loop filesystems working
under kernel 2.6.1, I found that the crypto system is not properly copying data to and from pages used by the cryptoloop driver (possibly only for file-backed loop filesystems). Using the following script with losetup from util-linux 2.12:
---- cut here ----
yes 0000000 | head -65536c > /tmp/test
head -8c /tmp/test
losetup /dev/loop0 /tmp/test
echo 1234567 > /dev/loop0
losetup -d /dev/loop0
head -8c /tmp/test
echo abcdefgh | losetup -e aes-cbc -p 0 /dev/loop0 /tmp/test echo 7654321 >/dev/loop0
losetup -d /dev/loop0
head -8c /tmp/test
---- cut here ----
kernel 2.4.21 with the kerneli.org and jari cryptoloop patches performs as expected (the first head -8c outputs "1234567", while the second outputs encrypted data), but kernel 2.6.1 outputs "1234567" both times, and attempting to decrypt the "7654321" encrypted under 2.4.21 produces garbage. Inserting debug printk's shows:
cryptoloop: cipher=[aes-cbc] keysize=32 key=[6162636465666768000000000000000000000000000000000000000000000000 [[ crypt ]]
enc=0 in=31323334 3536370A 30303030 3030300A
in: data=ffff1000 tmp=f7c63da0 // which_buf chose ffff1000
in: src_p is 55D8893C 24895C24 04FF1085 C074758B
after copy: 55D8893C 24895C24 04FF1085 C074758B
i.e., the right data is being passed into crypt(), but scatterwalk_map() isn't mapping it correctly. Likewise, the data encrypted on write isn't making it to the page allocated for writing by the cryptoloop driver. The patch below fixes the problem by bypassing the mapping completely and directly accessing the pages passed in, but I have no idea whether this is safe or not.
Is this a known problem, and if so, is there a solution for it?
--Andrew Church
[email protected] http://achurch.org/
---------------------------------------------------------------------------
cipher.c renamed from cipher.c.old +1 -3
@@ -98,7 +98,7 @@static void scatterwalk_map (struct scatter_walk *walk,int out) { - walk->data =crypto_kmap (walk->page, out) + walk->offset; + walk->data =pfn_to_kaddr (page_to_pfn (walk->page)) + walk->offset; } static void scatter_page_done(struct scatter_walk *walk, int out,
@@ -127,7 +127,6 @@static void scatter_done (struct scatter_walk *walk,int out,int more) { -crypto_kunmap (walk->data, out);if (walk->len_this_page ==0 || !more)scatter_page_done (walk, out, more); }
@@ -145,7 +144,6 @@ buf += walk->len_this_page; nbytes -= walk->len_this_page; -crypto_kunmap (walk->data, out);scatter_page_done (walk, out,1 );scatterwalk_map (walk, out); }