Revision 834a846eee9588ac672cb504677490c28b597871 authored by Cornelia Huck on 02 May 2018, 12:52:21 UTC, committed by Michael Roth on 21 June 2018, 01:45:02 UTC
We currently pass an integer as the subcode parameter. However,
the upper bits of the register containing the subcode need to
be 0, which is not guaranteed unless we explicitly specify the
subcode to be an unsigned long value.

Fixes: d046c51dad3 ("pc-bios/s390-ccw: Get device address via diag 308/6")
Cc: qemu-stable@nongnu.org
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Tested-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit 63d8b5ace31c1e1f3996fe4cd551d6d377594d5a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
1 parent 0304f75
Raw File
afalg.c
/*
 * QEMU Crypto af_alg support
 *
 * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
 *
 * Authors:
 *    Longpeng(Mike) <longpeng2@huawei.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * (at your option) any later version.  See the COPYING file in the
 * top-level directory.
 */
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qemu/sockets.h"
#include "qapi/error.h"
#include "afalgpriv.h"

static bool
qcrypto_afalg_build_saddr(const char *type, const char *name,
                          struct sockaddr_alg *salg, Error **errp)
{
    salg->salg_family = AF_ALG;

    if (strnlen(type, SALG_TYPE_LEN_MAX) >= SALG_TYPE_LEN_MAX) {
        error_setg(errp, "Afalg type(%s) is larger than %d bytes",
                   type, SALG_TYPE_LEN_MAX);
        return false;
    }

    if (strnlen(name, SALG_NAME_LEN_MAX) >= SALG_NAME_LEN_MAX) {
        error_setg(errp, "Afalg name(%s) is larger than %d bytes",
                   name, SALG_NAME_LEN_MAX);
        return false;
    }

    pstrcpy((char *)salg->salg_type, SALG_TYPE_LEN_MAX, type);
    pstrcpy((char *)salg->salg_name, SALG_NAME_LEN_MAX, name);

    return true;
}

static int
qcrypto_afalg_socket_bind(const char *type, const char *name,
                          Error **errp)
{
    int sbind;
    struct sockaddr_alg salg = {0};

    if (!qcrypto_afalg_build_saddr(type, name, &salg, errp)) {
        return -1;
    }

    sbind = qemu_socket(AF_ALG, SOCK_SEQPACKET, 0);
    if (sbind < 0) {
        error_setg_errno(errp, errno, "Failed to create socket");
        return -1;
    }

    if (bind(sbind, (const struct sockaddr *)&salg, sizeof(salg)) != 0) {
        error_setg_errno(errp, errno, "Failed to bind socket");
        closesocket(sbind);
        return -1;
    }

    return sbind;
}

QCryptoAFAlg *
qcrypto_afalg_comm_alloc(const char *type, const char *name,
                         Error **errp)
{
    QCryptoAFAlg *afalg;

    afalg = g_new0(QCryptoAFAlg, 1);
    /* initilize crypto API socket */
    afalg->opfd = -1;
    afalg->tfmfd = qcrypto_afalg_socket_bind(type, name, errp);
    if (afalg->tfmfd == -1) {
        goto error;
    }

    afalg->opfd = qemu_accept(afalg->tfmfd, NULL, 0);
    if (afalg->opfd == -1) {
        error_setg_errno(errp, errno, "Failed to accept socket");
        goto error;
    }

    return afalg;

error:
    qcrypto_afalg_comm_free(afalg);
    return NULL;
}

void qcrypto_afalg_comm_free(QCryptoAFAlg *afalg)
{
    if (!afalg) {
        return;
    }

    if (afalg->msg) {
        g_free(afalg->msg->msg_control);
        g_free(afalg->msg);
    }

    if (afalg->tfmfd != -1) {
        closesocket(afalg->tfmfd);
    }

    if (afalg->opfd != -1) {
        closesocket(afalg->opfd);
    }

    g_free(afalg);
}
back to top