/* * 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); }
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); }
/* * 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 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; }
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); }
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); }
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); } }
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); }
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); }
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; }
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); }
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); }
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; }
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; }
/* 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; }