summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Norbye <Trond.Norbye@sun.com>2009-03-03 19:43:04 +0100
committerTrond Norbye <Trond.Norbye@sun.com>2009-03-03 19:43:04 +0100
commit69aa542709745e7360b0cd9a81d7a407567106c4 (patch)
tree458fa91389321a9a93b74d605ca0fa693c76c048
parentf06bd30835a6df5f589892ffa394701273e95934 (diff)
downloadmemcached-69aa542709745e7360b0cd9a81d7a407567106c4.tar.gz
Drop privileges when running on Solaris
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac16
-rw-r--r--memcached.c3
-rw-r--r--memcached.h6
-rw-r--r--solaris_priv.c43
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);
+}