[Libvir] PATCH: Supress valgrind errors in bash
by Daniel P. Berrange
The test cases which have a shell wrapper script generate a pile of memory
leak warnings from valgrind due to various issues in bash itself. This
disguises the real errors valgrind finds in libvirt. So this patch adds
a surpressions file to hide the bash problems
Regards,
Daniel.
Index: .valgrind.supp
===================================================================
RCS file: .valgrind.supp
diff -N .valgrind.supp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ .valgrind.supp 27 Apr 2008 19:41:14 -0000
@@ -0,0 +1,44 @@
+{
+ bashMemoryLeak1
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ fun:set_signal
+ fun:trap_builtin
+ obj:/bin/bash
+ obj:/bin/bash
+ fun:execute_command_internal
+ fun:parse_and_execute
+ obj:/bin/bash
+ fun:source_file
+ fun:source_builtin
+ obj:/bin/bash
+}
+{
+ bashMemoryLeak2
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ fun:make_command
+ fun:yyparse
+ fun:parse_command
+ fun:read_command
+ fun:reader_loop
+ fun:main
+}
+{
+ bashMemoryLeak3
+ Memcheck:Leak
+ fun:malloc
+ fun:xmalloc
+ obj:/bin/bash
+ fun:execute_command_internal
+ obj:/bin/bash
+ fun:execute_command_internal
+ fun:execute_command_internal
+ obj:/bin/bash
+ obj:/bin/bash
+ fun:execute_command_internal
+ fun:parse_and_execute
+ fun:command_substitute
+}
Index: Makefile.am
===================================================================
RCS file: /data/cvs/libvirt/tests/Makefile.am,v
retrieving revision 1.41
diff -u -p -r1.41 Makefile.am
--- Makefile.am 18 Apr 2008 15:28:33 -0000 1.41
+++ Makefile.am 27 Apr 2008 19:41:14 -0000
@@ -73,7 +73,7 @@ TESTS_ENVIRONMENT = \
$(VG)
valgrind:
- $(MAKE) check VG="valgrind --quiet --leak-check=full"
+ $(MAKE) check VG="valgrind --quiet --leak-check=full --suppressions=$(srcdir)/.valgrind.supp"
# Note: xmlrpc.[c|h] is not in libvirt yet
xmlrpctest_SOURCES = \
--
|: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
16 years, 8 months
[Libvir] [PATCH] avoid format-related warnings
by Jim Meyering
This avoids two warnings:
avoid format-related warnings
* qemud/qemud.c (main): Fix a bogus format string reported as umarked.
* src/virsh.c (cmdVcpupin): Non-literal with no args.
Signed-off-by: Jim Meyering <meyering(a)redhat.com>
---
qemud/qemud.c | 4 ++--
src/virsh.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemud/qemud.c b/qemud/qemud.c
index a7b27ee..a9d825d 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -2164,8 +2164,8 @@ int main(int argc, char **argv) {
const char *sockdirname = LOCAL_STATE_DIR "/run/libvirt";
if (chown(sockdirname, -1, unix_sock_gid) < 0)
- qemudLog(QEMUD_ERR, "%s %s",
- _("Failed to change group ownership of "), sockdirname);
+ qemudLog(QEMUD_ERR, _("Failed to change group ownership of %s"),
+ sockdirname);
}
if (godaemon) {
diff --git a/src/virsh.c b/src/virsh.c
index ef6165b..5e098a7 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -1745,7 +1745,7 @@ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
}
if (vcpu >= info.nrVirtCpu) {
- vshError(ctl, FALSE, _("vcpupin: Invalid vCPU number."));
+ vshError(ctl, FALSE, "%s", _("vcpupin: Invalid vCPU number."));
virDomainFree(dom);
return FALSE;
}
--
1.5.5.1.69.g2ffd
16 years, 8 months
[libvir] [PATCH] Change group ownership of /var/run/libvirt/
by Anton Protopopov
2008/4/24, Daniel Veillard <veillard(a)redhat.com>:
>
> Okay, I take patches :-)
>
> thanks !
>
> Daniel
>
Here it is. The changes are:
1) If libvirtd is running as root, main() will try to change the group
ownership of /var/run/libvirt to one specified by unix_sock_gid.
2) Default permissions on /var/run/libvirt are now 0750
A.
16 years, 8 months
[Libvir] [PATCH] avoid problems with sign-extended "char" operand to is* functions
by Jim Meyering
I spotted this in existing code while doing a review:
These uses all cause trouble if the byte in question has a value
larger than 127 and the "char" type is signed.
avoid problems with sign-extended "char" operand to is* functions
* src/util.h (to_uchar): Define function.
* src/sexpr.c (_string2sexpr): Apply to_uchar to is* operand.
* src/nodeinfo.c (linuxNodeInfoCPUPopulate): Likewise.
* src/qemu_driver.c (qemudExtractMonitorPath): Likewise.
* src/stats_linux.c (xenLinuxDomainDeviceID): Likewise.
* src/util.c (TOLOWER, __virMacAddrCompare, virParseMacAddr): Likewise.
* src/virsh.c (cmdVcpupin, vshCommandGetToken): Likewise.
I'll post a separate patch to help ensure that there are no regressions.
Signed-off-by: Jim Meyering <meyering(a)redhat.com>
---
src/nodeinfo.c | 12 ++++++------
src/qemu_driver.c | 2 +-
src/sexpr.c | 4 +++-
src/stats_linux.c | 8 ++++----
src/util.c | 8 ++++----
src/util.h | 5 +++++
src/virsh.c | 6 +++---
7 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 77b2072..c1e8013 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -1,7 +1,7 @@
/*
* nodeinfo.c: Helper routines for OS specific node information
*
- * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -59,7 +59,7 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
char *buf = line;
if (STREQLEN(buf, "processor", 9)) { /* aka a single logical CPU */
buf += 9;
- while (*buf && isspace(*buf))
+ while (*buf && isspace(to_uchar(*buf)))
buf++;
if (*buf != ':') {
__virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
@@ -72,7 +72,7 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
char *p;
unsigned int ui;
buf += 9;
- while (*buf && isspace(*buf))
+ while (*buf && isspace(to_uchar(*buf)))
buf++;
if (*buf != ':' || !buf[1]) {
__virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
@@ -82,13 +82,13 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
}
if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
/* Accept trailing fractional part. */
- && (*p == '\0' || *p == '.' || isspace(*p)))
+ && (*p == '\0' || *p == '.' || isspace(to_uchar(*p))))
nodeinfo->mhz = ui;
} else if (STREQLEN(buf, "cpu cores", 9)) { /* aka cores */
char *p;
unsigned int id;
buf += 9;
- while (*buf && isspace(*buf))
+ while (*buf && isspace(to_uchar(*buf)))
buf++;
if (*buf != ':' || !buf[1]) {
__virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR,
@@ -97,7 +97,7 @@ int linuxNodeInfoCPUPopulate(virConnectPtr conn, FILE *cpuinfo, virNodeInfoPtr n
return -1;
}
if (virStrToLong_ui(buf+1, &p, 10, &id) == 0
- && (*p == '\0' || isspace(*p))
+ && (*p == '\0' || isspace(to_uchar(*p)))
&& id > nodeinfo->cores)
nodeinfo->cores = id;
}
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index b65ae66..eb2f6e8 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -513,7 +513,7 @@ static int qemudExtractMonitorPath(const char *haystack, char *path, int pathmax
* The monitor path ends at first whitespace char
* so lets search for it & NULL terminate it there
*/
- if (isspace(*path)) {
+ if (isspace(to_uchar(*path))) {
*path = '\0';
return 0;
}
diff --git a/src/sexpr.c b/src/sexpr.c
index 9f6ed0d..4cb4edf 100644
--- a/src/sexpr.c
+++ b/src/sexpr.c
@@ -20,6 +20,7 @@
#include "internal.h"
#include "sexpr.h"
+#include "util.h"
/**
* virSexprError:
@@ -357,7 +358,8 @@ _string2sexpr(const char *buffer, size_t * end)
} else {
start = ptr;
- while (*ptr && !isspace(*ptr) && *ptr != ')' && *ptr != '(') {
+ while (*ptr && !isspace(to_uchar(*ptr))
+ && *ptr != ')' && *ptr != '(') {
ptr++;
}
diff --git a/src/stats_linux.c b/src/stats_linux.c
index bf46ca2..e84e24f 100644
--- a/src/stats_linux.c
+++ b/src/stats_linux.c
@@ -1,7 +1,7 @@
/*
* Linux block and network stats.
*
- * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2007, 2008 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
@@ -262,7 +262,7 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
}
if (path[4] != '\0') {
- if (!isdigit(path[4]) || path[4] == '0' ||
+ if (!isdigit(to_uchar(path[4])) || path[4] == '0' ||
virStrToLong_i(path+4, NULL, 10, &part) < 0 ||
part < 1 || part > 15) {
statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
@@ -306,7 +306,7 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
} else {
p = path + 3;
}
- if (p && (!isdigit(*p) || *p == '0' ||
+ if (p && (!isdigit(to_uchar(*p)) || *p == '0' ||
virStrToLong_i(p, NULL, 10, &part) < 0 ||
part < 1 || part > 15)) {
statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
@@ -332,7 +332,7 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
}
if (path[3] != '\0') {
- if (!isdigit(path[3]) || path[3] == '0' ||
+ if (!isdigit(to_uchar(path[3])) || path[3] == '0' ||
virStrToLong_i(path+3, NULL, 10, &part) < 0 ||
part < 1 || part > 63) {
statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
diff --git a/src/util.c b/src/util.c
index 5a44f18..8f3cef9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -57,7 +57,7 @@
#define MAX_ERROR_LEN 1024
-#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+#define TOLOWER(Ch) (isupper (to_uchar(Ch)) ? tolower (Ch) : (Ch))
#define virLog(msg...) fprintf(stderr, msg)
@@ -704,9 +704,9 @@ __virMacAddrCompare (const char *p, const char *q)
{
unsigned char c, d;
do {
- while (*p == '0' && isxdigit (p[1]))
+ while (*p == '0' && isxdigit (to_uchar(p[1])))
++p;
- while (*q == '0' && isxdigit (q[1]))
+ while (*q == '0' && isxdigit (to_uchar(q[1])))
++q;
c = TOLOWER (*p);
d = TOLOWER (*q);
@@ -749,7 +749,7 @@ virParseMacAddr(const char* str, unsigned char *addr)
/* This is solely to avoid accepting the leading
* space or "+" that strtoul would otherwise accept.
*/
- if (!isxdigit(*str))
+ if (!isxdigit(to_uchar(*str)))
break;
result = strtoul(str, &end_ptr, 16);
diff --git a/src/util.h b/src/util.h
index 2516504..af68bc8 100644
--- a/src/util.h
+++ b/src/util.h
@@ -27,6 +27,11 @@
#include "internal.h"
#include "util-lib.h"
+/* Convert a possibly-signed character to an unsigned character. This is
+ a bit safer than casting to unsigned char, since it catches some type
+ errors that the cast doesn't. */
+static inline unsigned char to_uchar (char ch) { return ch; }
+
int virExec(virConnectPtr conn, char **argv, int *retpid,
int infd, int *outfd, int *errfd);
int virExecNonBlock(virConnectPtr conn, char **argv, int *retpid,
diff --git a/src/virsh.c b/src/virsh.c
index 772967e..ef6165b 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -1763,7 +1763,7 @@ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
for (i = 0; cpulist[i]; i++) {
switch (state) {
case expect_num:
- if (!isdigit (cpulist[i])) {
+ if (!isdigit (to_uchar(cpulist[i]))) {
vshError( ctl, FALSE, _("cpulist: %s: Invalid format. Expecting digit at position %d (near '%c')."), cpulist, i, cpulist[i]);
virDomainFree (dom);
return FALSE;
@@ -1773,7 +1773,7 @@ cmdVcpupin(vshControl * ctl, vshCmd * cmd)
case expect_num_or_comma:
if (cpulist[i] == ',')
state = expect_num;
- else if (!isdigit (cpulist[i])) {
+ else if (!isdigit (to_uchar(cpulist[i]))) {
vshError(ctl, FALSE, _("cpulist: %s: Invalid format. Expecting digit or comma at position %d (near '%c')."), cpulist, i, cpulist[i]);
virDomainFree (dom);
return FALSE;
@@ -5685,7 +5685,7 @@ vshCommandGetToken(vshControl * ctl, char *str, char **end, char **res)
if (tk == VSH_TK_NONE) {
if (*p == '-' && *(p + 1) == '-' && *(p + 2)
- && isalnum((unsigned char) *(p + 2))) {
+ && isalnum(to_uchar(*(p + 2)))) {
tk = VSH_TK_OPTION;
p += 2;
} else {
--
1.5.5.1.69.g2ffd
16 years, 8 months
[Libvir] [RFC PATCH] Solaris least privilege
by John Levon
In the interests of giving a 'heads-up' I'm posting this patch. It
implements least-privilege on Solaris. The basic idea is that all
libvirt clients are forced to go through libvirtd, which verifies a
particular privilege. virtd itself runs with enough privilege to
interact with Xen.
This patch is:
- not to be applied :)
- only against 0.4.0
- subject to further change
- not yet reviewed, not even by myself (properly)
Nonetheless, comments are more than welcome.
regards
john
--- libvirt-0.4.0/qemud/remote.c 2007-12-12 05:30:49.000000000 -0800
+++ libvirt-new/qemud/remote.c 2008-04-10 12:52:18.059618661 -0700
@@ -434,6 +434,15 @@ remoteDispatchOpen (struct qemud_server
flags = args->flags;
if (client->readonly) flags |= VIR_CONNECT_RO;
+#ifdef __sun
+ /*
+ * On Solaris, all clients are forced to go via virtd. As a result,
+ * virtd must indicate it really does want to connect to the
+ * hypervisor.
+ */
+ name = "xen:///";
+#endif
+
client->conn =
flags & VIR_CONNECT_RO
? virConnectOpenReadOnly (name)
--- libvirt-0.4.0/src/libvirt.c 2007-12-17 13:51:09.000000000 -0800
+++ libvirt-new/src/libvirt.c 2008-04-16 08:46:28.767087199 -0700
@@ -34,6 +34,7 @@
#include "uuid.h"
#include "test.h"
+#include "xen_internal.h"
#include "xen_unified.h"
#include "remote_internal.h"
#include "qemu_driver.h"
@@ -202,8 +203,16 @@ virInitialize(void)
if (qemudRegister() == -1) return -1;
#endif
#ifdef WITH_XEN
+ /*
+ * On Solaris, only initialize Xen if we're libvirtd.
+ */
+#ifdef __sun
+ if (geteuid() != 0 && xenHavePrivilege() &&
+ xenUnifiedRegister () == -1) return -1;
+#else
if (xenUnifiedRegister () == -1) return -1;
#endif
+#endif
#ifdef WITH_OPENVZ
if (openvzRegister() == -1) return -1;
#endif
@@ -525,6 +534,16 @@ do_open (const char *name,
if (STREQ (name, "xen://"))
name = "xen:///";
+#ifdef __sun
+ /*
+ * If we're not libvirtd, force us to go via the daemon.
+ */
+ if (geteuid() == 0 || !xenHavePrivilege())
+ name = "remote+unix:///";
+ else if (STREQ (name, "xen:///") && xenUnifiedRegister () == -1)
+ return NULL;
+#endif
+
if (!initialized)
if (virInitialize() < 0)
return NULL;
--- libvirt-0.4.0/qemud/qemud.c 2007-12-12 05:30:49.000000000 -0800
+++ libvirt-new/qemud/qemud.c 2008-04-17 17:16:47.075258251 -0700
@@ -60,6 +60,25 @@
#include "mdns.h"
#endif
+#ifdef __sun
+#include <ucred.h>
+#include <priv.h>
+
+#ifndef PRIV_VIRT_MANAGE
+#define PRIV_VIRT_MANAGE ((const char *)"virt_manage")
+#endif
+
+#ifndef PRIV_XVM_CONTROL
+#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
+#endif
+
+#define PU_RESETGROUPS 0x0001 /* Remove supplemental groups */
+#define PU_CLEARLIMITSET 0x0008 /* L=0 */
+
+extern int __init_daemon_priv(int, uid_t, gid_t, ...);
+
+#endif
+
static int godaemon = 0; /* -d: Be a daemon */
static int verbose = 0; /* -v: Verbose mode */
static int timeout = -1; /* -t: Shutdown timeout */
@@ -668,11 +687,13 @@ static int qemudInitPaths(struct qemud_s
unlink(sockname);
+#ifndef __sun
if (snprintf (roSockname, maxlen, "%s/run/libvirt/libvirt-sock-ro",
LOCAL_STATE_DIR) >= maxlen)
goto snprintf_error;
unlink(roSockname);
+#endif
if (snprintf(server->logDir, PATH_MAX, "%s/log/libvirt/", LOCAL_STATE_DIR) >= PATH_MAX)
goto snprintf_error;
@@ -1033,6 +1054,29 @@ static int qemudDispatchServer(struct qe
return -1;
}
+#ifdef __sun
+ {
+ ucred_t *ucred = NULL;
+ const priv_set_t *privs;
+
+ if (getpeerucred (fd, &ucred) == -1 ||
+ (privs = ucred_getprivset (ucred, PRIV_EFFECTIVE)) == NULL) {
+ if (ucred != NULL)
+ ucred_free (ucred);
+ close (fd);
+ return -1;
+ }
+
+ if (!priv_ismember (privs, PRIV_VIRT_MANAGE)) {
+ ucred_free (ucred);
+ close (fd);
+ return -1;
+ }
+
+ ucred_free (ucred);
+ }
+#endif /* __sun */
+
/* Disable Nagle. Unix sockets will ignore this. */
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
sizeof no_slow_start);
@@ -1864,6 +1908,10 @@ remoteReadConfigFile (struct qemud_serve
if (auth_unix_rw == REMOTE_AUTH_POLKIT)
unix_sock_rw_mask = 0777;
#endif
+#ifdef __sun
+ unix_sock_rw_mask = 0666;
+#endif
+
if (remoteConfigGetAuth(conf, "auth_unix_ro", &auth_unix_ro, filename) < 0)
return -1;
if (remoteConfigGetAuth(conf, "auth_tcp", &auth_tcp, filename) < 0)
@@ -1955,6 +2003,32 @@ remoteReadConfigFile (struct qemud_serve
return -1;
}
+#ifdef __sun
+static void
+qemudSetupPrivs (struct qemud_server *server)
+{
+ chown ("/var/run/libvirt", 60, 60);
+ chmod ("/var/run/libvirt", 0755);
+ chown ("/var/run/libvirt/libvirt-sock", 60, 60);
+ chmod ("/var/run/libvirt/libvirt-sock", 0666);
+ chown (server->logDir, 60, 60);
+
+ if (__init_daemon_priv (PU_RESETGROUPS | PU_CLEARLIMITSET,
+ 60, 60, PRIV_XVM_CONTROL, NULL)) {
+ fprintf (stderr, "additional privileges are required\n");
+ exit (1);
+ }
+
+ if (priv_set (PRIV_OFF, PRIV_ALLSETS, PRIV_FILE_LINK_ANY, PRIV_PROC_INFO,
+ PRIV_PROC_SESSION, PRIV_PROC_EXEC, PRIV_PROC_FORK, NULL)) {
+ fprintf (stderr, "failed to set reduced privileges\n");
+ exit (1);
+ }
+}
+#else
+#define qemudSetupPrivs
+#endif
+
/* Print command-line usage. */
static void
usage (const char *argv0)
@@ -2139,6 +2213,8 @@ int main(int argc, char **argv) {
goto error2;
}
+ qemudSetupPrivs(server);
+
qemudRunLoop(server);
qemudCleanup(server);
--- libvirt-0.4.0/src/xs_internal.c 2007-12-14 07:33:11.000000000 -0800
+++ libvirt-new/src/xs_internal.c 2008-04-10 09:54:38.676077954 -0700
@@ -31,7 +31,7 @@
#include "driver.h"
#include "xen_unified.h"
#include "xs_internal.h"
-#include "xen_internal.h" /* for xenHypervisorCheckID */
+#include "xen_internal.h"
#ifdef __linux__
#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
@@ -344,11 +344,11 @@ xenStoreOpen(virConnectPtr conn,
if (priv->xshandle == NULL) {
/*
- * not being able to connect via the socket as a normal user
- * is rather normal, this should fallback to the proxy (or
- * remote) mechanism.
+ * not being able to connect via the socket as an unprivileged
+ * user is rather normal, this should fallback to the proxy (or
+ * remote) mechanism.
*/
- if (getuid() == 0) {
+ if (!xenHavePrivilege()) {
virXenStoreError(NULL, VIR_ERR_NO_XEN,
_("failed to connect to Xen Store"));
}
--- libvirt-0.4.0/src/xen_internal.c 2007-12-12 05:30:49.000000000 -0800
+++ libvirt-new/src/xen_internal.c 2008-04-10 10:28:41.363704244 -0700
@@ -28,6 +28,15 @@
#include <errno.h>
#include <sys/utsname.h>
+#ifdef __sun
+#include <priv.h>
+
+#ifndef PRIV_XVM_CONTROL
+#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
+#endif
+
+#endif
+
#include "xs_internal.h"
#include "stats_linux.h"
#include "xend_internal.h"
@@ -3259,6 +3268,21 @@ xenHypervisorGetVcpuMax(virDomainPtr dom
return maxcpu;
}
+/**
+ * xenHavePrivilege()
+ *
+ * Return true if the current process should be able to connect to Xen.
+ */
+int
+xenHavePrivilege()
+{
+#ifdef __sun
+ return priv_ineffect (PRIV_XVM_CONTROL);
+#else
+ return getuid () == 0;
+#endif
+}
+
#endif /* WITH_XEN */
/*
* vim: set tabstop=4:
--- libvirt-0.4.0/src/xen_internal.h 2007-12-05 12:33:02.000000000 -0800
+++ libvirt-new/src/xen_internal.h 2008-04-10 09:34:16.379186656 -0700
@@ -98,6 +98,9 @@ int xenHypervisorNodeGetCellsFreeMemory(
unsigned long long *freeMems,
int startCell,
int maxCells);
+
+int xenHavePrivilege(void);
+
#ifdef __cplusplus
}
#endif
--- libvirt-0.4.0/src/xen_unified.c 2007-12-12 05:30:49.000000000 -0800
+++ libvirt-new/src/xen_unified.c 2008-04-10 15:10:53.653298774 -0700
@@ -266,8 +266,8 @@ xenUnifiedOpen (virConnectPtr conn, xmlU
priv->xendConfigVersion > 2)
continue;
- /* Ignore proxy for root */
- if (i == XEN_UNIFIED_PROXY_OFFSET && getuid() == 0)
+ /* Ignore proxy if we have privilege */
+ if (i == XEN_UNIFIED_PROXY_OFFSET && xenHavePrivilege())
continue;
if (drivers[i]->open) {
@@ -282,10 +282,10 @@ xenUnifiedOpen (virConnectPtr conn, xmlU
#endif
}
- /* If as root, then all drivers must succeed.
- If non-root, then only proxy must succeed */
+ /* If privileged, then all drivers must succeed.
+ If unprivileged, then only proxy must succeed */
if (!priv->opened[i] &&
- (getuid() == 0 || i == XEN_UNIFIED_PROXY_OFFSET)) {
+ (xenHavePrivilege() || i == XEN_UNIFIED_PROXY_OFFSET)) {
for (j = 0; j < i; ++j)
if (priv->opened[j]) drivers[j]->close (conn);
free (priv);
@@ -1266,6 +1266,12 @@ static virDriver xenUnifiedDriver = {
int
xenUnifiedRegister (void)
{
+ static int driver_priority = 0;
+ static int xen_initialized = 0;
+
+ if (xen_initialized)
+ return driver_priority;
+
/* Ignore failures here. */
(void) xenHypervisorInit ();
(void) xenProxyInit ();
@@ -1273,7 +1279,9 @@ xenUnifiedRegister (void)
(void) xenStoreInit ();
(void) xenXMInit ();
- return virRegisterDriver (&xenUnifiedDriver);
+ driver_priority = virRegisterDriver (&xenUnifiedDriver);
+ xen_initialized = 1;
+ return driver_priority;
}
#endif /* WITH_XEN */
--- libvirt-0.4.0/src/xend_internal.c 2007-12-17 15:05:27.000000000 -0800
+++ libvirt-new/src/xend_internal.c 2008-04-10 09:45:10.262989682 -0700
@@ -42,7 +42,7 @@
#include "uuid.h"
#include "xen_unified.h"
#include "xend_internal.h"
-#include "xen_internal.h" /* for DOM0_INTERFACE_VERSION */
+#include "xen_internal.h"
#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
/* required for cpumap_t */
@@ -235,7 +235,7 @@ do_connect(virConnectPtr xend)
* is rather normal, this should fallback to the proxy (or
* remote) mechanism.
*/
- if ((getuid() == 0) || (xend->flags & VIR_CONNECT_RO)) {
+ if (xenHavePrivilege() || (xend->flags & VIR_CONNECT_RO)) {
virXendError(xend, VIR_ERR_INTERNAL_ERROR,
"failed to connect to xend");
}
--- libvirt-0.4.0/src/virsh.c 2007-12-07 07:00:48.000000000 -0800
+++ libvirt-new/src/virsh.c 2008-04-16 08:44:35.668718168 -0700
@@ -36,6 +36,7 @@
#include <sys/stat.h>
#include <inttypes.h>
#include <test.h>
+#include <signal.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -50,6 +51,7 @@
#include "console.h"
static char *progname;
+static int sigpipe;
#ifndef TRUE
#define TRUE 1
@@ -202,9 +204,6 @@ typedef struct __vshControl {
virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */
vshCmd *cmd; /* the current command */
char *cmdstr; /* string with command */
-#ifndef __MINGW32__
- uid_t uid; /* process owner */
-#endif /* __MINGW32__ */
int imode; /* interactive mode? */
int quiet; /* quiet mode */
int debug; /* print debug messages? */
@@ -464,12 +463,8 @@ static vshCmdOptDef opts_console[] = {
static int
cmdConsole(vshControl * ctl, vshCmd * cmd)
{
- xmlDocPtr xml = NULL;
- xmlXPathObjectPtr obj = NULL;
- xmlXPathContextPtr ctxt = NULL;
virDomainPtr dom;
int ret = FALSE;
- char *doc;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
@@ -477,37 +472,16 @@ cmdConsole(vshControl * ctl, vshCmd * cm
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
return FALSE;
- doc = virDomainGetXMLDesc(dom, 0);
- if (!doc)
- goto cleanup;
-
- xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
- XML_PARSE_NOENT | XML_PARSE_NONET |
- XML_PARSE_NOWARNING);
- free(doc);
- if (!xml)
- goto cleanup;
- ctxt = xmlXPathNewContext(xml);
- if (!ctxt)
- goto cleanup;
+ ret = vshConsole(dom);
- obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
- if ((obj != NULL) && ((obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0))) {
- if (vshRunConsole((const char *)obj->stringval) == 0)
- ret = TRUE;
- } else {
+ if (ret == 0) {
vshPrintExtra(ctl, _("No console available for domain\n"));
+ } else if (ret == -1) {
+ fprintf(stderr, _("unable to open console: %s\n"),
+ strerror(errno));
}
- xmlXPathFreeObject(obj);
- cleanup:
- if (ctxt)
- xmlXPathFreeContext(ctxt);
- if (xml)
- xmlFreeDoc(xml);
- virDomainFree(dom);
- return ret;
+ return ret == 1;
}
#else /* __MINGW32__ */
@@ -4523,22 +4497,11 @@ vshInit(vshControl * ctl)
if (ctl->conn)
return FALSE;
-#ifndef __MINGW32__
- ctl->uid = getuid();
-#endif
-
vshOpenLogFile(ctl);
/* set up the library error handler */
virSetErrorFunc(NULL, virshErrorHandler);
-#ifndef __MINGW32__
- /* Force a non-root, Xen connection to readonly */
- if ((ctl->name == NULL ||
- !strcasecmp(ctl->name, "xen")) && ctl->uid != 0)
- ctl->readonly = 1;
-#endif
-
ctl->conn = virConnectOpenAuth(ctl->name,
virConnectAuthPtrDefault,
ctl->readonly ? VIR_CONNECT_RO : 0);
@@ -5021,12 +4984,21 @@ vshParseArgv(vshControl * ctl, int argc,
return TRUE;
}
-int
+static void sigpipe_handler(int sig)
+{
+ sigpipe = 1;
+ /*
+ * Force readline() to exit.
+ */
+ close(STDIN_FILENO);
+}
+
main(int argc, char **argv)
{
vshControl _ctl, *ctl = &_ctl;
char *defaultConn;
int ret = TRUE;
+ struct sigaction sig_action;
if (!setlocale(LC_ALL, "")) {
perror("setlocale");
@@ -5059,6 +5031,12 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ sig_action.sa_handler = sigpipe_handler;
+ sig_action.sa_flags = 0;
+ sigemptyset(&sig_action.sa_mask);
+
+ sigaction(SIGPIPE, &sig_action, NULL);
+
if (!vshInit(ctl)) {
vshDeinit(ctl);
exit(EXIT_FAILURE);
@@ -5098,6 +5076,13 @@ main(int argc, char **argv)
fputc('\n', stdout); /* line break after alone prompt */
}
+ /*
+ * If the connection over a socket failed abruptly, it's probably
+ * due to not having the right privileges.
+ */
+ if (sigpipe)
+ vshError(ctl, TRUE, _("failed to connect (insufficient privileges?)"));
+
vshDeinit(ctl);
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
}
--- libvirt-0.4.0/src/console.c 2007-12-07 07:00:48.000000000 -0800
+++ libvirt-new/src/console.c 2008-04-16 16:34:15.533322609 -0700
@@ -34,6 +34,11 @@
#include <errno.h>
#include <unistd.h>
#include <signal.h>
+#include <stdlib.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
#include "console.h"
#include "internal.h"
@@ -59,8 +64,10 @@ cfmakeraw (struct termios *attr)
}
#endif /* !HAVE_CFMAKERAW */
-int vshRunConsole(const char *tty) {
- int ttyfd, ret = -1;
+static int
+vshDirectConsole(int ttyfd)
+{
+ int ret = -1;
struct termios ttyattr, rawattr;
void (*old_sigquit)(int);
void (*old_sigterm)(int);
@@ -68,14 +75,6 @@ int vshRunConsole(const char *tty) {
void (*old_sighup)(int);
void (*old_sigpipe)(int);
-
- /* We do not want this to become the controlling TTY */
- if ((ttyfd = open(tty, O_NOCTTY | O_RDWR)) < 0) {
- fprintf(stderr, _("unable to open tty %s: %s\n"),
- tty, strerror(errno));
- return -1;
- }
-
/* Put STDIN into raw mode so that stuff typed
does not echo to the screen (the TTY reads will
result in it being echoed back already), and
@@ -174,7 +173,7 @@ int vshRunConsole(const char *tty) {
}
}
done:
- ret = 0;
+ ret = 1;
cleanup:
@@ -195,6 +194,106 @@ int vshRunConsole(const char *tty) {
return ret;
}
+/*
+ * Attempt to access the domain via 'xenconsole', which may have
+ * additional privilege to reach the console.
+ */
+static int
+vshXenConsole(int id)
+{
+ char arg[100];
+ char *argv[3];
+ pid_t pid;
+
+ if ((pid = fork()) < 0) {
+ return -1;
+ } else if (pid) {
+ int wstat;
+
+ if (waitpid(pid, &wstat, 0) < 0)
+ return -1;
+
+ if (WIFSIGNALED(wstat))
+ return -1;
+ if (WIFEXITED(wstat) && WEXITSTATUS(wstat))
+ return -1;
+
+ return 1;
+ }
+
+ /* child */
+
+ if (snprintf(arg, 100, "%d", id) < 0)
+ return -1;
+
+ argv[0] = "/usr/lib/xen/bin/xenconsole";
+ argv[1] = arg;
+ argv[2] = NULL;
+
+ if (execv("/usr/lib/xen/bin/xenconsole", argv))
+ fprintf(stderr, _("failed to run xenconsole: %s\n"),
+ strerror(errno));
+ _exit(1);
+}
+
+/*
+ * Returns 0 if no console is available, 1 if the console was accessed
+ * successfully, or -1 on error.
+ */
+int vshConsole(virDomainPtr dom)
+{
+ xmlDocPtr xml = NULL;
+ xmlXPathObjectPtr obj = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ char *doc;
+ int ttyfd;
+ int ret = -1;
+
+ doc = virDomainGetXMLDesc(dom, 0);
+ if (!doc)
+ goto cleanup;
+
+ xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ free(doc);
+ if (!xml)
+ goto cleanup;
+ ctxt = xmlXPathNewContext(xml);
+ if (!ctxt)
+ goto cleanup;
+
+ obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
+ if (obj == NULL || obj->type != XPATH_STRING || obj->stringval == NULL ||
+ obj->stringval[0] == '\0') {
+ ret = 0;
+ goto cleanup;
+ }
+
+ /* We do not want this to become the controlling TTY */
+ ttyfd = open((char *)obj->stringval, O_NOCTTY | O_RDWR);
+
+ if (ttyfd != -1) {
+ ret = vshDirectConsole(ttyfd);
+ goto cleanup;
+ } else if (errno != EACCES) {
+ fprintf(stderr, _("unable to open tty %s: %s\n"),
+ obj->stringval, strerror(errno));
+ } else {
+ ret = vshXenConsole(virDomainGetID(dom));
+ }
+
+ cleanup:
+ if (obj)
+ xmlXPathFreeObject(obj);
+ if (ctxt)
+ xmlXPathFreeContext(ctxt);
+ if (xml)
+ xmlFreeDoc(xml);
+ virDomainFree(dom);
+ return ret;
+}
+
#endif /* !__MINGW32__ */
/*
--- libvirt-0.4.0/src/console.h 2007-12-07 07:00:48.000000000 -0800
+++ libvirt-new/src/console.h 2008-04-16 08:49:20.165071296 -0700
@@ -25,11 +25,13 @@
#ifndef __MINGW32__
+#include "libvirt/libvirt.h"
+
#ifdef __cplusplus
extern "C" {
#endif
- int vshRunConsole(const char *tty);
+int vshConsole(virDomainPtr dom);
#ifdef __cplusplus
}
16 years, 8 months
[Libvir] Adding devices to a vm using virsh
by Gabriel Kaufmann
Hi,
I need to be able to attach a PCI device to an existing machine.
I know that in Xen's configuration file we need to add a line
PCI=[....]
The problem is that I didn't find any documentation on what the parametes are.
When looking at virsh, there's an 'attach' function, but the only documented devices are disk and Ethernet card.
Does anyone knows what is the format for adding a generic PCI card (or specifically, a Teradici card) using virsh attach
Best Regards,
Gabriel Kaufmann
Software Engineer
Gabriel.Kaufmann(a)ericom.com<mailto:Gabriel.Kaufmann@ericom.com>
Ericom Software
Tel (Dir): +972 2 591 1700 Ext 754
Tel (Main): +972 2 591 1700
http://www.ericom.com
Access Done Right
Empower Enterprise-Wide Access to Microsoft(r) Terminal Server, Virtual Desktops and Legacy Applications
16 years, 8 months
[Libvir] virConnectOpenReadOnly broken
by Richard W.M. Jones
This is just a note that the following program tickles a nasty (memory
corruptor?) bug somewhere in the open code. I'm still trying to look
into the cause and will post a followup if I find the problem.
Rich.
#include <libvirt/libvirt.h>
#include <stdlib.h>
#include <assert.h>
int
main ()
{
virConnectPtr conn;
conn = virConnectOpenReadOnly ("xen+unix:///");
assert (conn);
virConnectClose (conn);
exit (0);
}
$ gcc -Wall test.c -lvirt -o test
$ ./test
libvir: Domain error : invalid domain pointer in virDomainFree
test: test.c:11: main: Assertion `conn' failed.
Aborted
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
16 years, 8 months
[Libvir] [patch] fix typos and PROXY_SOCKET_PATCH
by Atsushi SAKAI
Hi, Daniel and Dan
This is various fixes mainly for docs and
Proxy path.
I want to fix proxy path to
-#define PROXY_SOCKET_PATH "/tmp/livirt_proxy_conn"
+#define PROXY_SOCKET_PATH "/tmp/libvirt_proxy_conn"
Is it OK?
docs/bindings.html | 2 +-
docs/deployment.html | 2 +-
docs/downloads.html | 6 +++---
docs/downloads.html.in | 6 +++---
docs/drivers.html | 2 +-
docs/drivers.html.in | 2 +-
docs/formatstorage.html | 2 +-
docs/formatstorage.html.in | 2 +-
docs/index.html | 2 +-
docs/index.html.in | 2 +-
docs/sitemap.html | 2 +-
src/proxy_internal.h | 2 +-
12 files changed, 16 insertions(+), 16 deletions(-)
Thanks
Atsushi SAKAI
16 years, 8 months
[libvir] [PATCH] Bad permissions on /var/run/libvirt/
by Anton Protopopov
Hi,
Non-root can't use /var/run/libvirt/libvirt-sock even in the case
"unix_sock_group" and "unix_sock_rw_perms" are set properly.
The reason:
# ls -l /var/run /var/run/libvirt | grep libvirt | grep -v pid
drwx------ 2 root root 4096 Apr 14 19:14 libvirt
srwxrwx--- 1 root libvirt 0 Apr 14 19:14 libvirt-sock
srwxrwxrwx 1 root libvirt 0 Apr 14 19:14 libvirt-sock-ro
i.e., bad permissions on /var/run/libvirt
One possible solution (implied in the attached patch) is the following:
Every time libvirtd starts
* it implicitly sets the group id of /var/run/libvirt:
chown(/var/run/libvirt, -1, unix_sock_gid).
* if "unix_sock_group" defined in /etc/libvirt/libvirtd.conf, libvirtd does
chmod g+x /var/run/libvirt
otherwise,
chmod g-x /var/run/libvirt
A.
16 years, 8 months