mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Least privilege support for Solaris
This commit is contained in:
parent
e52d74e536
commit
2b29698352
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
Thu Jan 22 09:23:53 PST 2009 John Levon <john.levon@sun.com>
|
||||
|
||||
Least privilege support for Solaris
|
||||
* qemud/qemud.c: init privs and refuse non-privileged
|
||||
connections
|
||||
* src/remote_internal.c: don't attempt user daemon instance on
|
||||
Solaris
|
||||
* src/xen_internal.c, src/xen_internal.h, src/xen_unified.c,
|
||||
src/xend_internal.c, src/xs_internal.c: replace UID checks
|
||||
with privilege checks. Refuse to load the Xen driver unless
|
||||
we're libvirtd
|
||||
|
||||
Wed Jan 21 18:10:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
Make Xen driver threadsafe
|
||||
|
104
qemud/qemud.c
104
qemud/qemud.c
@ -84,6 +84,39 @@
|
||||
#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, ...);
|
||||
|
||||
#define SYSTEM_UID 60
|
||||
|
||||
static gid_t unix_sock_gid = 60; /* Not used */
|
||||
static int unix_sock_rw_mask = 0666;
|
||||
static int unix_sock_ro_mask = 0666;
|
||||
|
||||
#else
|
||||
|
||||
#define SYSTEM_UID 0
|
||||
|
||||
static gid_t unix_sock_gid = 0; /* Only root by default */
|
||||
static int unix_sock_rw_mask = 0700; /* Allow user only */
|
||||
static int unix_sock_ro_mask = 0777; /* Allow world */
|
||||
|
||||
#endif /* __sun */
|
||||
|
||||
static int godaemon = 0; /* -d: Be a daemon */
|
||||
static int verbose = 0; /* -v: Verbose mode */
|
||||
static int timeout = -1; /* -t: Shutdown timeout */
|
||||
@ -102,10 +135,6 @@ static char *listen_addr = (char *) LIBVIRTD_LISTEN_ADDR;
|
||||
static char *tls_port = (char *) LIBVIRTD_TLS_PORT;
|
||||
static char *tcp_port = (char *) LIBVIRTD_TCP_PORT;
|
||||
|
||||
static gid_t unix_sock_gid = 0; /* Only root by default */
|
||||
static int unix_sock_rw_mask = 0700; /* Allow user only */
|
||||
static int unix_sock_ro_mask = 0777; /* Allow world */
|
||||
|
||||
#if HAVE_POLKIT
|
||||
static int auth_unix_rw = REMOTE_AUTH_POLKIT;
|
||||
static int auth_unix_ro = REMOTE_AUTH_POLKIT;
|
||||
@ -669,10 +698,11 @@ cleanup:
|
||||
static int qemudInitPaths(struct qemud_server *server,
|
||||
char *sockname,
|
||||
char *roSockname,
|
||||
int maxlen) {
|
||||
int maxlen)
|
||||
{
|
||||
uid_t uid = geteuid();
|
||||
|
||||
if (!uid) {
|
||||
if (uid == SYSTEM_UID) {
|
||||
if (snprintf (sockname, maxlen, "%s/run/libvirt/libvirt-sock",
|
||||
LOCAL_STATE_DIR) >= maxlen)
|
||||
goto snprintf_error;
|
||||
@ -1155,6 +1185,29 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
|
||||
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);
|
||||
@ -2524,6 +2577,30 @@ version (const char *argv0)
|
||||
printf ("%s (%s) %s\n", argv0, PACKAGE_NAME, PACKAGE_VERSION);
|
||||
}
|
||||
|
||||
#ifdef __sun
|
||||
static int
|
||||
qemudSetupPrivs (void)
|
||||
{
|
||||
chown ("/var/run/libvirt", SYSTEM_UID, SYSTEM_UID);
|
||||
|
||||
if (__init_daemon_priv (PU_RESETGROUPS | PU_CLEARLIMITSET,
|
||||
SYSTEM_UID, SYSTEM_UID, PRIV_XVM_CONTROL, NULL)) {
|
||||
fprintf (stderr, "additional privileges are required\n");
|
||||
return -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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define qemudSetupPrivs() 0
|
||||
#endif
|
||||
|
||||
/* Print command-line usage. */
|
||||
static void
|
||||
usage (const char *argv0)
|
||||
@ -2701,6 +2778,21 @@ int main(int argc, char **argv) {
|
||||
sig_action.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sig_action, NULL);
|
||||
|
||||
/* Ensure the rundir exists (on tmpfs on some systems) */
|
||||
if (geteuid () == 0) {
|
||||
const char *rundir = LOCAL_STATE_DIR "/run/libvirt";
|
||||
|
||||
if (mkdir (rundir, 0755)) {
|
||||
if (errno != EEXIST) {
|
||||
VIR_ERROR0 (_("unable to create rundir"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qemudSetupPrivs() < 0)
|
||||
goto error2;
|
||||
|
||||
if (!(server = qemudInitialize(sigpipe[0]))) {
|
||||
ret = 2;
|
||||
goto error2;
|
||||
|
@ -957,18 +957,21 @@ remoteOpen (virConnectPtr conn,
|
||||
}
|
||||
|
||||
/*
|
||||
* If URI is NULL, then do a UNIX connection
|
||||
* possibly auto-spawning unprivileged server
|
||||
* and probe remote server for URI
|
||||
* If URI is NULL, then do a UNIX connection possibly auto-spawning
|
||||
* unprivileged server and probe remote server for URI. On Solaris,
|
||||
* this isn't supported, but we may be privileged enough to connect
|
||||
* to the UNIX socket anyway.
|
||||
*/
|
||||
if (!conn->uri) {
|
||||
DEBUG0("Auto-probe remote URI");
|
||||
rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
|
||||
#ifndef __sun
|
||||
if (getuid() > 0) {
|
||||
DEBUG0("Auto-spawn user daemon instance");
|
||||
rflags |= VIR_DRV_OPEN_REMOTE_USER;
|
||||
rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
priv->sock = -1;
|
||||
|
@ -26,6 +26,17 @@
|
||||
#include <errno.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#ifdef __sun
|
||||
#include <sys/systeminfo.h>
|
||||
|
||||
#include <priv.h>
|
||||
|
||||
#ifndef PRIV_XVM_CONTROL
|
||||
#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
|
||||
#endif
|
||||
|
||||
#endif /* __sun */
|
||||
|
||||
/* required for dom0_getdomaininfo_t */
|
||||
#include <xen/dom0_ops.h>
|
||||
#include <xen/version.h>
|
||||
@ -37,10 +48,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#include <sys/systeminfo.h>
|
||||
#endif
|
||||
|
||||
/* required for shutdown flags */
|
||||
#include <xen/sched.h>
|
||||
|
||||
@ -3405,3 +3412,17 @@ xenHypervisorGetVcpuMax(virDomainPtr domain)
|
||||
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
|
||||
}
|
||||
|
@ -104,4 +104,6 @@ int xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn,
|
||||
int startCell,
|
||||
int maxCells);
|
||||
|
||||
int xenHavePrivilege(void);
|
||||
|
||||
#endif /* __VIR_XEN_INTERNAL_H__ */
|
||||
|
@ -67,6 +67,8 @@ static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int inside_daemon;
|
||||
|
||||
#define xenUnifiedError(conn, code, fmt...) \
|
||||
virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__, \
|
||||
__FUNCTION__, __LINE__, fmt)
|
||||
@ -168,6 +170,21 @@ done:
|
||||
return(res);
|
||||
}
|
||||
|
||||
#ifdef WITH_LIBVIRTD
|
||||
|
||||
static int
|
||||
xenInitialize (void)
|
||||
{
|
||||
inside_daemon = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virStateDriver state_driver = {
|
||||
.initialize = xenInitialize,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*----- Dispatch functions. -----*/
|
||||
|
||||
/* These dispatch functions follow the model used historically
|
||||
@ -204,6 +221,15 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
|
||||
xenUnifiedPrivatePtr priv;
|
||||
virDomainEventCallbackListPtr cbList;
|
||||
|
||||
#ifdef __sun
|
||||
/*
|
||||
* Only the libvirtd instance can open this driver.
|
||||
* Everything else falls back to the remote driver.
|
||||
*/
|
||||
if (!inside_daemon)
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
#endif
|
||||
|
||||
if (conn->uri == NULL) {
|
||||
if (!xenUnifiedProbe())
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
@ -265,8 +291,8 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
|
||||
priv->proxy = -1;
|
||||
|
||||
|
||||
/* Hypervisor is only run as root & required to succeed */
|
||||
if (getuid() == 0) {
|
||||
/* Hypervisor is only run with privilege & required to succeed */
|
||||
if (xenHavePrivilege()) {
|
||||
DEBUG0("Trying hypervisor sub-driver");
|
||||
if (drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->open(conn, auth, flags) ==
|
||||
VIR_DRV_OPEN_SUCCESS) {
|
||||
@ -275,7 +301,7 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
/* XenD is required to suceed if root.
|
||||
/* XenD is required to succeed if privileged.
|
||||
* If it fails as non-root, then the proxy driver may take over
|
||||
*/
|
||||
DEBUG0("Trying XenD sub-driver");
|
||||
@ -300,12 +326,12 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
|
||||
DEBUG0("Activated XS sub-driver");
|
||||
priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
|
||||
} else {
|
||||
if (getuid() == 0)
|
||||
goto fail; /* XS is mandatory as root */
|
||||
if (xenHavePrivilege())
|
||||
goto fail; /* XS is mandatory when privileged */
|
||||
}
|
||||
} else {
|
||||
if (getuid() == 0) {
|
||||
goto fail; /* XenD is mandatory as root */
|
||||
if (xenHavePrivilege()) {
|
||||
goto fail; /* XenD is mandatory when privileged */
|
||||
} else {
|
||||
#if WITH_PROXY
|
||||
DEBUG0("Trying proxy sub-driver");
|
||||
@ -1472,6 +1498,10 @@ xenRegister (void)
|
||||
/* Ignore failures here. */
|
||||
(void) xenHypervisorInit ();
|
||||
|
||||
#ifdef WITH_LIBVIRTD
|
||||
if (virRegisterStateDriver (&state_driver) == -1) return -1;
|
||||
#endif
|
||||
|
||||
return virRegisterDriver (&xenUnifiedDriver);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "buf.h"
|
||||
#include "uuid.h"
|
||||
#include "xen_unified.h"
|
||||
#include "xen_internal.h" /* for DOM0_INTERFACE_VERSION */
|
||||
#include "xen_internal.h"
|
||||
#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
|
||||
#include "memory.h"
|
||||
|
||||
@ -161,9 +161,10 @@ do_connect(virConnectPtr xend)
|
||||
s = -1;
|
||||
|
||||
/*
|
||||
* Connecting to XenD as root is mandatory, so log this error
|
||||
* Connecting to XenD when privileged is mandatory, so log this
|
||||
* error
|
||||
*/
|
||||
if (getuid() == 0) {
|
||||
if (xenHavePrivilege()) {
|
||||
virXendError(xend, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("failed to connect to xend"));
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "uuid.h"
|
||||
#include "xen_unified.h"
|
||||
#include "xs_internal.h"
|
||||
#include "xen_internal.h" /* for xenHypervisorCheckID */
|
||||
#include "xen_internal.h"
|
||||
|
||||
#ifndef PROXY
|
||||
static char *xenStoreDomainGetOSType(virDomainPtr domain);
|
||||
@ -290,11 +290,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
|
||||
* 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,
|
||||
"%s", _("failed to connect to Xen Store"));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user