Re: md5sum (from libkcapi) fails on kernel 4.9 but not on 4.13

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Again Stephan

Le 17/10/2017 à 09:58, Christophe LEROY a écrit :
Hi Stephan,

Le 16/10/2017 à 23:10, Stephan Mueller a écrit :
Am Montag, 16. Oktober 2017, 08:53:00 CEST schrieb Christophe LEROY:

Hi Christophe,

Hi Stephan,

I get an issue with md5sum of a big file with kernel 4.9. It don't get
that issue with kernel 4.13.

The key to the difference in libkcapi is the following code:

static void _kcapi_handle_flags(struct kcapi_handle *handle)
...
         /* older interfaces only processed 16 pages in a row */
         handle->flags.alg_max_pages = _kcapi_kernver_ge(handle, 4, 11, 0) ?
                                       UINT_MAX : ALG_MAX_PAGES;
...

This check is mainly for skcipher but it affects all cipher types. Thus, on older kernels, only 16 pages are injected into the kernel with splice and then it is reverted to sendmsg. Again, this logic is not so much of an issue for
algif_hash, but rather for algif_skcipher and algif_aead.

When I do an strace, I see a difference in the calls: at the end of the
file, with 4.9 md5sum uses sendmsg() for the last block while with 4.13
it uses splice() as for all the previous blocks.

The problem is that the last block has a size over 32kbytes, which is
the maximum size the talitos driver accepts to hash at once.
It looks like sendmsg() sends the entire block to the crypto driver
while splice() calls the crypto driver with blocks of page size.

I understand that your driver has this 32kb limit. But I am not sure what the difference between the handling of the sendmsg and the splice invocation is. According to the strace, the splice accepted 256kb of data. Looking into the hash_sendpage function implementing the backend of this splice system call, it simply performs an update invocation with this buffer size. I.e. it invokes your driver with 256kb of data. The sendmsg first performs a copy_from_user
with the maximum limit of 16 * PAGE_SIZE (see the limit variable in
hash_sendmsg) and then invokes the update function.

As far as I can see, hash_sendpage() is called with one single page, of size 16kb in my setup. If I understand correct, the loop over every page is implemented in __splice_from_pipe().


So, I am not sure why the sendmsg call chokes where the sendpage call
succeeds.

As far as I can see, the sendmsg() calls the update function with the full buffer, which in my case is over the 32kb limit of the driver.


If you tamper with the code shown above from libkcapi and set alg_max_pages to a low value, the library reverts to sendmsg after the given number of pages.

Couldn't we get the libkcapi to splice until the last full page, then only use sendmsg() for the last chunk once it is smaller than an entire page ?



Note that the test reported above is done with version 0.14.0

I've now tried a test with 1.0.0, and there seems to be another big issue: the error returned by sendmsg() is not taken into account anymore:

...
vmsplice(5, [{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 558080}], 1, SPLICE_F_MORE|SPLICE_F_GIFT) = 262144
splice(4, NULL, 7, NULL, 262144, SPLICE_F_MORE) = 262144
vmsplice(5, [{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 295936}], 1, SPLICE_F_MORE|SPLICE_F_GIFT) = 262144
splice(4, NULL, 7, NULL, 262144, SPLICE_F_MORE) = 262144
sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33792}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33814}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33836}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33858}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33880}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33902}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33924}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33946}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33968}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 33990}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument) sendmsg(7, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 34012}], msg_controllen=0, msg_flags=0}, MSG_MORE) = -1 EINVAL (Invalid argument)
...

Christophe



[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux