static int virNetDevSetupControlFull(const char *ifname, struct ifreq *ifr, int domain, int type) { int fd; memset(ifr, 0, sizeof(*ifr)); if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) { virReportSystemError(ERANGE, _("Network interface name '%s' is too long"), ifname); return -1; } if ((fd = socket(domain, type, 0)) < 0) { virReportSystemError(errno, "%s", _("Cannot open network interface control socket")); return -1; } if (virSetInherit(fd, false) < 0) { virReportSystemError(errno, "%s", _("Cannot set close-on-exec flag for socket")); VIR_FORCE_CLOSE(fd); return -1; } return fd; }
int virNetMessageDupFD(virNetMessagePtr msg, size_t slot) { int fd; if (slot >= msg->nfds) { virReportError(VIR_ERR_INTERNAL_ERROR, _("No FD available at slot %zu"), slot); return -1; } if ((fd = dup(msg->fds[slot])) < 0) { virReportSystemError(errno, _("Unable to duplicate FD %d"), msg->fds[slot]); return -1; } if (virSetInherit(fd, false) < 0) { VIR_FORCE_CLOSE(fd); virReportSystemError(errno, _("Cannot set close-on-exec %d"), fd); return -1; } return fd; }
int virNetMessageAddFD(virNetMessagePtr msg, int fd) { int newfd = -1; if ((newfd = dup(fd)) < 0) { virReportSystemError(errno, _("Unable to duplicate FD %d"), fd); goto error; } if (virSetInherit(newfd, false) < 0) { virReportSystemError(errno, _("Cannot set close-on-exec %d"), newfd); goto error; } if (VIR_APPEND_ELEMENT(msg->fds, msg->nfds, newfd) < 0) goto error; return 0; error: VIR_FORCE_CLOSE(newfd); return -1; }
static virLogHandlerLogFilePtr virLogHandlerLogFilePostExecRestart(virLogHandlerPtr handler, virJSONValuePtr object) { virLogHandlerLogFilePtr file; const char *path; if (VIR_ALLOC(file) < 0) return NULL; handler->inhibitor(true, handler->opaque); if ((path = virJSONValueObjectGetString(object, "path")) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing file path in JSON document")); goto error; } if ((file->file = virRotatingFileWriterNew(path, DEFAULT_FILE_SIZE, DEFAULT_MAX_BACKUP, false, DEFAULT_MODE)) == NULL) goto error; if (virJSONValueObjectGetNumberInt(object, "pipefd", &file->pipefd) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing file pipefd in JSON document")); goto error; } if (virSetInherit(file->pipefd, false) < 0) { virReportSystemError(errno, "%s", _("Cannot enable close-on-exec flag")); goto error; } return file; error: handler->inhibitor(false, handler->opaque); virLogHandlerLogFileFree(file); return NULL; }
static int virLockManagerSanlockAcquire(virLockManagerPtr lock, const char *state, unsigned int flags, virDomainLockFailureAction action, int *fd) { virLockManagerSanlockPrivatePtr priv = lock->privateData; struct sanlk_options *opt; struct sanlk_resource **res_args; int res_count; bool res_free = false; int sock = -1; int rv; int i; virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_RESTRICT | VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY, -1); if (priv->res_count == 0 && priv->hasRWDisks && driver->requireLeaseForDisks) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Read/write, exclusive access, disks were present, but no leases specified")); return -1; } if (VIR_ALLOC(opt) < 0) { virReportOOMError(); return -1; } if (!virStrcpy(opt->owner_name, priv->vm_name, SANLK_NAME_LEN)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Domain name '%s' exceeded %d characters"), priv->vm_name, SANLK_NAME_LEN); goto error; } if (state && STRNEQ(state, "")) { if ((rv = sanlock_state_to_args((char *)state, &res_count, &res_args)) < 0) { if (rv <= -200) virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to parse lock state %s: error %d"), state, rv); else virReportSystemError(-rv, _("Unable to parse lock state %s"), state); goto error; } res_free = true; } else { res_args = priv->res_args; res_count = priv->res_count; } /* We only initialize 'sock' if we are in the real * child process and we need it to be inherited * * If sock==-1, then sanlock auto-open/closes a * temporary sock */ if (priv->vm_pid == getpid()) { VIR_DEBUG("Register sanlock %d", flags); if ((sock = sanlock_register()) < 0) { if (sock <= -200) virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to open socket to sanlock daemon: error %d"), sock); else virReportSystemError(-sock, "%s", _("Failed to open socket to sanlock daemon")); goto error; } if (action != VIR_DOMAIN_LOCK_FAILURE_DEFAULT) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(priv->vm_uuid, uuidstr); if (virLockManagerSanlockRegisterKillscript(sock, priv->vm_uri, uuidstr, action) < 0) goto error; } } if (!(flags & VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY)) { VIR_DEBUG("Acquiring object %u", priv->res_count); if ((rv = sanlock_acquire(sock, priv->vm_pid, 0, priv->res_count, priv->res_args, opt)) < 0) { if (rv <= -200) virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to acquire lock: error %d"), rv); else virReportSystemError(-rv, "%s", _("Failed to acquire lock")); goto error; } } VIR_FREE(opt); /* * We are *intentionally* "leaking" sock file descriptor * because we want it to be inherited by QEMU. When the * sock FD finally closes upon QEMU exit (or crash) then * sanlock will notice EOF and release the lock */ if (sock != -1 && virSetInherit(sock, true) < 0) goto error; if (flags & VIR_LOCK_MANAGER_ACQUIRE_RESTRICT) { if ((rv = sanlock_restrict(sock, SANLK_RESTRICT_ALL)) < 0) { if (rv <= -200) virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to restrict process: error %d"), rv); else virReportSystemError(-rv, "%s", _("Failed to restrict process")); goto error; } } VIR_DEBUG("Acquire completed fd=%d", sock); if (res_free) { for (i = 0 ; i < res_count ; i++) { VIR_FREE(res_args[i]); } VIR_FREE(res_args); } if (fd) *fd = sock; return 0; error: if (res_free) { for (i = 0 ; i < res_count ; i++) { VIR_FREE(res_args[i]); } VIR_FREE(res_args); } VIR_FREE(opt); VIR_FORCE_CLOSE(sock); return -1; }
int virSetCloseExec(int fd) { return virSetInherit(fd, false); }
int virNetClientProgramCall(virNetClientProgramPtr prog, virNetClientPtr client, unsigned serial, int proc, size_t noutfds, int *outfds, size_t *ninfds, int **infds, xdrproc_t args_filter, void *args, xdrproc_t ret_filter, void *ret) { virNetMessagePtr msg; size_t i; if (infds) *infds = NULL; if (ninfds) *ninfds = 0; if (!(msg = virNetMessageNew(false))) return -1; msg->header.prog = prog->program; msg->header.vers = prog->version; msg->header.status = VIR_NET_OK; msg->header.type = noutfds ? VIR_NET_CALL_WITH_FDS : VIR_NET_CALL; msg->header.serial = serial; msg->header.proc = proc; msg->nfds = noutfds; if (VIR_ALLOC_N(msg->fds, msg->nfds) < 0) { virReportOOMError(); goto error; } for (i = 0; i < msg->nfds; i++) msg->fds[i] = -1; for (i = 0; i < msg->nfds; i++) { if ((msg->fds[i] = dup(outfds[i])) < 0) { virReportSystemError(errno, _("Cannot duplicate FD %d"), outfds[i]); goto error; } if (virSetInherit(msg->fds[i], false) < 0) { virReportSystemError(errno, _("Cannot set close-on-exec %d"), msg->fds[i]); goto error; } } if (virNetMessageEncodeHeader(msg) < 0) goto error; if (msg->nfds && virNetMessageEncodeNumFDs(msg) < 0) goto error; if (virNetMessageEncodePayload(msg, args_filter, args) < 0) goto error; if (virNetClientSendWithReply(client, msg) < 0) goto error; /* None of these 3 should ever happen here, because * virNetClientSend should have validated the reply, * but it doesn't hurt to check again. */ if (msg->header.type != VIR_NET_REPLY && msg->header.type != VIR_NET_REPLY_WITH_FDS) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected message type %d"), msg->header.type); goto error; } if (msg->header.proc != proc) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected message proc %d != %d"), msg->header.proc, proc); goto error; } if (msg->header.serial != serial) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected message serial %d != %d"), msg->header.serial, serial); goto error; } switch (msg->header.status) { case VIR_NET_OK: if (infds && ninfds) { *ninfds = msg->nfds; if (VIR_ALLOC_N(*infds, *ninfds) < 0) { virReportOOMError(); goto error; } for (i = 0; i < *ninfds; i++) (*infds)[i] = -1; for (i = 0; i < *ninfds; i++) { if (((*infds)[i] = dup(msg->fds[i])) < 0) { virReportSystemError(errno, _("Cannot duplicate FD %d"), msg->fds[i]); goto error; } if (virSetInherit((*infds)[i], false) < 0) { virReportSystemError(errno, _("Cannot set close-on-exec %d"), (*infds)[i]); goto error; } } } if (virNetMessageDecodePayload(msg, ret_filter, ret) < 0) goto error; break; case VIR_NET_ERROR: virNetClientProgramDispatchError(prog, msg); goto error; default: virReportError(VIR_ERR_RPC, _("Unexpected message status %d"), msg->header.status); goto error; } virNetMessageFree(msg); return 0; error: virNetMessageFree(msg); if (infds && ninfds) { for (i = 0; i < *ninfds; i++) VIR_FORCE_CLOSE((*infds)[i]); } return -1; }