Read fails when using large buffers (starting from around 4GB)
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
- #2587 của @afonsojanu — đã đóng, không merge
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- c
- Lĩnh vực
- backend, networking
Hướng nghiên cứu
Start by tracing libssh2_channel_read and the receive-window adjustment code mentioned in the report, then inspect the types used for buffer lengths and window values. Reproduce with the supplied example or a focused test using a buffer near 4GB. Done means oversized reads no longer trigger the reported overflow or server error; the issue does not name a test file.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
libssh2_channel_read starts misbehaving when using large buffers, around 4GB or more in size. It seems that the API accepts size_t buflen which is 64bit (on my machine), but that gets converted to uint32_t in the implementation causing various problems. One of the errors manifests when adjusting the receive window, e.g. Unable to send transfer-window adjustment packet, deferring, while the SSH server reports something like sshd[29804]: fatal: channel 0: adjust 4294967295 overflows remote window 2097152
Code To Reproduce
#include <libssh2.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Use your own SSH auth setup
static const char *username = "<username>";
int main(int argc, char *argv[]) {
uint32_t hostaddr = inet_addr("127.0.0.1");
libssh2_socket_t sock;
struct sockaddr_in sin;
int rc;
LIBSSH2_SESSION *session = NULL;
LIBSSH2_CHANNEL *channel = NULL;
LIBSSH2_AGENT *agent = NULL;
struct libssh2_agent_publickey *identity = NULL;
rc = libssh2_init(0);
if(rc) {
fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == LIBSSH2_INVALID_SOCKET) {
fprintf(stderr, "failed to create socket!\n");
goto shutdown;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
if(connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in))) {
fprintf(stderr, "failed to connect!\n");
goto shutdown;
}
session = libssh2_session_init();
if(!session) {
fprintf(stderr, "Could not initialize SSH session!\n");
goto shutdown;
}
libssh2_session_set_blocking(session, 1);
rc = libssh2_session_handshake(session, sock);
if(rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
goto shutdown;
}
agent = libssh2_agent_init(session);
if(!agent) {
fprintf(stderr, "Failure initializing ssh-agent support\n");
rc = 1;
goto shutdown;
}
if(libssh2_agent_connect(agent)) {
fprintf(stderr, "Failure connecting to ssh-agent\n");
rc = 1;
goto shutdown;
}
if(libssh2_agent_list_identities(agent)) {
fprintf(stderr, "Failure requesting identities to ssh-agent\n");
rc = 1;
goto shutdown;
}
rc = libssh2_agent_get_identity(agent, &identity, NULL);
if(rc) {
fprintf(stderr, "Failure obtaining identity from ssh-agent support %d\n", rc);
goto shutdown;
}
if(libssh2_agent_userauth(agent, username, identity)) {
fprintf(stderr, "Authentication with username %s and "
"public key %s failed!\n",
username, identity->comment);
}
channel = libssh2_channel_open_session(session);
if(!channel) {
fprintf(stderr, "Error\n");
goto shutdown;
}
FILE *file = fopen("/tmp/large_data", "w");
if (!file) {
fprintf(stderr, "file open error\n");
goto shutdown;
}
char buf[1024 * 1024 /* 1 MB */];
memset(buf, 'a', sizeof(buf));
for (int i = 0; i < 4 * 1024 /* GB */; ++i) {
if(fwrite(buf, sizeof(buf[0]), sizeof(buf), file) < sizeof(buf)) {
fprintf(stderr, "file write error\n");
fclose(file);
goto shutdown;
}
}
fclose(file);
rc = libssh2_channel_exec(channel, "cat /tmp/large_data");
if(rc) {
fprintf(stderr, "exec error\n");
goto shutdown;
}
// 4GB - 1byte reliably causes an error on my machine.
// You can play with different sizes and see when it fails for you, or if incomplete data is read.
size_t buflen = (2l << 31) - 1;
fprintf(stderr, "sizeof(size_t): %ld, buflen: %ld\n", sizeof(size_t), buflen);
char *buffer = malloc(buflen);
ssize_t nread = libssh2_channel_read(channel, buffer, buflen);
fprintf(stderr, "libssh2_channel_read returned: %ld\n", nread);
if (nread < 0) {
char *errmsg = NULL;
libssh2_session_last_error(session, &errmsg, NULL, 0);
fprintf(stderr, "%s\n", errmsg);
}
free(buffer);
shutdown:
if(agent) {
libssh2_agent_disconnect(agent);
libssh2_agent_free(agent);
}
if(session) {
libssh2_session_disconnect(session, "Normal Shutdown");
libssh2_session_free(session);
}
if(sock != LIBSSH2_INVALID_SOCKET) {
shutdown(sock, 2);
close(sock);
}
fprintf(stderr, "all done\n");
libssh2_exit();
return 0;
}
Expected behavior
libssh2 should handle u32 overflows gracefully
Version (please complete the following information):
- OS and version: 5.15.0-75-generic # 82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023 x86_64 GNU/Linux
- libssh2 version: 1.11.0
- crypto backend and version: OpenSSL 3.0.9
- Ngôn ngữ chính
- C
- Star
- 1.6k
- Fork
- 646
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Không có hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của libssh2/libssh2
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
libssh2/libssh2#2676 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
AEAD ciphers (chacha20-poly1305, AES-GCM) leak 16 bytes of uninitialized memory per outgoing encrypted packetCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởmemory-leak
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
libssh2/libssh2#2023 · 5 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
documentation
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
libssh2/libssh2#2597 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Q&A
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
libssh2/libssh2#1925 · 13 bình luận · 32 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của libssh2/libssh2
Issue tương tự
-
dspromote: /etc/exports uses -alldirs on non-mount-point directories, so mountd exports nothingĐang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
nextbsd/nextbsd-userland#434 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[YSQL] Local-node initdb reads postgres.bki, but YB clusters bootstrap only from yb_postgres.bkiĐang mởarea/ysql kind/enhancement priority/low status/awaiting-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
yugabyte/yugabyte-db#35763 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[mimalloc] update to 3.6.0Đang mởcategory:port-update
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Maintainer thường phản hồi trong vòng 2 ngày
-
emerge failure MARK mark-unstable media-kit
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
macaroni-os/mark-issues#834 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
NVIDIA/open-gpu-kernel-modules#1479 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày