Commit feff0208 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/berrange/tags/qio-next-pull-request' into staging



Merge qio 2010/01/24

Fixes accidental deletion of VNC server UNIX listener socket

# gpg: Signature made Thu 24 Jan 2019 12:24:43 GMT
# gpg:                using RSA key BE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* remotes/berrange/tags/qio-next-pull-request:
  io: ensure UNIX client doesn't unlink server socket

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 341b7186 73564c40
Loading
Loading
Loading
Loading
+4 −15
Original line number Diff line number Diff line
@@ -688,10 +688,13 @@ qio_channel_socket_close(QIOChannel *ioc,
    int rc = 0;

    if (sioc->fd != -1) {
        SocketAddress *addr = socket_local_address(sioc->fd, errp);
#ifdef WIN32
        WSAEventSelect(sioc->fd, NULL, 0);
#endif
        if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
            socket_listen_cleanup(sioc->fd, errp);
        }

        if (closesocket(sioc->fd) < 0) {
            sioc->fd = -1;
            error_setg_errno(errp, errno,
@@ -699,20 +702,6 @@ qio_channel_socket_close(QIOChannel *ioc,
            return -1;
        }
        sioc->fd = -1;

        if (addr && addr->type == SOCKET_ADDRESS_TYPE_UNIX
            && addr->u.q_unix.path) {
            if (unlink(addr->u.q_unix.path) < 0 && errno != ENOENT) {
                error_setg_errno(errp, errno,
                                 "Failed to unlink socket %s",
                                 addr->u.q_unix.path);
                rc = -1;
            }
        }

        if (addr) {
            qapi_free_SocketAddress(addr);
        }
    }
    return rc;
}
+76 −10
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ static void test_io_channel_set_socket_bufs(QIOChannel *src,

static void test_io_channel_setup_sync(SocketAddress *listen_addr,
                                       SocketAddress *connect_addr,
                                       QIOChannel **srv,
                                       QIOChannel **src,
                                       QIOChannel **dst)
{
@@ -78,7 +79,7 @@ static void test_io_channel_setup_sync(SocketAddress *listen_addr,

    test_io_channel_set_socket_bufs(*src, *dst);

    object_unref(OBJECT(lioc));
    *srv = QIO_CHANNEL(lioc);
}


@@ -99,6 +100,7 @@ static void test_io_channel_complete(QIOTask *task,

static void test_io_channel_setup_async(SocketAddress *listen_addr,
                                        SocketAddress *connect_addr,
                                        QIOChannel **srv,
                                        QIOChannel **src,
                                        QIOChannel **dst)
{
@@ -146,21 +148,34 @@ static void test_io_channel_setup_async(SocketAddress *listen_addr,
    qio_channel_set_delay(*src, false);
    test_io_channel_set_socket_bufs(*src, *dst);

    object_unref(OBJECT(lioc));
    *srv = QIO_CHANNEL(lioc);

    g_main_loop_unref(data.loop);
}


static void test_io_channel_socket_path_exists(SocketAddress *addr,
                                               bool expectExists)
{
    if (addr->type != SOCKET_ADDRESS_TYPE_UNIX) {
        return;
    }

    g_assert(g_file_test(addr->u.q_unix.path,
                         G_FILE_TEST_EXISTS) == expectExists);
}


static void test_io_channel(bool async,
                            SocketAddress *listen_addr,
                            SocketAddress *connect_addr,
                            bool passFD)
{
    QIOChannel *src, *dst;
    QIOChannel *src, *dst, *srv;
    QIOChannelTest *test;
    if (async) {
        test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
        test_io_channel_setup_async(listen_addr, connect_addr,
                                    &srv, &src, &dst);

        g_assert(!passFD ||
                 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
@@ -169,14 +184,25 @@ static void test_io_channel(bool async,
        g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
        g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));

        test_io_channel_socket_path_exists(listen_addr, true);

        test = qio_channel_test_new();
        qio_channel_test_run_threads(test, true, src, dst);
        qio_channel_test_validate(test);

        test_io_channel_socket_path_exists(listen_addr, true);

        /* unref without close, to ensure finalize() cleans up */

        object_unref(OBJECT(src));
        object_unref(OBJECT(dst));
        test_io_channel_socket_path_exists(listen_addr, true);

        test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
        object_unref(OBJECT(srv));
        test_io_channel_socket_path_exists(listen_addr, false);

        test_io_channel_setup_async(listen_addr, connect_addr,
                                    &srv, &src, &dst);

        g_assert(!passFD ||
                 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
@@ -189,10 +215,24 @@ static void test_io_channel(bool async,
        qio_channel_test_run_threads(test, false, src, dst);
        qio_channel_test_validate(test);

        /* close before unref, to ensure finalize copes with already closed */

        qio_channel_close(src, &error_abort);
        qio_channel_close(dst, &error_abort);
        test_io_channel_socket_path_exists(listen_addr, true);

        object_unref(OBJECT(src));
        object_unref(OBJECT(dst));
        test_io_channel_socket_path_exists(listen_addr, true);

        qio_channel_close(srv, &error_abort);
        test_io_channel_socket_path_exists(listen_addr, false);

        object_unref(OBJECT(srv));
        test_io_channel_socket_path_exists(listen_addr, false);
    } else {
        test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
        test_io_channel_setup_sync(listen_addr, connect_addr,
                                   &srv, &src, &dst);

        g_assert(!passFD ||
                 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
@@ -201,14 +241,25 @@ static void test_io_channel(bool async,
        g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
        g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));

        test_io_channel_socket_path_exists(listen_addr, true);

        test = qio_channel_test_new();
        qio_channel_test_run_threads(test, true, src, dst);
        qio_channel_test_validate(test);

        test_io_channel_socket_path_exists(listen_addr, true);

        /* unref without close, to ensure finalize() cleans up */

        object_unref(OBJECT(src));
        object_unref(OBJECT(dst));
        test_io_channel_socket_path_exists(listen_addr, true);

        object_unref(OBJECT(srv));
        test_io_channel_socket_path_exists(listen_addr, false);

        test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
        test_io_channel_setup_sync(listen_addr, connect_addr,
                                   &srv, &src, &dst);

        g_assert(!passFD ||
                 qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
@@ -221,8 +272,23 @@ static void test_io_channel(bool async,
        qio_channel_test_run_threads(test, false, src, dst);
        qio_channel_test_validate(test);

        test_io_channel_socket_path_exists(listen_addr, true);

        /* close before unref, to ensure finalize copes with already closed */

        qio_channel_close(src, &error_abort);
        qio_channel_close(dst, &error_abort);
        test_io_channel_socket_path_exists(listen_addr, true);

        object_unref(OBJECT(src));
        object_unref(OBJECT(dst));
        test_io_channel_socket_path_exists(listen_addr, true);

        qio_channel_close(srv, &error_abort);
        test_io_channel_socket_path_exists(listen_addr, false);

        object_unref(OBJECT(srv));
        test_io_channel_socket_path_exists(listen_addr, false);
    }
}

@@ -316,7 +382,6 @@ static void test_io_channel_unix(bool async)

    qapi_free_SocketAddress(listen_addr);
    qapi_free_SocketAddress(connect_addr);
    g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE);
}


@@ -335,7 +400,7 @@ static void test_io_channel_unix_fd_pass(void)
{
    SocketAddress *listen_addr = g_new0(SocketAddress, 1);
    SocketAddress *connect_addr = g_new0(SocketAddress, 1);
    QIOChannel *src, *dst;
    QIOChannel *src, *dst, *srv;
    int testfd;
    int fdsend[3];
    int *fdrecv = NULL;
@@ -359,7 +424,7 @@ static void test_io_channel_unix_fd_pass(void)
    connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
    connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);

    test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
    test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, &dst);

    memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend));

@@ -412,6 +477,7 @@ static void test_io_channel_unix_fd_pass(void)

    object_unref(OBJECT(src));
    object_unref(OBJECT(dst));
    object_unref(OBJECT(srv));
    qapi_free_SocketAddress(listen_addr);
    qapi_free_SocketAddress(connect_addr);
    unlink(TEST_SOCKET);