/*
 * virtio-net Fuzzing Target
 *
 * Copyright Red Hat Inc., 2019
 *
 * Authors:
 *  Alexander Bulekov   <alxndr@bu.edu>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"

#include "standard-headers/linux/virtio_config.h"
#include "tests/qtest/libqtest.h"
#include "tests/qtest/libqos/virtio-net.h"
#include "fuzz.h"
#include "qos_fuzz.h"


#define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
#define QVIRTIO_RX_VQ 0
#define QVIRTIO_TX_VQ 1
#define QVIRTIO_CTRL_VQ 2

static int sockfds[2];
static bool sockfds_initialized;

static void virtio_net_fuzz_multi(QTestState *s,
        const unsigned char *Data, size_t Size, bool check_used)
{
    typedef struct vq_action {
        uint8_t queue;
        uint8_t length;
        uint8_t write;
        uint8_t next;
        uint8_t rx;
    } vq_action;

    uint32_t free_head = 0;

    QGuestAllocator *t_alloc = fuzz_qos_alloc;

    QVirtioNet *net_if = fuzz_qos_obj;
    QVirtioDevice *dev = net_if->vdev;
    QVirtQueue *q;
    vq_action vqa;
    while (Size >= sizeof(vqa)) {
        memcpy(&vqa, Data, sizeof(vqa));
        Data += sizeof(vqa);
        Size -= sizeof(vqa);

        q = net_if->queues[vqa.queue % 3];

        vqa.length = vqa.length >= Size ? Size :  vqa.length;

        /*
         * Only attempt to write incoming packets, when using the socket
         * backend. Otherwise, always place the input on a virtqueue.
         */
        if (vqa.rx && sockfds_initialized) {
            int ignored = write(sockfds[0], Data, vqa.length);
            (void) ignored;
        } else {
            vqa.rx = 0;
            uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
            /*
             * If checking used ring, ensure that the fuzzer doesn't trigger
             * trivial asserion failure on zero-zied buffer
             */
            qtest_memwrite(s, req_addr, Data, vqa.length);


            free_head = qvirtqueue_add(s, q, req_addr, vqa.length,
                    vqa.write, vqa.next);
            qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
            qvirtqueue_kick(s, dev, q, free_head);
        }

        /* Run the main loop */
        qtest_clock_step(s, 100);
        flush_events(s);

        /* Wait on used descriptors */
        if (check_used && !vqa.rx) {
            gint64 start_time = g_get_monotonic_time();
            /*
             * normally, we could just use qvirtio_wait_used_elem, but since we
             * must manually run the main-loop for all the bhs to run, we use
             * this hack with flush_events(), to run the main_loop
             */
            while (!vqa.rx && q != net_if->queues[QVIRTIO_RX_VQ]) {
                uint32_t got_desc_idx;
                /* Input led to a virtio_error */
                if (dev->bus->get_status(dev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
                    break;
                }
                if (dev->bus->get_queue_isr_status(dev, q) &&
                        qvirtqueue_get_buf(s, q, &got_desc_idx, NULL)) {
                    g_assert_cmpint(got_desc_idx, ==, free_head);
                    break;
                }
                g_assert(g_get_monotonic_time() - start_time
                        <= QVIRTIO_NET_TIMEOUT_US);

                /* Run the main loop */
                qtest_clock_step(s, 100);
                flush_events(s);
            }
        }
        Data += vqa.length;
        Size -= vqa.length;
    }
}


static void virtio_net_fuzz_check_used(QTestState *s,
        const unsigned char *Data, size_t Size)
{
    virtio_net_fuzz_multi(s, Data, Size, true);
    flush_events(s);
    fuzz_reset(s);
}

static void virtio_net_pre_fuzz(QTestState *s)
{
    qos_init_path(s);
}

static void *virtio_net_test_setup_socket(GString *cmd_line, void *arg)
{
    int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sockfds);
    g_assert_cmpint(ret, !=, -1);
    g_unix_set_fd_nonblocking(sockfds[0], true, NULL);
    sockfds_initialized = true;
    g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
                           sockfds[1]);
    return arg;
}

static void register_virtio_net_fuzz_targets(void)
{

    fuzz_add_qos_target(&(FuzzTarget){
            .name = "virtio-net-socket-check-used",
            .description = "Fuzz the virtio-net virtual queues. Wait for the "
            "descriptors to be used. Timeout may indicate improperly handled "
            "input",
            .pre_fuzz = &virtio_net_pre_fuzz,
            .fuzz = virtio_net_fuzz_check_used,},
            "virtio-net",
            &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
            );
}

fuzz_target_init(register_virtio_net_fuzz_targets);
