summaryrefslogtreecommitdiff
path: root/core/syslog-ng/cap_syslog.patch
blob: b6e6db6e4966f1967a418b6fd535fbaf86ceb99f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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"
 
 #include <sys/types.h>
+#include <sys/utsname.h>
 
 #if ENABLE_LINUX_CAPS
 #  include <sys/capability.h>
+#
+#  ifndef CAP_SYSLOG
+#    define CAP_SYSLOG 34
+#  endif
 #endif
 
 typedef enum
@@ -78,5 +83,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 --git a/modules/affile/affile.c b/modules/affile/affile.c
index e145324..886fa72 100644
--- a/modules/affile/affile.c
+++ b/modules/affile/affile.c
@@ -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
     {
diff --git a/syslog-ng/main.c b/syslog-ng/main.c
index 9880c1f..ee5031b 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)
          ON_OFF_STR(ENABLE_PACCT_MODULE));
 }
 
+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[])
 {
@@ -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. */
   
-  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);