* Update security triage contact address

* Check and honour failures to the blocking flag on FDs
  * Don't touch blocking flags on FDs received during migration
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmjNQuAACgkQvobrtBUQ
 T99xaBAAr6zQPii1tjzuzLovF6MIqtldXnmVO/yjcl5NgLWonIRDt2JsxnRxi3es
 9uNDed5+ePNXmUAYd46k81gBEjBWbv465kt5FHAZZV6BRw/PPzkoh+jzGc8NVir8
 3GZJ2kPr51PxGEl8md2vRthg4bMuhlS5ogCEqAMDYT4f6AVemfnNQ5NttGX353T2
 etxoMhEeMtTBKjMoTBv+SVhhO4nKwZ+6CFhvuGON423EfrGlkNTXyprKTdzpr4i0
 4KDQLxxoANlmg/1W0PxfrLiBCmGpHweMR44Piv715VYa2YNPRq0G6EC6AFGbHZ51
 N+mKmWNE0CS5rP1TEacSCX4q6If5VxjSLLj+og8LmpIlJ6tiqdrisSqA6bzCJ1f/
 lMsfUsKoMqPhqat9ZGUkYu8REgKP+O+CSGJNftYTsEEY0oKZrAW4fsoN3E9qpfcG
 Xy6eSu0TTGDWE6CEe0vkHiQwlVHMtRcWMSPwlsvrgt2TO6k97reT3AoIBK2VfygC
 WzMv0P0nBvHFKeIbqmFOk3BEI5+JECgxVRc1WXWbSFLW0PBY/xd7g6ow8uaQsd9e
 pzMA1Pwh2EuM4DTlOy+m9zBOhm9YP9An188NLldOne3TFKFYe5QO1DQpvvEGvIGB
 +4XpmyOj3g2ycelZZ5XsDJk0LumCCOcbSPSiAvHZyWwLo24EABE=
 =rrMd
 -----END PGP SIGNATURE-----

Merge tag 'misc-fixes-pull-request' of https://gitlab.com/berrange/qemu into staging

 * Update security triage contact address
 * Check and honour failures to the blocking flag on FDs
 * Don't touch blocking flags on FDs received during migration

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmjNQuAACgkQvobrtBUQ
# T99xaBAAr6zQPii1tjzuzLovF6MIqtldXnmVO/yjcl5NgLWonIRDt2JsxnRxi3es
# 9uNDed5+ePNXmUAYd46k81gBEjBWbv465kt5FHAZZV6BRw/PPzkoh+jzGc8NVir8
# 3GZJ2kPr51PxGEl8md2vRthg4bMuhlS5ogCEqAMDYT4f6AVemfnNQ5NttGX353T2
# etxoMhEeMtTBKjMoTBv+SVhhO4nKwZ+6CFhvuGON423EfrGlkNTXyprKTdzpr4i0
# 4KDQLxxoANlmg/1W0PxfrLiBCmGpHweMR44Piv715VYa2YNPRq0G6EC6AFGbHZ51
# N+mKmWNE0CS5rP1TEacSCX4q6If5VxjSLLj+og8LmpIlJ6tiqdrisSqA6bzCJ1f/
# lMsfUsKoMqPhqat9ZGUkYu8REgKP+O+CSGJNftYTsEEY0oKZrAW4fsoN3E9qpfcG
# Xy6eSu0TTGDWE6CEe0vkHiQwlVHMtRcWMSPwlsvrgt2TO6k97reT3AoIBK2VfygC
# WzMv0P0nBvHFKeIbqmFOk3BEI5+JECgxVRc1WXWbSFLW0PBY/xd7g6ow8uaQsd9e
# pzMA1Pwh2EuM4DTlOy+m9zBOhm9YP9An188NLldOne3TFKFYe5QO1DQpvvEGvIGB
# +4XpmyOj3g2ycelZZ5XsDJk0LumCCOcbSPSiAvHZyWwLo24EABE=
# =rrMd
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 19 Sep 2025 04:47:44 AM PDT
# gpg:                using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [unknown]
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* tag 'misc-fixes-pull-request' of https://gitlab.com/berrange/qemu:
  util/vhost-user-server: vu_message_read(): improve error handling
  chardev: close an fd on failure path
  chardev: qemu_chr_open_fd(): add errp
  treewide: use qemu_set_blocking instead of g_unix_set_fd_nonblocking
  util: drop qemu_socket_set_block()
  io/channel-socket: rework qio_channel_socket_copy_fds()
  util: drop qemu_socket_try_set_nonblock()
  util: drop qemu_socket_set_nonblock()
  migration: qemu_file_set_blocking(): add errp parameter
  treewide: handle result of qio_channel_set_blocking()
  util: add qemu_set_blocking() function
  char-socket: tcp_chr_recv(): add comment
  char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec)
  io/channel: document how qio_channel_readv_full() handles fds
  migration/qemu-file: don't make incoming fds blocking again
  MAINTAINERS: list qemu-security@nongnu.org as security contact

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-09-19 12:20:43 -07:00
commit caf2e8de4e
63 changed files with 376 additions and 220 deletions

View file

@ -85,7 +85,7 @@ Responsible Disclosure, Reporting Security Issues
-------------------------------------------------
W: https://wiki.qemu.org/SecurityProcess
M: Michael S. Tsirkin <mst@redhat.com>
L: secalert@redhat.com
L: qemu-security@nongnu.org
Trivial patches
---------------

View file

@ -351,7 +351,9 @@ int coroutine_fn nbd_co_do_establish_connection(BlockDriverState *bs,
return ret;
}
qio_channel_set_blocking(s->ioc, false, NULL);
if (!qio_channel_set_blocking(s->ioc, false, errp)) {
return -EINVAL;
}
qio_channel_set_follow_coroutine_ctx(s->ioc, true);
/* successfully connected */

View file

@ -206,14 +206,16 @@ int qmp_chardev_open_file_source(char *src, int flags, Error **errp)
}
/* open a character device to a unix fd */
void qemu_chr_open_fd(Chardev *chr,
int fd_in, int fd_out)
bool qemu_chr_open_fd(Chardev *chr,
int fd_in, int fd_out, Error **errp)
{
FDChardev *s = FD_CHARDEV(chr);
g_autofree char *name = NULL;
if (fd_out >= 0 && !g_unix_set_fd_nonblocking(fd_out, true, NULL)) {
assert(!"Failed to set FD nonblocking");
if (fd_out >= 0) {
if (!qemu_set_blocking(fd_out, false, errp)) {
return false;
}
}
if (fd_out == fd_in && fd_in >= 0) {
@ -221,7 +223,7 @@ void qemu_chr_open_fd(Chardev *chr,
name = g_strdup_printf("chardev-file-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
s->ioc_out = QIO_CHANNEL(object_ref(s->ioc_in));
return;
return true;
}
if (fd_in >= 0) {
@ -236,6 +238,8 @@ void qemu_chr_open_fd(Chardev *chr,
name = g_strdup_printf("chardev-file-out-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
}
return true;
}
static void char_fd_class_init(ObjectClass *oc, const void *data)

View file

@ -92,7 +92,11 @@ static void qmp_chardev_open_file(Chardev *chr,
}
}
qemu_chr_open_fd(chr, in, out);
if (!qemu_chr_open_fd(chr, in, out, errp)) {
qemu_close(out);
qemu_close(in);
return;
}
#endif
}

View file

@ -150,7 +150,14 @@ static void qemu_chr_open_pipe(Chardev *chr,
return;
}
}
qemu_chr_open_fd(chr, fd_in, fd_out);
if (!qemu_chr_open_fd(chr, fd_in, fd_out, errp)) {
close(fd_in);
if (fd_out != fd_in) {
close(fd_out);
}
return;
}
}
#endif /* !_WIN32 */

View file

@ -349,8 +349,8 @@ static void char_pty_open(Chardev *chr,
}
close(slave_fd);
if (!g_unix_set_fd_nonblocking(master_fd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(master_fd, false, errp)) {
close(master_fd);
return;
}

View file

@ -271,13 +271,16 @@ static void qmp_chardev_open_serial(Chardev *chr,
if (fd < 0) {
return;
}
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return;
}
tty_serial_init(fd, 115200, 'N', 8, 1);
qemu_chr_open_fd(chr, fd, fd);
if (!qemu_chr_open_fd(chr, fd, fd, errp)) {
close(fd);
return;
}
}
#endif /* __linux__ || __sun__ */

View file

@ -294,7 +294,12 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
}
if (msgfds_num) {
/* close and clean read_msgfds */
/*
* Close and clean previous read_msgfds, they are obsolete at
* this point, regardless result of new call to
* qio_channel_readv_full().
*/
for (i = 0; i < s->read_msgfds_num; i++) {
close(s->read_msgfds[i]);
}
@ -307,20 +312,6 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
s->read_msgfds_num = msgfds_num;
}
for (i = 0; i < s->read_msgfds_num; i++) {
int fd = s->read_msgfds[i];
if (fd < 0) {
continue;
}
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
qemu_socket_set_block(fd);
#ifndef MSG_CMSG_CLOEXEC
qemu_set_cloexec(fd);
#endif
}
if (ret == QIO_CHANNEL_ERR_BLOCK) {
errno = EAGAIN;
ret = -1;
@ -539,16 +530,24 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
SocketChardev *s = SOCKET_CHARDEV(chr);
int size;
int saved_errno;
Error *local_err = NULL;
if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
return 0;
}
qio_channel_set_blocking(s->ioc, true, NULL);
if (!qio_channel_set_blocking(s->ioc, true, &local_err)) {
error_report_err(local_err);
return -1;
}
size = tcp_chr_recv(chr, (void *) buf, len);
saved_errno = errno;
if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
qio_channel_set_blocking(s->ioc, false, NULL);
if (!qio_channel_set_blocking(s->ioc, false, &local_err)) {
error_report_err(local_err);
/* failed to recover non-blocking state */
tcp_chr_disconnect(chr);
}
}
if (size == 0) {
/* connection closed */
@ -893,18 +892,22 @@ static void tcp_chr_set_client_ioc_name(Chardev *chr,
static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
Error *local_err = NULL;
if (s->state != TCP_CHARDEV_STATE_CONNECTING) {
return -1;
}
if (!qio_channel_set_blocking(QIO_CHANNEL(sioc), false, &local_err)) {
error_report_err(local_err);
return -1;
}
s->ioc = QIO_CHANNEL(sioc);
object_ref(OBJECT(sioc));
s->sioc = sioc;
object_ref(OBJECT(sioc));
qio_channel_set_blocking(s->ioc, false, NULL);
if (s->do_nodelay) {
qio_channel_set_delay(s->ioc, false);
}

View file

@ -107,18 +107,20 @@ static void qemu_chr_open_stdio(Chardev *chr,
old_fd0_flags = fcntl(0, F_GETFL);
old_fd1_flags = fcntl(1, F_GETFL);
tcgetattr(0, &oldtty);
if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(0, false, errp)) {
return;
}
if (!qemu_chr_open_fd(chr, 0, 1, errp)) {
return;
}
atexit(term_exit);
memset(&act, 0, sizeof(act));
act.sa_handler = term_stdio_handler;
sigaction(SIGCONT, &act, NULL);
qemu_chr_open_fd(chr, 0, 1);
stdio_allow_signal = !opts->has_signal || opts->signal;
qemu_chr_set_echo_stdio(chr, false);
}

View file

@ -6,6 +6,7 @@
* top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/host-utils.h"
#include "qemu/sockets.h"
@ -135,6 +136,7 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
socklen_t unaddr_len;
int newfd;
unsigned i;
Error *local_err = NULL;
/* accept the incoming connection */
unaddr_len = sizeof(unaddr);
@ -146,9 +148,14 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
return -1;
}
qemu_socket_set_nonblock(newfd);
IVSHMEM_SERVER_DEBUG(server, "accept()=%d\n", newfd);
if (!qemu_set_blocking(newfd, false, &local_err)) {
error_report_err(local_err);
close(newfd);
return -1;
}
/* allocate new structure for this peer */
peer = g_malloc0(sizeof(*peer));
peer->sock_fd = newfd;

View file

@ -338,7 +338,9 @@ static void hv_syndbg_realize(DeviceState *dev, Error **errp)
return;
}
qemu_socket_set_nonblock(syndbg->socket);
if (!qemu_set_blocking(syndbg->socket, false, errp)) {
return;
}
syndbg->servaddr.sin_port = htons(syndbg->host_port);
syndbg->servaddr.sin_family = AF_INET;

View file

@ -114,8 +114,7 @@ static void virtio_input_host_realize(DeviceState *dev, Error **errp)
error_setg_file_open(errp, errno, vih->evdev);
return;
}
if (!g_unix_set_fd_nonblocking(vih->fd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(vih->fd, false, errp)) {
goto err_close;
}

View file

@ -154,7 +154,8 @@ static void ivshmem_flat_add_vector(IvshmemFTState *s, IvshmemPeer *peer,
* peer.
*/
peer->vector[peer->vector_counter].id = peer->vector_counter;
g_unix_set_fd_nonblocking(vector_fd, true, NULL);
/* WARNING: qemu_socket_set_nonblock() return code ignored */
qemu_set_blocking(vector_fd, false, &error_warn);
event_notifier_init_fd(&peer->vector[peer->vector_counter].event_notifier,
vector_fd);

View file

@ -540,7 +540,12 @@ static void process_msg_connect(IVShmemState *s, uint16_t posn, int fd,
IVSHMEM_DPRINTF("eventfds[%d][%d] = %d\n", posn, vector, fd);
event_notifier_init_fd(&peer->eventfds[vector], fd);
g_unix_set_fd_nonblocking(fd, true, NULL); /* msix/irqfd poll non block */
/* msix/irqfd poll non block */
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return;
}
if (posn == s->vm_id) {
setup_interrupt(s, vector, errp);

View file

@ -112,8 +112,12 @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
return;
}
if (!qio_channel_set_blocking(dev->ioc, true, errp)) {
object_unref(dev->ioc);
return;
}
qemu_mutex_init(&dev->io_mutex);
qio_channel_set_blocking(dev->ioc, true, NULL);
pci_conf[PCI_LATENCY_TIMER] = 0xff;
pci_conf[PCI_INTERRUPT_PIN] = 0x01;

View file

@ -107,7 +107,11 @@ static void remote_object_machine_done(Notifier *notifier, void *data)
error_report_err(err);
return;
}
qio_channel_set_blocking(ioc, false, NULL);
if (!qio_channel_set_blocking(ioc, false, &err)) {
error_report_err(err);
object_unref(OBJECT(ioc));
return;
}
o->dev = dev;

View file

@ -886,10 +886,11 @@ VFIOUserProxy *vfio_user_connect_dev(SocketAddress *addr, Error **errp)
sioc = qio_channel_socket_new();
ioc = QIO_CHANNEL(sioc);
if (qio_channel_socket_connect_sync(sioc, addr, errp) < 0) {
object_unref(OBJECT(ioc));
return NULL;
goto fail;
}
if (!qio_channel_set_blocking(ioc, false, errp)) {
goto fail;
}
qio_channel_set_blocking(ioc, false, NULL);
proxy = g_malloc0(sizeof(VFIOUserProxy));
proxy->sockname = g_strdup_printf("unix:%s", sockname);
@ -923,6 +924,10 @@ VFIOUserProxy *vfio_user_connect_dev(SocketAddress *addr, Error **errp)
QLIST_INSERT_HEAD(&vfio_user_sockets, proxy, next);
return proxy;
fail:
object_unref(OBJECT(ioc));
return NULL;
}
void vfio_user_set_handler(VFIODevice *vbasedev,

View file

@ -2039,7 +2039,10 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
error_setg(errp, "%s: Failed to get ufd", __func__);
return -EIO;
}
qemu_socket_set_nonblock(ufd);
if (!qemu_set_blocking(ufd, false, errp)) {
close(ufd);
return -EINVAL;
}
/* register ufd with userfault thread */
u->postcopy_fd.fd = ufd;

View file

@ -147,9 +147,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
return;
}
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
error_setg_errno(errp, errno,
"vhost-vsock: unable to set non-blocking mode");
if (!qemu_set_blocking(vhostfd, false, errp)) {
return;
}
} else {
@ -160,9 +158,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
return;
}
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
error_setg_errno(errp, errno,
"Failed to set FD nonblocking");
if (!qemu_set_blocking(vhostfd, false, errp)) {
return;
}
}

View file

@ -41,7 +41,7 @@ typedef struct FDChardev FDChardev;
DECLARE_INSTANCE_CHECKER(FDChardev, FD_CHARDEV,
TYPE_CHARDEV_FD)
void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out);
bool qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out, Error **errp);
int qmp_chardev_open_file_source(char *src, int flags, Error **errp);
#endif /* CHAR_FD_H */

View file

@ -36,6 +36,7 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
#define QIO_CHANNEL_READ_FLAG_MSG_PEEK 0x1
#define QIO_CHANNEL_READ_FLAG_RELAXED_EOF 0x2
#define QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING 0x4
typedef enum QIOChannelFeature QIOChannelFeature;
@ -117,6 +118,15 @@ struct QIOChannelClass {
size_t nfds,
int flags,
Error **errp);
/*
* The io_readv handler must guarantee that all
* incoming fds are set BLOCKING (unless
* QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING flag is set) and
* CLOEXEC (if available).
* @fds and @nfds are set only on success path. Still, setting
* @fds and @nfds to zero is acceptable on failure path.
*/
ssize_t (*io_readv)(QIOChannel *ioc,
const struct iovec *iov,
size_t niov,
@ -124,6 +134,7 @@ struct QIOChannelClass {
size_t *nfds,
int flags,
Error **errp);
int (*io_close)(QIOChannel *ioc,
Error **errp);
GSource * (*io_create_watch)(QIOChannel *ioc,
@ -234,6 +245,13 @@ void qio_channel_set_name(QIOChannel *ioc,
* was allocated. It is the callers responsibility
* to call close() on each file descriptor and to
* call g_free() on the array pointer in @fds.
* @fds allocated and set (and @nfds is set too)
* _only_ on success path. Still, @fds and @nfds
* may be set to zero on failure path.
* qio_channel_readv_full() guarantees that all
* incoming fds are set BLOCKING (unless
* QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING flag
* is set) and CLOEXEC (if available).
*
* It is an error to pass a non-NULL @fds parameter
* unless qio_channel_has_feature() returns a true
@ -513,9 +531,9 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc,
* return QIO_CHANNEL_ERR_BLOCK if they would otherwise
* block on I/O
*/
int qio_channel_set_blocking(QIOChannel *ioc,
bool enabled,
Error **errp);
bool qio_channel_set_blocking(QIOChannel *ioc,
bool enabled,
Error **errp);
/**
* qio_channel_set_follow_coroutine_ctx:

View file

@ -687,6 +687,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
G_GNUC_WARN_UNUSED_RESULT;
void qemu_set_cloexec(int fd);
bool qemu_set_blocking(int fd, bool block, Error **errp);
/* Return a dynamically allocated directory path that is appropriate for storing
* local state.

View file

@ -46,9 +46,6 @@ ssize_t qemu_send_full(int s, const void *buf, size_t count)
G_GNUC_WARN_UNUSED_RESULT;
int socket_set_cork(int fd, int v);
int socket_set_nodelay(int fd);
void qemu_socket_set_block(int fd);
int qemu_socket_try_set_nonblock(int fd);
void qemu_socket_set_nonblock(int fd);
int socket_set_fast_reuse(int fd);
#ifdef WIN32

View file

@ -277,9 +277,12 @@ static int qio_channel_command_set_blocking(QIOChannel *ioc,
cioc->blocking = enabled;
#else
if ((cioc->writefd >= 0 && !g_unix_set_fd_nonblocking(cioc->writefd, !enabled, NULL)) ||
(cioc->readfd >= 0 && !g_unix_set_fd_nonblocking(cioc->readfd, !enabled, NULL))) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (cioc->writefd >= 0 &&
!qemu_set_blocking(cioc->writefd, enabled, errp)) {
return -1;
}
if (cioc->readfd >= 0 &&
!qemu_set_blocking(cioc->readfd, enabled, errp)) {
return -1;
}
#endif

View file

@ -223,8 +223,7 @@ static int qio_channel_file_set_blocking(QIOChannel *ioc,
#else
QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
if (!g_unix_set_fd_nonblocking(fioc->fd, !enabled, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(fioc->fd, enabled, errp)) {
return -1;
}
return 0;

View file

@ -472,7 +472,7 @@ static void qio_channel_socket_copy_fds(struct msghdr *msg,
*fds = NULL;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
int fd_size, i;
int fd_size;
int gotfds;
if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
@ -490,24 +490,55 @@ static void qio_channel_socket_copy_fds(struct msghdr *msg,
gotfds = fd_size / sizeof(int);
*fds = g_renew(int, *fds, *nfds + gotfds);
memcpy(*fds + *nfds, CMSG_DATA(cmsg), fd_size);
for (i = 0; i < gotfds; i++) {
int fd = (*fds)[*nfds + i];
if (fd < 0) {
continue;
}
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
qemu_socket_set_block(fd);
#ifndef MSG_CMSG_CLOEXEC
qemu_set_cloexec(fd);
#endif
}
*nfds += gotfds;
}
}
static bool qio_channel_handle_fds(int *fds, size_t nfds,
bool preserve_blocking, Error **errp)
{
int *end = fds + nfds, *fd;
#ifdef MSG_CMSG_CLOEXEC
if (preserve_blocking) {
/* Nothing to do */
return true;
}
#endif
for (fd = fds; fd != end; fd++) {
if (*fd < 0) {
continue;
}
if (!preserve_blocking) {
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
if (!qemu_set_blocking(*fd, true, errp)) {
return false;
}
}
#ifndef MSG_CMSG_CLOEXEC
qemu_set_cloexec(*fd);
#endif
}
return true;
}
static void qio_channel_cleanup_fds(int **fds, size_t *nfds)
{
for (size_t i = 0; i < *nfds; i++) {
if ((*fds)[i] < 0) {
continue;
}
close((*fds)[i]);
}
g_clear_pointer(fds, g_free);
*nfds = 0;
}
static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
const struct iovec *iov,
@ -556,7 +587,16 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
}
if (fds && nfds) {
bool preserve_blocking =
flags & QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING;
qio_channel_socket_copy_fds(&msg, fds, nfds);
if (!qio_channel_handle_fds(*fds, *nfds,
preserve_blocking, errp)) {
qio_channel_cleanup_fds(fds, nfds);
return -1;
}
}
return ret;
@ -820,11 +860,10 @@ qio_channel_socket_set_blocking(QIOChannel *ioc,
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
if (enabled) {
qemu_socket_set_block(sioc->fd);
} else {
qemu_socket_set_nonblock(sioc->fd);
if (!qemu_set_blocking(sioc->fd, enabled, errp)) {
return -1;
}
return 0;
}

View file

@ -425,7 +425,7 @@ static int qio_channel_tls_set_blocking(QIOChannel *ioc,
{
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
return qio_channel_set_blocking(tioc->master, enabled, errp);
return qio_channel_set_blocking(tioc->master, enabled, errp) ? 0 : -1;
}
static void qio_channel_tls_set_delay(QIOChannel *ioc,

View file

@ -1184,8 +1184,7 @@ static int qio_channel_websock_set_blocking(QIOChannel *ioc,
{
QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
qio_channel_set_blocking(wioc->master, enabled, errp);
return 0;
return qio_channel_set_blocking(wioc->master, enabled, errp) ? 0 : -1;
}
static void qio_channel_websock_set_delay(QIOChannel *ioc,

View file

@ -359,12 +359,12 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc,
}
int qio_channel_set_blocking(QIOChannel *ioc,
bool qio_channel_set_blocking(QIOChannel *ioc,
bool enabled,
Error **errp)
{
QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
return klass->io_set_blocking(ioc, enabled, errp);
return klass->io_set_blocking(ioc, enabled, errp) == 0;
}

View file

@ -859,7 +859,10 @@ static void *colo_process_incoming_thread(void *opaque)
* coroutine, and here we are in the COLO incoming thread, so it is ok to
* set the fd back to blocked.
*/
qemu_file_set_blocking(mis->from_src_file, true);
if (!qemu_file_set_blocking(mis->from_src_file, true, &local_err)) {
error_report_err(local_err);
goto out;
}
colo_incoming_start_dirty_log();

View file

@ -951,7 +951,7 @@ static void migration_incoming_setup(QEMUFile *f)
assert(!mis->from_src_file);
mis->from_src_file = f;
qemu_file_set_blocking(f, false);
qemu_file_set_blocking(f, false, &error_abort);
}
void migration_incoming_process(void)
@ -971,7 +971,7 @@ static bool postcopy_try_recover(void)
/* This should be set already in migration_incoming_setup() */
assert(mis->from_src_file);
/* Postcopy has standalone thread to do vm load */
qemu_file_set_blocking(mis->from_src_file, true);
qemu_file_set_blocking(mis->from_src_file, true, &error_abort);
/* Re-configure the return path */
mis->to_src_file = qemu_file_get_return_path(mis->from_src_file);
@ -4002,7 +4002,9 @@ void migration_connect(MigrationState *s, Error *error_in)
}
migration_rate_set(rate_limit);
qemu_file_set_blocking(s->to_dst_file, true);
if (!qemu_file_set_blocking(s->to_dst_file, true, &local_err)) {
goto fail;
}
/*
* Open the return path. For postcopy, it is used exclusively. For

View file

@ -1909,7 +1909,7 @@ void postcopy_preempt_new_channel(MigrationIncomingState *mis, QEMUFile *file)
* The new loading channel has its own threads, so it needs to be
* blocked too. It's by default true, just be explicit.
*/
qemu_file_set_blocking(file, true);
qemu_file_set_blocking(file, true, &error_abort);
mis->postcopy_qemufile_dst = file;
qemu_sem_post(&mis->postcopy_qemufile_dst_done);
trace_postcopy_preempt_new_channel();

View file

@ -340,7 +340,8 @@ static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f)
do {
struct iovec iov = { f->buf + pending, IO_BUF_SIZE - pending };
len = qio_channel_readv_full(f->ioc, &iov, 1, pfds, pnfd, 0,
len = qio_channel_readv_full(f->ioc, &iov, 1, pfds, pnfd,
QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING,
&local_error);
if (len == QIO_CHANNEL_ERR_BLOCK) {
if (qemu_in_coroutine()) {
@ -887,9 +888,9 @@ void qemu_put_counted_string(QEMUFile *f, const char *str)
* both directions, and thus changing the blocking on the main
* QEMUFile can also affect the return path.
*/
void qemu_file_set_blocking(QEMUFile *f, bool block)
bool qemu_file_set_blocking(QEMUFile *f, bool block, Error **errp)
{
qio_channel_set_blocking(f->ioc, block, NULL);
return qio_channel_set_blocking(f->ioc, block, errp);
}
/*

View file

@ -71,7 +71,7 @@ void qemu_file_set_error(QEMUFile *f, int ret);
int qemu_file_shutdown(QEMUFile *f);
QEMUFile *qemu_file_get_return_path(QEMUFile *f);
int qemu_fflush(QEMUFile *f);
void qemu_file_set_blocking(QEMUFile *f, bool block);
bool qemu_file_set_blocking(QEMUFile *f, bool block, Error **errp);
int qemu_file_get_to_fd(QEMUFile *f, int fd, size_t size);
void qemu_set_offset(QEMUFile *f, off_t off, int whence);
off_t qemu_get_offset(QEMUFile *f);

View file

@ -2095,7 +2095,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
* Because we're a thread and not a coroutine we can't yield
* in qemu_file, and thus we must be blocking now.
*/
qemu_file_set_blocking(f, true);
qemu_file_set_blocking(f, true, &error_fatal);
/* TODO: sanity check that only postcopiable data will be loaded here */
load_res = qemu_loadvm_state_main(f, mis);
@ -2108,7 +2108,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
f = mis->from_src_file;
/* And non-blocking again so we don't block in any cleanup */
qemu_file_set_blocking(f, false);
qemu_file_set_blocking(f, false, &error_fatal);
trace_postcopy_ram_listen_thread_exit();
if (load_res < 0) {

View file

@ -1411,7 +1411,9 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
....options sent, ending in NBD_OPT_EXPORT_NAME or NBD_OPT_GO....
*/
qio_channel_set_blocking(client->ioc, false, NULL);
if (!qio_channel_set_blocking(client->ioc, false, errp)) {
return -EINVAL;
}
qio_channel_set_follow_coroutine_ctx(client->ioc, true);
trace_nbd_negotiate_begin();

View file

@ -226,7 +226,10 @@ static int net_dgram_mcast_create(struct sockaddr_in *mcastaddr,
}
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
goto fail;
}
return fd;
fail:
if (fd >= 0) {
@ -284,7 +287,7 @@ static int net_dgram_mcast_init(NetClientState *peer,
Error **errp)
{
NetDgramState *s;
int fd, ret;
int fd;
struct sockaddr_in *saddr;
if (remote->type != SOCKET_ADDRESS_TYPE_INET) {
@ -332,11 +335,8 @@ static int net_dgram_mcast_init(NetClientState *peer,
g_free(saddr);
return -1;
}
ret = qemu_socket_try_set_nonblock(fd);
if (ret < 0) {
if (!qemu_set_blocking(fd, false, errp)) {
g_free(saddr);
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
name, fd);
return -1;
}
@ -504,7 +504,11 @@ int net_init_dgram(const Netdev *netdev, const char *name,
close(fd);
return -1;
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
dest_len = sizeof(raddr_in);
dest_addr = g_malloc(dest_len);
@ -551,7 +555,10 @@ int net_init_dgram(const Netdev *netdev, const char *name,
close(fd);
return -1;
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
dest_len = sizeof(raddr_un);
dest_addr = g_malloc(dest_len);
@ -562,10 +569,7 @@ int net_init_dgram(const Netdev *netdev, const char *name,
if (fd == -1) {
return -1;
}
ret = qemu_socket_try_set_nonblock(fd);
if (ret < 0) {
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
name, fd);
if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
dest_addr = NULL;

View file

@ -648,6 +648,9 @@ int net_init_l2tpv3(const Netdev *netdev,
error_setg(errp, "could not bind socket err=%i", errno);
goto outerr;
}
if (!qemu_set_blocking(fd, false, errp)) {
goto outerr;
}
freeaddrinfo(result);
@ -709,8 +712,6 @@ int net_init_l2tpv3(const Netdev *netdev,
s->vec = g_new(struct iovec, MAX_L2TPV3_IOVCNT);
s->header_buf = g_malloc(s->header_size);
qemu_socket_set_nonblock(fd);
s->fd = fd;
s->counter = 0;

View file

@ -295,7 +295,10 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
}
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
goto fail;
}
return fd;
fail:
if (fd >= 0)
@ -508,7 +511,10 @@ static int net_socket_listen_init(NetClientState *peer,
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
socket_set_fast_reuse(fd);
@ -556,7 +562,10 @@ static int net_socket_connect_init(NetClientState *peer,
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
connected = 0;
for(;;) {
@ -671,7 +680,10 @@ static int net_socket_udp_init(NetClientState *peer,
close(fd);
return -1;
}
qemu_socket_set_nonblock(fd);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp);
if (!s) {
@ -706,7 +718,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
}
if (sock->fd) {
int fd, ret, so_type;
int fd, so_type;
fd = monitor_fd_param(monitor_cur(), sock->fd, errp);
if (fd == -1) {
@ -716,10 +728,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
if (so_type < 0) {
return -1;
}
ret = qemu_socket_try_set_nonblock(fd);
if (ret < 0) {
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
name, fd);
if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
switch (so_type) {

View file

@ -138,7 +138,6 @@ static void net_stream_server_listening(QIOTask *task, gpointer opaque)
NetStreamData *d = opaque;
QIOChannelSocket *listen_sioc = QIO_CHANNEL_SOCKET(d->listen_ioc);
SocketAddress *addr;
int ret;
Error *err = NULL;
if (qio_task_propagate_error(task, &err)) {
@ -149,13 +148,11 @@ static void net_stream_server_listening(QIOTask *task, gpointer opaque)
addr = qio_channel_socket_get_local_address(listen_sioc, NULL);
g_assert(addr != NULL);
ret = qemu_socket_try_set_nonblock(listen_sioc->fd);
if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)",
addr->u.fd.str, -ret);
if (!qemu_set_blocking(listen_sioc->fd, false, &err)) {
qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err));
error_free(err);
return;
}
g_assert(ret == 0);
qapi_free_SocketAddress(addr);
d->nc.link_down = true;

View file

@ -12,6 +12,7 @@
#include "net/net.h"
#include "io/channel.h"
#include "io/net-listener.h"
#include "qemu/sockets.h"
#include "stream_data.h"
@ -154,7 +155,6 @@ int net_stream_data_client_connected(QIOTask *task, NetStreamData *d)
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(d->ioc);
SocketAddress *addr;
int ret;
Error *err = NULL;
if (qio_task_propagate_error(task, &err)) {
@ -166,14 +166,12 @@ int net_stream_data_client_connected(QIOTask *task, NetStreamData *d)
addr = qio_channel_socket_get_remote_address(sioc, NULL);
g_assert(addr != NULL);
ret = qemu_socket_try_set_nonblock(sioc->fd);
if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)",
addr->u.fd.str, -ret);
if (!qemu_set_blocking(sioc->fd, false, &err)) {
qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err));
error_free(err);
qapi_free_SocketAddress(addr);
goto error;
}
g_assert(ret == 0);
qapi_free_SocketAddress(addr);
net_socket_rs_init(&d->rs, net_stream_data_rs_finalize, false);

View file

@ -98,7 +98,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return -1;
}
}
g_unix_set_fd_nonblocking(fd, true, NULL);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
return fd;
}
@ -189,7 +194,10 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
goto error;
}
g_unix_set_fd_nonblocking(fd, true, NULL);
if (!qemu_set_blocking(fd, false, errp)) {
goto error;
}
return fd;
error:

View file

@ -124,7 +124,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return -1;
}
pstrcpy(ifname, ifname_size, ifr.ifr_name);
g_unix_set_fd_nonblocking(fd, true, NULL);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
return fd;
}

View file

@ -198,7 +198,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return -1;
}
}
g_unix_set_fd_nonblocking(fd, true, NULL);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
return fd;
}

View file

@ -627,8 +627,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
return -1;
}
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
@ -729,9 +728,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
error_propagate(errp, err);
goto failed;
}
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
name, fd);
if (!qemu_set_blocking(vhostfd, false, errp)) {
goto failed;
}
} else {
@ -741,8 +738,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
"tap: open vhost char device failed");
goto failed;
}
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(vhostfd, false, errp)) {
goto failed;
}
}
@ -839,9 +835,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
return -1;
}
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
name, fd);
if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
@ -895,10 +889,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
goto free_fail;
}
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
if (!qemu_set_blocking(fd, false, errp)) {
ret = -1;
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
name, fd);
goto free_fail;
}
@ -951,8 +943,7 @@ free_fail:
return -1;
}
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
vnet_hdr = tap_probe_vnet_hdr(fd, errp);

View file

@ -28,6 +28,7 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel,
GAChannel *c = data;
int ret, client_fd;
bool accepted = false;
Error *err = NULL;
g_assert(channel != NULL);
@ -36,7 +37,11 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel,
g_warning("error converting fd to gsocket: %s", strerror(errno));
goto out;
}
qemu_socket_set_nonblock(client_fd);
if (!qemu_set_blocking(client_fd, false, &err)) {
g_warning("%s", error_get_pretty(err));
error_free(err);
goto out;
}
ret = ga_channel_client_add(c, client_fd);
if (ret) {
g_warning("error setting up connection");

View file

@ -503,9 +503,8 @@ int64_t qmp_guest_file_open(const char *path, const char *mode,
/* set fd non-blocking to avoid common use cases (like reading from a
* named pipe) from hanging the agent
*/
if (!g_unix_set_fd_nonblocking(fileno(fh), true, NULL)) {
if (!qemu_set_blocking(fileno(fh), false, errp)) {
fclose(fh);
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
return -1;
}

View file

@ -733,8 +733,11 @@ static void coroutine_fn prh_co_entry(void *opaque)
uint32_t flags;
int r;
qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
false, NULL);
if (!qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
false, &local_err)) {
goto out;
}
qio_channel_set_follow_coroutine_ctx(QIO_CHANNEL(client->ioc), true);
/* A very simple negotiation for future extensibility. No features
@ -786,6 +789,7 @@ static void coroutine_fn prh_co_entry(void *opaque)
}
}
out:
if (local_err) {
if (verbose == 0) {
error_free(local_err);
@ -794,7 +798,6 @@ static void coroutine_fn prh_co_entry(void *opaque)
}
}
out:
object_unref(OBJECT(client->ioc));
g_free(client);
}

View file

@ -132,7 +132,7 @@ 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);
qemu_set_blocking(sockfds[0], false, &error_abort);
sockfds_initialized = true;
g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
sockfds[1]);

View file

@ -330,7 +330,6 @@ static int chr_can_read(void *opaque)
static void chr_read(void *opaque, const uint8_t *buf, int size)
{
g_autoptr(GError) err = NULL;
TestServer *s = opaque;
CharBackend *chr = &s->chr;
VhostUserMsg msg;
@ -471,8 +470,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
* The receive function forces it to be blocking,
* so revert it back to non-blocking.
*/
g_unix_set_fd_nonblocking(fd, true, &err);
g_assert_no_error(err);
qemu_set_blocking(fd, false, &error_abort);
break;
case VHOST_USER_SET_LOG_BASE:

View file

@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "io-channel-helpers.h"
#include "qapi/error.h"
#include "qemu/iov.h"
struct QIOChannelTest {
@ -109,8 +110,8 @@ void qio_channel_test_run_threads(QIOChannelTest *test,
test->src = src;
test->dst = dst;
qio_channel_set_blocking(test->dst, blocking, NULL);
qio_channel_set_blocking(test->src, blocking, NULL);
qio_channel_set_blocking(test->dst, blocking, &error_abort);
qio_channel_set_blocking(test->src, blocking, &error_abort);
reader = g_thread_new("reader",
test_io_thread_reader,

View file

@ -19,6 +19,7 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/sockets.h"
#include "socket-helpers.h"
@ -88,7 +89,8 @@ static int socket_can_bind_connect(const char *hostname, int family)
goto cleanup;
}
qemu_socket_set_nonblock(cfd);
qemu_set_blocking(cfd, false, &error_abort);
if (connect(cfd, (struct sockaddr *)&ss, sslen) < 0) {
if (errno == EINPROGRESS) {
check_soerr = true;

View file

@ -112,8 +112,8 @@ static void test_crypto_tls_session_psk(void)
* thread, so we need these non-blocking to avoid deadlock
* of ourselves
*/
qemu_socket_set_nonblock(channel[0]);
qemu_socket_set_nonblock(channel[1]);
qemu_set_blocking(channel[0], false, &error_abort);
qemu_set_blocking(channel[1], false, &error_abort);
clientCreds = test_tls_creds_psk_create(
QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
@ -264,8 +264,8 @@ static void test_crypto_tls_session_x509(const void *opaque)
* thread, so we need these non-blocking to avoid deadlock
* of ourselves
*/
qemu_socket_set_nonblock(channel[0]);
qemu_socket_set_nonblock(channel[1]);
qemu_set_blocking(channel[0], false, &error_abort);
qemu_set_blocking(channel[1], false, &error_abort);
#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"

View file

@ -184,8 +184,8 @@ static void test_io_channel_tls(const void *opaque)
* thread, so we need these non-blocking to avoid deadlock
* of ourselves
*/
qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, NULL);
qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, NULL);
qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, &error_abort);
qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, &error_abort);
/* Now the real part of the test, setup the sessions */
clientChanTLS = qio_channel_tls_new_client(

View file

@ -1,4 +1,5 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
@ -186,7 +187,7 @@ static void test_io(void)
close(sv[0]);
FD_SET(sv[1], &fds);
g_unix_set_fd_nonblocking(sv[1], true, NULL);
qemu_set_blocking(sv[1], false, &error_abort);
r = g_test_rand_int_range(sz / 2, sz);
setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
@ -222,7 +223,7 @@ static void test_io(void)
close(sv[1]);
FD_SET(sv[0], &fds);
g_unix_set_fd_nonblocking(sv[0], true, NULL);
qemu_set_blocking(sv[0], false, &error_abort);
r = g_test_rand_int_range(sz / 2, sz);
setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
usleep(500000);

View file

@ -213,8 +213,10 @@ static void coroutine_fn vh_co_entry(void *opaque)
uint64_t vmsr;
int r;
qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
false, NULL);
if (!qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
false, &local_err)) {
goto out;
}
qio_channel_set_follow_coroutine_ctx(QIO_CHANNEL(client->ioc), true);

View file

@ -316,8 +316,7 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
error_setg_file_open(errp, errno, il->evdev);
return;
}
if (!g_unix_set_fd_nonblocking(il->fd, true, NULL)) {
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
if (!qemu_set_blocking(il->fd, false, errp)) {
return;
}

View file

@ -3337,7 +3337,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
VNC_DEBUG("New client on socket %p\n", vs->sioc);
update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
qio_channel_set_blocking(vs->ioc, false, NULL);
qio_channel_set_blocking(vs->ioc, false, &error_abort);
if (vs->ioc_tag) {
g_source_remove(vs->ioc_tag);
}

View file

@ -11,6 +11,7 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/event_notifier.h"
#include "qemu/main-loop.h"
@ -36,6 +37,7 @@ int event_notifier_init(EventNotifier *e, int active)
{
int fds[2];
int ret;
Error *local_err = NULL;
#ifdef CONFIG_EVENTFD
ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
@ -52,11 +54,11 @@ int event_notifier_init(EventNotifier *e, int active)
if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
return -errno;
}
if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {
if (!qemu_set_blocking(fds[0], false, &local_err)) {
ret = -errno;
goto fail;
}
if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {
if (!qemu_set_blocking(fds[1], false, &local_err)) {
ret = -errno;
goto fail;
}
@ -70,6 +72,7 @@ int event_notifier_init(EventNotifier *e, int active)
return 0;
fail:
error_report_err(local_err);
close(fds[0]);
close(fds[1]);
return ret;

View file

@ -114,7 +114,10 @@ static int qemu_signal_init(Error **errp)
return -errno;
}
g_unix_set_fd_nonblocking(sigfd, true, NULL);
if (!qemu_set_blocking(sigfd, false, errp)) {
close(sigfd);
return -EINVAL;
}
qemu_set_fd_handler(sigfd, sigfd_handler, NULL, (void *)(intptr_t)sigfd);

View file

@ -250,21 +250,19 @@ void qemu_anon_ram_free(void *ptr, size_t size)
#endif
}
void qemu_socket_set_block(int fd)
bool qemu_set_blocking(int fd, bool block, Error **errp)
{
g_unix_set_fd_nonblocking(fd, false, NULL);
}
g_autoptr(GError) err = NULL;
int qemu_socket_try_set_nonblock(int fd)
{
return g_unix_set_fd_nonblocking(fd, true, NULL) ? 0 : -errno;
}
if (!g_unix_set_fd_nonblocking(fd, !block, &err)) {
error_setg_errno(errp, errno,
"Can't set file descriptor %d %s: %s", fd,
block ? "blocking" : "non-blocking",
err->message);
return false;
}
void qemu_socket_set_nonblock(int fd)
{
int f;
f = qemu_socket_try_set_nonblock(fd);
assert(f == 0);
return true;
}
int socket_set_fast_reuse(int fd)

View file

@ -177,25 +177,22 @@ static int socket_error(void)
}
}
void qemu_socket_set_block(int fd)
bool qemu_set_blocking(int fd, bool block, Error **errp)
{
unsigned long opt = 0;
qemu_socket_unselect(fd, NULL);
ioctlsocket(fd, FIONBIO, &opt);
}
unsigned long opt = block ? 0 : 1;
int qemu_socket_try_set_nonblock(int fd)
{
unsigned long opt = 1;
if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
return -socket_error();
if (block) {
qemu_socket_unselect(fd, NULL);
}
return 0;
}
void qemu_socket_set_nonblock(int fd)
{
(void)qemu_socket_try_set_nonblock(fd);
if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
error_setg_errno(errp, socket_error(),
"Can't set file descriptor %d %s", fd,
block ? "blocking" : "non-blocking");
return false;
}
return true;
}
int socket_set_fast_reuse(int fd)

View file

@ -62,7 +62,7 @@ static void vmsg_close_fds(VhostUserMsg *vmsg)
}
}
static void vmsg_unblock_fds(VhostUserMsg *vmsg)
static bool vmsg_unblock_fds(VhostUserMsg *vmsg, Error **errp)
{
int i;
@ -74,12 +74,16 @@ static void vmsg_unblock_fds(VhostUserMsg *vmsg)
*/
if (vmsg->request == VHOST_USER_ADD_MEM_REG ||
vmsg->request == VHOST_USER_SET_MEM_TABLE) {
return;
return true;
}
for (i = 0; i < vmsg->fd_num; i++) {
qemu_socket_set_nonblock(vmsg->fds[i]);
if (!qemu_set_blocking(vmsg->fds[i], false, errp)) {
return false;
}
}
return true;
}
static void panic_cb(VuDev *vu_dev, const char *buf)
@ -122,7 +126,6 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg)
vmsg->fd_num = 0;
if (!ioc) {
error_report_err(local_err);
goto fail;
}
@ -176,7 +179,10 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg)
} while (read_bytes != VHOST_USER_HDR_SIZE);
/* qio_channel_readv_full will make socket fds blocking, unblock them */
vmsg_unblock_fds(vmsg);
if (!vmsg_unblock_fds(vmsg, &local_err)) {
error_report_err(local_err);
goto fail;
}
if (vmsg->size > sizeof(vmsg->payload)) {
error_report("Error: too big message request: %d, "
"size: vmsg->size: %u, "
@ -303,7 +309,8 @@ set_watch(VuDev *vu_dev, int fd, int vu_evt,
vu_fd_watch->fd = fd;
vu_fd_watch->cb = cb;
qemu_socket_set_nonblock(fd);
/* TODO: handle error more gracefully than aborting */
qemu_set_blocking(fd, false, &error_abort);
aio_set_fd_handler(server->ctx, fd, kick_handler,
NULL, NULL, NULL, vu_fd_watch);
vu_fd_watch->vu_dev = vu_dev;
@ -336,6 +343,7 @@ static void vu_accept(QIONetListener *listener, QIOChannelSocket *sioc,
gpointer opaque)
{
VuServer *server = opaque;
Error *local_err = NULL;
if (server->sioc) {
warn_report("Only one vhost-user client is allowed to "
@ -368,7 +376,11 @@ static void vu_accept(QIONetListener *listener, QIOChannelSocket *sioc,
object_ref(OBJECT(server->ioc));
/* TODO vu_message_write() spins if non-blocking! */
qio_channel_set_blocking(server->ioc, false, NULL);
if (!qio_channel_set_blocking(server->ioc, false, &local_err)) {
error_report_err(local_err);
vu_deinit(&server->vu_dev);
return;
}
qio_channel_set_follow_coroutine_ctx(server->ioc, true);