diff -upr syslog-ng-3.0.9./src/affile.c syslog-ng-3.0.9/src/affile.c --- syslog-ng-3.0.9./src/affile.c 2011-01-19 15:14:11.813181829 +0100 +++ syslog-ng-3.0.9/src/affile.c 2011-01-19 16:10:12.399928759 +0100 @@ -59,7 +59,12 @@ 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); } else g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE); diff -upr syslog-ng-3.0.9./src/gprocess.h syslog-ng-3.0.9/src/gprocess.h --- syslog-ng-3.0.9./src/gprocess.h 2009-04-22 13:06:55.000000000 +0200 +++ syslog-ng-3.0.9/src/gprocess.h 2011-01-19 16:10:12.399928759 +0100 @@ -27,6 +27,7 @@ #include "syslog-ng.h" #include +#include #if ENABLE_LINUX_CAPS # include @@ -77,5 +78,8 @@ void g_process_finish(void); void g_process_add_option_group(GOptionContext *ctx); +extern int kernel_version; +extern void get_kernel_version(void); +#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) #endif diff -upr syslog-ng-3.0.9./src/main.c syslog-ng-3.0.9/src/main.c --- syslog-ng-3.0.9./src/main.c 2010-05-10 17:46:05.000000000 +0200 +++ syslog-ng-3.0.9/src/main.c 2011-01-19 16:10:25.346593248 +0100 @@ -64,6 +64,7 @@ static const gchar *persist_file = PATH_ static gboolean syntax_only = FALSE; static gboolean seed_rng = FALSE; static gboolean display_version = FALSE; +int kernel_version; static volatile sig_atomic_t sig_hup_received = FALSE; static volatile sig_atomic_t sig_term_received = FALSE; @@ -395,6 +396,20 @@ version(void) ON_OFF_STR(ENABLE_PCRE)); } +void +get_kernel_version(void) { + static struct utsname uts; + int x = 0, y = 0, z = 0; + + if (uname(&uts) == -1) { + fprintf(stderr, "Unable to retrieve kernel version.\n"); + exit(1); + } + + sscanf(uts.release, "%d.%d.%d", &x, &y, &z); + kernel_version = LINUX_VERSION(x, y, z); +} + int main(int argc, char *argv[]) { @@ -411,9 +426,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. */ - 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"); ctx = g_option_context_new("syslog-ng"); g_process_add_option_group(ctx); msg_add_option_group(ctx);