From: oetiker Date: Tue, 14 Oct 2008 19:08:36 +0000 (+0000) Subject: Now, the daemon will check that a base directory is NOT reached via X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=91fd5f7213be86177c498ffe6674caccf1ef2603;p=rrdtool.git 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 '/' -- kevin git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1603 a5681a0c-68f1-0310-ab6d-d61299d08faa --- 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 The paths up to and including the base directory B +symbolic links. In other words, if the base directory is +specified as: + + -b /base/dir/somewhere + +... then B 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] == '/')) {