openssh/openssh-9.9p1-copy-data-ext-self-copy.patch
Zoltan Fridrich 274a6bf6ad Fix self-copy guard bypass in copy-data extension
Resolves: RHEL-191388

Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
2026-07-17 16:34:44 +02:00

52 lines
1.9 KiB
Diff

diff --color -ruNp a/sftp-server.c b/sftp-server.c
--- a/sftp-server.c 2026-07-17 16:23:12.293427062 +0200
+++ b/sftp-server.c 2026-07-17 16:29:01.480535500 +0200
@@ -1625,6 +1625,7 @@ process_extended_copy_data(u_int32_t id)
u_int64_t len, read_off, read_len, write_off;
int r, copy_until_eof, status = SSH2_FX_OP_UNSUPPORTED;
size_t ret;
+ struct stat st_read, st_write;
if ((r = get_handle(iqueue, &read_handle)) != 0 ||
(r = sshbuf_get_u64(iqueue, &read_off)) != 0 ||
@@ -1647,12 +1648,35 @@ process_extended_copy_data(u_int32_t id)
} else
copy_until_eof = 0;
+ /* Disallow reading & writing to the same handle, path or inode */
read_fd = handle_to_fd(read_handle);
write_fd = handle_to_fd(write_handle);
-
- /* Disallow reading & writing to the same handle or same path or dirs */
- if (read_handle == write_handle || read_fd < 0 || write_fd < 0 ||
- !strcmp(handle_to_name(read_handle), handle_to_name(write_handle))) {
+ if (read_fd < 0 || write_fd < 0) {
+ error_f("bad read or write fd");
+ status = errno_to_portable(EBADF);
+ goto out;
+ }
+ if (fstat(read_fd, &st_read) != 0) {
+ status = errno_to_portable(errno);
+ error_f("fstat read_fd failed: %s", strerror(errno));
+ goto out;
+ }
+ if (fstat(write_fd, &st_write) != 0) {
+ status = errno_to_portable(errno);
+ error_f("fstat write_fd failed: %s", strerror(errno));
+ goto out;
+ }
+ if (read_handle == write_handle ||
+ !strcmp(handle_to_name(read_handle), handle_to_name(write_handle)) ||
+ (st_read.st_dev != 0 && st_read.st_ino != 0 &&
+ st_read.st_dev == st_write.st_dev &&
+ st_read.st_ino == st_write.st_ino)) {
+ error_f("refusing to read/write same file: "
+ "read \"%s\" dev %lu ino %lu, write \"%s\" dev %lu ino %lu",
+ handle_to_name(read_handle),
+ (u_long)st_read.st_dev, (u_long)st_read.st_ino,
+ handle_to_name(write_handle),
+ (u_long)st_write.st_dev, (u_long)st_write.st_ino);
status = SSH2_FX_FAILURE;
goto out;
}