/* Try to remove priv from the effective set. Returns 0 if priv was removed. Returns -1 on error with errno set appropriately. */ int priv_set_remove (const char *priv) { if (! initialized && priv_set_initialize () != 0) return -1; if (priv_ismember (eff_set, priv)) { /* priv_addset/priv_delset can only fail if priv is invalid, which is checked above by the priv_ismember call. */ priv_delset (eff_set, priv); if (setppriv (PRIV_SET, PRIV_EFFECTIVE, eff_set) != 0) { priv_addset (eff_set, priv); return -1; } priv_addset (rem_set, priv); } else { errno = EINVAL; return -1; } return 0; }
static void vjs_add_effective(priv_set_t *pset, enum jail_gen_e jge) { switch (jge) { case JAILG_SUBPROC_VCC: // open vmods priv_setop_assert(priv_addset(pset, "file_read")); // write .c output priv_setop_assert(priv_addset(pset, "file_write")); break; case JAILG_SUBPROC_CC: priv_setop_assert(priv_addset(pset, PRIV_PROC_EXEC)); priv_setop_assert(priv_addset(pset, PRIV_PROC_FORK)); priv_setop_assert(priv_addset(pset, "file_read")); priv_setop_assert(priv_addset(pset, "file_write")); break; case JAILG_SUBPROC_VCLLOAD: priv_setop_assert(priv_addset(pset, "file_read")); break; case JAILG_SUBPROC_WORKER: priv_setop_assert(priv_addset(pset, "net_access")); priv_setop_assert(priv_addset(pset, "file_read")); priv_setop_assert(priv_addset(pset, "file_write")); break; default: INCOMPL(); } }
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; }
/* * 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); }
/* effective during runtime of the child */ static inline void mgt_sandbox_solaris_add_effective(priv_set_t *pset) { /* PSARC/2009/685 - 8eca52188202 - onnv_132 */ priv_addset(pset, "net_access"); /* PSARC/2009/378 - 63678502e95e - onnv_140 */ priv_addset(pset, "file_read"); priv_addset(pset, "file_write"); }
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); }
static const char *vhost_secure(cmd_parms *cmd, void *dir, int arg) { priv_cfg *cfg = ap_get_module_config(cmd->server->module_config, &privileges_module); if (!arg) { /* add basic privileges, excluding those covered by cgimode */ CFG_CHECK(priv_addset(cfg->priv, PRIV_FILE_LINK_ANY)); CFG_CHECK(priv_addset(cfg->priv, PRIV_PROC_INFO)); CFG_CHECK(priv_addset(cfg->priv, PRIV_PROC_SESSION)); } return NULL; }
void priv_init(void) { #ifdef DEBUG int alloc_test_priv = 1; #else int alloc_test_priv = priv_debug; #endif rw_init(&privinfo_lock, NULL, RW_DRIVER, NULL); PRIV_BASIC_ASSERT(priv_basic); PRIV_UNSAFE_ASSERT(&priv_unsafe); priv_fillset(&priv_fullset); /* * When booting with priv_debug set or in a DEBUG kernel, then we'll * add an additional basic privilege and we verify that it is always * present in E. */ if (alloc_test_priv != 0 && (priv_basic_test = priv_getbyname("basic_test", PRIV_ALLOC)) >= 0) { priv_addset(priv_basic, priv_basic_test); } devpolicy_init(); }
/* * additional privileges needed by vjs_privsep - * will get waived in vjs_waive */ static void vjs_add_initial(priv_set_t *pset, enum jail_gen_e jge) { (void)jge; /* for setgid/setuid */ AZ(priv_addset(pset, PRIV_PROC_SETID)); }
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; }
/* * additional privileges needed by mgt_sandbox_solaris_privsep - * will get waived in mgt_sandbox_solaris_waive */ static void mgt_sandbox_solaris_add_initial(priv_set_t *pset, enum sandbox_e who) { (void)who; /* for setgid/setuid */ AZ(priv_addset(pset, PRIV_PROC_SETID)); }
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); }
static void vjs_add_inheritable(priv_set_t *pset, enum jail_gen_e jge) { switch (jge) { case JAILG_SUBPROC_VCC: break; case JAILG_SUBPROC_CC: priv_setop_assert(priv_addset(pset, PRIV_PROC_EXEC)); priv_setop_assert(priv_addset(pset, PRIV_PROC_FORK)); priv_setop_assert(priv_addset(pset, "file_read")); priv_setop_assert(priv_addset(pset, "file_write")); break; case JAILG_SUBPROC_VCLLOAD: break; case JAILG_SUBPROC_WORKER: break; default: INCOMPL(); } }
static void mgt_sandbox_solaris_add_effective(priv_set_t *pset, enum sandbox_e who) { switch (who) { case SANDBOX_VCC: priv_setop_assert(priv_addset(pset, "file_write")); break; case SANDBOX_CC: break; case SANDBOX_VCLLOAD: priv_setop_assert(priv_addset(pset, "file_read")); case SANDBOX_WORKER: priv_setop_assert(priv_addset(pset, "net_access")); priv_setop_assert(priv_addset(pset, "file_read")); priv_setop_assert(priv_addset(pset, "file_write")); break; default: REPORT(LOG_ERR, "INCOMPLETE AT: %s(%d)\n", __func__, __LINE__); exit(1); } }
int main(int argc, const char *argv[]) { int fd, ret; char *path; priv_set_t *ps; vnd_ioc_attach_t via; vnd_ioc_link_t vil; if (argc < 2) { (void) fprintf(stderr, "missing arguments...\n"); return (1); } if (strlen(argv[1]) >= VND_NAMELEN) { (void) fprintf(stderr, "vnic name too long...\n"); return (1); } fd = open(VND_PATH, O_RDWR); assert(fd > 0); (void) strlcpy(via.via_name, argv[1], VND_NAMELEN); via.via_zoneid = 0; via.via_errno = 0; ret = ioctl(fd, VND_IOC_ATTACH, &via); assert(ret == 0); assert(via.via_errno == 0); (void) strlcpy(vil.vil_name, argv[1], VND_NAMELEN); vil.vil_errno = 0; ret = ioctl(fd, VND_IOC_LINK, &vil); assert(ret == 0); assert(vil.vil_errno == 0); ret = asprintf(&path, "/dev/vnd/%s", argv[1]); assert(ret != -1); ps = priv_allocset(); assert(ps != NULL); assert(priv_addset(ps, PRIV_NET_RAWACCESS) == 0); assert(setppriv(PRIV_OFF, PRIV_PERMITTED, ps) == 0); ret = open(path, O_RDWR); assert(ret == -1); assert(errno == EPERM); return (0); }
static void mgt_sandbox_solaris_add_inheritable(priv_set_t *pset, enum sandbox_e who) { switch (who) { case SANDBOX_VCC: /* for /etc/resolv.conf and /etc/hosts */ priv_setop_assert(priv_addset(pset, "file_read")); break; case SANDBOX_CC: priv_setop_assert(priv_addset(pset, PRIV_PROC_EXEC)); priv_setop_assert(priv_addset(pset, PRIV_PROC_FORK)); priv_setop_assert(priv_addset(pset, "file_read")); priv_setop_assert(priv_addset(pset, "file_write")); break; case SANDBOX_VCLLOAD: break; case SANDBOX_WORKER: break; default: REPORT(LOG_ERR, "INCOMPLETE AT: %s(%d)\n", __func__, __LINE__); exit(1); } }
/* * Interface to set the effective and permitted privileges for * a credential; this interface does no security checks and is * intended for kernel (file)servers creating credentials with * specific privileges. */ int crsetpriv(cred_t *cr, ...) { va_list ap; const char *privnm; ASSERT(cr->cr_ref <= 2); priv_set_PA(cr); va_start(ap, cr); while ((privnm = va_arg(ap, const char *)) != NULL) { int priv = priv_getbyname(privnm, 0); if (priv < 0) return (-1); priv_addset(&CR_PPRIV(cr), priv); priv_addset(&CR_EPRIV(cr), priv); } priv_adjust_PA(cr); va_end(ap); return (0); }
static void vjs_add_permitted(priv_set_t *pset, enum jail_gen_e jge) { switch (jge) { case JAILG_SUBPROC_VCC: case JAILG_SUBPROC_CC: case JAILG_SUBPROC_VCLLOAD: break; case JAILG_SUBPROC_WORKER: /* for raising limits in cache_waiter_ports.c */ AZ(priv_addset(pset, PRIV_SYS_RESOURCE)); break; default: INCOMPL(); } }
static void mgt_sandbox_solaris_add_permitted(priv_set_t *pset, enum sandbox_e who) { switch (who) { case SANDBOX_VCC: case SANDBOX_CC: case SANDBOX_VCLLOAD: break; case SANDBOX_WORKER: /* for raising limits in cache_waiter_ports.c */ AZ(priv_addset(pset, PRIV_SYS_RESOURCE)); break; default: REPORT(LOG_ERR, "INCOMPLETE AT: %s(%d)\n", __func__, __LINE__); exit(1); } }
static void vjs_add_permitted(priv_set_t *pset, enum jail_gen_e jge) { (void) pset; switch (jge) { case JAILG_SUBPROC_VCC: case JAILG_SUBPROC_CC: case JAILG_SUBPROC_VCLLOAD: break; case JAILG_SUBPROC_WORKER: /* vmod_unix getpeerucred() */ AZ(priv_addset(pset, PRIV_PROC_INFO)); break; default: INCOMPL(); } }
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 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; }
/* * 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); }
/* 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; }
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; }
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 }
/* permitted during runtime of the child - for privilege bracketing */ static inline void mgt_sandbox_solaris_add_permitted(priv_set_t *pset) { /* for raising limits in cache_waiter_ports.c */ priv_addset(pset, PRIV_SYS_RESOURCE); }
/* effective during mgt_sandbox */ static inline void mgt_sandbox_solaris_add_initial(priv_set_t *pset) { /* for setgid/setuid */ priv_addset(pset, PRIV_PROC_SETID); }
/** * 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 }