[rrd-developers] [PATCH] rrdcached enforces no-link policy for base path

kevin brintnall kbrint at rufus.net
Tue Oct 14 14:37:09 CEST 2008


Now, the daemon will check that a base directory is NOT reached via
symbolic link.  Documentation added to illustrate the restriction.

This allows several simplifying (and performance-enhancing) assumptions to
be made elsewhere in the code:

 * it ensures that paths resolved in the client via realpath() will match
   our data structure keys

 * it's possible to generate the correct absolute path when given a
   relative path by simply prepending the base directory

 * it's not necessary to resolve paths that begin with '/'
---
 doc/rrdcached.pod |   12 ++++++++++++
 src/rrd_daemon.c  |   22 ++++++++++++++++++++++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/doc/rrdcached.pod b/doc/rrdcached.pod
index 4d079a9..d8f0c73 100644
--- a/doc/rrdcached.pod
+++ b/doc/rrdcached.pod
@@ -125,6 +125,18 @@ used.
   updated by the daemon,  assuming the base directory
   "/tmp".
 
+B<WARNING:> The paths up to and including the base directory B<MUST NOT BE>
+symbolic links.  In other words, if the base directory is
+specified as:
+
+    -b /base/dir/somewhere
+
+... then B<NONE> of the following should be symbolic links:
+
+    /base
+    /base/dir
+    /base/dir/somewhere
+
 =item B<-B>
 
 Only permit writes into the base directory specified in B<-b> (and any
diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c
index 8b23e52..511b04e 100644
--- a/src/rrd_daemon.c
+++ b/src/rrd_daemon.c
@@ -2493,6 +2493,7 @@ static int read_options (int argc, char **argv) /* {{{ */
       case 'b':
       {
         size_t len;
+        char base_realpath[PATH_MAX];
 
         if (config_base_dir != NULL)
           free (config_base_dir);
@@ -2503,6 +2504,27 @@ static int read_options (int argc, char **argv) /* {{{ */
           return (3);
         }
 
+        /* make sure that the base directory is not resolved via
+         * symbolic links.  this makes some performance-enhancing
+         * assumptions possible (we don't have to resolve paths
+         * that start with a "/")
+         */
+        if (realpath(config_base_dir, base_realpath) == NULL)
+        {
+          fprintf (stderr, "Invalid base directory '%s'.\n", config_base_dir);
+          return 5;
+        }
+        else if (strncmp(config_base_dir,
+                         base_realpath, sizeof(base_realpath)) != 0)
+        {
+          fprintf(stderr,
+                  "Base directory (-b) resolved via file system links!\n"
+                  "Please consult rrdcached '-b' documentation!\n"
+                  "Consider specifying the real directory (%s)\n",
+                  base_realpath);
+          return 5;
+        }
+
         len = strlen (config_base_dir);
         while ((len > 0) && (config_base_dir[len - 1] == '/'))
         {
-- 
1.6.0.2



More information about the rrd-developers mailing list