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