X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/6ce9432d755104c8fb6afe82ddcdfc905d498da7..83078af5b0b1db4eb185cb256ebb76c117eea110:/util.c diff --git a/util.c b/util.c index afff767d..0887e7fc 100644 --- a/util.c +++ b/util.c @@ -45,7 +45,7 @@ void set_nonblocking(int fd) { int val; - if ((val = fcntl(fd, F_GETFL, 0)) == -1) + if ((val = fcntl(fd, F_GETFL)) == -1) return; if (!(val & NONBLOCK_FLAG)) { val |= NONBLOCK_FLAG; @@ -58,7 +58,7 @@ void set_blocking(int fd) { int val; - if ((val = fcntl(fd, F_GETFL, 0)) == -1) + if ((val = fcntl(fd, F_GETFL)) == -1) return; if (val & NONBLOCK_FLAG) { val &= ~NONBLOCK_FLAG; @@ -109,13 +109,13 @@ void print_child_argv(char **cmd) rprintf(FCLIENT, "\n"); } -void out_of_memory(char *str) +NORETURN void out_of_memory(char *str) { rprintf(FERROR, "ERROR: out of memory in %s [%s]\n", str, who_am_i()); exit_cleanup(RERR_MALLOC); } -void overflow_exit(char *str) +NORETURN void overflow_exit(char *str) { rprintf(FERROR, "ERROR: buffer overflow in %s [%s]\n", str, who_am_i()); exit_cleanup(RERR_MALLOC); @@ -359,7 +359,7 @@ int robust_unlink(const char *fname) /* start where the last one left off to reduce chance of clashes */ start = counter; do { - sprintf(&path[pos], "%03d", counter); + snprintf(&path[pos], 4, "%03d", counter); if (++counter >= MAX_RENAMES) counter = 1; } while ((rc = access(path, 0)) == 0 && counter != start); @@ -861,90 +861,10 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth, return dest; } -/* If sanitize_paths is not set, this works exactly the same as do_stat(). - * Otherwise, we verify that no symlink takes us outside the module path. - * If we encounter an escape attempt, we return a symlink's stat info! */ -int safe_stat(const char *fname, STRUCT_STAT *stp) -{ -#ifdef SUPPORT_LINKS - char tmpbuf[MAXPATHLEN], linkbuf[MAXPATHLEN], *mod_path; - int i, llen, mod_path_len; - - if (!sanitize_paths) - return do_stat(fname, stp); - - mod_path = lp_path(module_id); - mod_path_len = strlen(mod_path); - - for (i = 0; i < 16; i++) { -#ifdef DEBUG - if (*fname == '/') - assert(strncmp(fname, mod_path, mod_path_len) == 0 && fname[mod_path_len] == '/'); -#endif - if (do_lstat(fname, stp) < 0) - return -1; - if (!S_ISLNK(stp->st_mode)) - return 0; - if ((llen = readlink(fname, linkbuf, sizeof linkbuf - 1)) < 0) - return -1; - linkbuf[llen] = '\0'; - if (*fname == '/') - fname += mod_path_len; - if (!(fname = sanitize_path(tmpbuf, fname, mod_path, curr_dir_depth, linkbuf))) - break; - } - - return 0; /* Leave *stp set to the last symlink. */ -#else - return do_stat(fname, stp); -#endif -} - -void die_on_unsafe_path(char *path, int strip_filename) -{ -#ifdef SUPPORT_LINKS - char *final_slash, *p; - STRUCT_STAT st; - - if (!path) - return; - if (strip_filename) { - if (!(final_slash = strrchr(path, '/'))) - return; - *final_slash = '\0'; - } else - final_slash = NULL; - - p = path; - if (*p == '/') - p += module_dirlen + 1; - while (*p) { - if ((p = strchr(p, '/')) != NULL) - *p = '\0'; - if (safe_stat(path, &st) < 0) { - if (p) - *p = '/'; - goto done; - } - if (S_ISLNK(st.st_mode)) { - rprintf(FERROR, "Unsafe path: %s\n", path); - exit_cleanup(RERR_SYNTAX); - } - if (!p) - break; - *p++ = '/'; - } - - done: - if (final_slash) - *final_slash = '/'; -#endif -} - /* Like chdir(), but it keeps track of the current directory (in the * global "curr_dir"), and ensures that the path size doesn't overflow. * Also cleans the path using the clean_fname() function. */ -int push_dir(char *dir) +int push_dir(char *dir, int set_path_only) { static int initialised; unsigned int len; @@ -965,7 +885,7 @@ int push_dir(char *dir) if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir) return 0; - if (chdir(dir)) + if (!set_path_only && chdir(dir)) return 0; if (*dir == '/') { @@ -1091,8 +1011,6 @@ int handle_partial_dir(const char *fname, int create) if (create) { STRUCT_STAT st; int statret = do_lstat(dir, &st); - if (sanitize_paths && *partial_dir != '/') - die_on_unsafe_path(dir, 1); /* lstat handles last element */ if (statret == 0 && !S_ISDIR(st.st_mode)) { if (do_unlink(dir) < 0) return 0; @@ -1197,7 +1115,7 @@ char *human_num(int64 num) units = 'K'; } if (units) { - sprintf(bufs[n], "%.2f%c", dnum, units); + snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); return bufs[n]; } }