[arch-commits] Commit in syslog-ng/trunk (cap_syslog.patch)

Dave Reisner dreisner at archlinux.org
Sat Sep 17 18:52:55 UTC 2011


    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 <bazsi at balabit.hu>
+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 <serge.hallyn at ubuntu.com>
+Signed-off-by: Gergely Nagy <algernon at balabit.hu>
+Signed-off-by: Balazs Scheidler <bazsi at balabit.hu>
+---
+ 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
+




More information about the arch-commits mailing list