Beispiel #1
0
int
zone_get_id(const char *str, zoneid_t *zip)
{
	zoneid_t zoneid;
	char *cp;

	/*
	 * The first time we are called, attempt to dlopen() libzonecfg.so.1
	 * and get a pointer to the real zone_get_id().
	 * If we fail, set our pointer to -1 so we won't try again.
	 */
	if (real_zone_get_id == NULL) {
		/*
		 * There's no harm in doing this more than once, even
		 * concurrently.  We will get the same result each time,
		 * and the dynamic linker will single-thread the dlopen()
		 * with its own internal lock.  The worst that can happen
		 * is that the handle gets a reference count greater than
		 * one, which doesn't matter since we never dlclose()
		 * the handle if we successfully find the symbol; the
		 * library just stays in the address space until exit().
		 */
		void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY);
		void *sym = (void *)(-1);

		if (dlhandle != NULL &&
		    (sym = dlsym(dlhandle, "zone_get_id")) == NULL) {
			sym = (void *)(-1);
			(void) dlclose(dlhandle);
		}
		real_zone_get_id = (zone_get_id_t)sym;
	}

	/*
	 * If we've successfully loaded it, call the real zone_get_id().
	 * Otherwise, perform our stripped-down version of the code.
	 */
	if (real_zone_get_id != (zone_get_id_t)(-1))
		return (real_zone_get_id(str, zip));

	/* first try looking for active zone by id */
	errno = 0;
	zoneid = (zoneid_t)strtol(str, &cp, 0);
	if (errno == 0 && cp != str && *cp == '\0' &&
	    getzonenamebyid(zoneid, NULL, 0) != -1) {
		*zip = zoneid;
		return (0);
	}

	/* then look for active zone by name */
	if ((zoneid = getzoneidbyname(str)) != -1) {
		*zip = zoneid;
		return (0);
	}

	/* not an active zone, return error */
	return (-1);
}
Beispiel #2
0
/*
 * Lookup ids for each zone name; this is done once each time /proc
 * is scanned to avoid calling getzoneidbyname for each process.
 */
void
convert_zone(zonetbl_t *tbl)
{
    long i;
    zoneid_t id;
    char *name;

    for (i = 0; i < tbl->z_nent; i++) {
        name = tbl->z_list[i].z_name;
        if (name != NULL) {
            if ((id = getzoneidbyname(name)) != -1)
                tbl->z_list[i].z_id = id;
        }
    }
}
Beispiel #3
0
/*
 * Print all of the MLPs for the given zone.
 */
static int
print_mlp(const char *zonename)
{
	tsol_mlpent_t tsme;

	if ((tsme.tsme_zoneid = getzoneidbyname(zonename)) == -1) {
		(void) fprintf(stderr, gettext("tninfo: zone '%s' unknown\n"),
		    zonename);
		return (1);
	}
	tsme.tsme_flags = 0;
	if (iterate_mlps(&tsme, gettext("private")) == -1)
		return (1);
	tsme.tsme_flags = TSOL_MEF_SHARED;
	if (iterate_mlps(&tsme, gettext("shared")) == -1)
		return (1);
	return (0);
}
Beispiel #4
0
int
main(int argc, char *argv[])
{
	int ii;
	ipdadm_cmd_t *cmd;

	g_pname = basename(argv[0]);

	if (argc < 2)
		return (usage(stderr));
	argc--;
	argv++;

	g_zid = getzoneid();
	if (strcmp("-z", argv[0]) == 0) {
		argc--;
		argv++;
		if (argc < 1) {
			(void) fprintf(stderr, "%s: -z requires an argument\n",
			    g_pname);
			return (usage(stderr));
		}

		if (g_zid != GLOBAL_ZONEID) {
			(void) fprintf(stderr, "%s: -z option only permitted "
			    "in global zone\n", g_pname);
			return (usage(stderr));
		}

		g_zid = getzoneidbyname(argv[0]);
		if (g_zid == -1) {
			(void) fprintf(stderr, "%s: %s: invalid zone\n",
			    g_pname, argv[0]);
			return (E_ERROR);
		}
		argc--;
		argv++;
	}

	if (getzonenamebyid(g_zid, g_zonename, sizeof (g_zonename)) < 0) {
		(void) fprintf(stderr, "%s: failed to get zonename: %s\n",
		    g_pname, strerror(errno));
		return (E_ERROR);
	}

	if (argc < 1)
		return (usage(stderr));

	for (ii = 0; ii < IPDADM_NCMDS; ii++) {
		cmd = &ipdadm_cmds[ii];
		if (strcmp(argv[0], cmd->idc_name) == 0) {
			argv++;
			argc--;
			assert(cmd->idc_func != NULL);
			return (cmd->idc_func(argc, argv));
		}
	}

	(void) fprintf(stderr, "%s: %s: unknown command\n", g_pname, argv[0]);
	return (usage(stderr));
}
Beispiel #5
0
int
_zexec(const char *a_zoneName, const char *a_path, char *a_argv[])
{
	zoneid_t zoneid;
	zone_state_t st;
	char **new_env = { NULL };
	priv_set_t *privset;

	/* entry assertions */

	assert(a_zoneName != NULL);
	assert(*a_zoneName != '\0');
	assert(a_path != NULL);
	assert(*a_path != '\0');

	/* establish locale settings */

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	/* can only be invoked from within the global zone */

	if (getzoneid() != GLOBAL_ZONEID) {
		_z_program_error(ERR_ZEXEC_NOT_IN_GZ, a_zoneName);
		return (-1);
	}

	if (strcmp(a_zoneName, GLOBAL_ZONENAME) == 0) {
		_z_program_error(ERR_ZEXEC_GZUSED, a_zoneName);
		return (-1);
	}

	/* get the state of the specified zone */

	if (zone_get_state((char *)a_zoneName, &st) != Z_OK) {
		_z_program_error(ERR_ZEXEC_BADZONE, a_zoneName);
		return (-1);
	}

	if (st < ZONE_STATE_INSTALLED) {
		_z_program_error(ERR_ZEXEC_BADSTATE, a_zoneName,
		    zone_state_str(st));
		return (-1);
	}

	if (st != ZONE_STATE_RUNNING && st != ZONE_STATE_MOUNTED) {
		_z_program_error(ERR_ZEXEC_NOTRUNNING, a_zoneName,
		    zone_state_str(st));
		return (-1);
	}

	/*
	 * In both console and non-console cases, we require all privs.
	 * In the console case, because we may need to startup zoneadmd.
	 * In the non-console case in order to do zone_enter(2), zonept()
	 * and other tasks.
	 *
	 * Future work: this solution is temporary.  Ultimately, we need to
	 * move to a flexible system which allows the global admin to
	 * designate that a particular user can zlogin (and probably zlogin
	 * -C) to a particular zone.  This all-root business we have now is
	 * quite sketchy.
	 */

	if ((privset = priv_allocset()) == NULL) {
		_z_program_error(ERR_ZEXEC_PRIV_ALLOCSET, a_zoneName,
		    strerror(errno));
		return (-1);
	}

	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
		_z_program_error(ERR_ZEXEC_GETPPRIV, a_zoneName,
		    strerror(errno));
		priv_freeset(privset);
		return (-1);
	}

	if (priv_isfullset(privset) == B_FALSE) {
		_z_program_error(ERR_ZEXEC_PRIVS, a_zoneName);
		priv_freeset(privset);
		return (-1);
	}
	priv_freeset(privset);

	if ((zoneid = getzoneidbyname(a_zoneName)) == -1) {
		_z_program_error(ERR_ZEXEC_NOZONEID, a_zoneName,
		    strerror(errno));
		return (-1);
	}

	if ((new_env = _zexec_prep_env()) == NULL) {
		_z_program_error(ERR_ZEXEC_ASSEMBLE, a_zoneName);
		return (-1);
	}

	/*
	 * In case any of stdin, stdout or stderr are streams,
	 * anchor them to prevent malicious I_POPs.
	 *
	 * Future work: use pipes to entirely eliminate FD leakage
	 * into the zone.
	 */

	(void) ioctl(STDIN_FILENO, I_ANCHOR);
	(void) ioctl(STDOUT_FILENO, I_ANCHOR);
	(void) ioctl(STDERR_FILENO, I_ANCHOR);

	if (zone_enter(zoneid) == -1) {
		int	lerrno = errno;

		_z_program_error(ERR_ZEXEC_ZONEENTER, a_zoneName,
		    strerror(errno));

		if (lerrno == EFAULT) {
			_z_program_error(ERR_ZEXEC_EFAULT, a_zoneName);
		}

		free(new_env);

		return (-1);
	}

	(void) execve(a_path, &a_argv[0], new_env);

	_z_program_error(ERR_ZEXEC_EXECFAILURE, a_zoneName, strerror(errno));

	return (-1);
}
Beispiel #6
0
}

static void
zsock_ctx_set_errno(zsock_create_ctx_t *ccp, const char *syscall, int err)
{
  if (ccp->zcc_syscall == NULL)
    ccp->zcc_syscall = syscall;

  ccp->zcc_errno = err;
}

static void *
zsocket_create(void *op __UNUSED, void *ctx)
{
  zsock_create_ctx_t *ccp = ctx;
  zoneid_t zoneid = getzoneidbyname(ccp->zcc_zone);
  int sock_fd = -1;
  int attempts = 1;

  if (zoneid < 0) {
    zsock_ctx_set_errno(ccp, "getzoneidbyname", errno);
    return (NULL);
  }

  do {
    /* This call suffers from EINTR, so just retry */
    sock_fd = zsocket(zoneid, ccp->zcc_path);
  } while (attempts++ < 3 && sock_fd < 0);

  ccp->zcc_fd = sock_fd;
Beispiel #7
0
int
main(int argc, char *argv[])
{
	FILE	*f;
	char	*ptr, *start;
	struct	passwd *pwd;
	char	*term_name;
	int	c;
	int	aflag = 0;
	int	errflg = 0;
	int zflg = 0;
	int Zflg = 0;

	char *zonename = NULL;
	zoneid_t *zoneidlist = NULL;
	uint_t nzids_saved, nzids = 0;

	(void) setlocale(LC_ALL, "");

	while ((c = getopt(argc, argv, "g:az:Z")) != EOF)
		switch (c) {
		case 'a':
			aflag++;
			break;
		case 'g':
			if (gflag) {
				(void) fprintf(stderr,
				    "Only one group allowed\n");
				return (1);
			}
			if ((pgrp = getgrnam(grpname = optarg)) == NULL) {
				(void) fprintf(stderr, "Unknown group %s\n",
				    grpname);
				return (1);
			}
			gflag++;
			break;
		case 'z':
			zflg++;
			zonename = optarg;
			if (getzoneidbyname(zonename) == -1) {
				(void) fprintf(stderr, "Specified zone %s "
				    "is invalid", zonename);
				return (1);
			}
			break;
		case 'Z':
			Zflg++;
			break;
		case '?':
			errflg++;
			break;
		}

	if (errflg) {
		(void) fprintf(stderr,
		    "Usage: wall [-a] [-g group] [-z zone] [-Z] [files...]\n");
		return (1);
	}

	if (zflg && Zflg) {
		(void) fprintf(stderr, "Cannot use -z with -Z\n");
		return (1);
	}

	if (optind < argc)
		infile = argv[optind];

	if (uname(&utsn) == -1) {
		(void) fprintf(stderr, "wall: uname() failed, %s\n",
		    strerror(errno));
		return (2);
	}
	(void) strcpy(systm, utsn.nodename);

	/*
	 * Get the name of the terminal wall is running from.
	 */

	if ((term_name = ttyname(fileno(stderr))) != NULL) {
		/*
		 * skip the leading "/dev/" in term_name
		 */
		(void) strncpy(line, &term_name[5], sizeof (line) - 1);
	}

	if (who[0] == '?') {
		if (pwd = getpwuid(getuid()))
			(void) strncpy(&who[0], pwd->pw_name, sizeof (who));
	}

	f = stdin;
	if (infile) {
		f = fopen(infile, "r");
		if (f == NULL) {
			(void) fprintf(stderr, "Cannot open %s\n", infile);
			return (1);
		}
	}

	start = &mesg[0];
	ptr = start;
	while ((ptr - start) < 3000) {
		size_t n;

		if (fgets(ptr, &mesg[sizeof (mesg)] - ptr, f) == NULL)
			break;
		if ((n = strlen(ptr)) == 0)
			break;
		ptr += n;
	}
	(void) fclose(f);

	/*
	 * If the request is from the rwall daemon then use the caller's
	 * name and host.  We determine this if all of the following is true:
	 *	1) First 5 characters are "From "
	 *	2) Next non-white characters are of the form "name@host:"
	 */
	if (strcmp(line, "???") == 0) {
		char rwho[MAXNAMLEN+1];
		char rsystm[MAXNAMLEN+1];
		char *cp;

		if (strncmp(mesg, "From ", 5) == 0) {
			cp = &mesg[5];
			cp = copy_str_till(rwho, cp, '@', MAXNAMLEN + 1);
			if (rwho[0] != '\0') {
				cp = copy_str_till(rsystm, ++cp, ':',
				    MAXNAMLEN + 1);
				if (rsystm[0] != '\0') {
					(void) strcpy(systm, rsystm);
					(void) strncpy(rwho, who,
					    sizeof (who));
					(void) strcpy(line, "rpc.rwalld");
				}
			}
		}
	}
	(void) time(&tloc);
	(void) strftime(time_buf, sizeof (time_buf),
	    DATE_FMT, localtime(&tloc));

	if (zflg != 0) {
		if ((zoneidlist =
		    malloc(sizeof (zoneid_t))) == NULL ||
		    (*zoneidlist = getzoneidbyname(zonename)) == -1)
			return (errno);
		nzids = 1;
	} else if (Zflg != 0) {
		if (zone_list(NULL, &nzids) != 0)
			return (errno);
again:
		nzids *= 2;
		if ((zoneidlist = malloc(nzids * sizeof (zoneid_t))) == NULL)
			exit(errno);
		nzids_saved = nzids;
		if (zone_list(zoneidlist, &nzids) != 0) {
			(void) free(zoneidlist);
			return (errno);
		}
		if (nzids > nzids_saved) {
			free(zoneidlist);
			goto again;
		}
	}
	if (zflg || Zflg) {
		for (; nzids > 0; --nzids)
			sendmes_tozone(zoneidlist[nzids-1], aflag);
		free(zoneidlist);
	} else
		sendmes_tozone(getzoneid(), aflag);

	return (0);
}