<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux/lib/mpi/mpicoder.c, branch v4.7</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
</subtitle>
<id>https://git.shady.money/linux/atom?h=v4.7</id>
<link rel='self' href='https://git.shady.money/linux/atom?h=v4.7'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/'/>
<updated>2016-04-05T12:35:51Z</updated>
<entry>
<title>lib/mpi: mpi_read_raw_from_sgl(): fix out-of-bounds buffer access</title>
<updated>2016-04-05T12:35:51Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:18:16Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=0bb5c9ead62f4e1eaf226744076e0b4e8348f68f'/>
<id>urn:sha1:0bb5c9ead62f4e1eaf226744076e0b4e8348f68f</id>
<content type='text'>
Within the copying loop in mpi_read_raw_from_sgl(), the last input SGE's
byte count gets artificially extended as follows:

  if (sg_is_last(sg) &amp;&amp; (len % BYTES_PER_MPI_LIMB))
    len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB);

Within the following byte copying loop, this causes reads beyond that
SGE's allocated buffer:

  BUG: KASAN: slab-out-of-bounds in mpi_read_raw_from_sgl+0x331/0x650
                                     at addr ffff8801e168d4d8
  Read of size 1 by task systemd-udevd/721
  [...]
  Call Trace:
   [&lt;ffffffff818c4d35&gt;] dump_stack+0xbc/0x117
   [&lt;ffffffff818c4c79&gt;] ? _atomic_dec_and_lock+0x169/0x169
   [&lt;ffffffff814af5d1&gt;] ? print_section+0x61/0xb0
   [&lt;ffffffff814b1109&gt;] print_trailer+0x179/0x2c0
   [&lt;ffffffff814bc524&gt;] object_err+0x34/0x40
   [&lt;ffffffff814bfdc7&gt;] kasan_report_error+0x307/0x8c0
   [&lt;ffffffff814bf315&gt;] ? kasan_unpoison_shadow+0x35/0x50
   [&lt;ffffffff814bf38e&gt;] ? kasan_kmalloc+0x5e/0x70
   [&lt;ffffffff814c0ad1&gt;] kasan_report+0x71/0xa0
   [&lt;ffffffff81938171&gt;] ? mpi_read_raw_from_sgl+0x331/0x650
   [&lt;ffffffff814bf1a6&gt;] __asan_load1+0x46/0x50
   [&lt;ffffffff81938171&gt;] mpi_read_raw_from_sgl+0x331/0x650
   [&lt;ffffffff817f41b6&gt;] rsa_verify+0x106/0x260
   [&lt;ffffffff817f40b0&gt;] ? rsa_set_pub_key+0xf0/0xf0
   [&lt;ffffffff818edc79&gt;] ? sg_init_table+0x29/0x50
   [&lt;ffffffff817f4d22&gt;] ? pkcs1pad_sg_set_buf+0xb2/0x2e0
   [&lt;ffffffff817f5b74&gt;] pkcs1pad_verify+0x1f4/0x2b0
   [&lt;ffffffff81831057&gt;] public_key_verify_signature+0x3a7/0x5e0
   [&lt;ffffffff81830cb0&gt;] ? public_key_describe+0x80/0x80
   [&lt;ffffffff817830f0&gt;] ? keyring_search_aux+0x150/0x150
   [&lt;ffffffff818334a4&gt;] ? x509_request_asymmetric_key+0x114/0x370
   [&lt;ffffffff814b83f0&gt;] ? kfree+0x220/0x370
   [&lt;ffffffff818312c2&gt;] public_key_verify_signature_2+0x32/0x50
   [&lt;ffffffff81830b5c&gt;] verify_signature+0x7c/0xb0
   [&lt;ffffffff81835d0c&gt;] pkcs7_validate_trust+0x42c/0x5f0
   [&lt;ffffffff813c391a&gt;] system_verify_data+0xca/0x170
   [&lt;ffffffff813c3850&gt;] ? top_trace_array+0x9b/0x9b
   [&lt;ffffffff81510b29&gt;] ? __vfs_read+0x279/0x3d0
   [&lt;ffffffff8129372f&gt;] mod_verify_sig+0x1ff/0x290
  [...]

The exact purpose of the len extension isn't clear to me, but due to
its form, I suspect that it's a leftover somehow accounting for leading
zero bytes within the most significant output limb.

Note however that without that len adjustement, the total number of bytes
ever processed by the inner loop equals nbytes and thus, the last output
limb gets written at this point. Thus the net effect of the len adjustement
cited above is just to keep the inner loop running for some more
iterations, namely &lt; BYTES_PER_MPI_LIMB ones, reading some extra bytes from
beyond the last SGE's buffer and discarding them afterwards.

Fix this issue by purging the extension of len beyond the last input SGE's
buffer length.

Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers")
Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_raw_from_sgl(): sanitize meaning of indices</title>
<updated>2016-04-05T12:35:51Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:18:07Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=85d541a3d14ab7a4e08c280740d9a7e097b04835'/>
<id>urn:sha1:85d541a3d14ab7a4e08c280740d9a7e097b04835</id>
<content type='text'>
Within the byte reading loop in mpi_read_raw_sgl(), there are two
housekeeping indices used, z and x.

At all times, the index z represents the number of output bytes covered
by the input SGEs for which processing has completed so far. This includes
any leading zero bytes within the most significant limb.

The index x changes its meaning after the first outer loop's iteration
though: while processing the first input SGE, it represents

  "number of leading zero bytes in most significant output limb" +
   "current position within current SGE"

For the remaining SGEs OTOH, x corresponds just to

  "current position within current SGE"

After all, it is only the sum of z and x that has any meaning for the
output buffer and thus, the

  "number of leading zero bytes in most significant output limb"

part can be moved away from x into z from the beginning, opening up the
opportunity for cleaner code.

Before the outer loop iterating over the SGEs, don't initialize z with
zero, but with the number of leading zero bytes in the most significant
output limb. For the inner loop iterating over a single SGE's bytes,
get rid of the buf_shift offset to x' bounds and let x run from zero to
sg-&gt;length - 1.

Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_raw_from_sgl(): fix nbits calculation</title>
<updated>2016-04-05T12:35:51Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:17:27Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=64c09b0b59b92ad231dd526f57f24139b728044b'/>
<id>urn:sha1:64c09b0b59b92ad231dd526f57f24139b728044b</id>
<content type='text'>
The number of bits, nbits, is calculated in mpi_read_raw_from_sgl() as
follows:

  nbits = nbytes * 8;

Afterwards, the number of leading zero bits of the first byte get
subtracted:

  nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros));

However, count_leading_zeros() takes an unsigned long and thus,
the u8 gets promoted to an unsigned long.

Thus, the above doesn't subtract the number of leading zeros in the most
significant nonzero input byte from nbits, but the number of leading
zeros of the most significant nonzero input byte promoted to unsigned long,
i.e. BITS_PER_LONG - 8 too many.

Fix this by subtracting

  count_leading_zeros(...) - (BITS_PER_LONG - 8)

from nbits only.

Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers")
Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_raw_from_sgl(): purge redundant clearing of nbits</title>
<updated>2016-04-05T12:35:51Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:45Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=60e1b74c224e9eda14e5b479413c5d990373c2cb'/>
<id>urn:sha1:60e1b74c224e9eda14e5b479413c5d990373c2cb</id>
<content type='text'>
In mpi_read_raw_from_sgl(), unsigned nbits is calculated as follows:

  nbits = nbytes * 8;

and redundantly cleared later on if nbytes == 0:

  if (nbytes &gt; 0)
    ...
  else
    nbits = 0;

Purge this redundant clearing for the sake of clarity.

Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_raw_from_sgl(): don't include leading zero SGEs in nbytes</title>
<updated>2016-04-05T12:35:50Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:44Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=ab1e912ec1021e7532148398a01eb1283437fe62'/>
<id>urn:sha1:ab1e912ec1021e7532148398a01eb1283437fe62</id>
<content type='text'>
At the very beginning of mpi_read_raw_from_sgl(), the leading zeros of
the input scatterlist are counted:

  lzeros = 0;
  for_each_sg(sgl, sg, ents, i) {
    ...
    if (/* sg contains nonzero bytes */)
      break;

    /* sg contains nothing but zeros here */
    ents--;
    lzeros = 0;
  }

Later on, the total number of trailing nonzero bytes is calculated by
subtracting the number of leading zero bytes from the total number of input
bytes:

  nbytes -= lzeros;

However, since lzeros gets reset to zero for each completely zero leading
sg in the loop above, it doesn't include those.

Besides wasting resources by allocating a too large output buffer,
this mistake propagates into the calculation of x, the number of
leading zeros within the most significant output limb:

  x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;

What's more, the low order bytes of the output, equal in number to the
extra bytes in nbytes, are left uninitialized.

Fix this by adjusting nbytes for each completely zero leading scatterlist
entry.

Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers")
Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_raw_from_sgl(): replace len argument by nbytes</title>
<updated>2016-04-05T12:35:49Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:43Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=b698538951a45dd853d9e40f51e143fdd46a60c6'/>
<id>urn:sha1:b698538951a45dd853d9e40f51e143fdd46a60c6</id>
<content type='text'>
Currently, the nbytes local variable is calculated from the len argument
as follows:

  ... mpi_read_raw_from_sgl(..., unsigned int len)
  {
    unsigned nbytes;
    ...
    if (!ents)
      nbytes = 0;
    else
      nbytes = len - lzeros;
    ...
  }

Given that nbytes is derived from len in a trivial way and that the len
argument is shadowed by a local len variable in several loops, this is just
confusing.

Rename the len argument to nbytes and get rid of the nbytes local variable.
Do the nbytes calculation in place.

Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_buffer(): fix buffer overflow</title>
<updated>2016-04-05T12:35:49Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:42Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=462696fd0fd2aae2fd38d22d19b2d08a55606014'/>
<id>urn:sha1:462696fd0fd2aae2fd38d22d19b2d08a55606014</id>
<content type='text'>
Currently, mpi_read_buffer() writes full limbs to the output buffer
and moves memory around to purge leading zero limbs afterwards.

However, with

  commit 9cbe21d8f89d ("lib/mpi: only require buffers as big as needed for
                        the integer")

the caller is only required to provide a buffer large enough to hold the
result without the leading zeros.

This might result in a buffer overflow for small MP numbers with leading
zeros.

Fix this by coping the result to its final destination within the output
buffer and not copying the leading zeros at all.

Fixes: 9cbe21d8f89d ("lib/mpi: only require buffers as big as needed for
                      the integer")
Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_buffer(): replace open coded endian conversion</title>
<updated>2016-04-05T12:35:49Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:41Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=90f864e20029600a8dc33e27b1192af4636100d4'/>
<id>urn:sha1:90f864e20029600a8dc33e27b1192af4636100d4</id>
<content type='text'>
Currently, the endian conversion from CPU order to BE is open coded in
mpi_read_buffer().

Replace this by the centrally provided cpu_to_be*() macros.
Copy from the temporary storage on stack to the destination buffer
by means of memcpy().

Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_read_buffer(): optimize skipping of leading zero limbs</title>
<updated>2016-04-05T12:35:49Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:40Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=f00fa2417b3e1252b1a761f88731af03afff4407'/>
<id>urn:sha1:f00fa2417b3e1252b1a761f88731af03afff4407</id>
<content type='text'>
Currently, if the number of leading zeros is greater than fits into a
complete limb, mpi_read_buffer() skips them by iterating over them
limb-wise.

Instead of skipping the high order zero limbs within the loop as shown
above, adjust the copying loop's bounds.

Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
<entry>
<title>lib/mpi: mpi_write_sgl(): replace open coded endian conversion</title>
<updated>2016-04-05T12:35:48Z</updated>
<author>
<name>Nicolai Stange</name>
<email>nicstange@gmail.com</email>
</author>
<published>2016-03-22T12:12:39Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=d755290689646fa66cc4830ca55569f2c9863666'/>
<id>urn:sha1:d755290689646fa66cc4830ca55569f2c9863666</id>
<content type='text'>
Currently, the endian conversion from CPU order to BE is open coded in
mpi_write_sgl().

Replace this by the centrally provided cpu_to_be*() macros.

Signed-off-by: Nicolai Stange &lt;nicstange@gmail.com&gt;
Signed-off-by: Herbert Xu &lt;herbert@gondor.apana.org.au&gt;
</content>
</entry>
</feed>
