From 4626cbaf78767fc8e9c86dd04785386c59ae0839 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 8 Jan 2016 14:24:56 +1100 Subject: Support Illumos/Solaris fine-grained privileges Includes a pre-auth privsep sandbox and several pledge() emulations. bz#2511, patch by Alex Wilson. ok dtucker@ --- openbsd-compat/port-solaris.c | 114 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) (limited to 'openbsd-compat/port-solaris.c') diff --git a/openbsd-compat/port-solaris.c b/openbsd-compat/port-solaris.c index 25382f1c9..962cd1685 100644 --- a/openbsd-compat/port-solaris.c +++ b/openbsd-compat/port-solaris.c @@ -227,3 +227,117 @@ solaris_set_default_project(struct passwd *pw) } } #endif /* USE_SOLARIS_PROJECTS */ + +#ifdef USE_SOLARIS_PRIVS +# ifdef HAVE_PRIV_H +# include +# endif + +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); +} + +void +solaris_drop_privs_root_pinfo_net(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_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_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); +} + +#endif -- cgit v1.2.3