Date: Saturday, September 17, 2011 @ 14:52:54 Author: dreisner Revision: 138145
use backport of upstream patch for cap_syslog usage Modified: syslog-ng/trunk/cap_syslog.patch ------------------+ cap_syslog.patch | 211 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 144 insertions(+), 67 deletions(-) Modified: cap_syslog.patch =================================================================== --- cap_syslog.patch 2011-09-17 18:50:18 UTC (rev 138144) +++ cap_syslog.patch 2011-09-17 18:52:54 UTC (rev 138145) @@ -1,101 +1,178 @@ -diff --git a/lib/gprocess.h b/lib/gprocess.h -index cda35b0..5c449f7 100644 ---- a/lib/gprocess.h -+++ b/lib/gprocess.h -@@ -28,9 +28,14 @@ - #include "syslog-ng.h" +From ae0ff59d9a761c2fda8a19b0c05e0e05c59bae57 Mon Sep 17 00:00:00 2001 +From: Balazs Scheidler <[email protected]> +Date: Thu, 12 May 2011 13:11:58 +0200 +Subject: [PATCH] Use CAP_SYSLOG instead of CAP_SYS_ADMIN, if available. + +If cap_syslog exists, the kernel will complain (once) that we only +have cap_sys_admin. Additionally, using cap_syslog instead of +cap_sys_admin significantly lowers the unneeded privs we are +using. + +Upon startup, syslog-ng will detect whether CAP_SYSLOG is available, +and use capabilities based on that finding. This detection will also +have a side-effect, which will make it so that +g_process_cap_modify(CAP_SYSLOG) will fall back to CAP_SYS_ADMIN, if +CAP_SYSLOG support was not detected. + +Thanks to Andrew Morgan for pointing out a nice way to detect whether +the kernel has CAP_SYSLOG. Original code by Serge Hallyn, with minor +changes based on Balazs Scheidler's review by Gergely Nagy. + +Signed-off-by: Serge Hallyn <[email protected]> +Signed-off-by: Gergely Nagy <[email protected]> +Signed-off-by: Balazs Scheidler <[email protected]> +--- + lib/gprocess.c | 27 +++++++++++++++++++++++++++ + lib/gprocess.h | 6 ++++++ + modules/affile/affile.c | 2 +- + syslog-ng/main.c | 38 ++++++++++++++++++++++++++++++-------- + 4 files changed, 64 insertions(+), 9 deletions(-) + +diff --git a/lib/gprocess.c b/lib/gprocess.c +index 38bcb12..e2159fc 100644 +--- a/lib/gprocess.c ++++ b/lib/gprocess.c +@@ -98,6 +98,7 @@ static gint startup_result_pipe[2] = { -1, -1 }; + static gint init_result_pipe[2] = { -1, -1 }; + static GProcessKind process_kind = G_PK_STARTUP; + static gboolean stderr_present = TRUE; ++static int have_capsyslog = FALSE; - #include <sys/types.h> -+#include <sys/utsname.h> + /* global variables */ + static struct +@@ -216,6 +217,13 @@ g_process_cap_modify(int capability, int onoff) + if (!process_opts.caps) + return TRUE; - #if ENABLE_LINUX_CAPS - # include <sys/capability.h> -+# -+# ifndef CAP_SYSLOG -+# define CAP_SYSLOG 34 -+# endif ++ /* ++ * if libcap or kernel doesn't support cap_syslog, then resort to ++ * cap_sys_admin ++ */ ++ if (capability == CAP_SYSLOG && (!have_capsyslog || CAP_SYSLOG == -1)) ++ capability = CAP_SYS_ADMIN; ++ + caps = cap_get_proc(); + if (!caps) + return FALSE; +@@ -297,6 +305,25 @@ g_process_cap_restore(cap_t r) + return; + } + ++gboolean ++g_process_check_cap_syslog(void) ++{ ++ int ret; ++ ++ if (have_capsyslog) ++ return TRUE; ++ ++ if (CAP_SYSLOG == -1) ++ return FALSE; ++ ++ ret = prctl(PR_CAPBSET_READ, CAP_SYSLOG); ++ if (ret == -1) ++ return FALSE; ++ ++ have_capsyslog = TRUE; ++ return TRUE; ++} ++ #endif - typedef enum -@@ -78,5 +83,8 @@ void g_process_finish(void); + /** +diff --git a/lib/gprocess.h b/lib/gprocess.h +index a6dd7c4..1bdd719 100644 +--- a/lib/gprocess.h ++++ b/lib/gprocess.h +@@ -46,6 +46,10 @@ gboolean g_process_cap_modify(int capability, int onoff); + cap_t g_process_cap_save(void); + void g_process_cap_restore(cap_t r); - void g_process_add_option_group(GOptionContext *ctx); ++#ifndef CAP_SYSLOG ++#define CAP_SYSLOG -1 ++#endif ++ + #else -+extern int kernel_version; -+extern void get_kernel_version(void); -+#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) + typedef gpointer cap_t; +@@ -71,6 +75,8 @@ void g_process_set_argv_space(gint argc, gchar **argv); + void g_process_set_use_fdlimit(gboolean use); + void g_process_set_check(gint check_period, gboolean (*check_fn)(void)); - #endif ++gboolean g_process_check_cap_syslog(void); ++ + void g_process_start(void); + void g_process_startup_failed(guint ret_num, gboolean may_exit); + void g_process_startup_ok(void); diff --git a/modules/affile/affile.c b/modules/affile/affile.c -index e145324..886fa72 100644 +index ce343cd..bb8aa75 100644 --- a/modules/affile/affile.c +++ b/modules/affile/affile.c -@@ -59,7 +59,12 @@ affile_open_file(gchar *name, gint flags, +@@ -59,7 +59,7 @@ affile_open_file(gchar *name, gint flags, if (privileged) { g_process_cap_modify(CAP_DAC_READ_SEARCH, TRUE); - g_process_cap_modify(CAP_SYS_ADMIN, TRUE); -+ if (!kernel_version) -+ get_kernel_version(); -+ if (kernel_version < LINUX_VERSION(2, 6, 38)) -+ g_process_cap_modify(CAP_SYS_ADMIN, TRUE); -+ else -+ g_process_cap_modify(CAP_SYSLOG, TRUE); ++ g_process_cap_modify(CAP_SYSLOG, TRUE); } else { diff --git a/syslog-ng/main.c b/syslog-ng/main.c -index 9880c1f..ee5031b 100644 +index 9880c1f..02f17b6 100644 --- a/syslog-ng/main.c +++ b/syslog-ng/main.c -@@ -67,6 +67,7 @@ static gboolean syntax_only = FALSE; - static gboolean display_version = FALSE; - static gchar *ctlfilename = PATH_CONTROL_SOCKET; - static gchar *preprocess_into = NULL; -+int kernel_version; - - static volatile sig_atomic_t sig_hup_received = FALSE; - static volatile sig_atomic_t sig_term_received = FALSE; -@@ -363,6 +364,20 @@ version(void) +@@ -363,6 +363,33 @@ version(void) ON_OFF_STR(ENABLE_PACCT_MODULE)); } -+void -+get_kernel_version(void) { -+ static struct utsname uts; -+ int x = 0, y = 0, z = 0; ++#if ENABLE_LINUX_CAPS ++#define BASE_CAPS "cap_net_bind_service,cap_net_broadcast,cap_net_raw," \ ++ "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner=p " + -+ if (uname(&uts) == -1) { -+ fprintf(stderr, "Unable to retrieve kernel version.\n"); -+ exit(1); -+ } ++static void ++setup_caps (void) ++{ ++ static gchar *capsstr_syslog = BASE_CAPS "cap_syslog=ep"; ++ static gchar *capsstr_sys_admin = BASE_CAPS "cap_sys_admin=ep"; + -+ sscanf(uts.release, "%d.%d.%d", &x, &y, &z); -+ kernel_version = LINUX_VERSION(x, y, z); ++ /* Set up the minimal privilege we'll need ++ * ++ * NOTE: polling /proc/kmsg requires cap_sys_admin, otherwise it'll always ++ * indicate readability. Enabling/disabling cap_sys_admin on every poll ++ * invocation seems to be too expensive. So I enable it for now. ++ */ ++ if (g_process_check_cap_syslog()) ++ g_process_set_caps(capsstr_syslog); ++ else ++ g_process_set_caps(capsstr_sys_admin); +} ++#else + ++#define setup_caps() ++ ++#endif ++ int main(int argc, char *argv[]) { -@@ -379,9 +394,20 @@ main(int argc, char *argv[]) - * indicate readability. Enabling/disabling cap_sys_admin on every poll - * invocation seems to be too expensive. So I enable it for now. */ - +@@ -374,14 +401,9 @@ main(int argc, char *argv[]) + z_mem_trace_init("syslog-ng.trace"); + + g_process_set_argv_space(argc, (gchar **) argv); +- +- /* NOTE: polling /proc/kmsg requires cap_sys_admin, otherwise it'll always +- * indicate readability. Enabling/disabling cap_sys_admin on every poll +- * invocation seems to be too expensive. So I enable it for now. */ +- - g_process_set_caps("cap_net_bind_service,cap_net_broadcast,cap_net_raw," -+ if (!kernel_version) -+ get_kernel_version(); -+ if (kernel_version < LINUX_VERSION(2, 6, 34)) -+ g_process_set_caps("cap_net_bind_service,cap_net_broadcast,cap_net_raw," - "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner=p " - "cap_sys_admin=ep"); -+ else if (kernel_version < LINUX_VERSION(2, 6, 38)) -+ g_process_set_caps("cap_net_bind_service,cap_net_broadcast,cap_net_raw," -+ "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner," -+ "cap_sys_admin=p"); -+ else -+ g_process_set_caps("cap_net_bind_service,cap_net_broadcast,cap_net_raw," -+ "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner," -+ "cap_syslog=p"); +- "cap_dac_read_search,cap_dac_override,cap_chown,cap_fowner=p " +- "cap_sys_admin=ep"); ++ ++ setup_caps(); ++ ctx = g_option_context_new("syslog-ng"); g_process_add_option_group(ctx); msg_add_option_group(ctx); +-- +1.7.6.1 +
