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); }
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); }
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); }
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); }
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; }
/** * 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 }
/* 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; }
static void privupdate(prpriv_t *pr, const char *arg) { int i; if (sets != NULL) { for (i = 0; i < pri->priv_nsets; i++) { priv_set_t *target = (priv_set_t *)&pr->pr_sets[pr->pr_setsize * i]; if (rem[i] != NULL) priv_intersect(rem[i], target); if (add[i] != NULL) priv_union(add[i], target); if (assign[i] != NULL) priv_copyset(assign[i], target); } } if (Doff || Don || pfexec || xpol) { priv_info_uint_t *pii; int sz = PRIV_PRPRIV_SIZE(pr); char *x = (char *)pr + PRIV_PRPRIV_INFO_OFFSET(pr); uint32_t fl = 0; while (x < (char *)pr + sz) { /* LINTED: alignment */ priv_info_t *pi = (priv_info_t *)x; if (pi->priv_info_type == PRIV_INFO_FLAGS) { /* LINTED: alignment */ pii = (priv_info_uint_t *)x; fl = pii->val; goto done; } if (pi->priv_info_size > pr->pr_infosize || pi->priv_info_size <= sizeof (priv_info_t) || (pi->priv_info_size & 3) != 0) break; x += pi->priv_info_size; } (void) fprintf(stderr, "%s: cannot find privilege flags to set\n", arg); pr->pr_infosize = 0; return; done: pr->pr_infosize = sizeof (priv_info_uint_t); /* LINTED: alignment */ pii = (priv_info_uint_t *) ((char *)pr + PRIV_PRPRIV_INFO_OFFSET(pr)); if (Don) fl |= PRIV_DEBUG; if (Doff) fl &= ~PRIV_DEBUG; if (pfexec) fl |= PRIV_PFEXEC; if (xpol) fl |= PRIV_XPOLICY; pii->info.priv_info_size = sizeof (*pii); pii->info.priv_info_type = PRIV_INFO_FLAGS; pii->val = fl; } else { pr->pr_infosize = 0; } }