+Thu Jan 21 19:04:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+
+ Remove use of non-reentrant POSIX api calls
+ * configure.in: Check for strtok_r getmntent_r getgrnam_r getpwuid_r
+ * proxy/libvirt_proxy.c: Remove initialize of obsolete fields
+ * qemud/qemud.c: Use virGetUserDirectory instead of getpwuid()
+ * src/libvirt_private.syms, src/util.c, src/util.h: Add a generic
+ virGetUserDirectory call around getpwuid()
+ * src/lxc_container.c, src/storage_backend_fs.c: Use getmntent_r()
+ * src/network_driver.c, src/qemu_driver.c, src/storage_driver.c,
+ src/remote_internal.c, src/uml_driver.c: Use virGetUserDirectory()
+ * src/openvz_driver.c: Use strtok_r()
+ * src/xen_unified.c, src/xen_unified.h, src/xend_internal.c:
+ Replace gethostname() with getaddrinfo()
+
Thu Jan 22 20:17:35 +0100 2009 Jim Meyering <meyering@redhat.com>
xm_internal.c: fix locking bug: s/Lock/Unlock/
tests/sexpr2xmldata/sexpr2xml-net-bridged.xml,
tests/sexpr2xmldata/sexpr2xml-net-e1000.xml: update tests
-Wed Jan 21 18:18:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+Thu Jan 22 18:18:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
Missing test case fix up from Xen threadsafety changes
* tests/sexpr2xmltest.c, tests/Makefile.am: Pass a real
AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity getuid getgid])
dnl Availability of various not common threadsafe functions
-AC_CHECK_FUNCS([strerror_r])
+AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r])
dnl Availability of various common headers (non-fatal if missing).
AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/syslimits.h sys/utsname.h sys/wait.h winsock2.h sched.h termios.h sys/poll.h syslog.h])
priv->handle = -1;
priv->xendConfigVersion = -1;
- priv->type = -1;
- priv->len = -1;
- priv->addr = NULL;
priv->xshandle = NULL;
priv->proxy = -1;
if (snprintf(server->logDir, PATH_MAX, "%s/log/libvirt/", LOCAL_STATE_DIR) >= PATH_MAX)
goto snprintf_error;
} else {
- struct passwd *pw;
+ char *userdir = virGetUserDirectory(NULL, uid);
- if (!(pw = getpwuid(uid))) {
- VIR_ERROR(_("Failed to find user record for uid '%d': %s"),
- uid, strerror(errno));
- return -1;
- }
-
- if (snprintf(sockname, maxlen, "@%s/.libvirt/libvirt-sock", pw->pw_dir) >= maxlen)
+ if (snprintf(sockname, maxlen, "@%s/.libvirt/libvirt-sock", userdir) >= maxlen) {
+ VIR_FREE(userdir);
goto snprintf_error;
+ }
- if (snprintf(server->logDir, PATH_MAX, "%s/.libvirt/log", pw->pw_dir) >= PATH_MAX)
+ if (snprintf(server->logDir, PATH_MAX, "%s/.libvirt/log", userdir) >= PATH_MAX) {
+ VIR_FREE(userdir);
goto snprintf_error;
-
+ }
+ VIR_FREE(userdir);
} /* !remote */
return 0;
if (getuid() != 0) {
VIR_WARN0(_("Cannot set group when not running as root"));
} else {
- struct group *grp = getgrnam(unix_sock_group);
- if (!grp) {
+ char buf[1024];
+ struct group grpdata, *grp;
+ if (getgrnam_r(unix_sock_group, &grpdata, buf, sizeof(buf), &grp) != 0 || !grp) {
VIR_ERROR(_("Failed to lookup group '%s'"), unix_sock_group);
goto free_and_fail;
}
virRun;
virSkipSpaces;
virKillProcess;
+virGetUserDirectory;
# uuid.h
static int lxcContainerUnmountOldFS(void)
{
- struct mntent *mntent;
+ struct mntent mntent;
char **mounts = NULL;
int nmounts = 0;
FILE *procmnt;
int i;
+ char mntbuf[1024];
if (!(procmnt = setmntent("/proc/mounts", "r"))) {
virReportSystemError(NULL, errno, "%s",
_("failed to read /proc/mounts"));
return -1;
}
- while ((mntent = getmntent(procmnt)) != NULL) {
- if (!STRPREFIX(mntent->mnt_dir, "/.oldroot"))
+ while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
+ if (!STRPREFIX(mntent.mnt_dir, "/.oldroot"))
continue;
if (VIR_REALLOC_N(mounts, nmounts+1) < 0) {
lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1;
}
- if (!(mounts[nmounts++] = strdup(mntent->mnt_dir))) {
+ if (!(mounts[nmounts++] = strdup(mntent.mnt_dir))) {
endmntent(procmnt);
lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1;
static int
networkStartup(void) {
uid_t uid = geteuid();
- struct passwd *pw;
char *base = NULL;
int err;
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
goto out_of_memory;
} else {
- if (!(pw = getpwuid(uid))) {
- networkLog(NETWORK_ERR, _("Failed to find user record for uid '%d': %s\n"),
- uid, strerror(errno));
- goto out_of_memory;
- }
+ char *userdir = virGetUserDirectory(NULL, uid);
+
+ if (!userdir)
+ goto error;
if (virAsprintf(&driverState->logDir,
- "%s/.libvirt/qemu/log", pw->pw_dir) == -1)
+ "%s/.libvirt/qemu/log", userdir) == -1) {
+ VIR_FREE(userdir);
goto out_of_memory;
+ }
- if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1) {
+ if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
+ VIR_FREE(userdir);
goto out_of_memory;
}
+ VIR_FREE(userdir);
}
/* Configuration paths are either ~/.libvirt/qemu/... (session) or
if ( (ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
snprintf(temp, sizeof(temp), "eth0");
} else {
+ char *saveptr;
char *s;
int max = 0;
/* get maximum interface number (actually, it is the last one) */
- for (s=strtok(temp, ";"); s; s=strtok(NULL, ";")) {
+ for (s=strtok_r(temp, ";", &saveptr); s; s=strtok_r(NULL, ";", &saveptr)) {
int x;
if (sscanf(s, "ifname=eth%d", &x) != 1) return NULL;
static int
qemudStartup(void) {
uid_t uid = geteuid();
- struct passwd *pw;
char *base = NULL;
char driverConf[PATH_MAX];
"%s/run/libvirt/qemu/", LOCAL_STATE_DIR) == -1)
goto out_of_memory;
} else {
- if (!(pw = getpwuid(uid))) {
- qemudLog(QEMUD_ERR, _("Failed to find user record for uid '%d': %s\n"),
- uid, strerror(errno));
+ char *userdir = virGetUserDirectory(NULL, uid);
+ if (!userdir)
goto error;
- }
if (virAsprintf(&qemu_driver->logDir,
- "%s/.libvirt/qemu/log", pw->pw_dir) == -1)
+ "%s/.libvirt/qemu/log", userdir) == -1) {
+ VIR_FREE(userdir);
goto out_of_memory;
+ }
- if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1)
+ if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
+ VIR_FREE(userdir);
goto out_of_memory;
+ }
+ VIR_FREE(userdir);
if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
goto out_of_memory;
}
if (virFileMakePath(qemu_driver->stateDir) < 0) {
- qemudLog(QEMUD_ERR, _("Failed to create state dir '%s': %s\n"),
- qemu_driver->stateDir, strerror(errno));
- goto error;
+ qemudLog(QEMUD_ERR, _("Failed to create state dir '%s': %s\n"),
+ qemu_driver->stateDir, strerror(errno));
+ goto error;
}
/* Configuration paths are either ~/.libvirt/qemu/... (session) or
case trans_unix: {
if (!sockname) {
if (flags & VIR_DRV_OPEN_REMOTE_USER) {
- struct passwd *pw;
- uid_t uid = getuid();
+ char *userdir = virGetUserDirectory(conn, getuid());
- if (!(pw = getpwuid(uid))) {
- virReportSystemError(conn, errno,
- _("unable to lookup user '%d'"),
- uid);
+ if (!userdir)
goto failed;
- }
- if (virAsprintf(&sockname, "@%s" LIBVIRTD_USER_UNIX_SOCKET, pw->pw_dir) < 0)
+ if (virAsprintf(&sockname, "@%s" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0) {
+ VIR_FREE(userdir);
goto out_of_memory;
-
+ }
+ VIR_FREE(userdir);
} else {
if (flags & VIR_DRV_OPEN_REMOTE_RO)
sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET_RO);
virStorageBackendFileSystemIsMounted(virConnectPtr conn,
virStoragePoolObjPtr pool) {
FILE *mtab;
- struct mntent *ent;
+ struct mntent ent;
+ char buf[1024];
if ((mtab = fopen(_PATH_MOUNTED, "r")) == NULL) {
virReportSystemError(conn, errno,
return -1;
}
- while ((ent = getmntent(mtab)) != NULL) {
- if (STREQ(ent->mnt_dir, pool->def->target.path)) {
+ while ((getmntent_r(mtab, &ent, buf, sizeof(buf))) != NULL) {
+ if (STREQ(ent.mnt_dir, pool->def->target.path)) {
fclose(mtab);
return 1;
}
static int
storageDriverStartup(void) {
uid_t uid = geteuid();
- struct passwd *pw;
char *base = NULL;
char driverConf[PATH_MAX];
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
goto out_of_memory;
} else {
- if (!(pw = getpwuid(uid))) {
- storageLog("Failed to find user record for uid '%d': %s",
- uid, strerror(errno));
- goto out_of_memory;
- }
+ char *userdir = virGetUserDirectory(NULL, uid);
+
+ if (!userdir)
+ goto error;
- if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1) {
+ if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
storageLog("out of memory in virAsprintf");
+ VIR_FREE(userdir);
goto out_of_memory;
}
+ VIR_FREE(userdir);
}
/* Configuration paths are either ~/.libvirt/storage/... (session) or
static int
umlStartup(void) {
uid_t uid = geteuid();
- struct passwd *pw;
char *base = NULL;
char driverConf[PATH_MAX];
+ char *userdir = NULL;
if (VIR_ALLOC(uml_driver) < 0)
return -1;
/* Don't have a dom0 so start from 1 */
uml_driver->nextvmid = 1;
- if (!(pw = getpwuid(uid))) {
- umlLog(VIR_LOG_ERROR, _("Failed to find user record for uid '%d': %s\n"),
- uid, strerror(errno));
+ userdir = virGetUserDirectory(NULL, uid);
+ if (!userdir)
goto error;
- }
if (!uid) {
if (virAsprintf(¨_driver->logDir,
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
goto out_of_memory;
} else {
+
if (virAsprintf(¨_driver->logDir,
- "%s/.libvirt/uml/log", pw->pw_dir) == -1)
+ "%s/.libvirt/uml/log", userdir) == -1)
goto out_of_memory;
- if (virAsprintf(&base, "%s/.libvirt", pw->pw_dir) == -1)
+ if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
goto out_of_memory;
}
if (virAsprintf(¨_driver->monitorDir,
- "%s/.uml", pw->pw_dir) == -1)
+ "%s/.uml", userdir) == -1)
goto out_of_memory;
/* Configuration paths are either ~/.libvirt/uml/... (session) or
umlAutostartConfigs(uml_driver);
umlDriverUnlock(uml_driver);
+ VIR_FREE(userdir);
+
return 0;
out_of_memory:
"%s", _("umlStartup: out of memory\n"));
error:
+ VIR_FREE(userdir);
VIR_FREE(base);
umlDriverUnlock(uml_driver);
umlShutdown();
#include <paths.h>
#endif
#include <netdb.h>
+#ifdef HAVE_GETPWUID_R
+#include <pwd.h>
+#endif
#include "virterror_internal.h"
#include "logging.h"
return kill(pid, sig);
#endif
}
+
+
+#ifdef HAVE_GETPWUID_R
+char *virGetUserDirectory(virConnectPtr conn,
+ uid_t uid)
+{
+ char *strbuf;
+ char *ret;
+ struct passwd pwbuf;
+ struct passwd *pw;
+ size_t strbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+
+ if (VIR_ALLOC_N(strbuf, strbuflen) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ if (getpwuid_r(uid, &pwbuf, strbuf, strbuflen, &pw) != 0) {
+ virReportSystemError(conn, errno,
+ _("Failed to find user record for uid '%d'"),
+ uid);
+ VIR_FREE(strbuf);
+ return NULL;
+ }
+
+ ret = strdup(pw->pw_dir);
+
+ VIR_FREE(strbuf);
+ if (!ret)
+ virReportOOMError(conn);
+
+ return ret;
+}
+#endif
int virKillProcess(pid_t pid, int sig);
+#ifdef HAVE_GETPWUID_R
+char *virGetUserDirectory(virConnectPtr conn,
+ uid_t uid);
+#endif
+
#endif /* __VIR_UTIL_H__ */
priv->handle = -1;
priv->xendConfigVersion = -1;
- priv->type = -1;
- priv->len = -1;
- priv->addr = NULL;
priv->xshandle = NULL;
priv->proxy = -1;
int xendConfigVersion; /* XenD config version */
- /* XXX This code is not IPv6 aware. */
/* connection to xend */
- int type; /* PF_UNIX or PF_INET */
- int len; /* length of addr */
- struct sockaddr *addr; /* type of address used */
- struct sockaddr_un addr_un; /* the unix address */
- struct sockaddr_in addr_in; /* the inet address */
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int addrfamily;
+ int addrprotocol;
/* Keep track of the drivers which opened. We keep a yes/no flag
* here for each driver, corresponding to the array drivers in
#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
#endif
-/**
- * xend_connection_type:
- *
- * The connection to the Xen Daemon can be done either though a normal TCP
- * socket or a local domain direct connection.
- */
-enum xend_connection_type {
- XEND_DOMAIN,
- XEND_TCP,
-};
-
-/**
- * xend:
- *
- * Structure associated to a connection to a Xen daemon
- */
-struct xend {
- int len;
- int type;
- struct sockaddr *addr;
- struct sockaddr_un addr_un;
- struct sockaddr_in addr_in;
-};
-
#ifndef PROXY
static int
int no_slow_start = 1;
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) xend->privateData;
- s = socket(priv->type, SOCK_STREAM, 0);
+ s = socket(priv->addrfamily, SOCK_STREAM, priv->addrprotocol);
if (s == -1) {
virXendError(xend, VIR_ERR_INTERNAL_ERROR,
"%s", _("failed to create a socket"));
sizeof(no_slow_start));
- if (connect(s, priv->addr, priv->len) == -1) {
+ if (connect(s, (struct sockaddr *)&priv->addr, priv->addrlen) == -1) {
serrno = errno;
close(s);
errno = serrno;
if ((conn == NULL) || (path == NULL))
return (-1);
- addr = &priv->addr_un;
+ memset(&priv->addr, 0, sizeof(priv->addr));
+ priv->addrfamily = AF_UNIX;
+ priv->addrprotocol = PF_UNIX;
+ priv->addrlen = sizeof(struct sockaddr_un);
+
+ addr = (struct sockaddr_un *)&priv->addr;
addr->sun_family = AF_UNIX;
memset(addr->sun_path, 0, sizeof(addr->sun_path));
strncpy(addr->sun_path, path, sizeof(addr->sun_path));
- priv->len = sizeof(addr->sun_family) + strlen(addr->sun_path);
- if ((unsigned int) priv->len > sizeof(addr->sun_path))
- priv->len = sizeof(addr->sun_path);
-
- priv->addr = (struct sockaddr *) addr;
- priv->type = PF_UNIX;
-
return (0);
}
* Returns 0 in case of success, -1 in case of error.
*/
static int
-xenDaemonOpen_tcp(virConnectPtr conn, const char *host, int port)
+xenDaemonOpen_tcp(virConnectPtr conn, const char *host, const char *port)
{
- struct in_addr ip;
- struct hostent *pent;
xenUnifiedPrivatePtr priv;
+ struct addrinfo *res, *r;
+ struct addrinfo hints;
+ int saved_errno = EINVAL;
+ int ret;
- if ((conn == NULL) || (host == NULL) || (port <= 0))
+ if ((conn == NULL) || (host == NULL) || (port == NULL))
return (-1);
priv = (xenUnifiedPrivatePtr) conn->privateData;
- pent = gethostbyname(host);
- if (pent == NULL) {
- if (inet_aton(host, &ip) == 0) {
- virXendError(NULL, VIR_ERR_UNKNOWN_HOST,
- _("gethostbyname failed: %s"), host);
- errno = ESRCH;
- return (-1);
+ priv->addrlen = 0;
+ memset(&priv->addr, 0, sizeof(priv->addr));
+
+ // http://people.redhat.com/drepper/userapi-ipv6.html
+ memset (&hints, 0, sizeof hints);
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+
+ ret = getaddrinfo (host, port, &hints, &res);
+ if (ret != 0) {
+ virXendError(NULL, VIR_ERR_UNKNOWN_HOST,
+ _("unable to resolve hostname '%s': %s"),
+ host, gai_strerror (ret));
+ return -1;
+ }
+
+ /* Try to connect to each returned address in turn. */
+ for (r = res; r; r = r->ai_next) {
+ int sock;
+
+ sock = socket (r->ai_family, SOCK_STREAM, r->ai_protocol);
+ if (sock == -1) {
+ saved_errno = errno;
+ continue;
}
- } else {
- memcpy(&ip, pent->h_addr_list[0], sizeof(ip));
+
+ if (connect (sock, r->ai_addr, r->ai_addrlen) == -1) {
+ saved_errno = errno;
+ close (sock);
+ continue;
+ }
+
+ priv->addrlen = r->ai_addrlen;
+ priv->addrfamily = r->ai_family;
+ priv->addrprotocol = r->ai_protocol;
+ memcpy(&priv->addr,
+ r->ai_addr,
+ r->ai_addrlen);
+ close(sock);
+ break;
}
- priv->len = sizeof(struct sockaddr_in);
- priv->addr = (struct sockaddr *) &priv->addr_in;
- priv->type = PF_INET;
+ freeaddrinfo (res);
- priv->addr_in.sin_family = AF_INET;
- priv->addr_in.sin_port = htons(port);
- memcpy(&priv->addr_in.sin_addr, &ip, sizeof(ip));
+ if (!priv->addrlen) {
+ virReportSystemError(conn, saved_errno,
+ _("unable to connect to '%s:%s'"),
+ host, port);
+ return -1;
+ }
- return (0);
+ return 0;
}
/*
* try though http on port 8000
*/
- ret = xenDaemonOpen_tcp(conn, "localhost", 8000);
+ ret = xenDaemonOpen_tcp(conn, "localhost", "8000");
if (ret < 0)
goto failed;
ret = xend_detect_config_version(conn);
if (ret == -1)
goto failed;
} else if (STRCASEEQ (conn->uri->scheme, "http")) {
- ret = xenDaemonOpen_tcp(conn, conn->uri->server, conn->uri->port);
+ char *port;
+ if (virAsprintf(&port, "%d", conn->uri->port) == -1)
+ goto failed;
+ ret = xenDaemonOpen_tcp(conn, conn->uri->server, port);
+ VIR_FREE(port);
if (ret < 0)
goto failed;
ret = xend_detect_config_version(conn);