[PATCH 2/3] rrd_daemon.c: modified get_abs_path() to avoid PATH_MAX, modified journal_new_file() likewise, modified journal_init() likewise modified read_options() cases 'b' and 'j' to use realpath(path, NULL)
Index: rrdtool-1.4.8.new/src/rrd_daemon.c =================================================================== --- rrdtool-1.4.8.new.orig/src/rrd_daemon.c 2013-08-05 18:02:26.000000000 +0200 +++ rrdtool-1.4.8.new/src/rrd_daemon.c 2013-08-05 18:37:37.000000000 +0200 @@ -1078,21 +1078,26 @@ /* when using a base dir, convert relative paths to absolute paths. * if necessary, modifies the "filename" pointer to point * to the new path created in "tmp". "tmp" is provided - * by the caller and sizeof(tmp) must be >= PATH_MAX. + * by the called function, see below. * + * FIXME: Check this! * this allows us to optimize for the expected case (absolute path) * with a no-op. */ -static void get_abs_path(char **filename, char *tmp) +static void get_abs_path(char **filename) { - assert(tmp != NULL); + char *tmp = NULL; + int len = 0; assert(filename != NULL && *filename != NULL); if (config_base_dir == NULL || **filename == '/') return; - snprintf(tmp, PATH_MAX, "%s/%s", config_base_dir, *filename); + len = strlen(config_base_dir) + 1 + strlen(*filename) + 1; + tmp = malloc(len); + snprintf(tmp, len, "%s/%s", config_base_dir, *filename); *filename = tmp; + free(tmp); } /* }}} static int get_abs_path */ static int flush_file (const char *filename) /* {{{ */ @@ -1183,7 +1188,7 @@ static int handle_request_flush (HANDLER_PROTO) /* {{{ */ { - char *file, file_tmp[PATH_MAX]; + char *file; int status; status = buffer_get_field (&buffer, &buffer_size, &file); @@ -1197,7 +1202,7 @@ stats_flush_received++; pthread_mutex_unlock(&stats_lock); - get_abs_path(&file, file_tmp); + get_abs_path(&file); if (!check_file_access(file, sock)) return 0; status = flush_file (file); @@ -1238,14 +1243,14 @@ static int handle_request_pending(HANDLER_PROTO) /* {{{ */ { int status; - char *file, file_tmp[PATH_MAX]; + char *file; cache_item_t *ci; status = buffer_get_field(&buffer, &buffer_size, &file); if (status != 0) return syntax_error(sock,cmd); - get_abs_path(&file, file_tmp); + get_abs_path(&file); pthread_mutex_lock(&cache_lock); ci = g_tree_lookup(cache_tree, file); @@ -1266,13 +1271,13 @@ { int status; gboolean found; - char *file, file_tmp[PATH_MAX]; + char *file; status = buffer_get_field(&buffer, &buffer_size, &file); if (status != 0) return syntax_error(sock,cmd); - get_abs_path(&file, file_tmp); + get_abs_path(&file); if (!check_file_access(file, sock)) return 0; pthread_mutex_lock(&cache_lock); @@ -1313,7 +1318,7 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */ { - char *file, file_tmp[PATH_MAX]; + char *file; int values_num = 0; int status; char orig_buf[CMD_MAX]; @@ -1332,7 +1337,7 @@ stats_updates_received++; pthread_mutex_unlock(&stats_lock); - get_abs_path(&file, file_tmp); + get_abs_path(&file); if (!check_file_access(file, sock)) return 0; pthread_mutex_lock (&cache_lock); @@ -1867,8 +1872,8 @@ static void journal_new_file(void) /* {{{ */ { struct timeval now; - int new_fd; - char new_file[PATH_MAX + 1]; + int new_fd, len; + char *new_file = NULL; assert(journal_dir != NULL); assert(journal_cur != NULL); @@ -1877,7 +1882,9 @@ gettimeofday(&now, NULL); /* this format assures that the files sort in strcmp() order */ - snprintf(new_file, PATH_MAX, "%s/%s.%010d.%06d", + len = strlen(journal_dir) + 1 + strlen(JOURNAL_BASE) + 10 + 6 + 1; + new_file = malloc(len); + snprintf(new_file, len, "%s/%s.%010d.%06d", journal_dir, JOURNAL_BASE, (int)now.tv_sec, (int)now.tv_usec); new_fd = open(new_file, O_WRONLY|O_CREAT|O_APPEND, @@ -1895,6 +1902,7 @@ /* record the file in the journal set */ rrd_add_strdup(&journal_cur->files, &journal_cur->files_num, new_file); + free(new_file); return; error: @@ -1904,6 +1912,7 @@ RRDD_LOG(LOG_CRIT, "JOURNALING DISABLED: All values will be flushed at shutdown"); + free(new_file); close(new_fd); config_flush_at_shutdown = 1; @@ -1966,7 +1975,6 @@ journal_set_free(journal_cur); journal_set_free(journal_old); - free(journal_dir); } /* }}} static void journal_done */ @@ -2100,10 +2108,10 @@ static void journal_init(void) /* {{{ */ { - int had_journal = 0; + int had_journal = 0, len = 0; DIR *dir; struct dirent *dent; - char path[PATH_MAX+1]; + char *path = NULL; if (journal_dir == NULL) return; @@ -2122,19 +2130,27 @@ * correct sort order. TODO: remove after first release */ { - char old_path[PATH_MAX+1]; - snprintf(old_path, PATH_MAX, "%s/%s", journal_dir, JOURNAL_BASE ".old" ); - snprintf(path, PATH_MAX, "%s/%s", journal_dir, JOURNAL_BASE ".0000"); + char *old_path = NULL; + if (journal_dir != NULL) { + len = strlen(journal_dir) + 1 + strlen(JOURNAL_BASE) + 5 + 1; + old_path = malloc(len); + path = malloc(len); + snprintf(old_path, len, "%s/%s", journal_dir, JOURNAL_BASE ".old" ); + snprintf(path, len, "%s/%s", journal_dir, JOURNAL_BASE ".0000"); rename(old_path, path); - snprintf(old_path, PATH_MAX, "%s/%s", journal_dir, JOURNAL_BASE ); - snprintf(path, PATH_MAX, "%s/%s", journal_dir, JOURNAL_BASE ".0001"); + snprintf(old_path, len, "%s/%s", journal_dir, JOURNAL_BASE ); + snprintf(path, len, "%s/%s", journal_dir, JOURNAL_BASE ".0001"); rename(old_path, path); + free(old_path); + } } + /* FIXME: Check all free(path) !! */ dir = opendir(journal_dir); if (!dir) { RRDD_LOG(LOG_CRIT, "journal_init: opendir(%s) failed\n", journal_dir); + free(path); return; } while ((dent = readdir(dir)) != NULL) @@ -2143,15 +2159,20 @@ if (strncmp(dent->d_name, JOURNAL_BASE, strlen(JOURNAL_BASE))) continue; - snprintf(path, PATH_MAX, "%s/%s", journal_dir, dent->d_name); + len = strlen(journal_dir) + 1 + strlen(dent->d_name) + 1; + path = realloc(path, len); + snprintf(path, len, "%s/%s", journal_dir, dent->d_name); if (!rrd_add_strdup(&journal_cur->files, &journal_cur->files_num, path)) { RRDD_LOG(LOG_CRIT, "journal_init: cannot add journal file %s!", dent->d_name); + free(path); break; } + free(path); } + free(path); closedir(dir); qsort(journal_cur->files, journal_cur->files_num, @@ -2827,14 +2848,14 @@ case 'l': { - listen_socket_t *new; + listen_socket_t *new; - new = malloc(sizeof(listen_socket_t)); - if (new == NULL) - { - fprintf(stderr, "read_options: malloc failed.\n"); - return(2); - } + new = malloc(sizeof(listen_socket_t)); + if (new == NULL) + { + fprintf(stderr, "read_options: malloc failed.\n"); + return(2); + } memset(new, 0, sizeof(listen_socket_t)); strncpy(new->addr, optarg, sizeof(new->addr)-1); @@ -3007,7 +3028,7 @@ case 'b': { size_t len; - char base_realpath[PATH_MAX]; + char *base_realpath = NULL; if (config_base_dir != NULL) free (config_base_dir); @@ -3030,7 +3051,7 @@ * assumptions possible (we don't have to resolve paths * that start with a "/") */ - if (realpath(config_base_dir, base_realpath) == NULL) + if ((base_realpath = realpath(config_base_dir, NULL)) == NULL) { fprintf (stderr, "Failed to canonicalize the base directory '%s': " "%s\n", config_base_dir, rrd_strerror(errno)); @@ -3060,15 +3081,17 @@ } if (strncmp(config_base_dir, - base_realpath, sizeof(base_realpath)) != 0) + base_realpath, len) != 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); + free(base_realpath); return 5; } + free(base_realpath); } break; @@ -3091,20 +3114,7 @@ case 'j': { - char journal_dir_actual[PATH_MAX]; - const char *dir; - if (realpath((const char *)optarg, journal_dir_actual) == NULL) - { - fprintf(stderr, "Failed to canonicalize the journal directory '%s': %s\n", - optarg, rrd_strerror(errno)); - return 7; - } - dir = journal_dir = strdup(journal_dir_actual); - if (dir == NULL) { - fprintf (stderr, "read_options: strdup failed.\n"); - return (3); - } - + const char *dir = (const char *)optarg; status = rrd_mkdir_p(dir, 0777); if (status != 0) { @@ -3112,13 +3122,21 @@ dir, rrd_strerror(errno)); return 6; } + journal_dir = realpath((const char *)dir, NULL); + if (! journal_dir) { + fprintf(stderr, "Failed to canonicalize journal directory '%s': %s\n", + dir, rrd_strerror(errno)); + return 6; + } - if (access(dir, R_OK|W_OK|X_OK) != 0) + if (access(journal_dir, R_OK|W_OK|X_OK) != 0) { fprintf(stderr, "Must specify a writable directory with -j! (%s)\n", errno ? rrd_strerror(errno) : ""); + free(journal_dir); return 6; } + free(journal_dir); } break;
_______________________________________________ rrd-developers mailing list rrd-developers@lists.oetiker.ch https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers