char *virSystemdMakeMachineName(const char *name, const char *drivername, bool privileged) { char *machinename = NULL; char *username = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; if (privileged) { virBufferAsprintf(&buf, "%s-", drivername); } else { if (!(username = virGetUserName(geteuid()))) goto cleanup; virBufferAsprintf(&buf, "%s-%s-", username, drivername); } virSystemdEscapeName(&buf, name, false); machinename = virBufferContentAndReset(&buf); cleanup: VIR_FREE(username); return machinename; }
/** * virIdentityGetSystem: * * Returns an identity that represents the system itself. * This is the identity that the process is running as * * Returns a reference to the system identity, or NULL */ virIdentityPtr virIdentityGetSystem(void) { char *username = NULL; char *groupname = NULL; char *seccontext = NULL; virIdentityPtr ret = NULL; #if WITH_SELINUX security_context_t con; #endif if (!(username = virGetUserName(getuid()))) goto cleanup; if (!(groupname = virGetGroupName(getgid()))) goto cleanup; #if WITH_SELINUX if (getcon(&con) < 0) { virReportSystemError(errno, "%s", _("Unable to lookup SELinux process context")); goto cleanup; } if (VIR_STRDUP(seccontext, con) < 0) { freecon(con); goto cleanup; } freecon(con); #endif if (!(ret = virIdentityNew())) goto cleanup; if (username && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_NAME, username) < 0) goto error; if (groupname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, groupname) < 0) goto error; if (seccontext && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SELINUX_CONTEXT, seccontext) < 0) goto error; cleanup: VIR_FREE(username); VIR_FREE(groupname); VIR_FREE(seccontext); return ret; error: virObjectUnref(ret); ret = NULL; goto cleanup; }
/** * virIdentityGetSystem: * * Returns an identity that represents the system itself. * This is the identity that the process is running as * * Returns a reference to the system identity, or NULL */ virIdentityPtr virIdentityGetSystem(void) { VIR_AUTOFREE(char *) username = NULL; VIR_AUTOFREE(char *) groupname = NULL; unsigned long long startTime; virIdentityPtr ret = NULL; #if WITH_SELINUX security_context_t con; #endif if (!(ret = virIdentityNew())) goto error; if (virIdentitySetUNIXProcessID(ret, getpid()) < 0) goto error; if (virProcessGetStartTime(getpid(), &startTime) < 0) goto error; if (startTime != 0 && virIdentitySetUNIXProcessTime(ret, startTime) < 0) goto error; if (!(username = virGetUserName(geteuid()))) return ret; if (virIdentitySetUNIXUserName(ret, username) < 0) goto error; if (virIdentitySetUNIXUserID(ret, getuid()) < 0) goto error; if (!(groupname = virGetGroupName(getegid()))) return ret; if (virIdentitySetUNIXGroupName(ret, groupname) < 0) goto error; if (virIdentitySetUNIXGroupID(ret, getgid()) < 0) goto error; #if WITH_SELINUX if (is_selinux_enabled() > 0) { if (getcon(&con) < 0) { virReportSystemError(errno, "%s", _("Unable to lookup SELinux process context")); return ret; } if (virIdentitySetSELinuxContext(ret, con) < 0) { freecon(con); goto error; } freecon(con); } #endif return ret; error: virObjectUnref(ret); return NULL; }
char *virSystemdMakeMachineName(const char *name, const char *drivername, bool privileged) { char *machinename = NULL; char *username = NULL; if (privileged) { if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0) goto cleanup; } else { if (!(username = virGetUserName(geteuid()))) goto cleanup; if (virAsprintf(&machinename, "%s-%s-%s", username, drivername, name) < 0) goto cleanup; } cleanup: VIR_FREE(username); return machinename; }
static int virCgroupAppRoot(int privileged, virCgroupPtr *group, int create) { virCgroupPtr rootgrp = NULL; int rc; rc = virCgroupNew("/", &rootgrp); if (rc != 0) return rc; if (privileged) { rc = virCgroupNew("/libvirt", group); } else { char *rootname; char *username; username = virGetUserName(getuid()); if (!username) { rc = -ENOMEM; goto cleanup; } rc = virAsprintf(&rootname, "/libvirt-%s", username); VIR_FREE(username); if (rc < 0) { rc = -ENOMEM; goto cleanup; } rc = virCgroupNew(rootname, group); VIR_FREE(rootname); } if (rc != 0) goto cleanup; rc = virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE); cleanup: virCgroupFree(&rootgrp); return rc; }
static int virStorageBackendVzPoolStart(virStoragePoolObjPtr pool) { virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool); VIR_AUTOFREE(char *) grp_name = NULL; VIR_AUTOFREE(char *) usr_name = NULL; VIR_AUTOFREE(char *) mode = NULL; VIR_AUTOPTR(virCommand) cmd = NULL; /* Check the permissions */ if (def->target.perms.mode == (mode_t)-1) def->target.perms.mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE; if (def->target.perms.uid == (uid_t)-1) def->target.perms.uid = geteuid(); if (def->target.perms.gid == (gid_t)-1) def->target.perms.gid = getegid(); /* Convert ids to names because vstorage uses names */ if (!(grp_name = virGetGroupName(def->target.perms.gid))) return -1; if (!(usr_name = virGetUserName(def->target.perms.uid))) return -1; if (virAsprintf(&mode, "%o", def->target.perms.mode) < 0) return -1; cmd = virCommandNewArgList(VSTORAGE_MOUNT, "-c", def->source.name, def->target.path, "-m", mode, "-g", grp_name, "-u", usr_name, NULL); return virCommandRun(cmd, NULL); }
static virIdentityPtr virNetServerClientCreateIdentity(virNetServerClientPtr client) { char *username = NULL; char *groupname = NULL; char *seccontext = NULL; virIdentityPtr ret = NULL; if (!(ret = virIdentityNew())) goto error; if (client->sock && virNetSocketIsLocal(client->sock)) { gid_t gid; uid_t uid; pid_t pid; unsigned long long timestamp; if (virNetSocketGetUNIXIdentity(client->sock, &uid, &gid, &pid, ×tamp) < 0) goto error; if (!(username = virGetUserName(uid))) goto error; if (virIdentitySetUNIXUserName(ret, username) < 0) goto error; if (virIdentitySetUNIXUserID(ret, uid) < 0) goto error; if (!(groupname = virGetGroupName(gid))) goto error; if (virIdentitySetUNIXGroupName(ret, groupname) < 0) goto error; if (virIdentitySetUNIXGroupID(ret, gid) < 0) goto error; if (virIdentitySetUNIXProcessID(ret, pid) < 0) goto error; if (virIdentitySetUNIXProcessTime(ret, timestamp) < 0) goto error; } #if WITH_SASL if (client->sasl) { const char *identity = virNetSASLSessionGetIdentity(client->sasl); if (virIdentitySetSASLUserName(ret, identity) < 0) goto error; } #endif #if WITH_GNUTLS if (client->tls) { const char *identity = virNetTLSSessionGetX509DName(client->tls); if (virIdentitySetX509DName(ret, identity) < 0) goto error; } #endif if (client->sock && virNetSocketGetSELinuxContext(client->sock, &seccontext) < 0) goto error; if (seccontext && virIdentitySetSELinuxContext(ret, seccontext) < 0) goto error; cleanup: VIR_FREE(username); VIR_FREE(groupname); VIR_FREE(seccontext); return ret; error: virObjectUnref(ret); ret = NULL; goto cleanup; }
static virIdentityPtr virNetServerClientCreateIdentity(virNetServerClientPtr client) { char *processid = NULL; char *processtime = NULL; char *username = NULL; char *userid = NULL; char *groupname = NULL; char *groupid = NULL; #if WITH_SASL char *saslname = NULL; #endif #if WITH_GNUTLS char *x509dname = NULL; #endif char *seccontext = NULL; virIdentityPtr ret = NULL; if (client->sock && virNetSocketIsLocal(client->sock)) { gid_t gid; uid_t uid; pid_t pid; unsigned long long timestamp; if (virNetSocketGetUNIXIdentity(client->sock, &uid, &gid, &pid, ×tamp) < 0) goto cleanup; if (!(username = virGetUserName(uid))) goto cleanup; if (virAsprintf(&userid, "%d", (int)uid) < 0) goto cleanup; if (!(groupname = virGetGroupName(gid))) goto cleanup; if (virAsprintf(&groupid, "%d", (int)gid) < 0) goto cleanup; if (virAsprintf(&processid, "%llu", (unsigned long long)pid) < 0) goto cleanup; if (virAsprintf(&processtime, "%llu", timestamp) < 0) goto cleanup; } #if WITH_SASL if (client->sasl) { const char *identity = virNetSASLSessionGetIdentity(client->sasl); if (VIR_STRDUP(saslname, identity) < 0) goto cleanup; } #endif #if WITH_GNUTLS if (client->tls) { const char *identity = virNetTLSSessionGetX509DName(client->tls); if (VIR_STRDUP(x509dname, identity) < 0) goto cleanup; } #endif if (client->sock && virNetSocketGetSELinuxContext(client->sock, &seccontext) < 0) goto cleanup; if (!(ret = virIdentityNew())) goto cleanup; if (username && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_NAME, username) < 0) goto error; if (userid && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_ID, userid) < 0) goto error; if (groupname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, groupname) < 0) goto error; if (groupid && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_ID, groupid) < 0) goto error; if (processid && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, processid) < 0) goto error; if (processtime && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME, processtime) < 0) goto error; #if WITH_SASL if (saslname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SASL_USER_NAME, saslname) < 0) goto error; #endif #if WITH_GNUTLS if (x509dname && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_X509_DISTINGUISHED_NAME, x509dname) < 0) goto error; #endif if (seccontext && virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SELINUX_CONTEXT, seccontext) < 0) goto error; cleanup: VIR_FREE(username); VIR_FREE(userid); VIR_FREE(groupname); VIR_FREE(groupid); VIR_FREE(processid); VIR_FREE(processtime); VIR_FREE(seccontext); #if WITH_SASL VIR_FREE(saslname); #endif #if WITH_GNUTLS VIR_FREE(x509dname); #endif return ret; error: virObjectUnref(ret); ret = NULL; goto cleanup; }
int main(int argc, char **argv) { virConfPtr conf = NULL; const char *login_shell_path = conf_file; pid_t cpid = -1; int ret = EXIT_CANCELED; int status; uid_t uid = getuid(); gid_t gid = getgid(); char *name = NULL; char **shargv = NULL; virSecurityModelPtr secmodel = NULL; virSecurityLabelPtr seclabel = NULL; virDomainPtr dom = NULL; virConnectPtr conn = NULL; char *homedir = NULL; int arg; int longindex = -1; int ngroups; gid_t *groups = NULL; ssize_t nfdlist = 0; int *fdlist = NULL; int openmax; size_t i; struct option opt[] = { {"help", no_argument, NULL, 'h'}, {"version", optional_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; if (virInitialize() < 0) { fprintf(stderr, _("Failed to initialize libvirt error handling")); return EXIT_CANCELED; } setenv("PATH", "/bin:/usr/bin", 1); virSetErrorFunc(NULL, NULL); virSetErrorLogPriorityFunc(NULL); progname = argv[0]; if (!setlocale(LC_ALL, "")) { perror("setlocale"); /* failure to setup locale is not fatal */ } if (!bindtextdomain(PACKAGE, LOCALEDIR)) { perror("bindtextdomain"); return ret; } if (!textdomain(PACKAGE)) { perror("textdomain"); return ret; } while ((arg = getopt_long(argc, argv, "hV", opt, &longindex)) != -1) { switch (arg) { case 'h': usage(); exit(EXIT_SUCCESS); case 'V': show_version(); exit(EXIT_SUCCESS); case '?': default: usage(); exit(EXIT_CANCELED); } } if (argc > optind) { virReportSystemError(EINVAL, _("%s takes no options"), progname); goto cleanup; } if (uid == 0) { virReportSystemError(EPERM, _("%s must be run by non root users"), progname); goto cleanup; } name = virGetUserName(uid); if (!name) goto cleanup; homedir = virGetUserDirectoryByUID(uid); if (!homedir) goto cleanup; if (!(conf = virConfReadFile(login_shell_path, 0))) goto cleanup; if ((ngroups = virGetGroupList(uid, gid, &groups)) < 0) goto cleanup; if (virLoginShellAllowedUser(conf, name, groups) < 0) goto cleanup; if (!(shargv = virLoginShellGetShellArgv(conf))) goto cleanup; conn = virConnectOpen("lxc:///"); if (!conn) goto cleanup; dom = virDomainLookupByName(conn, name); if (!dom) goto cleanup; if (!virDomainIsActive(dom) && virDomainCreate(dom)) { virErrorPtr last_error; last_error = virGetLastError(); if (last_error->code != VIR_ERR_OPERATION_INVALID) { virReportSystemError(last_error->code, _("Can't create %s container: %s"), name, last_error->message); goto cleanup; } } openmax = sysconf(_SC_OPEN_MAX); if (openmax < 0) { virReportSystemError(errno, "%s", _("sysconf(_SC_OPEN_MAX) failed")); goto cleanup; } if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0) goto cleanup; if (VIR_ALLOC(secmodel) < 0) goto cleanup; if (VIR_ALLOC(seclabel) < 0) goto cleanup; if (virNodeGetSecurityModel(conn, secmodel) < 0) goto cleanup; if (virDomainGetSecurityLabel(dom, seclabel) < 0) goto cleanup; if (virSetUIDGID(0, 0, NULL, 0) < 0) goto cleanup; if (virDomainLxcEnterSecurityLabel(secmodel, seclabel, NULL, 0) < 0) goto cleanup; if (nfdlist > 0 && virDomainLxcEnterNamespace(dom, nfdlist, fdlist, NULL, NULL, 0) < 0) goto cleanup; if (virSetUIDGID(uid, gid, groups, ngroups) < 0) goto cleanup; if (chdir(homedir) < 0) { virReportSystemError(errno, _("Unable to chdir(%s)"), homedir); goto cleanup; } /* A fork is required to create new process in correct pid namespace. */ if ((cpid = virFork()) < 0) goto cleanup; if (cpid == 0) { int tmpfd; for (i = 3; i < openmax; i++) { tmpfd = i; VIR_MASS_CLOSE(tmpfd); } if (execv(shargv[0], (char *const*) shargv) < 0) { virReportSystemError(errno, _("Unable to exec shell %s"), shargv[0]); virDispatchError(NULL); return errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; } } /* At this point, the parent is now waiting for the child to exit, * but as that may take a long time, we release resources now. */ cleanup: if (nfdlist > 0) for (i = 0; i < nfdlist; i++) VIR_FORCE_CLOSE(fdlist[i]); VIR_FREE(fdlist); virConfFree(conf); if (dom) virDomainFree(dom); if (conn) virConnectClose(conn); virStringFreeList(shargv); VIR_FREE(name); VIR_FREE(homedir); VIR_FREE(seclabel); VIR_FREE(secmodel); VIR_FREE(groups); if (virProcessWait(cpid, &status, true) == 0) virProcessExitWithStatus(status); if (virGetLastError()) virDispatchError(NULL); return ret; }