cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qcow2-threads.c (14866B)


      1/*
      2 * Threaded data processing for Qcow2: compression, encryption
      3 *
      4 * Copyright (c) 2004-2006 Fabrice Bellard
      5 * Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved.
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in
     15 * all copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23 * THE SOFTWARE.
     24 */
     25
     26#include "qemu/osdep.h"
     27
     28#define ZLIB_CONST
     29#include <zlib.h>
     30
     31#ifdef CONFIG_ZSTD
     32#include <zstd.h>
     33#include <zstd_errors.h>
     34#endif
     35
     36#include "qcow2.h"
     37#include "block/thread-pool.h"
     38#include "crypto.h"
     39
     40static int coroutine_fn
     41qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
     42{
     43    int ret;
     44    BDRVQcow2State *s = bs->opaque;
     45    ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
     46
     47    qemu_co_mutex_lock(&s->lock);
     48    while (s->nb_threads >= QCOW2_MAX_THREADS) {
     49        qemu_co_queue_wait(&s->thread_task_queue, &s->lock);
     50    }
     51    s->nb_threads++;
     52    qemu_co_mutex_unlock(&s->lock);
     53
     54    ret = thread_pool_submit_co(pool, func, arg);
     55
     56    qemu_co_mutex_lock(&s->lock);
     57    s->nb_threads--;
     58    qemu_co_queue_next(&s->thread_task_queue);
     59    qemu_co_mutex_unlock(&s->lock);
     60
     61    return ret;
     62}
     63
     64
     65/*
     66 * Compression
     67 */
     68
     69typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size,
     70                                     const void *src, size_t src_size);
     71typedef struct Qcow2CompressData {
     72    void *dest;
     73    size_t dest_size;
     74    const void *src;
     75    size_t src_size;
     76    ssize_t ret;
     77
     78    Qcow2CompressFunc func;
     79} Qcow2CompressData;
     80
     81/*
     82 * qcow2_zlib_compress()
     83 *
     84 * Compress @src_size bytes of data using zlib compression method
     85 *
     86 * @dest - destination buffer, @dest_size bytes
     87 * @src - source buffer, @src_size bytes
     88 *
     89 * Returns: compressed size on success
     90 *          -ENOMEM destination buffer is not enough to store compressed data
     91 *          -EIO    on any other error
     92 */
     93static ssize_t qcow2_zlib_compress(void *dest, size_t dest_size,
     94                                   const void *src, size_t src_size)
     95{
     96    ssize_t ret;
     97    z_stream strm;
     98
     99    /* best compression, small window, no zlib header */
    100    memset(&strm, 0, sizeof(strm));
    101    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
    102                       -12, 9, Z_DEFAULT_STRATEGY);
    103    if (ret != Z_OK) {
    104        return -EIO;
    105    }
    106
    107    /*
    108     * strm.next_in is not const in old zlib versions, such as those used on
    109     * OpenBSD/NetBSD, so cast the const away
    110     */
    111    strm.avail_in = src_size;
    112    strm.next_in = (void *) src;
    113    strm.avail_out = dest_size;
    114    strm.next_out = dest;
    115
    116    ret = deflate(&strm, Z_FINISH);
    117    if (ret == Z_STREAM_END) {
    118        ret = dest_size - strm.avail_out;
    119    } else {
    120        ret = (ret == Z_OK ? -ENOMEM : -EIO);
    121    }
    122
    123    deflateEnd(&strm);
    124
    125    return ret;
    126}
    127
    128/*
    129 * qcow2_zlib_decompress()
    130 *
    131 * Decompress some data (not more than @src_size bytes) to produce exactly
    132 * @dest_size bytes using zlib compression method
    133 *
    134 * @dest - destination buffer, @dest_size bytes
    135 * @src - source buffer, @src_size bytes
    136 *
    137 * Returns: 0 on success
    138 *          -EIO on fail
    139 */
    140static ssize_t qcow2_zlib_decompress(void *dest, size_t dest_size,
    141                                     const void *src, size_t src_size)
    142{
    143    int ret;
    144    z_stream strm;
    145
    146    memset(&strm, 0, sizeof(strm));
    147    strm.avail_in = src_size;
    148    strm.next_in = (void *) src;
    149    strm.avail_out = dest_size;
    150    strm.next_out = dest;
    151
    152    ret = inflateInit2(&strm, -12);
    153    if (ret != Z_OK) {
    154        return -EIO;
    155    }
    156
    157    ret = inflate(&strm, Z_FINISH);
    158    if ((ret == Z_STREAM_END || ret == Z_BUF_ERROR) && strm.avail_out == 0) {
    159        /*
    160         * We approve Z_BUF_ERROR because we need @dest buffer to be filled, but
    161         * @src buffer may be processed partly (because in qcow2 we know size of
    162         * compressed data with precision of one sector)
    163         */
    164        ret = 0;
    165    } else {
    166        ret = -EIO;
    167    }
    168
    169    inflateEnd(&strm);
    170
    171    return ret;
    172}
    173
    174#ifdef CONFIG_ZSTD
    175
    176/*
    177 * qcow2_zstd_compress()
    178 *
    179 * Compress @src_size bytes of data using zstd compression method
    180 *
    181 * @dest - destination buffer, @dest_size bytes
    182 * @src - source buffer, @src_size bytes
    183 *
    184 * Returns: compressed size on success
    185 *          -ENOMEM destination buffer is not enough to store compressed data
    186 *          -EIO    on any other error
    187 */
    188static ssize_t qcow2_zstd_compress(void *dest, size_t dest_size,
    189                                   const void *src, size_t src_size)
    190{
    191    ssize_t ret;
    192    size_t zstd_ret;
    193    ZSTD_outBuffer output = {
    194        .dst = dest,
    195        .size = dest_size,
    196        .pos = 0
    197    };
    198    ZSTD_inBuffer input = {
    199        .src = src,
    200        .size = src_size,
    201        .pos = 0
    202    };
    203    ZSTD_CCtx *cctx = ZSTD_createCCtx();
    204
    205    if (!cctx) {
    206        return -EIO;
    207    }
    208    /*
    209     * Use the zstd streamed interface for symmetry with decompression,
    210     * where streaming is essential since we don't record the exact
    211     * compressed size.
    212     *
    213     * ZSTD_compressStream2() tries to compress everything it could
    214     * with a single call. Although, ZSTD docs says that:
    215     * "You must continue calling ZSTD_compressStream2() with ZSTD_e_end
    216     * until it returns 0, at which point you are free to start a new frame",
    217     * in out tests we saw the only case when it returned with >0 -
    218     * when the output buffer was too small. In that case,
    219     * ZSTD_compressStream2() expects a bigger buffer on the next call.
    220     * We can't provide a bigger buffer because we are limited with dest_size
    221     * which we pass to the ZSTD_compressStream2() at once.
    222     * So, we don't need any loops and just abort the compression when we
    223     * don't get 0 result on the first call.
    224     */
    225    zstd_ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
    226
    227    if (zstd_ret) {
    228        if (zstd_ret > output.size - output.pos) {
    229            ret = -ENOMEM;
    230        } else {
    231            ret = -EIO;
    232        }
    233        goto out;
    234    }
    235
    236    /* make sure that zstd didn't overflow the dest buffer */
    237    assert(output.pos <= dest_size);
    238    ret = output.pos;
    239out:
    240    ZSTD_freeCCtx(cctx);
    241    return ret;
    242}
    243
    244/*
    245 * qcow2_zstd_decompress()
    246 *
    247 * Decompress some data (not more than @src_size bytes) to produce exactly
    248 * @dest_size bytes using zstd compression method
    249 *
    250 * @dest - destination buffer, @dest_size bytes
    251 * @src - source buffer, @src_size bytes
    252 *
    253 * Returns: 0 on success
    254 *          -EIO on any error
    255 */
    256static ssize_t qcow2_zstd_decompress(void *dest, size_t dest_size,
    257                                     const void *src, size_t src_size)
    258{
    259    size_t zstd_ret = 0;
    260    ssize_t ret = 0;
    261    ZSTD_outBuffer output = {
    262        .dst = dest,
    263        .size = dest_size,
    264        .pos = 0
    265    };
    266    ZSTD_inBuffer input = {
    267        .src = src,
    268        .size = src_size,
    269        .pos = 0
    270    };
    271    ZSTD_DCtx *dctx = ZSTD_createDCtx();
    272
    273    if (!dctx) {
    274        return -EIO;
    275    }
    276
    277    /*
    278     * The compressed stream from the input buffer may consist of more
    279     * than one zstd frame. So we iterate until we get a fully
    280     * uncompressed cluster.
    281     * From zstd docs related to ZSTD_decompressStream:
    282     * "return : 0 when a frame is completely decoded and fully flushed"
    283     * We suppose that this means: each time ZSTD_decompressStream reads
    284     * only ONE full frame and returns 0 if and only if that frame
    285     * is completely decoded and flushed. Only after returning 0,
    286     * ZSTD_decompressStream reads another ONE full frame.
    287     */
    288    while (output.pos < output.size) {
    289        size_t last_in_pos = input.pos;
    290        size_t last_out_pos = output.pos;
    291        zstd_ret = ZSTD_decompressStream(dctx, &output, &input);
    292
    293        if (ZSTD_isError(zstd_ret)) {
    294            ret = -EIO;
    295            break;
    296        }
    297
    298        /*
    299         * The ZSTD manual is vague about what to do if it reads
    300         * the buffer partially, and we don't want to get stuck
    301         * in an infinite loop where ZSTD_decompressStream
    302         * returns > 0 waiting for another input chunk. So, we add
    303         * a check which ensures that the loop makes some progress
    304         * on each step.
    305         */
    306        if (last_in_pos >= input.pos &&
    307            last_out_pos >= output.pos) {
    308            ret = -EIO;
    309            break;
    310        }
    311    }
    312    /*
    313     * Make sure that we have the frame fully flushed here
    314     * if not, we somehow managed to get uncompressed cluster
    315     * greater then the cluster size, possibly because of its
    316     * damage.
    317     */
    318    if (zstd_ret > 0) {
    319        ret = -EIO;
    320    }
    321
    322    ZSTD_freeDCtx(dctx);
    323    assert(ret == 0 || ret == -EIO);
    324    return ret;
    325}
    326#endif
    327
    328static int qcow2_compress_pool_func(void *opaque)
    329{
    330    Qcow2CompressData *data = opaque;
    331
    332    data->ret = data->func(data->dest, data->dest_size,
    333                           data->src, data->src_size);
    334
    335    return 0;
    336}
    337
    338static ssize_t coroutine_fn
    339qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size,
    340                     const void *src, size_t src_size, Qcow2CompressFunc func)
    341{
    342    Qcow2CompressData arg = {
    343        .dest = dest,
    344        .dest_size = dest_size,
    345        .src = src,
    346        .src_size = src_size,
    347        .func = func,
    348    };
    349
    350    qcow2_co_process(bs, qcow2_compress_pool_func, &arg);
    351
    352    return arg.ret;
    353}
    354
    355/*
    356 * qcow2_co_compress()
    357 *
    358 * Compress @src_size bytes of data using the compression
    359 * method defined by the image compression type
    360 *
    361 * @dest - destination buffer, @dest_size bytes
    362 * @src - source buffer, @src_size bytes
    363 *
    364 * Returns: compressed size on success
    365 *          a negative error code on failure
    366 */
    367ssize_t coroutine_fn
    368qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
    369                  const void *src, size_t src_size)
    370{
    371    BDRVQcow2State *s = bs->opaque;
    372    Qcow2CompressFunc fn;
    373
    374    switch (s->compression_type) {
    375    case QCOW2_COMPRESSION_TYPE_ZLIB:
    376        fn = qcow2_zlib_compress;
    377        break;
    378
    379#ifdef CONFIG_ZSTD
    380    case QCOW2_COMPRESSION_TYPE_ZSTD:
    381        fn = qcow2_zstd_compress;
    382        break;
    383#endif
    384    default:
    385        abort();
    386    }
    387
    388    return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
    389}
    390
    391/*
    392 * qcow2_co_decompress()
    393 *
    394 * Decompress some data (not more than @src_size bytes) to produce exactly
    395 * @dest_size bytes using the compression method defined by the image
    396 * compression type
    397 *
    398 * @dest - destination buffer, @dest_size bytes
    399 * @src - source buffer, @src_size bytes
    400 *
    401 * Returns: 0 on success
    402 *          a negative error code on failure
    403 */
    404ssize_t coroutine_fn
    405qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
    406                    const void *src, size_t src_size)
    407{
    408    BDRVQcow2State *s = bs->opaque;
    409    Qcow2CompressFunc fn;
    410
    411    switch (s->compression_type) {
    412    case QCOW2_COMPRESSION_TYPE_ZLIB:
    413        fn = qcow2_zlib_decompress;
    414        break;
    415
    416#ifdef CONFIG_ZSTD
    417    case QCOW2_COMPRESSION_TYPE_ZSTD:
    418        fn = qcow2_zstd_decompress;
    419        break;
    420#endif
    421    default:
    422        abort();
    423    }
    424
    425    return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
    426}
    427
    428
    429/*
    430 * Cryptography
    431 */
    432
    433/*
    434 * Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and
    435 * qcrypto_block_decrypt() functions.
    436 */
    437typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset,
    438                               uint8_t *buf, size_t len, Error **errp);
    439
    440typedef struct Qcow2EncDecData {
    441    QCryptoBlock *block;
    442    uint64_t offset;
    443    uint8_t *buf;
    444    size_t len;
    445
    446    Qcow2EncDecFunc func;
    447} Qcow2EncDecData;
    448
    449static int qcow2_encdec_pool_func(void *opaque)
    450{
    451    Qcow2EncDecData *data = opaque;
    452
    453    return data->func(data->block, data->offset, data->buf, data->len, NULL);
    454}
    455
    456static int coroutine_fn
    457qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset,
    458                uint64_t guest_offset, void *buf, size_t len,
    459                Qcow2EncDecFunc func)
    460{
    461    BDRVQcow2State *s = bs->opaque;
    462    Qcow2EncDecData arg = {
    463        .block = s->crypto,
    464        .offset = s->crypt_physical_offset ? host_offset : guest_offset,
    465        .buf = buf,
    466        .len = len,
    467        .func = func,
    468    };
    469    uint64_t sector_size;
    470
    471    assert(s->crypto);
    472
    473    sector_size = qcrypto_block_get_sector_size(s->crypto);
    474    assert(QEMU_IS_ALIGNED(guest_offset, sector_size));
    475    assert(QEMU_IS_ALIGNED(host_offset, sector_size));
    476    assert(QEMU_IS_ALIGNED(len, sector_size));
    477
    478    return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
    479}
    480
    481/*
    482 * qcow2_co_encrypt()
    483 *
    484 * Encrypts one or more contiguous aligned sectors
    485 *
    486 * @host_offset - underlying storage offset of the first sector of the
    487 * data to be encrypted
    488 *
    489 * @guest_offset - guest (virtual) offset of the first sector of the
    490 * data to be encrypted
    491 *
    492 * @buf - buffer with the data to encrypt, that after encryption
    493 *        will be written to the underlying storage device at
    494 *        @host_offset
    495 *
    496 * @len - length of the buffer (must be a multiple of the encryption
    497 *        sector size)
    498 *
    499 * Depending on the encryption method, @host_offset and/or @guest_offset
    500 * may be used for generating the initialization vector for
    501 * encryption.
    502 *
    503 * Note that while the whole range must be aligned on sectors, it
    504 * does not have to be aligned on clusters and can also cross cluster
    505 * boundaries
    506 */
    507int coroutine_fn
    508qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
    509                 uint64_t guest_offset, void *buf, size_t len)
    510{
    511    return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
    512                           qcrypto_block_encrypt);
    513}
    514
    515/*
    516 * qcow2_co_decrypt()
    517 *
    518 * Decrypts one or more contiguous aligned sectors
    519 * Similar to qcow2_co_encrypt
    520 */
    521int coroutine_fn
    522qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
    523                 uint64_t guest_offset, void *buf, size_t len)
    524{
    525    return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
    526                           qcrypto_block_decrypt);
    527}