Ejemplo n.º 1
0
/*
 * Initialize the device policy code
 */
void
devpolicy_init(void)
{
	rw_init(&policyrw, NULL, RW_DRIVER, NULL);
	mutex_init(&policymutex, NULL, MUTEX_DRIVER, NULL);

	/* The mutex is held here in order to satisfy the ASSERT in dpget() */
	mutex_enter(&policymutex);

	nullpolicy = dpget();
	dfltpolicy = dpget();
	netpolicy = dpget();

	/*
	 * Initially, we refuse access to all devices except
	 * to processes with all privileges.
	 */
	priv_fillset(&dfltpolicy->dp_rdp);
	priv_fillset(&dfltpolicy->dp_wrp);

	totitems = 1;

	devplcy_gen++;
	mutex_exit(&policymutex);

	/* initialize default network privilege */
	priv_emptyset(&netpolicy->dp_rdp);
	priv_emptyset(&netpolicy->dp_wrp);
	priv_addset(&netpolicy->dp_rdp, PRIV_NET_RAWACCESS);
	priv_addset(&netpolicy->dp_wrp, PRIV_NET_RAWACCESS);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
static int privileges_postconf(apr_pool_t *pconf, apr_pool_t *plog,
                               apr_pool_t *ptemp, server_rec *s)
{
    priv_cfg *cfg;
    server_rec *sp;

    /* if we have dtrace enabled, merge it into everything */
    if (dtrace_enabled) {
        for (sp = s; sp != NULL; sp = sp->next) {
            cfg = ap_get_module_config(sp->module_config, &privileges_module);
            CR_CHECK(priv_addset(cfg->priv, PRIV_DTRACE_KERNEL), APLOGNO(03168));
            CR_CHECK(priv_addset(cfg->priv, PRIV_DTRACE_PROC), APLOGNO(03169));
            CR_CHECK(priv_addset(cfg->priv, PRIV_DTRACE_USER), APLOGNO(03170));
            CR_CHECK(priv_addset(cfg->child_priv, PRIV_DTRACE_KERNEL), APLOGNO(03171));
            CR_CHECK(priv_addset(cfg->child_priv, PRIV_DTRACE_PROC), APLOGNO(03172));
            CR_CHECK(priv_addset(cfg->child_priv, PRIV_DTRACE_USER), APLOGNO(03173));
        }
        CR_CHECK(priv_addset(priv_default, PRIV_DTRACE_KERNEL), APLOGNO(03174));
        CR_CHECK(priv_addset(priv_default, PRIV_DTRACE_PROC), APLOGNO(03175));
        CR_CHECK(priv_addset(priv_default, PRIV_DTRACE_USER), APLOGNO(03176));
    }

    /* set up priv_setid for per-request use */
    priv_setid = priv_allocset();
    apr_pool_cleanup_register(pconf, NULL, privileges_term,
                              apr_pool_cleanup_null);
    priv_emptyset(priv_setid);
    if (priv_addset(priv_setid, PRIV_PROC_SETID) == -1) {
        ap_log_perror(APLOG_MARK, APLOG_CRIT, errno, ptemp, APLOGNO(02152)
                      "priv_addset");
        return !OK;
    }
    return OK;
}
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);
}
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);
}
Ejemplo n.º 9
0
static void
priv_str_to_set(const char *priv_name, priv_set_t *priv_set)
{
	if (priv_name == NULL || strcmp(priv_name, "none") == 0) {
		priv_emptyset(priv_set);
	} else if (strcmp(priv_name, "all") == 0) {
		priv_fillset(priv_set);
	} else {
		int priv;
		priv = priv_getbyname(priv_name, PRIV_ALLOC);
		if (priv < 0) {
			cmn_err(CE_WARN, "fail to allocate privilege: %s",
			    priv_name);
			return;
		}
		priv_emptyset(priv_set);
		priv_addset(priv_set, priv);
	}
}
Ejemplo n.º 10
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);
}
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);
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
0
static const char *vhost_cgiprivs(cmd_parms *cmd, void *dir, const char *arg)
{
    priv_cfg *cfg = ap_get_module_config(cmd->server->module_config,
                                         &privileges_module);
    const char *priv = arg;
    if (*priv == '-') {
        CFG_CHECK(priv_delset(cfg->child_priv, priv+1));
    }
    else if (*priv == '+') {
        CFG_CHECK(priv_addset(cfg->child_priv, priv+1));
    }
    else {
        priv_emptyset(cfg->child_priv);
        CFG_CHECK(priv_addset(cfg->child_priv, priv));
    }
    return NULL;
}
Ejemplo n.º 14
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);
}
Ejemplo 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);
}
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);
}
Ejemplo n.º 17
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;
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
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;
}