diff options
author | Trond Norbye <Trond.Norbye@sun.com> | 2009-03-03 19:43:04 +0100 |
---|---|---|
committer | Trond Norbye <Trond.Norbye@sun.com> | 2009-03-03 19:43:04 +0100 |
commit | 69aa542709745e7360b0cd9a81d7a407567106c4 (patch) | |
tree | 458fa91389321a9a93b74d605ca0fa693c76c048 | |
parent | f06bd30835a6df5f589892ffa394701273e95934 (diff) | |
download | memcached-69aa542709745e7360b0cd9a81d7a407567106c4.tar.gz |
Drop privileges when running on Solaris
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | memcached.c | 3 | ||||
-rw-r--r-- | memcached.h | 6 | ||||
-rw-r--r-- | solaris_priv.c | 43 |
5 files changed, 73 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index a867515..2482624 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,11 @@ memcached_SOURCES = memcached.c memcached.h \ thread.c daemon.c \ stats.c stats.h \ trace.h + +if BUILD_SOLARIS_PRIVS +memcached_SOURCES += solaris_priv.c +endif + memcached_debug_SOURCES = $(memcached_SOURCES) memcached_CPPFLAGS = -DNDEBUG memcached_LDADD = @DTRACE_OBJ@ diff --git a/configure.ac b/configure.ac index 6d41070..6deed86 100644 --- a/configure.ac +++ b/configure.ac @@ -303,6 +303,22 @@ fi AC_C_ALIGNMENT +dnl Check for the requirements for running memcached with less privileges +dnl than the default privilege set. On Solaris we need setppriv and priv.h +dnl If you want to add support for other platforms you should check for +dnl your requirements, define HAVE_DROP_PRIVILEGES, and make sure you add +dnl the source file containing the implementation into memcached_SOURCE +dnl in Makefile.am +AC_CHECK_FUNCS(setppriv, [ + AC_CHECK_HEADER(priv.h, [ + AC_DEFINE([HAVE_DROP_PRIVILEGES], 1, + [Define this if you have an implementation of drop_privileges()]) + build_solaris_privs=yes + ], []) +],[]) + +AM_CONDITIONAL([BUILD_SOLARIS_PRIVS],[test "$build_solaris_privs" = "yes"]) + dnl Let the compiler be a bit more picky. Please note that you cannot dnl specify these flags to the compiler before AC_CHECK_FUNCS, because dnl the test program will generate a compilation warning and hence fail diff --git a/memcached.c b/memcached.c index 1f87832..32eea3d 100644 --- a/memcached.c +++ b/memcached.c @@ -4241,6 +4241,9 @@ int main (int argc, char **argv) { } } + /* Drop privileges no longer needed */ + drop_privileges(); + /* enter the event loop */ event_base_loop(main_base, 0); diff --git a/memcached.h b/memcached.h index f057da5..0fe56cb 100644 --- a/memcached.h +++ b/memcached.h @@ -351,6 +351,12 @@ void STATS_LOCK(void); void STATS_UNLOCK(void); enum store_item_type store_item(item *item, int comm, conn *c); +#if HAVE_DROP_PRIVILEGES +extern void drop_privileges(); +#else +#define drop_privileges() +#endif + /* If supported, give compiler hints for branch prediction. */ #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) #define __builtin_expect(x, expected_value) (x) diff --git a/solaris_priv.c b/solaris_priv.c new file mode 100644 index 0000000..c730eb2 --- /dev/null +++ b/solaris_priv.c @@ -0,0 +1,43 @@ +#include <stdlib.h> +#include <priv.h> +#include <stdio.h> + +/* + * 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() { + 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); +} |