Now, the daemon will check that a base directory is NOT reached via
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 14 Oct 2008 19:08:36 +0000 (19:08 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 14 Oct 2008 19:08:36 +0000 (19:08 +0000)
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 '/'
 -- kevin

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1603 a5681a0c-68f1-0310-ab6d-d61299d08faa

doc/rrdcached.pod
src/rrd_daemon.c

index 4d079a9..d8f0c73 100644 (file)
@@ -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
index 8b23e52..511b04e 100644 (file)
@@ -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] == '/'))
         {