Exemplo n.º 1
0
static int
priv_set_initialize (void)
{
  if (! initialized)
    {
      eff_set = priv_allocset ();
      if (!eff_set)
        {
          return -1;
        }
      rem_set = priv_allocset ();
      if (!rem_set)
        {
          priv_freeset (eff_set);
          return -1;
        }
      if (getppriv (PRIV_EFFECTIVE, eff_set) != 0)
        {
          priv_freeset (eff_set);
          priv_freeset (rem_set);
          return -1;
        }
      priv_emptyset (rem_set);
      initialized = true;
    }

  return 0;
}
Exemplo n.º 2
0
static apr_status_t priv_cfg_cleanup(void *CFG)
{
    priv_cfg *cfg = CFG;
    priv_freeset(cfg->priv);
    priv_freeset(cfg->child_priv);
    return APR_SUCCESS;
}
Exemplo n.º 3
0
static void
change_user_set_privs(void)
{
    priv_set_t *priv_set;

    priv_set = priv_allocset();
    if (getppriv(PRIV_PERMITTED, priv_set) == -1) {
        dprintf("getppriv %s", strerror(errno));
    } else {
        char *p;

        p = priv_set_to_str(priv_set, ',', 0);
        dprintf("started with privs %s", p != NULL ? p : "Unknown");
        free(p);
    }
    priv_freeset(priv_set);

    /* always start with the basic set */
    priv_set = priv_str_to_set("basic", ",", NULL);
    if (priv_set == NULL) {
        syslog(LOG_ERR, "converting basic privilege set: %m");
        exit(EXIT_FAILURE);
    }
    (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF);
    (void) priv_addset(priv_set, PRIV_FILE_DAC_READ);
    (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE);
    (void) priv_addset(priv_set, PRIV_NET_PRIVADDR);
    (void) priv_addset(priv_set, PRIV_NET_RAWACCESS);
    (void) priv_addset(priv_set, PRIV_PROC_AUDIT);
    (void) priv_addset(priv_set, PRIV_PROC_OWNER);
    (void) priv_addset(priv_set, PRIV_PROC_SETID);
    (void) priv_addset(priv_set, PRIV_SYS_CONFIG);
    (void) priv_addset(priv_set, PRIV_SYS_IP_CONFIG);
    (void) priv_addset(priv_set, PRIV_SYS_IPC_CONFIG);
    (void) priv_addset(priv_set, PRIV_SYS_NET_CONFIG);
    (void) priv_addset(priv_set, PRIV_SYS_RES_CONFIG);
    (void) priv_addset(priv_set, PRIV_SYS_RESOURCE);

    if (setppriv(PRIV_SET, PRIV_INHERITABLE, priv_set) == -1) {
        syslog(LOG_ERR, "setppriv inheritable: %m");
        priv_freeset(priv_set);
        exit(EXIT_FAILURE);
    }

    if (setppriv(PRIV_SET, PRIV_PERMITTED, priv_set) == -1) {
        syslog(LOG_ERR, "setppriv permitted: %m");
        priv_freeset(priv_set);
        exit(EXIT_FAILURE);
    }

    if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
        syslog(LOG_ERR, "setppriv effective: %m");
        priv_freeset(priv_set);
        exit(EXIT_FAILURE);
    }

    priv_freeset(priv_set);
}
Exemplo n.º 4
0
void
solaris_drop_privs_pinfo_net_fork_exec(void)
{
	priv_set_t *pset = NULL, *npset = NULL;

	/*
	 * Note: this variant avoids dropping DAC filesystem rights, in case
	 * the process calling it is running as root and should have the
	 * ability to read/write/chown any file on the system.
	 *
	 * We start with the basic set, then *add* the DAC rights to it while
	 * taking away other parts of BASIC we don't need. Then we intersect
	 * this with our existing PERMITTED set. In this way we keep any
	 * DAC rights we had before, while otherwise reducing ourselves to
	 * the minimum set of privileges we need to proceed.
	 *
	 * This also means we drop any other parts of "root" that we don't
	 * need (e.g. the ability to kill any process, create new device nodes
	 * etc etc).
	 */

	if ((pset = priv_allocset()) == NULL ||
	    (npset = priv_allocset()) == NULL)
		fatal("priv_allocset: %s", strerror(errno));

	priv_basicset(npset);

	if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 ||
	    priv_addset(npset, PRIV_FILE_DAC_READ) != 0 ||
	    priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 ||
	    priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 ||
	    priv_addset(npset, PRIV_FILE_OWNER) != 0)
		fatal("priv_addset: %s", strerror(errno));

	if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 ||
	    priv_delset(npset, PRIV_NET_ACCESS) != 0 ||
	    priv_delset(npset, PRIV_PROC_EXEC) != 0 ||
	    priv_delset(npset, PRIV_PROC_FORK) != 0 ||
	    priv_delset(npset, PRIV_PROC_INFO) != 0 ||
	    priv_delset(npset, PRIV_PROC_SESSION) != 0)
		fatal("priv_delset: %s", strerror(errno));

	if (getppriv(PRIV_PERMITTED, pset) != 0)
		fatal("getppriv: %s", strerror(errno));

	priv_intersect(pset, npset);

	if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 ||
	    setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0 ||
	    setppriv(PRIV_SET, PRIV_INHERITABLE, npset) != 0)
		fatal("setppriv: %s", strerror(errno));

	priv_freeset(pset);
	priv_freeset(npset);
}
Exemplo n.º 5
0
static void
vjs_waive(enum jail_gen_e jge)
{
	priv_set_t *effective, *inheritable, *permitted, *limited;

	if (!(effective = priv_allocset()) ||
	    !(inheritable = priv_allocset()) ||
	    !(permitted = priv_allocset()) ||
	    !(limited = priv_allocset())) {
		MGT_complain(C_SECURITY,
		    "Solaris Jail warning: "
		    " vjs_waive - priv_allocset failed: errno=%d (%s)",
		    errno, strerror(errno));
		return;
	}

	/*
	 * inheritable and effective are distinct sets
	 * effective is a subset of permitted
	 * limit is the union of all
	 */

	priv_emptyset(inheritable);
	vjs_add_inheritable(inheritable, jge);

	priv_emptyset(effective);
	vjs_add_effective(effective, jge);

	priv_copyset(effective, permitted);
	vjs_add_permitted(permitted, jge);

	priv_copyset(inheritable, limited);
	priv_union(permitted, limited);
	/*
	 * invert the sets and clear privileges such that setppriv will always
	 * succeed
	 */
	priv_inverse(limited);
	priv_inverse(permitted);
	priv_inverse(effective);
	priv_inverse(inheritable);

	AZ(setppriv(PRIV_OFF, PRIV_LIMIT, limited));
	AZ(setppriv(PRIV_OFF, PRIV_PERMITTED, permitted));
	AZ(setppriv(PRIV_OFF, PRIV_EFFECTIVE, effective));
	AZ(setppriv(PRIV_OFF, PRIV_INHERITABLE, inheritable));

	priv_freeset(limited);
	priv_freeset(permitted);
	priv_freeset(effective);
	priv_freeset(inheritable);
}
Exemplo n.º 6
0
static void
vjs_setup(enum jail_gen_e jge)
{
	priv_set_t *priv_all;

	if (! (priv_all = priv_allocset())) {
		MGT_complain(C_SECURITY,
		    "Solaris Jail warning: "
		    " vjs_setup - priv_allocset failed: errno=%d (%s)",
		    errno, strerror(errno));
		return;
	}

	priv_emptyset(priv_all);

	vjs_add_inheritable(priv_all, jge);
	vjs_add_effective(priv_all, jge);
	vjs_add_permitted(priv_all, jge);
	vjs_add_initial(priv_all, jge);

	/* try to get all possible privileges, expect EPERM here */
	setppriv_assert(setppriv(PRIV_ON, PRIV_PERMITTED, priv_all));
	setppriv_assert(setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_all));
	setppriv_assert(setppriv(PRIV_ON, PRIV_INHERITABLE, priv_all));

	priv_freeset(priv_all);
}
Exemplo n.º 7
0
void
solaris_drop_privs_root_pinfo_net_exec(void)
{
	priv_set_t *pset = NULL;

	if ((pset = priv_allocset()) == NULL)
		fatal("priv_allocset: %s", strerror(errno));

	/* Start with "basic" and drop everything we don't need. */
	priv_basicset(pset);

	if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
	    priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
	    priv_delset(pset, PRIV_PROC_EXEC) != 0 ||
	    priv_delset(pset, PRIV_PROC_INFO) != 0 ||
	    priv_delset(pset, PRIV_PROC_SESSION) != 0)
		fatal("priv_delset: %s", strerror(errno));

	if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 ||
	    setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 ||
	    setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0)
		fatal("setppriv: %s", strerror(errno));

	priv_freeset(pset);
}
Exemplo n.º 8
0
/*
 * this section of code will drop all (Solaris) privileges including
 * those normally granted to all userland process (basic privileges). The
 * effect of this is that after running this code, the process will not able
 * to fork(), exec(), etc.  See privileges(5) for more information.
 */
void drop_privileges(void) {
   priv_set_t *privs = priv_str_to_set("basic", ",", NULL);

   if (privs == NULL) {
      perror("priv_str_to_set");
      exit(EXIT_FAILURE);
   }

   (void)priv_delset(privs, PRIV_FILE_LINK_ANY);
   (void)priv_delset(privs, PRIV_PROC_EXEC);
   (void)priv_delset(privs, PRIV_PROC_FORK);
   (void)priv_delset(privs, PRIV_PROC_INFO);
   (void)priv_delset(privs, PRIV_PROC_SESSION);

   if (setppriv(PRIV_SET, PRIV_PERMITTED, privs) != 0) {
      perror("setppriv(PRIV_SET, PRIV_PERMITTED)");
      exit(EXIT_FAILURE);
   }

   priv_emptyset(privs);

   if (setppriv(PRIV_SET, PRIV_INHERITABLE, privs) != 0) {
      perror("setppriv(PRIV_SET, PRIV_INHERITABLE)");
      exit(EXIT_FAILURE);
   }

   if (setppriv(PRIV_SET, PRIV_LIMIT, privs) != 0) {
      perror("setppriv(PRIV_SET, PRIV_LIMIT)");
      exit(EXIT_FAILURE);
   }

   priv_freeset(privs);
}
static void
mgt_sandbox_solaris_init(enum sandbox_e who)
{
	priv_set_t *priv_all;

	if (! (priv_all = priv_allocset())) {
		REPORT(LOG_ERR,
		    "Sandbox warning: "
		    " mgt_sandbox_init - priv_allocset failed: errno=%d (%s)",
		    errno, strerror(errno));
		return;
	}

	priv_emptyset(priv_all);

	mgt_sandbox_solaris_add_inheritable(priv_all, who);
	mgt_sandbox_solaris_add_effective(priv_all, who);
	mgt_sandbox_solaris_add_permitted(priv_all, who);
	mgt_sandbox_solaris_add_initial(priv_all, who);

	/* try to get all possible privileges, expect EPERM here */
	setppriv_assert(setppriv(PRIV_ON, PRIV_PERMITTED, priv_all));
	setppriv_assert(setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_all));
	setppriv_assert(setppriv(PRIV_ON, PRIV_INHERITABLE, priv_all));

	priv_freeset(priv_all);
}
static void
mgt_sandbox_solaris_waive(enum sandbox_e who)
{
	priv_set_t *effective, *inheritable, *permitted;

	if (!(effective = priv_allocset()) ||
	    !(inheritable = priv_allocset()) ||
	    !(permitted = priv_allocset())) {
		REPORT(LOG_ERR,
		    "Sandbox warning: "
		    " mgt_sandbox_waive - priv_allocset failed: errno=%d (%s)",
		    errno, strerror(errno));
		return;
	}

	/*
	 * simple scheme:
	 *     (inheritable subset-of effective) subset-of permitted
	 */

	priv_emptyset(inheritable);
	mgt_sandbox_solaris_add_inheritable(inheritable, who);

	priv_copyset(inheritable, effective);
	mgt_sandbox_solaris_add_effective(effective, who);

	priv_copyset(effective, permitted);
	mgt_sandbox_solaris_add_permitted(permitted, who);

	/*
	 * invert the sets and clear privileges such that setppriv will always
	 * succeed
	 */
	priv_inverse(inheritable);
	priv_inverse(effective);
	priv_inverse(permitted);

	AZ(setppriv(PRIV_OFF, PRIV_LIMIT, permitted));
	AZ(setppriv(PRIV_OFF, PRIV_PERMITTED, permitted));
	AZ(setppriv(PRIV_OFF, PRIV_EFFECTIVE, effective));
	AZ(setppriv(PRIV_OFF, PRIV_INHERITABLE, inheritable));

	priv_freeset(inheritable);
	priv_freeset(effective);
	priv_freeset(permitted);
}
Exemplo n.º 11
0
static void
privupdate_self(void)
{
	int set;

	if (mac_aware) {
		if (setpflags(NET_MAC_AWARE, 1) != 0)
			fatal("setpflags(NET_MAC_AWARE)");
		if (setpflags(NET_MAC_AWARE_INHERIT, 1) != 0)
			fatal("setpflags(NET_MAC_AWARE_INHERIT)");
	}
	if (pfexec) {
		if (setpflags(PRIV_PFEXEC, 1) != 0)
			fatal("setpflags(PRIV_PFEXEC)");
	}

	if (sets != NULL) {
		priv_set_t *target = priv_allocset();

		if (target == NULL)
			fatal("priv_allocet");

		set = priv_getsetbyname(PRIV_INHERITABLE);
		if (rem[set] != NULL || add[set] != NULL ||
		    assign[set] != NULL) {
			(void) getppriv(PRIV_INHERITABLE, target);
			if (rem[set] != NULL)
				priv_intersect(rem[set], target);
			if (add[set] != NULL)
				priv_union(add[set], target);
			if (assign[set] != NULL)
				priv_copyset(assign[set], target);
			if (setppriv(PRIV_SET, PRIV_INHERITABLE, target) != 0)
				fatal("setppriv(Inheritable)");
		}
		set = priv_getsetbyname(PRIV_LIMIT);
		if (rem[set] != NULL || add[set] != NULL ||
		    assign[set] != NULL) {
			(void) getppriv(PRIV_LIMIT, target);
			if (rem[set] != NULL)
				priv_intersect(rem[set], target);
			if (add[set] != NULL)
				priv_union(add[set], target);
			if (assign[set] != NULL)
				priv_copyset(assign[set], target);
			if (setppriv(PRIV_SET, PRIV_LIMIT, target) != 0)
				fatal("setppriv(Limit)");
		}
		priv_freeset(target);
	}

	if (Doff || Don)
		(void) setpflags(PRIV_DEBUG, Don ? 1 : 0);
	if (xpol)
		(void) setpflags(PRIV_XPOLICY, 1);
	if (pfexec)
		(void) setpflags(PRIV_PFEXEC, 1);
}
void
mgt_sandbox_solaris_fini(void)
{
	priv_set_t *effective, *inheritable, *permitted;

	if (!(effective = priv_allocset()) ||
	    !(inheritable = priv_allocset()) ||
	    !(permitted = priv_allocset())) {
		REPORT(LOG_ERR,
		    "Child start warning: mgt_sandbox_waive - priv_allocset failed: errno=%d (%s)",
		    errno, strerror(errno));
		return;
	}

	priv_emptyset(inheritable);

	priv_emptyset(effective);
	mgt_sandbox_solaris_add_effective(effective);

	priv_copyset(effective, permitted);
	mgt_sandbox_solaris_add_permitted(permitted);

	/* 
	 * invert the sets and clear privileges such that setppriv will always
	 * succeed
	 */
	priv_inverse(inheritable);
	priv_inverse(effective);
	priv_inverse(permitted);

#define SETPPRIV(which, set)						\
	if (setppriv(PRIV_OFF, which, set))				\
		REPORT(LOG_ERR,						\
		    "Child start warning: Waiving privileges failed on %s: errno=%d (%s)", \
		    #which, errno, strerror(errno));

	SETPPRIV(PRIV_INHERITABLE, inheritable);
	SETPPRIV(PRIV_EFFECTIVE, effective);
	SETPPRIV(PRIV_PERMITTED, permitted);
	SETPPRIV(PRIV_LIMIT, permitted);
#undef SETPPRIV

	priv_freeset(inheritable);
	priv_freeset(effective);
}
Exemplo n.º 13
0
/* Permanently disable those privileges passed in __init_suid_priv.  */
void __priv_relinquish (void)
{
  if (__suidset)
    {
      setppriv (PRIV_OFF, PRIV_PERMITTED, __suidset);
      priv_freeset (__suidset);
      __suidset = NULL;
    }
}
Exemplo n.º 14
0
int mtev_security_setcaps(mtev_security_captype_t type,
                          const char *capstring) {
#ifndef CAP_SUPPORTED
  mtevL(mtev_error, "Capabilities not supported on this platform.\n");
  return -1;
#endif
#ifdef HAVE_SETPPRIV
  int rv;
  const char *endptr;
  char *str;
  priv_set_t *set, *old;
  priv_ptype_t ptype = "Permitted";
  set = priv_str_to_set(capstring, ",", &endptr);
  if(!set) {
    mtevL(mtev_error, "Cannot translate '%s' to privilege set.\n", capstring);
    return -1;
  }
  switch(type) {
    case MTEV_SECURITY_CAP_PERMITTED: ptype = "Permitted"; break;
    case MTEV_SECURITY_CAP_EFFECTIVE: ptype = "Effective"; break;
    case MTEV_SECURITY_CAP_INHERITABLE: ptype = "Inheritable"; break;
  }

  old = priv_allocset();
  getppriv(ptype, old);
  str = priv_set_to_str(old, ',', PRIV_STR_PORT);
  mtevL(mtev_debug, "Old privs(%s) -> %s\n", ptype, str);
  priv_freeset(old);
  free(str);
  rv = setppriv(PRIV_SET, ptype, set);
  str = priv_set_to_str(set, ',', PRIV_STR_PORT);
  mtevL(mtev_debug, "%s privs(%s) -> %s\n",
        (rv == 0) ? "Changed to" : "Failed to change to", ptype, str);
  free(str);
  priv_freeset(set);

  return rv;
#else
  return -1;
#endif
}
Exemplo n.º 15
0
void
drop_privs(void)
{
	priv_set_t *pPrivSet = NULL;
	priv_set_t *lPrivSet = NULL;

	if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
		(void) fprintf(stderr, "Unable to get 'basic' privset\n");
		exit(EXIT_FAILURE);
	}

	/* Drop any privs out of the basic set that we won't need */
	(void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY);
	(void) priv_delset(pPrivSet, PRIV_PROC_INFO);
	(void) priv_delset(pPrivSet, PRIV_PROC_SESSION);
	(void) priv_delset(pPrivSet, PRIV_PROC_FORK);
	(void) priv_delset(pPrivSet, PRIV_PROC_EXEC);
	(void) priv_delset(pPrivSet, PRIV_FILE_WRITE);

	/* Set permitted set */
	if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
		(void) fprintf(stderr, "Unable to drop privs\n");
		exit(EXIT_FAILURE);
	}

	/* clear limit set */
	if ((lPrivSet = priv_allocset()) == NULL) {
		(void) fprintf(stderr, "Unable to allocate privset\n");
		exit(EXIT_FAILURE);
	}

	priv_emptyset(lPrivSet);

	if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) {
		(void) fprintf(stderr, "Unable to set limit set\n");
		exit(EXIT_FAILURE);
	}

	priv_freeset(lPrivSet);
	priv_freeset(pPrivSet);
}
Exemplo n.º 16
0
static int
smb_init_daemon_priv(int flags, uid_t uid, gid_t gid)
{
	priv_set_t *perm = NULL;
	int ret = -1;
	char buf[1024];

	/*
	 * This is not a significant failure: it allows us to start programs
	 * with sufficient privileges and with the proper uid.   We don't
	 * care enough about the extra groups in that case.
	 */
	if (flags & PU_RESETGROUPS)
		(void) setgroups(0, NULL);

	if (gid != (gid_t)-1 && setgid(gid) != 0)
		goto end;

	perm = priv_allocset();
	if (perm == NULL)
		goto end;

	/* E = P */
	(void) getppriv(PRIV_PERMITTED, perm);
	(void) setppriv(PRIV_SET, PRIV_EFFECTIVE, perm);

	/* Now reset suid and euid */
	if (uid != (uid_t)-1 && setreuid(uid, uid) != 0)
		goto end;

	/* I = 0 */
	priv_emptyset(perm);
	ret = setppriv(PRIV_SET, PRIV_INHERITABLE, perm);
end:
	priv_freeset(perm);

	if (core_get_process_path(buf, sizeof (buf), getpid()) == 0 &&
	    strcmp(buf, "core") == 0) {

		if ((uid == (uid_t)-1 ? geteuid() : uid) == 0) {
			(void) core_set_process_path(root_cp, sizeof (root_cp),
			    getpid());
		} else {
			(void) core_set_process_path(daemon_cp,
			    sizeof (daemon_cp), getpid());
		}
	}
	(void) setpflags(__PROC_PROTECT, 0);

	return (ret);
}
Exemplo n.º 17
0
static const char *
check_privset(const char *pset)
{
	priv_set_t *tmp;
	const char *res;

	tmp = priv_str_to_set(pset, ",", &res);

	if (tmp != NULL) {
		res = NULL;
		priv_freeset(tmp);
	} else if (res == NULL)
		res = strerror(errno);

	return (res);
}
Exemplo n.º 18
0
static void
drop_privileges ()
{
	priv_set_t *pPrivSet = NULL;
	priv_set_t *lPrivSet = NULL;

	/*
	 * Start with the 'basic' privilege set and then remove any
	 * of the 'basic' privileges that will not be needed.
	 */
	if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
		return;
	}

	/* Clear privileges we will not need from the 'basic' set */
	(void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY);
	(void) priv_delset(pPrivSet, PRIV_PROC_INFO);
	(void) priv_delset(pPrivSet, PRIV_PROC_SESSION);
	(void) priv_delset(pPrivSet, PRIV_PROC_EXEC);
	(void) priv_delset(pPrivSet, PRIV_PROC_FORK);

	/* for uscsi */
	(void) priv_addset(pPrivSet, PRIV_SYS_DEVICES);


	/* to open logindevperm'd devices */
	(void) priv_addset(pPrivSet, PRIV_FILE_DAC_READ);

	/* Set the permitted privilege set. */
	if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
		return;
	}

	/* Clear the limit set. */
	if ((lPrivSet = priv_allocset()) == NULL) {
		return;
	}

	priv_emptyset(lPrivSet);

	if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) {
		return;
	}

	priv_freeset(lPrivSet);
}
Exemplo n.º 19
0
static void
setup_privs()
{
	priv_set_t *privset;

	if (seteuid(getuid()) == -1 || setegid(getgid()) == -1)
		die(gettext("seteuid()/setegid() failed"));

	/*
	 * Add our privileges and remove unneeded 'basic' privileges from the
	 * permitted set.
	 */
	if ((privset = priv_str_to_set("basic", ",", NULL)) == NULL)
		die(gettext("cannot setup privileges"));

	(void) priv_addset(privset, PRIV_SYS_ACCT);
	(void) priv_addset(privset, PRIV_FILE_DAC_WRITE);
	(void) priv_addset(privset, PRIV_SYS_DL_CONFIG);
	(void) priv_delset(privset, PRIV_FILE_LINK_ANY);
	(void) priv_delset(privset, PRIV_PROC_EXEC);
	(void) priv_delset(privset, PRIV_PROC_FORK);
	(void) priv_delset(privset, PRIV_PROC_INFO);
	(void) priv_delset(privset, PRIV_PROC_SESSION);
	priv_inverse(privset);
	if (setppriv(PRIV_OFF, PRIV_PERMITTED, privset) == -1)
		die(gettext("cannot setup privileges"));
	priv_freeset(privset);

	/*
	 * Clear the Inheritable and Limit sets.
	 */
	if ((privset = priv_allocset()) == NULL)
		die(gettext("cannot setup privileges"));
	priv_emptyset(privset);
	if (setppriv(PRIV_SET, PRIV_INHERITABLE, privset) == -1 ||
	    setppriv(PRIV_SET, PRIV_LIMIT, privset) == -1)
		die(gettext("cannot setup privileges"));

	/*
	 * Turn off the sys_acct, file_dac_write and dl_config privileges
	 * until needed.
	 */
	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_WRITE,
	    PRIV_SYS_ACCT, PRIV_SYS_DL_CONFIG, NULL);
}
Exemplo n.º 20
0
/*
 * Check to see if the door client's euid is 0 or if it has required_priv
 * privilege. Return 0 if yes, -1 otherwise.
 * Supported values for required_priv are:
 *    - NSCD_ALL_PRIV: for all zones privileges
 *    - NSCD_READ_PRIV: for PRIV_FILE_DAC_READ privilege
 */
int
_nscd_check_client_priv(int required_priv)
{
	int			rc = 0;
	ucred_t			*uc = NULL;
	const priv_set_t	*eset;
	char			*me = "_nscd_check_client_read_priv";
	priv_set_t		*zs;	/* zone */

	if (door_ucred(&uc) != 0) {
		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "door_ucred: %s\n", strerror(errno));
		return (-1);
	}

	if (ucred_geteuid(uc) == 0) {
		ucred_free(uc);
		return (0);
	}

	eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
	switch (required_priv) {
		case NSCD_ALL_PRIV:
			zs = priv_str_to_set("zone", ",", NULL);
			if (!priv_isequalset(eset, zs)) {
				_NSCD_LOG(NSCD_LOG_FRONT_END,
				    NSCD_LOG_LEVEL_ERROR)
				(me, "missing all zones privileges\n");
				rc = -1;
			}
			priv_freeset(zs);
			break;
		case NSCD_READ_PRIV:
			if (!priv_ismember(eset, PRIV_FILE_DAC_READ))
				rc = -1;
			break;
		default:
			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
			(me, "unknown required_priv: %d\n", required_priv);
			rc = -1;
			break;
	}
	ucred_free(uc);
	return (rc);
}
Exemplo n.º 21
0
static int privileges_drop_first(apr_pool_t *pool, server_rec *s)
{
    /* We need to set privileges before mod_unixd,
     * 'cos otherwise setuid will wipe our privilege to do so
     */
    priv_cfg *spcfg;
    server_rec *sp;
    priv_set_t *ppriv = priv_allocset();

    /* compute ppriv from the union of all the vhosts plus setid */
    priv_copyset(priv_setid, ppriv);
    for (sp = s; sp != NULL; sp=sp->next) {
        spcfg = ap_get_module_config(sp->module_config, &privileges_module);
        priv_union(spcfg->priv, ppriv);
    }
    PDROP_CHECK(setppriv(PRIV_SET, PRIV_PERMITTED, ppriv))
    PDROP_CHECK(setppriv(PRIV_SET, PRIV_EFFECTIVE, ppriv))
    priv_freeset(ppriv);

    return OK;
}
Exemplo n.º 22
0
/*
 * Most privileges, except the ones that are required for smbd, are turn off
 * in the effective set.  They will be turn on when needed for command
 * execution during share connection/disconnection.
 */
static void
smbd_daemonize_fini(int fd, int exit_status)
{
	priv_set_t *pset;

	/*
	 * Now that we're running, if a pipe fd was specified, write an exit
	 * status to it to indicate that our parent process can safely detach.
	 * Then proceed to loading the remaining non-built-in modules.
	 */
	if (fd >= 0)
		(void) write(fd, &exit_status, sizeof (exit_status));

	(void) close(fd);

	pset = priv_allocset();
	if (pset == NULL)
		return;

	priv_basicset(pset);

	/* list of privileges for smbd */
	(void) priv_addset(pset, PRIV_NET_MAC_AWARE);
	(void) priv_addset(pset, PRIV_NET_PRIVADDR);
	(void) priv_addset(pset, PRIV_PROC_AUDIT);
	(void) priv_addset(pset, PRIV_SYS_DEVICES);
	(void) priv_addset(pset, PRIV_SYS_SMB);
	(void) priv_addset(pset, PRIV_SYS_MOUNT);

	priv_inverse(pset);

	/* turn off unneeded privileges */
	(void) setppriv(PRIV_OFF, PRIV_EFFECTIVE, pset);

	priv_freeset(pset);

	/* reenable core dumps */
	__fini_daemon_priv(NULL);
}
Exemplo n.º 23
0
static int drop_privs()
{
	static const char *privs[] = {
		"file_read",
		"file_write",
		"net_access",
		NULL,
	};

	priv_set_t *wanted;
	int ret;
	int i;

	wanted = priv_allocset();
	if (!wanted)
		return -errno;

	priv_emptyset(wanted);

	for (i = 0; privs[i]; i++) {
		ret = priv_addset(wanted, privs[i]);
		if (ret) {
			ret = -errno;
			goto err_free;
		}
	}

	ret = setppriv(PRIV_SET, PRIV_PERMITTED, wanted);
	if (ret == -1)
		ret = -errno;

err_free:
	priv_freeset(wanted);

	return ret;
}
void
mgt_sandbox_solaris_init(void)
{
	priv_set_t *priv_all;

	if (! (priv_all = priv_allocset())) {
		REPORT(LOG_ERR,
		    "Child start warning: mgt_sandbox_init - priv_allocset failed: errno=%d (%s)",
		    errno, strerror(errno));
		return;
	}
	
	priv_emptyset(priv_all);

	mgt_sandbox_solaris_add_effective(priv_all);
	mgt_sandbox_solaris_add_permitted(priv_all);
	mgt_sandbox_solaris_add_initial(priv_all);

	setppriv(PRIV_ON, PRIV_PERMITTED, priv_all);
	setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_all);
	setppriv(PRIV_ON, PRIV_INHERITABLE, priv_all);

	priv_freeset(priv_all);
}
Exemplo n.º 25
0
Arquivo: util.c Projeto: budisfg/spine
void checkAsRoot() {
	#ifndef __CYGWIN__
	#ifdef SOLAR_PRIV
	priv_set_t *privset;
	char *p;

	/* Get the basic set */
	privset = priv_str_to_set("basic", ",", NULL);
	if (privset == NULL) {
		die("ERROR: Could not get basic privset from priv_str_to_set().");
	} else {
		p = priv_set_to_str(privset, ',', 0);
		SPINE_LOG_DEBUG(("DEBUG: Basic privset is: '%s'.", p != NULL ? p : "Unknown"));
	}

	/* Add priviledge to send/receive ICMP packets */
	if (priv_addset(privset, PRIV_NET_ICMPACCESS) < 0 ) {
		SPINE_LOG_DEBUG(("Warning: Addition of PRIV_NET_ICMPACCESS to privset failed: '%s'.", strerror(errno)));
	}

	/* Compute the set of privileges that are never needed */
	priv_inverse(privset);

	/* Remove the set of unneeded privs from Permitted (and by
	 * implication from Effective) */
	if (setppriv(PRIV_OFF, PRIV_PERMITTED, privset) < 0) {
		SPINE_LOG_DEBUG(("Warning: Dropping privileges from PRIV_PERMITTED failed: '%s'.", strerror(errno)));
	}

	/* Remove unneeded priv set from Limit to be safe */
	if (setppriv(PRIV_OFF, PRIV_LIMIT, privset) < 0) {
		SPINE_LOG_DEBUG(("Warning: Dropping privileges from PRIV_LIMIT failed: '%s'.", strerror(errno)));
	}

	boolean_t pe = priv_ineffect(PRIV_NET_ICMPACCESS);
	SPINE_LOG_DEBUG(("DEBUG: Privilege PRIV_NET_ICMPACCESS is: '%s'.", pe != 0 ? "Enabled" : "Disabled"));

	set.icmp_avail = pe;

	/* Free the privset */
	priv_freeset(privset);
	free(p);
	#else
	if (hasCaps() != TRUE) {
		seteuid(0);
	
		if (geteuid() != 0) {
			SPINE_LOG_DEBUG(("WARNING: Spine NOT running asroot.  This is required if using ICMP.  Please run \"chmod +s;chown root:root spine\" to resolve."));
			set.icmp_avail = FALSE;
		}else{
			SPINE_LOG_DEBUG(("DEBUG: Spine is running asroot."));
			set.icmp_avail = TRUE;
			seteuid(getuid());
		}
	} else {
		SPINE_LOG_DEBUG(("DEBUG: Spine has cap_net_raw capability."));
		set.icmp_avail = TRUE;
	}
	#endif
	#endif
}
Exemplo n.º 26
0
int
ntpdmain(
	int argc,
	char *argv[]
	)
{
	l_fp		now;
	struct recvbuf *rbuf;
	const char *	logfilename;
# ifdef HAVE_UMASK
	mode_t		uv;
# endif
# if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
	uid_t		uid;
# endif
# if defined(HAVE_WORKING_FORK)
	long		wait_sync = 0;
	int		pipe_fds[2];
	int		rc;
	int		exit_code;
#  ifdef _AIX
	struct sigaction sa;
#  endif
#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
	int		fid;
#  endif
# endif	/* HAVE_WORKING_FORK*/
# ifdef SCO5_CLOCK
	int		fd;
	int		zero;
# endif

# ifdef NEED_PTHREAD_WARMUP
	my_pthread_warmup();
# endif
	
# ifdef HAVE_UMASK
	uv = umask(0);
	if (uv)
		umask(uv);
	else
		umask(022);
# endif
	saved_argc = argc;
	saved_argv = argv;
	progname = argv[0];
	initializing = TRUE;		/* mark that we are initializing */
	parse_cmdline_opts(&argc, &argv);
# ifdef DEBUG
	debug = OPT_VALUE_SET_DEBUG_LEVEL;
#  ifdef HAVE_SETLINEBUF
	setlinebuf(stdout);
#  endif
# endif

	if (HAVE_OPT(NOFORK) || HAVE_OPT(QUIT)
# ifdef DEBUG
	    || debug
# endif
	    || HAVE_OPT(SAVECONFIGQUIT))
		nofork = TRUE;

	init_logging(progname, NLOG_SYNCMASK, TRUE);
	/* honor -l/--logfile option to log to a file */
	if (HAVE_OPT(LOGFILE)) {
		logfilename = OPT_ARG(LOGFILE);
		syslogit = FALSE;
		change_logfile(logfilename, FALSE);
	} else {
		logfilename = NULL;
		if (nofork)
			msyslog_term = TRUE;
		if (HAVE_OPT(SAVECONFIGQUIT))
			syslogit = FALSE;
	}
	msyslog(LOG_NOTICE, "%s: Starting", Version);

	{
		int i;
		char buf[1024];	/* Secret knowledge of msyslog buf length */
		char *cp = buf;

		/* Note that every arg has an initial space character */
		snprintf(cp, sizeof(buf), "Command line:");
		cp += strlen(cp);

		for (i = 0; i < saved_argc ; ++i) {
			snprintf(cp, sizeof(buf) - (cp - buf),
				" %s", saved_argv[i]);
			cp += strlen(cp);
		}
		msyslog(LOG_INFO, "%s", buf);
	}

	/*
	 * Install trap handlers to log errors and assertion failures.
	 * Default handlers print to stderr which doesn't work if detached.
	 */
	isc_assertion_setcallback(assertion_failed);
	isc_error_setfatal(library_fatal_error);
	isc_error_setunexpected(library_unexpected_error);

	/* MPE lacks the concept of root */
# if defined(HAVE_GETUID) && !defined(MPE)
	uid = getuid();
	if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
		msyslog_term = TRUE;
		msyslog(LOG_ERR,
			"must be run as root, not uid %ld", (long)uid);
		exit(1);
	}
# endif

/*
 * Enable the Multi-Media Timer for Windows?
 */
# ifdef SYS_WINNT
	if (HAVE_OPT( MODIFYMMTIMER ))
		set_mm_timer(MM_TIMER_HIRES);
# endif

#ifdef HAVE_DNSREGISTRATION
/*
 * Enable mDNS registrations?
 */
	if (HAVE_OPT( MDNS )) {
		mdnsreg = TRUE;
	}
#endif  /* HAVE_DNSREGISTRATION */

	if (HAVE_OPT( NOVIRTUALIPS ))
		listen_to_virtual_ips = 0;

	/*
	 * --interface, listen on specified interfaces
	 */
	if (HAVE_OPT( INTERFACE )) {
		int		ifacect = STACKCT_OPT( INTERFACE );
		const char**	ifaces  = STACKLST_OPT( INTERFACE );
		sockaddr_u	addr;

		while (ifacect-- > 0) {
			add_nic_rule(
				is_ip_address(*ifaces, AF_UNSPEC, &addr)
					? MATCH_IFADDR
					: MATCH_IFNAME,
				*ifaces, -1, ACTION_LISTEN);
			ifaces++;
		}
	}

	if (HAVE_OPT( NICE ))
		priority_done = 0;

# ifdef HAVE_SCHED_SETSCHEDULER
	if (HAVE_OPT( PRIORITY )) {
		config_priority = OPT_VALUE_PRIORITY;
		config_priority_override = 1;
		priority_done = 0;
	}
# endif

# ifdef HAVE_WORKING_FORK
	/* make sure the FDs are initialised */
	pipe_fds[0] = -1;
	pipe_fds[1] = -1;
	do {					/* 'loop' once */
		if (!HAVE_OPT( WAIT_SYNC ))
			break;
		wait_sync = OPT_VALUE_WAIT_SYNC;
		if (wait_sync <= 0) {
			wait_sync = 0;
			break;
		}
		/* -w requires a fork() even with debug > 0 */
		nofork = FALSE;
		if (pipe(pipe_fds)) {
			exit_code = (errno) ? errno : -1;
			msyslog(LOG_ERR,
				"Pipe creation failed for --wait-sync: %m");
			exit(exit_code);
		}
		waitsync_fd_to_close = pipe_fds[1];
	} while (0);				/* 'loop' once */
# endif	/* HAVE_WORKING_FORK */

	init_lib();
# ifdef SYS_WINNT
	/*
	 * Start interpolation thread, must occur before first
	 * get_systime()
	 */
	init_winnt_time();
# endif
	/*
	 * Initialize random generator and public key pair
	 */
	get_systime(&now);

	ntp_srandom((int)(now.l_i * now.l_uf));

	/*
	 * Detach us from the terminal.  May need an #ifndef GIZMO.
	 */
	if (!nofork) {

# ifdef HAVE_WORKING_FORK
		rc = fork();
		if (-1 == rc) {
			exit_code = (errno) ? errno : -1;
			msyslog(LOG_ERR, "fork: %m");
			exit(exit_code);
		}
		if (rc > 0) {	
			/* parent */
			exit_code = wait_child_sync_if(pipe_fds[0],
						       wait_sync);
			exit(exit_code);
		}
		
		/*
		 * child/daemon 
		 * close all open files excepting waitsync_fd_to_close.
		 * msyslog() unreliable until after init_logging().
		 */
		closelog();
		if (syslog_file != NULL) {
			fclose(syslog_file);
			syslog_file = NULL;
			syslogit = TRUE;
		}
		close_all_except(waitsync_fd_to_close);
		INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \
			&& 2 == dup2(0, 2));

		init_logging(progname, 0, TRUE);
		/* we lost our logfile (if any) daemonizing */
		setup_logfile(logfilename);

#  ifdef SYS_DOMAINOS
		{
			uid_$t puid;
			status_$t st;

			proc2_$who_am_i(&puid);
			proc2_$make_server(&puid, &st);
		}
#  endif	/* SYS_DOMAINOS */
#  ifdef HAVE_SETSID
		if (setsid() == (pid_t)-1)
			msyslog(LOG_ERR, "setsid(): %m");
#  elif defined(HAVE_SETPGID)
		if (setpgid(0, 0) == -1)
			msyslog(LOG_ERR, "setpgid(): %m");
#  else		/* !HAVE_SETSID && !HAVE_SETPGID follows */
#   ifdef TIOCNOTTY
		fid = open("/dev/tty", 2);
		if (fid >= 0) {
			ioctl(fid, (u_long)TIOCNOTTY, NULL);
			close(fid);
		}
#   endif	/* TIOCNOTTY */
		ntp_setpgrp(0, getpid());
#  endif	/* !HAVE_SETSID && !HAVE_SETPGID */
#  ifdef _AIX
		/* Don't get killed by low-on-memory signal. */
		sa.sa_handler = catch_danger;
		sigemptyset(&sa.sa_mask);
		sa.sa_flags = SA_RESTART;
		sigaction(SIGDANGER, &sa, NULL);
#  endif	/* _AIX */
# endif		/* HAVE_WORKING_FORK */
	}

# ifdef SCO5_CLOCK
	/*
	 * SCO OpenServer's system clock offers much more precise timekeeping
	 * on the base CPU than the other CPUs (for multiprocessor systems),
	 * so we must lock to the base CPU.
	 */
	fd = open("/dev/at1", O_RDONLY);		
	if (fd >= 0) {
		zero = 0;
		if (ioctl(fd, ACPU_LOCK, &zero) < 0)
			msyslog(LOG_ERR, "cannot lock to base CPU: %m");
		close(fd);
	}
# endif

	/* Setup stack size in preparation for locking pages in memory. */
# if defined(HAVE_MLOCKALL)
#  ifdef HAVE_SETRLIMIT
	ntp_rlimit(RLIMIT_STACK, DFLT_RLIMIT_STACK * 4096, 4096, "4k");
#   ifdef RLIMIT_MEMLOCK
	/*
	 * The default RLIMIT_MEMLOCK is very low on Linux systems.
	 * Unless we increase this limit malloc calls are likely to
	 * fail if we drop root privilege.  To be useful the value
	 * has to be larger than the largest ntpd resident set size.
	 */
	ntp_rlimit(RLIMIT_MEMLOCK, DFLT_RLIMIT_MEMLOCK * 1024 * 1024, 1024 * 1024, "MB");
#   endif	/* RLIMIT_MEMLOCK */
#  endif	/* HAVE_SETRLIMIT */
# else	/* !HAVE_MLOCKALL follows */
#  ifdef HAVE_PLOCK
#   ifdef PROCLOCK
#    ifdef _AIX
	/*
	 * set the stack limit for AIX for plock().
	 * see get_aix_stack() for more info.
	 */
	if (ulimit(SET_STACKLIM, (get_aix_stack() - 8 * 4096)) < 0)
		msyslog(LOG_ERR,
			"Cannot adjust stack limit for plock: %m");
#    endif	/* _AIX */
#   endif	/* PROCLOCK */
#  endif	/* HAVE_PLOCK */
# endif	/* !HAVE_MLOCKALL */

	/*
	 * Set up signals we pay attention to locally.
	 */
# ifdef SIGDIE1
	signal_no_reset(SIGDIE1, finish);
	signal_no_reset(SIGDIE2, finish);
	signal_no_reset(SIGDIE3, finish);
	signal_no_reset(SIGDIE4, finish);
# endif
# ifdef SIGBUS
	signal_no_reset(SIGBUS, finish);
# endif

# if !defined(SYS_WINNT) && !defined(VMS)
#  ifdef DEBUG
	(void) signal_no_reset(MOREDEBUGSIG, moredebug);
	(void) signal_no_reset(LESSDEBUGSIG, lessdebug);
#  else
	(void) signal_no_reset(MOREDEBUGSIG, no_debug);
	(void) signal_no_reset(LESSDEBUGSIG, no_debug);
#  endif	/* DEBUG */
# endif	/* !SYS_WINNT && !VMS */

	/*
	 * Set up signals we should never pay attention to.
	 */
# ifdef SIGPIPE
	signal_no_reset(SIGPIPE, SIG_IGN);
# endif

	/*
	 * Call the init_ routines to initialize the data structures.
	 *
	 * Exactly what command-line options are we expecting here?
	 */
	INIT_SSL();
	init_auth();
	init_util();
	init_restrict();
	init_mon();
	init_timer();
	init_request();
	init_control();
	init_peer();
# ifdef REFCLOCK
	init_refclock();
# endif
	set_process_priority();
	init_proto();		/* Call at high priority */
	init_io();
	init_loopfilter();
	mon_start(MON_ON);	/* monitor on by default now	  */
				/* turn off in config if unwanted */

	/*
	 * Get the configuration.  This is done in a separate module
	 * since this will definitely be different for the gizmo board.
	 */
	getconfig(argc, argv);

	if (-1 == cur_memlock) {
# if defined(HAVE_MLOCKALL)
		/*
		 * lock the process into memory
		 */
		if (   !HAVE_OPT(SAVECONFIGQUIT)
#  ifdef RLIMIT_MEMLOCK
		    && -1 != DFLT_RLIMIT_MEMLOCK
#  endif
		    && 0 != mlockall(MCL_CURRENT|MCL_FUTURE))
			msyslog(LOG_ERR, "mlockall(): %m");
# else	/* !HAVE_MLOCKALL follows */
#  ifdef HAVE_PLOCK
#   ifdef PROCLOCK
		/*
		 * lock the process into memory
		 */
		if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(PROCLOCK))
			msyslog(LOG_ERR, "plock(PROCLOCK): %m");
#   else	/* !PROCLOCK follows  */
#    ifdef TXTLOCK
		/*
		 * Lock text into ram
		 */
		if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(TXTLOCK))
			msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
#    else	/* !TXTLOCK follows */
		msyslog(LOG_ERR, "plock() - don't know what to lock!");
#    endif	/* !TXTLOCK */
#   endif	/* !PROCLOCK */
#  endif	/* HAVE_PLOCK */
# endif	/* !HAVE_MLOCKALL */
	}

	loop_config(LOOP_DRIFTINIT, 0);
	report_event(EVNT_SYSRESTART, NULL, NULL);
	initializing = FALSE;

# ifdef HAVE_DROPROOT
	if (droproot) {
		/* Drop super-user privileges and chroot now if the OS supports this */

#  ifdef HAVE_LINUX_CAPABILITIES
		/* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
		if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) {
			msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
			exit(-1);
		}
#  elif HAVE_SOLARIS_PRIVS
		/* Nothing to do here */
#  else
		/* we need a user to switch to */
		if (user == NULL) {
			msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
			exit(-1);
		}
#  endif	/* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */

		if (user != NULL) {
			if (isdigit((unsigned char)*user)) {
				sw_uid = (uid_t)strtoul(user, &endp, 0);
				if (*endp != '\0')
					goto getuser;

				if ((pw = getpwuid(sw_uid)) != NULL) {
					free(user);
					user = estrdup(pw->pw_name);
					sw_gid = pw->pw_gid;
				} else {
					errno = 0;
					msyslog(LOG_ERR, "Cannot find user ID %s", user);
					exit (-1);
				}

			} else {
getuser:
				errno = 0;
				if ((pw = getpwnam(user)) != NULL) {
					sw_uid = pw->pw_uid;
					sw_gid = pw->pw_gid;
				} else {
					if (errno)
						msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
					else
						msyslog(LOG_ERR, "Cannot find user `%s'", user);
					exit (-1);
				}
			}
		}
		if (group != NULL) {
			if (isdigit((unsigned char)*group)) {
				sw_gid = (gid_t)strtoul(group, &endp, 0);
				if (*endp != '\0')
					goto getgroup;
			} else {
getgroup:
				if ((gr = getgrnam(group)) != NULL) {
					sw_gid = gr->gr_gid;
				} else {
					errno = 0;
					msyslog(LOG_ERR, "Cannot find group `%s'", group);
					exit (-1);
				}
			}
		}

		if (chrootdir ) {
			/* make sure cwd is inside the jail: */
			if (chdir(chrootdir)) {
				msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
				exit (-1);
			}
			if (chroot(chrootdir)) {
				msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
				exit (-1);
			}
			if (chdir("/")) {
				msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m");
				exit (-1);
			}
		}
#  ifdef HAVE_SOLARIS_PRIVS
		if ((lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) {
			msyslog(LOG_ERR, "priv_str_to_set() failed:%m");
			exit(-1);
		}
		if ((highprivs = priv_allocset()) == NULL) {
			msyslog(LOG_ERR, "priv_allocset() failed:%m");
			exit(-1);
		}
		(void) getppriv(PRIV_PERMITTED, highprivs);
		(void) priv_intersect(highprivs, lowprivs);
		if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) {
			msyslog(LOG_ERR, "setppriv() failed:%m");
			exit(-1);
		}
#  endif /* HAVE_SOLARIS_PRIVS */
		if (user && initgroups(user, sw_gid)) {
			msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
			exit (-1);
		}
		if (group && setgid(sw_gid)) {
			msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
			exit (-1);
		}
		if (group && setegid(sw_gid)) {
			msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
			exit (-1);
		}
		if (group) {
			if (0 != setgroups(1, &sw_gid)) {
				msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid);
				exit (-1);
			}
		}
		else if (pw)
			if (0 != initgroups(pw->pw_name, pw->pw_gid)) {
				msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid);
				exit (-1);
			}
		if (user && setuid(sw_uid)) {
			msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
			exit (-1);
		}
		if (user && seteuid(sw_uid)) {
			msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
			exit (-1);
		}

#  if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS)
		/*
		 * for now assume that the privilege to bind to privileged ports
		 * is associated with running with uid 0 - should be refined on
		 * ports that allow binding to NTP_PORT with uid != 0
		 */
		disable_dynamic_updates |= (sw_uid != 0);  /* also notifies routing message listener */
#  endif /* !HAVE_LINUX_CAPABILITIES && !HAVE_SOLARIS_PRIVS */

		if (disable_dynamic_updates && interface_interval) {
			interface_interval = 0;
			msyslog(LOG_INFO, "running as non-root disables dynamic interface tracking");
		}

#  ifdef HAVE_LINUX_CAPABILITIES
		{
			/*
			 *  We may be running under non-root uid now, but we still hold full root privileges!
			 *  We drop all of them, except for the crucial one or two: cap_sys_time and
			 *  cap_net_bind_service if doing dynamic interface tracking.
			 */
			cap_t caps;
			char *captext;
			
			captext = (0 != interface_interval)
				      ? "cap_sys_time,cap_net_bind_service=pe"
				      : "cap_sys_time=pe";
			caps = cap_from_text(captext);
			if (!caps) {
				msyslog(LOG_ERR,
					"cap_from_text(%s) failed: %m",
					captext);
				exit(-1);
			}
			if (-1 == cap_set_proc(caps)) {
				msyslog(LOG_ERR,
					"cap_set_proc() failed to drop root privs: %m");
				exit(-1);
			}
			cap_free(caps);
		}
#  endif	/* HAVE_LINUX_CAPABILITIES */
#  ifdef HAVE_SOLARIS_PRIVS
		if (priv_delset(lowprivs, "proc_setid") == -1) {
			msyslog(LOG_ERR, "priv_delset() failed:%m");
			exit(-1);
		}
		if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) {
			msyslog(LOG_ERR, "setppriv() failed:%m");
			exit(-1);
		}
		priv_freeset(lowprivs);
		priv_freeset(highprivs);
#  endif /* HAVE_SOLARIS_PRIVS */
		root_dropped = TRUE;
		fork_deferred_worker();
	}	/* if (droproot) */
# endif	/* HAVE_DROPROOT */

/* libssecomp sandboxing */
#if defined (LIBSECCOMP) && (KERN_SECCOMP)
	scmp_filter_ctx ctx;

	if ((ctx = seccomp_init(SCMP_ACT_KILL)) < 0)
		msyslog(LOG_ERR, "%s: seccomp_init(SCMP_ACT_KILL) failed: %m", __func__);
	else {
		msyslog(LOG_DEBUG, "%s: seccomp_init(SCMP_ACT_KILL) succeeded", __func__);
	}

#ifdef __x86_64__
int scmp_sc[] = {
	SCMP_SYS(adjtimex),
	SCMP_SYS(bind),
	SCMP_SYS(brk),
	SCMP_SYS(chdir),
	SCMP_SYS(clock_gettime),
	SCMP_SYS(clock_settime),
	SCMP_SYS(close),
	SCMP_SYS(connect),
	SCMP_SYS(exit_group),
	SCMP_SYS(fstat),
	SCMP_SYS(fsync),
	SCMP_SYS(futex),
	SCMP_SYS(getitimer),
	SCMP_SYS(getsockname),
	SCMP_SYS(ioctl),
	SCMP_SYS(lseek),
	SCMP_SYS(madvise),
	SCMP_SYS(mmap),
	SCMP_SYS(munmap),
	SCMP_SYS(open),
	SCMP_SYS(poll),
	SCMP_SYS(read),
	SCMP_SYS(recvmsg),
	SCMP_SYS(rename),
	SCMP_SYS(rt_sigaction),
	SCMP_SYS(rt_sigprocmask),
	SCMP_SYS(rt_sigreturn),
	SCMP_SYS(select),
	SCMP_SYS(sendto),
	SCMP_SYS(setitimer),
	SCMP_SYS(setsid),
	SCMP_SYS(socket),
	SCMP_SYS(stat),
	SCMP_SYS(time),
	SCMP_SYS(write),
};
#endif
#ifdef __i386__
int scmp_sc[] = {
	SCMP_SYS(_newselect),
	SCMP_SYS(adjtimex),
	SCMP_SYS(brk),
	SCMP_SYS(chdir),
	SCMP_SYS(clock_gettime),
	SCMP_SYS(clock_settime),
	SCMP_SYS(close),
	SCMP_SYS(exit_group),
	SCMP_SYS(fsync),
	SCMP_SYS(futex),
	SCMP_SYS(getitimer),
	SCMP_SYS(madvise),
	SCMP_SYS(mmap),
	SCMP_SYS(mmap2),
	SCMP_SYS(munmap),
	SCMP_SYS(open),
	SCMP_SYS(poll),
	SCMP_SYS(read),
	SCMP_SYS(rename),
	SCMP_SYS(rt_sigaction),
	SCMP_SYS(rt_sigprocmask),
	SCMP_SYS(select),
	SCMP_SYS(setitimer),
	SCMP_SYS(setsid),
	SCMP_SYS(sigprocmask),
	SCMP_SYS(sigreturn),
	SCMP_SYS(socketcall),
	SCMP_SYS(stat64),
	SCMP_SYS(time),
	SCMP_SYS(write),
};
#endif
	{
		int i;

		for (i = 0; i < COUNTOF(scmp_sc); i++) {
			if (seccomp_rule_add(ctx,
			    SCMP_ACT_ALLOW, scmp_sc[i], 0) < 0) {
				msyslog(LOG_ERR,
				    "%s: seccomp_rule_add() failed: %m",
				    __func__);
			}
		}
	}

	if (seccomp_load(ctx) < 0)
		msyslog(LOG_ERR, "%s: seccomp_load() failed: %m",
		    __func__);	
	else {
		msyslog(LOG_DEBUG, "%s: seccomp_load() succeeded", __func__);
	}
#endif /* LIBSECCOMP and KERN_SECCOMP */

# ifdef HAVE_IO_COMPLETION_PORT

	for (;;) {
		GetReceivedBuffers();
# else /* normal I/O */

	BLOCK_IO_AND_ALARM();
	was_alarmed = FALSE;

	for (;;) {
		if (alarm_flag) {	/* alarmed? */
			was_alarmed = TRUE;
			alarm_flag = FALSE;
		}

		if (!was_alarmed && !has_full_recv_buffer()) {
			/*
			 * Nothing to do.  Wait for something.
			 */
			io_handler();
		}

		if (alarm_flag) {	/* alarmed? */
			was_alarmed = TRUE;
			alarm_flag = FALSE;
		}

		if (was_alarmed) {
			UNBLOCK_IO_AND_ALARM();
			/*
			 * Out here, signals are unblocked.  Call timer routine
			 * to process expiry.
			 */
			timer();
			was_alarmed = FALSE;
			BLOCK_IO_AND_ALARM();
		}

# endif		/* !HAVE_IO_COMPLETION_PORT */

# ifdef DEBUG_TIMING
		{
			l_fp pts;
			l_fp tsa, tsb;
			int bufcount = 0;

			get_systime(&pts);
			tsa = pts;
# endif
			rbuf = get_full_recv_buffer();
			while (rbuf != NULL) {
				if (alarm_flag) {
					was_alarmed = TRUE;
					alarm_flag = FALSE;
				}
				UNBLOCK_IO_AND_ALARM();

				if (was_alarmed) {
					/* avoid timer starvation during lengthy I/O handling */
					timer();
					was_alarmed = FALSE;
				}

				/*
				 * Call the data procedure to handle each received
				 * packet.
				 */
				if (rbuf->receiver != NULL) {
# ifdef DEBUG_TIMING
					l_fp dts = pts;

					L_SUB(&dts, &rbuf->recv_time);
					DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
					collect_timing(rbuf, "buffer processing delay", 1, &dts);
					bufcount++;
# endif
					(*rbuf->receiver)(rbuf);
				} else {
					msyslog(LOG_ERR, "fatal: receive buffer callback NULL");
					abort();
				}

				BLOCK_IO_AND_ALARM();
				freerecvbuf(rbuf);
				rbuf = get_full_recv_buffer();
			}
# ifdef DEBUG_TIMING
			get_systime(&tsb);
			L_SUB(&tsb, &tsa);
			if (bufcount) {
				collect_timing(NULL, "processing", bufcount, &tsb);
				DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
			}
		}
# endif

		/*
		 * Go around again
		 */

# ifdef HAVE_DNSREGISTRATION
		if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) {
			mdnsreg = current_time;
			msyslog(LOG_INFO, "Attempting to register mDNS");
			if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, 
			    htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
				if (!--mdnstries) {
					msyslog(LOG_ERR, "Unable to register mDNS, giving up.");
				} else {	
					msyslog(LOG_INFO, "Unable to register mDNS, will try later.");
				}
			} else {
				msyslog(LOG_INFO, "mDNS service registered.");
				mdnsreg = FALSE;
			}
		}
# endif /* HAVE_DNSREGISTRATION */

	}
	UNBLOCK_IO_AND_ALARM();
	return 1;
}
#endif	/* !SIM */


#if !defined(SIM) && defined(SIGDIE1)
/*
 * finish - exit gracefully
 */
static RETSIGTYPE
finish(
	int sig
	)
{
	const char *sig_desc;

	sig_desc = NULL;
#ifdef HAVE_STRSIGNAL
	sig_desc = strsignal(sig);
#endif
	if (sig_desc == NULL)
		sig_desc = "";
	msyslog(LOG_NOTICE, "%s exiting on signal %d (%s)", progname,
		sig, sig_desc);
	/* See Bug 2513 and Bug 2522 re the unlink of PIDFILE */
# ifdef HAVE_DNSREGISTRATION
	if (mdns != NULL)
		DNSServiceRefDeallocate(mdns);
# endif
	peer_cleanup();
	exit(0);
}
#endif	/* !SIM && SIGDIE1 */


#ifndef SIM
/*
 * wait_child_sync_if - implements parent side of -w/--wait-sync
 */
# ifdef HAVE_WORKING_FORK
static int
wait_child_sync_if(
	int	pipe_read_fd,
	long	wait_sync
	)
{
	int	rc;
	int	exit_code;
	time_t	wait_end_time;
	time_t	cur_time;
	time_t	wait_rem;
	fd_set	readset;
	struct timeval wtimeout;

	if (0 == wait_sync) 
		return 0;

	/* waitsync_fd_to_close used solely by child */
	close(waitsync_fd_to_close);
	wait_end_time = time(NULL) + wait_sync;
	do {
		cur_time = time(NULL);
		wait_rem = (wait_end_time > cur_time)
				? (wait_end_time - cur_time)
				: 0;
		wtimeout.tv_sec = wait_rem;
		wtimeout.tv_usec = 0;
		FD_ZERO(&readset);
		FD_SET(pipe_read_fd, &readset);
		rc = select(pipe_read_fd + 1, &readset, NULL, NULL,
			    &wtimeout);
		if (-1 == rc) {
			if (EINTR == errno)
				continue;
			exit_code = (errno) ? errno : -1;
			msyslog(LOG_ERR,
				"--wait-sync select failed: %m");
			return exit_code;
		}
		if (0 == rc) {
			/*
			 * select() indicated a timeout, but in case
			 * its timeouts are affected by a step of the
			 * system clock, select() again with a zero 
			 * timeout to confirm.
			 */
			FD_ZERO(&readset);
			FD_SET(pipe_read_fd, &readset);
			wtimeout.tv_sec = 0;
			wtimeout.tv_usec = 0;
			rc = select(pipe_read_fd + 1, &readset, NULL,
				    NULL, &wtimeout);
			if (0 == rc)	/* select() timeout */
				break;
			else		/* readable */
				return 0;
		} else			/* readable */
			return 0;
	} while (wait_rem > 0);

	fprintf(stderr, "%s: -w/--wait-sync %ld timed out.\n",
		progname, wait_sync);
	return ETIMEDOUT;
}
Exemplo n.º 27
0
/**
 * Grabs extra non-root capabilities / privileges that we might require.
 *
 * This is currently only used for being able to do ICMP from the NAT engine.
 *
 * @note We still have root privileges at the time of this call.
 */
static void supR3HardenedMainGrabCapabilites(void)
{
# if defined(RT_OS_LINUX)
    /*
     * We are about to drop all our privileges. Remove all capabilities but
     * keep the cap_net_raw capability for ICMP sockets for the NAT stack.
     */
    if (g_uCaps != 0)
    {
#  ifdef USE_LIB_PCAP
        /* XXX cap_net_bind_service */
        if (!cap_set_proc(cap_from_text("all-eip cap_net_raw+ep")))
            prctl(PR_SET_KEEPCAPS, 1 /*keep=*/, 0, 0, 0);
        prctl(PR_SET_DUMPABLE, 1 /*dump*/, 0, 0, 0);
#  else
        cap_user_header_t hdr = (cap_user_header_t)alloca(sizeof(*hdr));
        cap_user_data_t   cap = (cap_user_data_t)alloca(sizeof(*cap));
        memset(hdr, 0, sizeof(*hdr));
        hdr->version = _LINUX_CAPABILITY_VERSION;
        memset(cap, 0, sizeof(*cap));
        cap->effective = g_uCaps;
        cap->permitted = g_uCaps;
        if (!capset(hdr, cap))
            prctl(PR_SET_KEEPCAPS, 1 /*keep*/, 0, 0, 0);
        prctl(PR_SET_DUMPABLE, 1 /*dump*/, 0, 0, 0);
#  endif /* !USE_LIB_PCAP */
    }

# elif defined(RT_OS_SOLARIS)
    /*
     * Add net_icmpaccess privilege to effective privileges and limit
     * permitted privileges before completely dropping root privileges.
     * This requires dropping root privileges temporarily to get the normal
     * user's privileges.
     */
    seteuid(g_uid);
    priv_set_t *pPrivEffective = priv_allocset();
    priv_set_t *pPrivNew = priv_allocset();
    if (pPrivEffective && pPrivNew)
    {
        int rc = getppriv(PRIV_EFFECTIVE, pPrivEffective);
        seteuid(0);
        if (!rc)
        {
            priv_copyset(pPrivEffective, pPrivNew);
            rc = priv_addset(pPrivNew, PRIV_NET_ICMPACCESS);
            if (!rc)
            {
                /* Order is important, as one can't set a privilege which is
                 * not in the permitted privilege set. */
                rc = setppriv(PRIV_SET, PRIV_EFFECTIVE, pPrivNew);
                if (rc)
                    supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to set effective privilege set.\n");
                rc = setppriv(PRIV_SET, PRIV_PERMITTED, pPrivNew);
                if (rc)
                    supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to set permitted privilege set.\n");
            }
            else
                supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to add NET_ICMPACCESS privilege.\n");
        }
    }
    else
    {
        /* for memory allocation failures just continue */
        seteuid(0);
    }

    if (pPrivEffective)
        priv_freeset(pPrivEffective);
    if (pPrivNew)
        priv_freeset(pPrivNew);
# endif
}
Exemplo n.º 28
0
/* Specify what privileges an suid root binary needs.  */
int __init_suid_priv (int flags, ...)
{
  int res = 0;
  priv_set_t *permit = NULL, *inherit = NULL, *scratch = NULL;

  /* Check flags.  */
  if (flags != PU_LIMITPRIVS && flags != PU_CLEARLIMITSET)
    return -1;

  /* We can only initialize once.  */
  if (__suidset)
    return -1;

  /* Do nothing if we are running as root but not setuid root.  */
  uid_t uid = getuid ();
  uid_t euid = geteuid ();
  if (uid == 0 && euid == 0)
    return 0;

  /* Allocate a scratch set.  */
  scratch = priv_allocset ();
  if (!scratch)
    goto error;

  /* Get the basic set.  */
  const priv_data_t *pd = __priv_parse_data_cached ();
  if (!pd)
    goto error;
  priv_set_t *basic = pd->pd_basicprivs;

  /* Get the inherited set.  */
  inherit = priv_allocset ();
  if (!inherit)
    goto error;
  if (getppriv (PRIV_INHERITABLE, inherit) != 0)
    goto error;

  /* Get the permitted set.  */
  permit = priv_allocset ();
  if (!permit)
    goto error;
  if (getppriv (PRIV_PERMITTED, permit) != 0)
    goto error;

  /* Get passed privileges.  */
  __suidset = priv_allocset ();
  if (!__suidset)
    goto error;
  priv_emptyset (__suidset);
  va_list ap;
  va_start (ap, flags);
  const char *priv;
  while ((priv = va_arg (ap, const char *)))
    if (priv_addset (__suidset, priv) != 0)
      goto error;

  /* Make sure that the passed privileges are a subset of the current
     permitted privileges.  */
  if (priv_issubset (__suidset, permit) != _B_TRUE)
    goto error;

  /* Set the effective privileges to the inherited ones.  */
  if (setppriv (PRIV_SET, PRIV_EFFECTIVE, inherit) != 0)
    goto error;

  /* Set the permitted privileges to those currently permitted privileges in
     set of the ones passed in, the inherited ones, and the basic set.  */
  priv_copyset (__suidset, scratch);
  priv_union (inherit, scratch);
  if (basic)
    priv_union (basic, scratch);
  priv_intersect (permit, scratch);
  if (setppriv (PRIV_SET, PRIV_PERMITTED, scratch) != 0)
    goto error;

  /* Check if we need to set the limit set.  */
  if (flags & PU_CLEARLIMITSET)
    {
      priv_emptyset (scratch);
      if (setppriv (PRIV_SET, PRIV_LIMIT, scratch) != 0)
        goto error;
    }
  else if (flags & PU_LIMITPRIVS)
    {
      if (setppriv (PRIV_SET, PRIV_LIMIT, scratch) != 0)
        goto error;
    }

  /* Change the uid to the caller's uid if we're setuid root.  */
  if (euid == 0 && setreuid (uid, uid) != 0)
    goto error;

  goto out;

error:
  res = -1;
  if (__suidset)
    {
      priv_freeset (__suidset);
      __suidset = NULL;
    }
  if (euid == 0)
    setreuid (uid, uid);

out:
  priv_freeset (permit);
  priv_freeset (inherit);
  priv_freeset (scratch);

  return res;
}
Exemplo n.º 29
0
priv_set_t *priv_str_to_set (const char *buf, const char *sep,
      const char **endptr)
{
  /* Take a copy of the string since strtok_r will modify it.  */
  char *str = strdup (buf);
  if (!str)
    return NULL;

  priv_set_t *set = priv_allocset ();
  if (!set)
    {
      free (str);
      return NULL;
    }
  priv_emptyset (set);
  const priv_data_t *data = __priv_parse_data_cached ();
  if (!data)
    return NULL;
  priv_set_t *basic = data->pd_basicprivs;

  char *saveptr;
  char *priv = strtok_r (str, sep, &saveptr);
  if (!priv)
    return set;
  do
    {
      if (strcmp (priv, "basic") == 0 && basic)
          priv_union (basic, set);
      else if (strcmp (priv, "all") == 0)
          priv_fillset (set);
      else if (strcmp (priv, "none") == 0)
          priv_emptyset (set);
      else if (strcmp (priv, "zone") == 0)
        {
          priv_set_t *zone = priv_allocset ();
          if (!zone)
            goto inval;
          if (zone_getattr (getzoneid (), ZONE_ATTR_PRIVSET,
                zone, __PRIVSETSIZE) == 0)
            priv_union (zone, set);
          priv_freeset (zone);
        }
      else
        {
          int negate = *str == '-' || *str == '!';
          if (negate)
            str++;

          int res;
          if (negate)
            res = priv_delset (set, str);
          else
            res = priv_addset (set, str);
          if (res == -1)
            goto inval;
        }
    }
  while ((priv = strtok_r (NULL, sep, &saveptr))) ;

  free (str);
  return set;

inval:

   priv_freeset (set);
   free (str);
   __set_errno (EINVAL);
  return NULL;
}
Exemplo n.º 30
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);
}