static int qemu_signalfd_compat(const sigset_t *mask) { pthread_attr_t attr; pthread_t tid; struct sigfd_compat_info *info; int fds[2]; info = malloc(sizeof(*info)); if (info == NULL) { errno = ENOMEM; return -1; } if (pipe(fds) == -1) { free(info); return -1; } qemu_set_cloexec(fds[0]); qemu_set_cloexec(fds[1]); memcpy(&info->mask, mask, sizeof(*mask)); info->fd = fds[1]; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&tid, &attr, sigwait_compat, info); pthread_attr_destroy(&attr); return fds[0]; }
/* * Creates a pipe with FD_CLOEXEC set on both file descriptors */ int qemu_pipe(int pipefd[2]) { int ret; #ifdef CONFIG_PIPE2 ret = pipe2(pipefd, O_CLOEXEC); if (ret != -1 || errno != ENOSYS) { return ret; } #endif ret = pipe(pipefd); if (ret == 0) { qemu_set_cloexec(pipefd[0]); qemu_set_cloexec(pipefd[1]); } return ret; }
static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len) { SocketChardev *s = SOCKET_CHARDEV(chr); struct iovec iov = { .iov_base = buf, .iov_len = len }; int ret; size_t i; int *msgfds = NULL; size_t msgfds_num = 0; if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) { ret = qio_channel_readv_full(s->ioc, &iov, 1, &msgfds, &msgfds_num, NULL); } else { ret = qio_channel_readv_full(s->ioc, &iov, 1, NULL, NULL, NULL); } if (ret == QIO_CHANNEL_ERR_BLOCK) { errno = EAGAIN; ret = -1; } else if (ret == -1) { errno = EIO; } if (msgfds_num) { /* close and clean read_msgfds */ for (i = 0; i < s->read_msgfds_num; i++) { close(s->read_msgfds[i]); } if (s->read_msgfds_num) { g_free(s->read_msgfds); } s->read_msgfds = msgfds; 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_set_block(fd); #ifndef MSG_CMSG_CLOEXEC qemu_set_cloexec(fd); #endif } return ret; }
int qemu_dup(int fd) { int ret; #ifdef F_DUPFD_CLOEXEC ret = fcntl(fd, F_DUPFD_CLOEXEC, 0); #else ret = dup(fd); if (ret != -1) { qemu_set_cloexec(ret); } #endif return ret; }
/* * Dups an fd and sets the flags */ static int qemu_dup_flags(int fd, int flags) { int ret; int serrno; int dup_flags; #ifdef F_DUPFD_CLOEXEC ret = fcntl(fd, F_DUPFD_CLOEXEC, 0); #else ret = dup(fd); if (ret != -1) { qemu_set_cloexec(ret); } #endif if (ret == -1) { goto fail; } dup_flags = fcntl(ret, F_GETFL); if (dup_flags == -1) { goto fail; } if ((flags & O_SYNC) != (dup_flags & O_SYNC)) { errno = EINVAL; goto fail; } /* Set/unset flags that we can with fcntl */ if (fcntl(ret, F_SETFL, flags) == -1) { goto fail; } /* Truncate the file in the cases that open() would truncate it */ if (flags & O_TRUNC || ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) { if (ftruncate(ret, 0) == -1) { goto fail; } } return ret; fail: serrno = errno; if (ret != -1) { close(ret); } errno = serrno; return -1; }
int qemu_signalfd(const sigset_t *mask) { #if defined(CONFIG_SYS_SIGNALFD) int ret; ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8); if (ret != -1) { qemu_set_cloexec(ret); return ret; } #endif return qemu_signalfd_compat(mask); }
void os_daemonize(void) { if (daemonize) { pid_t pid; int fds[2]; if (pipe(fds) == -1) { exit(1); } pid = fork(); if (pid > 0) { uint8_t status; ssize_t len; close(fds[1]); do { len = read(fds[0], &status, 1); } while (len < 0 && errno == EINTR); /* only exit successfully if our child actually wrote * a one-byte zero to our pipe, upon successful init */ exit(len == 1 && status == 0 ? 0 : 1); } else if (pid < 0) { exit(1); } close(fds[0]); daemon_pipe = fds[1]; qemu_set_cloexec(daemon_pipe); setsid(); pid = fork(); if (pid > 0) { exit(0); } else if (pid < 0) { exit(1); } umask(027); signal(SIGTSTP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); rcu_after_fork(); } }
void os_daemonize(void) { if (daemonize) { pid_t pid; if (pipe(fds) == -1) exit(1); pid = fork(); if (pid > 0) { uint8_t status; ssize_t len; close(fds[1]); again: len = read(fds[0], &status, 1); LOGV("%s:%s, read(), len = %d", __FILE__, __func__, len); if (len == -1 && (errno == EINTR)) goto again; if (len != 1) exit(1); else if (status == 1) { fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno)); exit(1); } else exit(0); } else if (pid < 0) exit(1); close(fds[0]); qemu_set_cloexec(fds[1]); setsid(); pid = fork(); if (pid > 0) exit(0); else if (pid < 0) exit(1); umask(027); signal(SIGTSTP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); } }
/* * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set. */ int qemu_eventfd(int fds[2]) { #ifdef CONFIG_EVENTFD int ret; ret = eventfd(0, 0); if (ret >= 0) { fds[0] = ret; qemu_set_cloexec(ret); if ((fds[1] = dup(ret)) == -1) { close(ret); return -1; } qemu_set_cloexec(fds[1]); return 0; } if (errno != ENOSYS) { return -1; } #endif return qemu_pipe(fds); }
static void qio_channel_socket_copy_fds(struct msghdr *msg, int **fds, size_t *nfds) { struct cmsghdr *cmsg; *nfds = 0; *fds = NULL; for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { int fd_size, i; int gotfds; if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { continue; } fd_size = cmsg->cmsg_len - CMSG_LEN(0); if (!fd_size) { continue; } 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_set_block(fd); #ifndef MSG_CMSG_CLOEXEC qemu_set_cloexec(fd); #endif } *nfds += gotfds; } }
static void ga_log(const gchar *domain, GLogLevelFlags level, const gchar *msg, gpointer opaque) { GAState *s = opaque; GTimeVal time; const char *level_str = ga_log_level_str(level); if (!ga_logging_enabled(s)) { return; } level &= G_LOG_LEVEL_MASK; #ifndef _WIN32 if (g_strcmp0(domain, "syslog") == 0) { syslog(LOG_INFO, "%s: %s", level_str, msg); } else if (level & s->log_level) { #else if (level & s->log_level) { #endif g_get_current_time(&time); fprintf(s->log_file, "%lu.%lu: %s: %s\n", time.tv_sec, time.tv_usec, level_str, msg); fflush(s->log_file); } } void ga_set_response_delimited(GAState *s) { s->delimit_response = true; } static FILE *ga_open_logfile(const char *logfile) { FILE *f; f = fopen(logfile, "a"); if (!f) { return NULL; } qemu_set_cloexec(fileno(f)); return f; }
static int init_socket(const char *socket_path) { struct sockaddr_un addr; int sock; int ret; sock = socket(PF_UNIX, SOCK_STREAM, 0); g_assert_no_errno(sock); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path); qemu_set_cloexec(sock); do { ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); } while (ret == -1 && errno == EINTR); g_assert_no_errno(ret); listen(sock, 1); return sock; }
static int raw_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) { BDRVRawState *s; BDRVRawReopenState *raw_s; int ret = 0; assert(state != NULL); assert(state->bs != NULL); s = state->bs->opaque; state->opaque = g_malloc0(sizeof(BDRVRawReopenState)); raw_s = state->opaque; #ifdef CONFIG_LINUX_AIO raw_s->use_aio = s->use_aio; /* we can use s->aio_ctx instead of a copy, because the use_aio flag is * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio() * won't override aio_ctx if aio_ctx is non-NULL */ if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) { return -1; } #endif if (s->type == FTYPE_FD || s->type == FTYPE_CD) { raw_s->open_flags |= O_NONBLOCK; } raw_parse_flags(state->flags, &raw_s->open_flags); raw_s->fd = -1; int fcntl_flags = O_APPEND | O_NONBLOCK; #ifdef O_NOATIME fcntl_flags |= O_NOATIME; #endif #ifdef O_ASYNC /* Not all operating systems have O_ASYNC, and those that don't * will not let us track the state into raw_s->open_flags (typically * you achieve the same effect with an ioctl, for example I_SETSIG * on Solaris). But we do not use O_ASYNC, so that's fine. */ assert((s->open_flags & O_ASYNC) == 0); #endif if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) { /* dup the original fd */ /* TODO: use qemu fcntl wrapper */ #ifdef F_DUPFD_CLOEXEC raw_s->fd = fcntl(s->fd, F_DUPFD_CLOEXEC, 0); #else raw_s->fd = dup(s->fd); if (raw_s->fd != -1) { qemu_set_cloexec(raw_s->fd); } #endif if (raw_s->fd >= 0) { ret = fcntl_setfl(raw_s->fd, raw_s->open_flags); if (ret) { qemu_close(raw_s->fd); raw_s->fd = -1; } } } /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */ if (raw_s->fd == -1) { assert(!(raw_s->open_flags & O_CREAT)); raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags); if (raw_s->fd == -1) { ret = -1; } } return ret; }
static int xen_9pfs_connect(struct XenLegacyDevice *xendev) { Error *err = NULL; int i; Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev); V9fsState *s = &xen_9pdev->state; QemuOpts *fsdev; if (xenstore_read_fe_int(&xen_9pdev->xendev, "num-rings", &xen_9pdev->num_rings) == -1 || xen_9pdev->num_rings > MAX_RINGS || xen_9pdev->num_rings < 1) { return -1; } xen_9pdev->rings = g_new0(Xen9pfsRing, xen_9pdev->num_rings); for (i = 0; i < xen_9pdev->num_rings; i++) { char *str; int ring_order; xen_9pdev->rings[i].priv = xen_9pdev; xen_9pdev->rings[i].evtchn = -1; xen_9pdev->rings[i].local_port = -1; str = g_strdup_printf("ring-ref%u", i); if (xenstore_read_fe_int(&xen_9pdev->xendev, str, &xen_9pdev->rings[i].ref) == -1) { g_free(str); goto out; } g_free(str); str = g_strdup_printf("event-channel-%u", i); if (xenstore_read_fe_int(&xen_9pdev->xendev, str, &xen_9pdev->rings[i].evtchn) == -1) { g_free(str); goto out; } g_free(str); xen_9pdev->rings[i].intf = xen_be_map_grant_ref(&xen_9pdev->xendev, xen_9pdev->rings[i].ref, PROT_READ | PROT_WRITE); if (!xen_9pdev->rings[i].intf) { goto out; } ring_order = xen_9pdev->rings[i].intf->ring_order; if (ring_order > MAX_RING_ORDER) { goto out; } xen_9pdev->rings[i].ring_order = ring_order; xen_9pdev->rings[i].data = xen_be_map_grant_refs(&xen_9pdev->xendev, xen_9pdev->rings[i].intf->ref, (1 << ring_order), PROT_READ | PROT_WRITE); if (!xen_9pdev->rings[i].data) { goto out; } xen_9pdev->rings[i].ring.in = xen_9pdev->rings[i].data; xen_9pdev->rings[i].ring.out = xen_9pdev->rings[i].data + XEN_FLEX_RING_SIZE(ring_order); xen_9pdev->rings[i].bh = qemu_bh_new(xen_9pfs_bh, &xen_9pdev->rings[i]); xen_9pdev->rings[i].out_cons = 0; xen_9pdev->rings[i].out_size = 0; xen_9pdev->rings[i].inprogress = false; xen_9pdev->rings[i].evtchndev = xenevtchn_open(NULL, 0); if (xen_9pdev->rings[i].evtchndev == NULL) { goto out; } qemu_set_cloexec(xenevtchn_fd(xen_9pdev->rings[i].evtchndev)); xen_9pdev->rings[i].local_port = xenevtchn_bind_interdomain (xen_9pdev->rings[i].evtchndev, xendev->dom, xen_9pdev->rings[i].evtchn); if (xen_9pdev->rings[i].local_port == -1) { xen_pv_printf(xendev, 0, "xenevtchn_bind_interdomain failed port=%d\n", xen_9pdev->rings[i].evtchn); goto out; } xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port); qemu_set_fd_handler(xenevtchn_fd(xen_9pdev->rings[i].evtchndev), xen_9pfs_evtchn_event, NULL, &xen_9pdev->rings[i]); } xen_9pdev->security_model = xenstore_read_be_str(xendev, "security_model"); xen_9pdev->path = xenstore_read_be_str(xendev, "path"); xen_9pdev->id = s->fsconf.fsdev_id = g_strdup_printf("xen9p%d", xendev->dev); xen_9pdev->tag = s->fsconf.tag = xenstore_read_fe_str(xendev, "tag"); fsdev = qemu_opts_create(qemu_find_opts("fsdev"), s->fsconf.tag, 1, NULL); qemu_opt_set(fsdev, "fsdriver", "local", NULL); qemu_opt_set(fsdev, "path", xen_9pdev->path, NULL); qemu_opt_set(fsdev, "security_model", xen_9pdev->security_model, NULL); qemu_opts_set_id(fsdev, s->fsconf.fsdev_id); qemu_fsdev_add(fsdev, &err); if (err) { error_report_err(err); } v9fs_device_realize_common(s, &xen_9p_transport, NULL); return 0; out: xen_9pfs_free(xendev); return -1; }