Пример #1
0
/**
 * virDomainLxcEnterCGroup:
 * @domain: a domain object
 * @flags: currently unused, pass 0
 *
 * This API is LXC specific, so it will only work with hypervisor
 * connections to the LXC driver.
 *
 * Attaches the process to the control cgroups associated
 * with the container @domain.
 *
 * Returns 0 on success, -1 on error
 */
int virDomainLxcEnterCGroup(virDomainPtr domain,
                            unsigned int flags)
{
    virConnectPtr conn;
    virCgroupPtr cgroup = NULL;

    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);

    virResetLastError();

    virCheckDomainReturn(domain, -1);
    conn = domain->conn;

    virCheckReadOnlyGoto(conn->flags, error);
    virCheckFlagsGoto(0, error);

    if (virCgroupNewDetect(domain->id, -1, &cgroup) < 0)
        goto error;

    if (virCgroupAddTask(cgroup, getpid()) < 0)
        goto error;

    virCgroupFree(&cgroup);

    return 0;

 error:
    virDispatchError(NULL);
    virCgroupFree(&cgroup);
    return -1;
}
Пример #2
0
/* Functions */
static int
adminDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED,
                         virNetServerClientPtr client,
                         virNetMessagePtr msg ATTRIBUTE_UNUSED,
                         virNetMessageErrorPtr rerr,
                         struct admin_connect_open_args *args)
{
    unsigned int flags;
    struct daemonAdmClientPrivate *priv =
        virNetServerClientGetPrivateData(client);
    int ret = -1;

    VIR_DEBUG("priv=%p dmn=%p", priv, priv->dmn);
    virMutexLock(&priv->lock);

    flags = args->flags;
    virCheckFlagsGoto(0, cleanup);

    ret = 0;
 cleanup:
    if (ret < 0)
        virNetMessageSaveError(rerr);
    virMutexUnlock(&priv->lock);
    return ret;
}
Пример #3
0
/**
 * virAdmConnectOpen:
 * @name: uri of the daemon to connect to, NULL for default
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Opens connection to admin interface of the daemon.
 *
 * Returns @virAdmConnectPtr object or NULL on error
 */
virAdmConnectPtr
virAdmConnectOpen(const char *name, unsigned int flags)
{
    char *sock_path = NULL;
    char *alias = NULL;
    virAdmConnectPtr conn = NULL;
    virConfPtr conf = NULL;

    if (virAdmInitialize() < 0)
        goto error;

    VIR_DEBUG("flags=%x", flags);
    virResetLastError();
    virCheckFlagsGoto(VIR_CONNECT_NO_ALIASES, error);

    if (!(conn = virAdmConnectNew()))
        goto error;

    if (virConfLoadConfig(&conf, "libvirt-admin.conf") < 0)
        goto error;

    if (!name && !(name = virAdmGetDefaultURI(conf)))
        goto error;

    if ((!(flags & VIR_CONNECT_NO_ALIASES) &&
         virURIResolveAlias(conf, name, &alias) < 0))
        goto error;

    if (!(conn->uri = virURIParse(alias ? alias : name)))
        goto error;

    if (!(sock_path = getSocketPath(conn->uri)))
        goto error;

    if (!(conn->privateData = remoteAdminPrivNew(sock_path)))
        goto error;

    conn->privateDataFreeFunc = remoteAdminPrivFree;

    if (remoteAdminConnectOpen(conn, flags) < 0)
        goto error;

 cleanup:
    VIR_FREE(sock_path);
    VIR_FREE(alias);
    virConfFree(conf);
    return conn;

 error:
    virDispatchError(NULL);
    virObjectUnref(conn);
    conn = NULL;
    goto cleanup;
}
Пример #4
0
/**
 * virDomainLxcEnterNamespace:
 * @domain: a domain object
 * @nfdlist: number of FDs in @fdlist
 * @fdlist: list of namespace file descriptors
 * @noldfdlist: filled with number of old FDs
 * @oldfdlist: pointer to hold list of old namespace file descriptors
 * @flags: currently unused, pass 0
 *
 * This API is LXC specific, so it will only work with hypervisor
 * connections to the LXC driver.
 *
 * Attaches the process to the namespaces associated
 * with the FDs in @fdlist
 *
 * If @oldfdlist is non-NULL, it will be populated with file
 * descriptors representing the old namespace. This allows
 * the caller to switch back to its current namespace later
 *
 * Returns 0 on success, -1 on error
 */
int
virDomainLxcEnterNamespace(virDomainPtr domain,
                           unsigned int nfdlist,
                           int *fdlist,
                           unsigned int *noldfdlist,
                           int **oldfdlist,
                           unsigned int flags)
{
    size_t i;

    VIR_DOMAIN_DEBUG(domain, "nfdlist=%d, fdlist=%p, "
                     "noldfdlist=%p, oldfdlist=%p, flags=%x",
                     nfdlist, fdlist, noldfdlist, oldfdlist, flags);

    virResetLastError();

    virCheckFlagsGoto(0, error);

    if (noldfdlist && oldfdlist) {
        size_t nfds;
        if (virProcessGetNamespaces(getpid(),
                                    &nfds,
                                    oldfdlist) < 0)
            goto error;
        *noldfdlist = nfds;
    }

    if (virProcessSetNamespaces(nfdlist, fdlist) < 0) {
        if (oldfdlist && noldfdlist) {
            for (i = 0; i < *noldfdlist; i++)
                VIR_FORCE_CLOSE((*oldfdlist)[i]);
            VIR_FREE(*oldfdlist);
            *noldfdlist = 0;
        }
        goto error;
    }

    return 0;

 error:
    virDispatchError(domain->conn);
    return -1;
}
Пример #5
0
/**
 * virAdmConnectLookupServer:
 * @conn: daemon connection reference
 * @name: name of the server too lookup
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Try to lookup a server on the given daemon based on @name.
 *
 * virAdmServerFree() should be used to free the resources after the
 * server object is no longer needed.
 *
 * Returns the requested server or NULL in case of failure.  If the
 * server cannot be found, then VIR_ERR_NO_SERVER error is raised.
 */
virAdmServerPtr
virAdmConnectLookupServer(virAdmConnectPtr conn,
                          const char *name,
                          unsigned int flags)
{
    virAdmServerPtr ret = NULL;

    VIR_DEBUG("conn=%p, name=%s, flags=%x", conn, NULLSTR(name), flags);
    virResetLastError();

    virCheckAdmConnectGoto(conn, cleanup);
    virCheckNonNullArgGoto(name, cleanup);
    virCheckFlagsGoto(0, cleanup);

    ret = remoteAdminConnectLookupServer(conn, name, flags);
 cleanup:
    if (!ret)
        virDispatchError(NULL);
    return ret;
}
Пример #6
0
/**
 * virDomainLxcEnterNamespace:
 * @domain: a domain object
 * @nfdlist: number of FDs in @fdlist
 * @fdlist: list of namespace file descriptors
 * @noldfdlist: filled with number of old FDs
 * @oldfdlist: pointer to hold list of old namespace file descriptors
 * @flags: currently unused, pass 0
 *
 * This API is LXC specific, so it will only work with hypervisor
 * connections to the LXC driver.
 *
 * Attaches the process to the namespaces associated
 * with the FDs in @fdlist
 *
 * If @oldfdlist is non-NULL, it will be populated with file
 * descriptors representing the old namespace. This allows
 * the caller to switch back to its current namespace later
 *
 * Returns 0 on success, -1 on error
 */
int
virDomainLxcEnterNamespace(virDomainPtr domain,
                           unsigned int nfdlist,
                           int *fdlist,
                           unsigned int *noldfdlist,
                           int **oldfdlist,
                           unsigned int flags)
{
    int i;

    virCheckFlagsGoto(0, error);

    if (noldfdlist && oldfdlist) {
        size_t nfds;
        if (virProcessGetNamespaces(getpid(),
                                    &nfds,
                                    oldfdlist) < 0)
            goto error;
        *noldfdlist = nfds;
    }

    if (virProcessSetNamespaces(nfdlist, fdlist) < 0) {
        if (oldfdlist && noldfdlist) {
            for (i = 0 ; i < *noldfdlist ; i++) {
                VIR_FORCE_CLOSE((*oldfdlist)[i]);
            }
            VIR_FREE(*oldfdlist);
            *noldfdlist = 0;
        }
        goto error;
    }

    return 0;

error:
    virDispatchError(domain->conn);
    return -1;
}
Пример #7
0
/**
 * virAdmConnectListServers:
 * @conn: daemon connection reference
 * @servers: Pointer to a list to store an array containing objects or NULL
 *           if the list is not required (number of servers only)
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Collect list of all servers provided by daemon the client is connected to.
 *
 * Returns the number of servers available on daemon side or -1 in case of a
 * failure, setting @servers to NULL. There is a guaranteed extra element set
 * to NULL in the @servers list returned to make the iteration easier, excluding
 * this extra element from the final count.
 * Caller is responsible to call virAdmServerFree() on each list element,
 * followed by freeing @servers.
 */
int
virAdmConnectListServers(virAdmConnectPtr conn,
                         virAdmServerPtr **servers,
                         unsigned int flags)
{
    int ret = -1;

    VIR_DEBUG("conn=%p, servers=%p, flags=%x", conn, servers, flags);

    virResetLastError();
    virCheckFlagsGoto(0, error);

    if (servers)
        *servers = NULL;

    virCheckAdmConnectReturn(conn, -1);
    if ((ret = remoteAdminConnectListServers(conn, servers, flags)) < 0)
        goto error;

    return ret;
 error:
    virDispatchError(NULL);
    return -1;
}
Пример #8
0
/**
 * virDomainLxcEnterSecurityLabel:
 * @model: the security model to set
 * @label: the security label to apply
 * @oldlabel: filled with old security label
 * @flags: currently unused, pass 0
 *
 * This API is LXC specific, so it will only work with hypervisor
 * connections to the LXC driver.
 *
 * Attaches the process to the security label specified
 * by @label. @label is interpreted relative to @model
 * Depending on the security driver, this may
 * not take effect until the next call to exec().
 *
 * If @oldlabel is not NULL, it will be filled with info
 * about the current security label. This may let the
 * process be moved back to the previous label if no
 * exec() has yet been performed.
 *
 * Returns 0 on success, -1 on error
 */
int
virDomainLxcEnterSecurityLabel(virSecurityModelPtr model,
                               virSecurityLabelPtr label,
                               virSecurityLabelPtr oldlabel,
                               unsigned int flags)
{
    VIR_DEBUG("model=%p, label=%p, oldlabel=%p, flags=%x",
              model, label, oldlabel, flags);

    virResetLastError();

    virCheckFlagsGoto(0, error);

    virCheckNonNullArgGoto(model, error);
    virCheckNonNullArgGoto(label, error);

    if (oldlabel)
        memset(oldlabel, 0, sizeof(*oldlabel));

    if (STREQ(model->model, "selinux")) {
#ifdef WITH_SELINUX
        if (oldlabel) {
            security_context_t ctx;

            if (getcon(&ctx) < 0) {
                virReportSystemError(errno,
                                     _("unable to get PID %d security context"),
                                     getpid());
                goto error;
            }

            if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label exceeds "
                                 "maximum length: %d"),
                               VIR_SECURITY_LABEL_BUFLEN - 1);
                freecon(ctx);
                goto error;
            }

            strcpy(oldlabel->label, (char *) ctx);
            freecon(ctx);

            if ((oldlabel->enforcing = security_getenforce()) < 0) {
                virReportSystemError(errno, "%s",
                                     _("error calling security_getenforce()"));
                goto error;
            }
        }

        if (setexeccon(label->label) < 0) {
            virReportSystemError(errno,
                            _("Cannot set context %s"),
                            label->label);
            goto error;
        }
#else
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Support for SELinux is not enabled"));
        goto error;
#endif
    } else if (STREQ(model->model, "apparmor")) {
#ifdef WITH_APPARMOR
        if (aa_change_profile(label->label) < 0) {
            virReportSystemError(errno, _("error changing profile to %s"),
                                 label->label);
            goto error;
        }
#else
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Support for AppArmor is not enabled"));
        goto error;
#endif
    } else if (STREQ(model->model, "none")) {
        /* nothing todo */
    } else {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                       _("Security model %s cannot be entered"),
                       model->model);
        goto error;
    }

    return 0;

 error:
    virDispatchError(NULL);
    return -1;
}