commit 3fa889b71dd543b70c511d9b84894bd096061d51 Author: Cedric Buissart Date: Thu Jun 15 21:00:43 2017 +0200 Prevent symlink follow when no-absolute-path diff --git a/src/copyin.c b/src/copyin.c index 38d809f..809b9e9 100644 --- a/src/copyin.c +++ b/src/copyin.c @@ -1465,6 +1465,16 @@ process_copy_in () } } + +#ifdef CP_IFLNK + /* no_abs_paths_flag prevents us to follow symlink */ + if (no_abs_paths_flag && existing_path_has_symlink(file_hdr.c_name) == -1) { + error (0, 0, _("%s not created: symlink in its path"), file_hdr.c_name); + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; + } +#endif copyin_file(&file_hdr, in_file_des); if (verbose_flag) diff --git a/src/util.c b/src/util.c index 18b3e42..dd04edf 100644 --- a/src/util.c +++ b/src/util.c @@ -1627,3 +1627,45 @@ change_dir () _("cannot change to directory `%s'"), change_directory_option); } } + +#ifdef CP_IFLNK +/* existing_path_has_symlink will walk the path as far as possible. + * returns -1 if unexpected error or if any non-directory is found on the way + * (with the exception of the filename) + * returns 0 otherwise + * Note: if part of the path is missing, it's ok, cpio might be allowed to create it + */ +int existing_path_has_symlink(char* path) { + int ret = 0; + struct stat stat; + char *next, *dup; + dup = malloc((strlen(path)+1) * sizeof(char)); + if (! dup) + return -1; + + next = path; + while (1) { + next = strchr(next, '/'); + if (! next) { + break; + } + strncpy(dup, path, next - path); + dup[next - path] = '\0'; + if ( lstat(dup, &stat) != 0) { + /* only ENOENT is expected here (we let cpio create path if required */ + if ( errno != ENOENT ) + ret = -1; + break; + } + + if ( ! S_ISDIR(stat.st_mode) ) { + ret = -1; + break; + } + next++; + } + + free(dup); + return ret; +} +#endif