diff --git a/SOURCES/openssh-6.7p1-coverity.patch b/SOURCES/openssh-6.7p1-coverity.patch index 6852384..28632e0 100644 --- a/SOURCES/openssh-6.7p1-coverity.patch +++ b/SOURCES/openssh-6.7p1-coverity.patch @@ -405,7 +405,7 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c _exit(1); @@ -762,6 +762,8 @@ process_put(struct sftp_conn *conn, cons - fflag || global_fflag) == -1) + fflag || global_fflag, 0) == -1) err = -1; } + free(abs_dst); diff --git a/SOURCES/openssh-8.7p1-scp-clears-file.patch b/SOURCES/openssh-8.7p1-scp-clears-file.patch new file mode 100644 index 0000000..4c033da --- /dev/null +++ b/SOURCES/openssh-8.7p1-scp-clears-file.patch @@ -0,0 +1,304 @@ +diff --color -rup a/scp.c b/scp.c +--- a/scp.c 2022-07-26 14:51:40.560120817 +0200 ++++ b/scp.c 2022-07-26 14:52:37.118213004 +0200 +@@ -1324,12 +1324,12 @@ source_sftp(int argc, char *src, char *t + + if (src_is_dir && iamrecursive) { + if (upload_dir(conn, src, abs_dst, pflag, +- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { ++ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) { + error("failed to upload directory %s to %s", + src, abs_dst); + errs = 1; + } +- } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) { ++ } else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { + error("failed to upload file %s to %s", src, abs_dst); + errs = 1; + } +@@ -1566,11 +1566,11 @@ sink_sftp(int argc, char *dst, const cha + debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); + if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { + if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, +- pflag, SFTP_PROGRESS_ONLY, 0, 0, 1) == -1) ++ pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) + err = -1; + } else { + if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, +- pflag, 0, 0) == -1) ++ pflag, 0, 0, 1) == -1) + err = -1; + } + free(abs_dst); +diff --color -rup a/sftp.c b/sftp.c +--- a/sftp.c 2022-07-26 14:51:40.561120836 +0200 ++++ b/sftp.c 2022-07-26 14:52:37.119213023 +0200 +@@ -666,12 +666,12 @@ process_get(struct sftp_conn *conn, cons + if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { + if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, + pflag || global_pflag, 1, resume, +- fflag || global_fflag, 0) == -1) ++ fflag || global_fflag, 0, 0) == -1) + err = -1; + } else { + if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, + pflag || global_pflag, resume, +- fflag || global_fflag) == -1) ++ fflag || global_fflag, 0) == -1) + err = -1; + } + free(abs_dst); +@@ -760,12 +760,12 @@ process_put(struct sftp_conn *conn, cons + if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { + if (upload_dir(conn, g.gl_pathv[i], abs_dst, + pflag || global_pflag, 1, resume, +- fflag || global_fflag, 0, 0) == -1) ++ fflag || global_fflag, 0, 0, 0) == -1) + err = -1; + } else { + if (do_upload(conn, g.gl_pathv[i], abs_dst, + pflag || global_pflag, resume, +- fflag || global_fflag) == -1) ++ fflag || global_fflag, 0) == -1) + err = -1; + } + } +diff --color -rup a/sftp-client.c b/sftp-client.c +--- a/sftp-client.c 2022-07-26 14:51:40.561120836 +0200 ++++ b/sftp-client.c 2022-07-26 15:09:54.825295533 +0200 +@@ -1454,7 +1454,7 @@ progress_meter_path(const char *path) + int + do_download(struct sftp_conn *conn, const char *remote_path, + const char *local_path, Attrib *a, int preserve_flag, int resume_flag, +- int fsync_flag) ++ int fsync_flag, int inplace_flag) + { + struct sshbuf *msg; + u_char *handle; +@@ -1498,8 +1498,8 @@ do_download(struct sftp_conn *conn, cons + &handle, &handle_len) != 0) + return -1; + +- local_fd = open(local_path, +- O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); ++ local_fd = open(local_path, O_WRONLY | O_CREAT | ++ ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); + if (local_fd == -1) { + error("Couldn't open local file \"%s\" for writing: %s", + local_path, strerror(errno)); +@@ -1661,8 +1661,11 @@ do_download(struct sftp_conn *conn, cons + /* Sanity check */ + if (TAILQ_FIRST(&requests) != NULL) + fatal("Transfer complete, but requests still in queue"); +- /* Truncate at highest contiguous point to avoid holes on interrupt */ +- if (read_error || write_error || interrupted) { ++ /* ++ * Truncate at highest contiguous point to avoid holes on interrupt, ++ * or unconditionally if writing in place. ++ */ ++ if (inplace_flag || read_error || write_error || interrupted) { + if (reordered && resume_flag) { + error("Unable to resume download of \"%s\": " + "server reordered requests", local_path); +@@ -1724,7 +1727,7 @@ do_download(struct sftp_conn *conn, cons + static int + download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int depth, Attrib *dirattrib, int preserve_flag, int print_flag, +- int resume_flag, int fsync_flag, int follow_link_flag) ++ int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) + { + int i, ret = 0; + SFTP_DIRENT **dir_entries; +@@ -1781,7 +1784,7 @@ download_dir_internal(struct sftp_conn * + if (download_dir_internal(conn, new_src, new_dst, + depth + 1, &(dir_entries[i]->a), preserve_flag, + print_flag, resume_flag, +- fsync_flag, follow_link_flag) == -1) ++ fsync_flag, follow_link_flag, inplace_flag) == -1) + ret = -1; + } else if (S_ISREG(dir_entries[i]->a.perm) || + (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { +@@ -1793,7 +1796,8 @@ download_dir_internal(struct sftp_conn * + if (do_download(conn, new_src, new_dst, + S_ISLNK(dir_entries[i]->a.perm) ? NULL : + &(dir_entries[i]->a), +- preserve_flag, resume_flag, fsync_flag) == -1) { ++ preserve_flag, resume_flag, fsync_flag, ++ inplace_flag) == -1) { + error("Download of file %s to %s failed", + new_src, new_dst); + ret = -1; +@@ -1831,7 +1835,7 @@ download_dir_internal(struct sftp_conn * + int + download_dir(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, +- int fsync_flag, int follow_link_flag) ++ int fsync_flag, int follow_link_flag, int inplace_flag) + { + char *src_canon; + int ret; +@@ -1843,26 +1847,25 @@ download_dir(struct sftp_conn *conn, con + + ret = download_dir_internal(conn, src_canon, dst, 0, + dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, +- follow_link_flag); ++ follow_link_flag, inplace_flag); + free(src_canon); + return ret; + } + + int + do_upload(struct sftp_conn *conn, const char *local_path, +- const char *remote_path, int preserve_flag, int resume, int fsync_flag) ++ const char *remote_path, int preserve_flag, int resume, ++ int fsync_flag, int inplace_flag) + { + int r, local_fd; +- u_int status = SSH2_FX_OK; +- u_int id; +- u_char type; ++ u_int openmode, id, status = SSH2_FX_OK, reordered = 0; + off_t offset, progress_counter; +- u_char *handle, *data; ++ u_char type, *handle, *data; + struct sshbuf *msg; + struct stat sb; +- Attrib a, *c = NULL; +- u_int32_t startid; +- u_int32_t ackid; ++ Attrib a, t, *c = NULL; ++ u_int32_t startid, ackid; ++ u_int64_t highwater = 0; + struct request *ack = NULL; + struct requests acks; + size_t handle_len; +@@ -1913,10 +1916,15 @@ do_upload(struct sftp_conn *conn, const + } + } + ++ openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; ++ if (resume) ++ openmode |= SSH2_FXF_APPEND; ++ else if (!inplace_flag) ++ openmode |= SSH2_FXF_TRUNC; ++ + /* Send open request */ +- if (send_open(conn, remote_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT| +- (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC), +- &a, &handle, &handle_len) != 0) { ++ if (send_open(conn, remote_path, "dest", openmode, &a, ++ &handle, &handle_len) != 0) { + close(local_fd); + return -1; + } +@@ -1999,6 +2007,12 @@ do_upload(struct sftp_conn *conn, const + ack->id, ack->len, (unsigned long long)ack->offset); + ++ackid; + progress_counter += ack->len; ++ if (!reordered && ack->offset <= highwater) ++ highwater = ack->offset + ack->len; ++ else if (!reordered && ack->offset > highwater) { ++ debug3_f("server reordered ACKs"); ++ reordered = 1; ++ } + free(ack); + } + offset += len; +@@ -2017,6 +2031,14 @@ do_upload(struct sftp_conn *conn, const + status = SSH2_FX_FAILURE; + } + ++ if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { ++ debug("truncating at %llu", (unsigned long long)highwater); ++ attrib_clear(&t); ++ t.flags = SSH2_FILEXFER_ATTR_SIZE; ++ t.size = highwater; ++ do_fsetstat(conn, handle, handle_len, &t); ++ } ++ + if (close(local_fd) == -1) { + error("Couldn't close local file \"%s\": %s", local_path, + strerror(errno)); +@@ -2041,7 +2063,7 @@ do_upload(struct sftp_conn *conn, const + static int + upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, +- int follow_link_flag) ++ int follow_link_flag, int inplace_flag) + { + int ret = 0; + DIR *dirp; +@@ -2119,12 +2141,13 @@ upload_dir_internal(struct sftp_conn *co + + if (upload_dir_internal(conn, new_src, new_dst, + depth + 1, preserve_flag, print_flag, resume, +- fsync_flag, follow_link_flag) == -1) ++ fsync_flag, follow_link_flag, inplace_flag) == -1) + ret = -1; + } else if (S_ISREG(sb.st_mode) || + (follow_link_flag && S_ISLNK(sb.st_mode))) { + if (do_upload(conn, new_src, new_dst, +- preserve_flag, resume, fsync_flag) == -1) { ++ preserve_flag, resume, fsync_flag, ++ inplace_flag) == -1) { + error("Uploading of file %s to %s failed!", + new_src, new_dst); + ret = -1; +@@ -2144,7 +2167,7 @@ upload_dir_internal(struct sftp_conn *co + int + upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + int preserve_flag, int print_flag, int resume, int fsync_flag, +- int follow_link_flag, int create_dir) ++ int follow_link_flag, int create_dir, int inplace_flag) + { + char *dst_canon; + int ret; +@@ -2155,7 +2178,7 @@ upload_dir(struct sftp_conn *conn, const + } + + ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, +- print_flag, resume, fsync_flag, follow_link_flag); ++ print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); + + free(dst_canon); + return ret; +diff --color -rup a/sftp-client.h b/sftp-client.h +--- a/sftp-client.h 2022-07-26 14:51:40.561120836 +0200 ++++ b/sftp-client.h 2022-07-26 14:52:37.120213042 +0200 +@@ -138,28 +138,29 @@ int do_fsync(struct sftp_conn *conn, u_c + * Download 'remote_path' to 'local_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_download(struct sftp_conn *, const char *, const char *, +- Attrib *, int, int, int); ++int do_download(struct sftp_conn *, const char *, const char *, Attrib *, ++ int, int, int, int); + + /* + * Recursively download 'remote_directory' to 'local_directory'. Preserve + * times if 'pflag' is set + */ +-int download_dir(struct sftp_conn *, const char *, const char *, +- Attrib *, int, int, int, int, int); ++int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, ++ int, int, int, int, int, int); + + /* + * Upload 'local_path' to 'remote_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_upload(struct sftp_conn *, const char *, const char *, int, int, int); ++int do_upload(struct sftp_conn *, const char *, const char *, ++ int, int, int, int); + + /* + * Recursively upload 'local_directory' to 'remote_directory'. Preserve + * times if 'pflag' is set + */ +-int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, +- int, int, int); ++int upload_dir(struct sftp_conn *, const char *, const char *, ++ int, int, int, int, int, int, int); + + /* + * Download a 'from_path' from the 'from' connection and upload it to diff --git a/SPECS/openssh.spec b/SPECS/openssh.spec index 6f6e971..a5d09f0 100644 --- a/SPECS/openssh.spec +++ b/SPECS/openssh.spec @@ -51,7 +51,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 8.7p1 -%global openssh_rel 8 +%global openssh_rel 10 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 4 @@ -214,6 +214,10 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch Patch981: openssh-8.7p1-recursive-scp.patch Patch1000: openssh-8.7p1-minimize-sha1-use.patch +# Fix for scp clearing file when src and dest are the same (#2108409) +# upstream commits: +# 7b1cbcb7599d9f6a3bbad79d412604aa1203b5ee +Patch1001: openssh-8.7p1-scp-clears-file.patch License: BSD Requires: /sbin/nologin @@ -401,6 +405,7 @@ popd %patch700 -p1 -b .fips %patch1000 -p1 -b .minsha1 +%patch1001 -p1 -b .scp-clears-file %patch100 -p1 -b .coverity @@ -681,6 +686,14 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Jul 26 2022 Zoltan Fridrich - 8.7p1-10 +- Fix openssh-8.7p1-scp-clears-file.patch + Related: rhbz#2108409 + +* Thu Jul 21 2022 Zoltan Fridrich - 8.7p1-9 +- Fix scp clearing file when src and dest are the same + Resolves: rhbz#2108409 + * Mon Feb 21 2022 Dmitry Belyavskiy - 8.7p1-8 - Workaround for RHEL 8 incompatibility in scp utility in SFTP mode Related: rhbz#2038854