diff options
author | Colin Watson <cjwatson@debian.org> | 2019-02-08 15:41:19 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2019-02-08 16:24:58 +0000 |
commit | bbf87fe18360e9dabdeb9af0cadff0f8087a5492 (patch) | |
tree | 6aba9afdccceb18a863f0fc6c89d3ec06a2961ac /debian/patches | |
parent | d6448492718c5e1174323eebcc696364e96d5047 (diff) | |
parent | 2a8f710447442e9a03e71c022859112ec2d77d17 (diff) |
Sanitize scp filenames via snmprintf
CVE-2019-6109
Closes: #793412
Diffstat (limited to 'debian/patches')
-rw-r--r-- | debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch | 120 | ||||
-rw-r--r-- | debian/patches/sanitize-scp-filenames-via-snmprintf.patch | 276 | ||||
-rw-r--r-- | debian/patches/series | 2 |
3 files changed, 398 insertions, 0 deletions
diff --git a/debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch b/debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch new file mode 100644 index 000000000..767dbf2b5 --- /dev/null +++ b/debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch | |||
@@ -0,0 +1,120 @@ | |||
1 | From 2a8f710447442e9a03e71c022859112ec2d77d17 Mon Sep 17 00:00:00 2001 | ||
2 | From: "dtucker@openbsd.org" <dtucker@openbsd.org> | ||
3 | Date: Thu, 24 Jan 2019 16:52:17 +0000 | ||
4 | Subject: upstream: Have progressmeter force an update at the beginning and | ||
5 | |||
6 | end of each transfer. Fixes the problem recently introduces where very quick | ||
7 | transfers do not display the progressmeter at all. Spotted by naddy@ | ||
8 | |||
9 | OpenBSD-Commit-ID: 68dc46c259e8fdd4f5db3ec2a130f8e4590a7a9a | ||
10 | |||
11 | Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=bdc6c63c80b55bcbaa66b5fde31c1cb1d09a41eb | ||
12 | Last-Update: 2019-02-08 | ||
13 | |||
14 | Patch-Name: have-progressmeter-force-update-at-beginning-and-end-transfer.patch | ||
15 | --- | ||
16 | progressmeter.c | 13 +++++-------- | ||
17 | progressmeter.h | 4 ++-- | ||
18 | scp.c | 2 +- | ||
19 | sftp-client.c | 2 +- | ||
20 | 4 files changed, 9 insertions(+), 12 deletions(-) | ||
21 | |||
22 | diff --git a/progressmeter.c b/progressmeter.c | ||
23 | index add462dde..e385c1254 100644 | ||
24 | --- a/progressmeter.c | ||
25 | +++ b/progressmeter.c | ||
26 | @@ -1,4 +1,4 @@ | ||
27 | -/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */ | ||
28 | +/* $OpenBSD: progressmeter.c,v 1.47 2019/01/24 16:52:17 dtucker Exp $ */ | ||
29 | /* | ||
30 | * Copyright (c) 2003 Nils Nordman. All rights reserved. | ||
31 | * | ||
32 | @@ -59,9 +59,6 @@ static void format_rate(char *, int, off_t); | ||
33 | static void sig_winch(int); | ||
34 | static void setscreensize(void); | ||
35 | |||
36 | -/* updates the progressmeter to reflect the current state of the transfer */ | ||
37 | -void refresh_progress_meter(void); | ||
38 | - | ||
39 | /* signal handler for updating the progress meter */ | ||
40 | static void sig_alarm(int); | ||
41 | |||
42 | @@ -120,7 +117,7 @@ format_size(char *buf, int size, off_t bytes) | ||
43 | } | ||
44 | |||
45 | void | ||
46 | -refresh_progress_meter(void) | ||
47 | +refresh_progress_meter(int force_update) | ||
48 | { | ||
49 | char buf[MAX_WINSIZE + 1]; | ||
50 | off_t transferred; | ||
51 | @@ -131,7 +128,7 @@ refresh_progress_meter(void) | ||
52 | int hours, minutes, seconds; | ||
53 | int file_len; | ||
54 | |||
55 | - if ((!alarm_fired && !win_resized) || !can_output()) | ||
56 | + if ((!force_update && !alarm_fired && !win_resized) || !can_output()) | ||
57 | return; | ||
58 | alarm_fired = 0; | ||
59 | |||
60 | @@ -254,7 +251,7 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr) | ||
61 | bytes_per_second = 0; | ||
62 | |||
63 | setscreensize(); | ||
64 | - refresh_progress_meter(); | ||
65 | + refresh_progress_meter(1); | ||
66 | |||
67 | signal(SIGALRM, sig_alarm); | ||
68 | signal(SIGWINCH, sig_winch); | ||
69 | @@ -271,7 +268,7 @@ stop_progress_meter(void) | ||
70 | |||
71 | /* Ensure we complete the progress */ | ||
72 | if (cur_pos != end_pos) | ||
73 | - refresh_progress_meter(); | ||
74 | + refresh_progress_meter(1); | ||
75 | |||
76 | atomicio(vwrite, STDOUT_FILENO, "\n", 1); | ||
77 | } | ||
78 | diff --git a/progressmeter.h b/progressmeter.h | ||
79 | index 8f6678060..1703ea75b 100644 | ||
80 | --- a/progressmeter.h | ||
81 | +++ b/progressmeter.h | ||
82 | @@ -1,4 +1,4 @@ | ||
83 | -/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */ | ||
84 | +/* $OpenBSD: progressmeter.h,v 1.5 2019/01/24 16:52:17 dtucker Exp $ */ | ||
85 | /* | ||
86 | * Copyright (c) 2002 Nils Nordman. All rights reserved. | ||
87 | * | ||
88 | @@ -24,5 +24,5 @@ | ||
89 | */ | ||
90 | |||
91 | void start_progress_meter(const char *, off_t, off_t *); | ||
92 | -void refresh_progress_meter(void); | ||
93 | +void refresh_progress_meter(int); | ||
94 | void stop_progress_meter(void); | ||
95 | diff --git a/scp.c b/scp.c | ||
96 | index 80308573c..1971c80cd 100644 | ||
97 | --- a/scp.c | ||
98 | +++ b/scp.c | ||
99 | @@ -593,7 +593,7 @@ scpio(void *_cnt, size_t s) | ||
100 | off_t *cnt = (off_t *)_cnt; | ||
101 | |||
102 | *cnt += s; | ||
103 | - refresh_progress_meter(); | ||
104 | + refresh_progress_meter(0); | ||
105 | if (limit_kbps > 0) | ||
106 | bandwidth_limit(&bwlimit, s); | ||
107 | return 0; | ||
108 | diff --git a/sftp-client.c b/sftp-client.c | ||
109 | index 2bc698f86..cf2887a40 100644 | ||
110 | --- a/sftp-client.c | ||
111 | +++ b/sftp-client.c | ||
112 | @@ -101,7 +101,7 @@ sftpio(void *_bwlimit, size_t amount) | ||
113 | { | ||
114 | struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; | ||
115 | |||
116 | - refresh_progress_meter(); | ||
117 | + refresh_progress_meter(0); | ||
118 | if (bwlimit != NULL) | ||
119 | bandwidth_limit(bwlimit, amount); | ||
120 | return 0; | ||
diff --git a/debian/patches/sanitize-scp-filenames-via-snmprintf.patch b/debian/patches/sanitize-scp-filenames-via-snmprintf.patch new file mode 100644 index 000000000..e58b8b1bd --- /dev/null +++ b/debian/patches/sanitize-scp-filenames-via-snmprintf.patch | |||
@@ -0,0 +1,276 @@ | |||
1 | From 11b88754cadcad0ba79b4ffcc127223248dccb54 Mon Sep 17 00:00:00 2001 | ||
2 | From: "dtucker@openbsd.org" <dtucker@openbsd.org> | ||
3 | Date: Wed, 23 Jan 2019 08:01:46 +0000 | ||
4 | Subject: upstream: Sanitize scp filenames via snmprintf. To do this we move | ||
5 | |||
6 | the progressmeter formatting outside of signal handler context and have the | ||
7 | atomicio callback called for EINTR too. bz#2434 with contributions from djm | ||
8 | and jjelen at redhat.com, ok djm@ | ||
9 | |||
10 | OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8 | ||
11 | |||
12 | CVE-2019-6109 | ||
13 | |||
14 | Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=8976f1c4b2721c26e878151f52bdf346dfe2d54c | ||
15 | Bug-Debian: https://bugs.debian.org/793412 | ||
16 | Last-Update: 2019-02-08 | ||
17 | |||
18 | Patch-Name: sanitize-scp-filenames-via-snmprintf.patch | ||
19 | --- | ||
20 | atomicio.c | 20 ++++++++++++++----- | ||
21 | progressmeter.c | 53 ++++++++++++++++++++++--------------------------- | ||
22 | progressmeter.h | 3 ++- | ||
23 | scp.c | 1 + | ||
24 | sftp-client.c | 16 ++++++++------- | ||
25 | 5 files changed, 51 insertions(+), 42 deletions(-) | ||
26 | |||
27 | diff --git a/atomicio.c b/atomicio.c | ||
28 | index f854a06f5..d91bd7621 100644 | ||
29 | --- a/atomicio.c | ||
30 | +++ b/atomicio.c | ||
31 | @@ -1,4 +1,4 @@ | ||
32 | -/* $OpenBSD: atomicio.c,v 1.28 2016/07/27 23:18:12 djm Exp $ */ | ||
33 | +/* $OpenBSD: atomicio.c,v 1.29 2019/01/23 08:01:46 dtucker Exp $ */ | ||
34 | /* | ||
35 | * Copyright (c) 2006 Damien Miller. All rights reserved. | ||
36 | * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. | ||
37 | @@ -65,9 +65,14 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n, | ||
38 | res = (f) (fd, s + pos, n - pos); | ||
39 | switch (res) { | ||
40 | case -1: | ||
41 | - if (errno == EINTR) | ||
42 | + if (errno == EINTR) { | ||
43 | + /* possible SIGALARM, update callback */ | ||
44 | + if (cb != NULL && cb(cb_arg, 0) == -1) { | ||
45 | + errno = EINTR; | ||
46 | + return pos; | ||
47 | + } | ||
48 | continue; | ||
49 | - if (errno == EAGAIN || errno == EWOULDBLOCK) { | ||
50 | + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { | ||
51 | #ifndef BROKEN_READ_COMPARISON | ||
52 | (void)poll(&pfd, 1, -1); | ||
53 | #endif | ||
54 | @@ -122,9 +127,14 @@ atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd, | ||
55 | res = (f) (fd, iov, iovcnt); | ||
56 | switch (res) { | ||
57 | case -1: | ||
58 | - if (errno == EINTR) | ||
59 | + if (errno == EINTR) { | ||
60 | + /* possible SIGALARM, update callback */ | ||
61 | + if (cb != NULL && cb(cb_arg, 0) == -1) { | ||
62 | + errno = EINTR; | ||
63 | + return pos; | ||
64 | + } | ||
65 | continue; | ||
66 | - if (errno == EAGAIN || errno == EWOULDBLOCK) { | ||
67 | + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { | ||
68 | #ifndef BROKEN_READV_COMPARISON | ||
69 | (void)poll(&pfd, 1, -1); | ||
70 | #endif | ||
71 | diff --git a/progressmeter.c b/progressmeter.c | ||
72 | index fe9bf52e4..add462dde 100644 | ||
73 | --- a/progressmeter.c | ||
74 | +++ b/progressmeter.c | ||
75 | @@ -1,4 +1,4 @@ | ||
76 | -/* $OpenBSD: progressmeter.c,v 1.45 2016/06/30 05:17:05 dtucker Exp $ */ | ||
77 | +/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */ | ||
78 | /* | ||
79 | * Copyright (c) 2003 Nils Nordman. All rights reserved. | ||
80 | * | ||
81 | @@ -31,6 +31,7 @@ | ||
82 | |||
83 | #include <errno.h> | ||
84 | #include <signal.h> | ||
85 | +#include <stdarg.h> | ||
86 | #include <stdio.h> | ||
87 | #include <string.h> | ||
88 | #include <time.h> | ||
89 | @@ -39,6 +40,7 @@ | ||
90 | #include "progressmeter.h" | ||
91 | #include "atomicio.h" | ||
92 | #include "misc.h" | ||
93 | +#include "utf8.h" | ||
94 | |||
95 | #define DEFAULT_WINSIZE 80 | ||
96 | #define MAX_WINSIZE 512 | ||
97 | @@ -61,7 +63,7 @@ static void setscreensize(void); | ||
98 | void refresh_progress_meter(void); | ||
99 | |||
100 | /* signal handler for updating the progress meter */ | ||
101 | -static void update_progress_meter(int); | ||
102 | +static void sig_alarm(int); | ||
103 | |||
104 | static double start; /* start progress */ | ||
105 | static double last_update; /* last progress update */ | ||
106 | @@ -74,6 +76,7 @@ static long stalled; /* how long we have been stalled */ | ||
107 | static int bytes_per_second; /* current speed in bytes per second */ | ||
108 | static int win_size; /* terminal window size */ | ||
109 | static volatile sig_atomic_t win_resized; /* for window resizing */ | ||
110 | +static volatile sig_atomic_t alarm_fired; | ||
111 | |||
112 | /* units for format_size */ | ||
113 | static const char unit[] = " KMGT"; | ||
114 | @@ -126,9 +129,17 @@ refresh_progress_meter(void) | ||
115 | off_t bytes_left; | ||
116 | int cur_speed; | ||
117 | int hours, minutes, seconds; | ||
118 | - int i, len; | ||
119 | int file_len; | ||
120 | |||
121 | + if ((!alarm_fired && !win_resized) || !can_output()) | ||
122 | + return; | ||
123 | + alarm_fired = 0; | ||
124 | + | ||
125 | + if (win_resized) { | ||
126 | + setscreensize(); | ||
127 | + win_resized = 0; | ||
128 | + } | ||
129 | + | ||
130 | transferred = *counter - (cur_pos ? cur_pos : start_pos); | ||
131 | cur_pos = *counter; | ||
132 | now = monotime_double(); | ||
133 | @@ -158,16 +169,11 @@ refresh_progress_meter(void) | ||
134 | |||
135 | /* filename */ | ||
136 | buf[0] = '\0'; | ||
137 | - file_len = win_size - 35; | ||
138 | + file_len = win_size - 36; | ||
139 | if (file_len > 0) { | ||
140 | - len = snprintf(buf, file_len + 1, "\r%s", file); | ||
141 | - if (len < 0) | ||
142 | - len = 0; | ||
143 | - if (len >= file_len + 1) | ||
144 | - len = file_len; | ||
145 | - for (i = len; i < file_len; i++) | ||
146 | - buf[i] = ' '; | ||
147 | - buf[file_len] = '\0'; | ||
148 | + buf[0] = '\r'; | ||
149 | + snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s", | ||
150 | + file_len * -1, file); | ||
151 | } | ||
152 | |||
153 | /* percent of transfer done */ | ||
154 | @@ -228,22 +234,11 @@ refresh_progress_meter(void) | ||
155 | |||
156 | /*ARGSUSED*/ | ||
157 | static void | ||
158 | -update_progress_meter(int ignore) | ||
159 | +sig_alarm(int ignore) | ||
160 | { | ||
161 | - int save_errno; | ||
162 | - | ||
163 | - save_errno = errno; | ||
164 | - | ||
165 | - if (win_resized) { | ||
166 | - setscreensize(); | ||
167 | - win_resized = 0; | ||
168 | - } | ||
169 | - if (can_output()) | ||
170 | - refresh_progress_meter(); | ||
171 | - | ||
172 | - signal(SIGALRM, update_progress_meter); | ||
173 | + signal(SIGALRM, sig_alarm); | ||
174 | + alarm_fired = 1; | ||
175 | alarm(UPDATE_INTERVAL); | ||
176 | - errno = save_errno; | ||
177 | } | ||
178 | |||
179 | void | ||
180 | @@ -259,10 +254,9 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr) | ||
181 | bytes_per_second = 0; | ||
182 | |||
183 | setscreensize(); | ||
184 | - if (can_output()) | ||
185 | - refresh_progress_meter(); | ||
186 | + refresh_progress_meter(); | ||
187 | |||
188 | - signal(SIGALRM, update_progress_meter); | ||
189 | + signal(SIGALRM, sig_alarm); | ||
190 | signal(SIGWINCH, sig_winch); | ||
191 | alarm(UPDATE_INTERVAL); | ||
192 | } | ||
193 | @@ -286,6 +280,7 @@ stop_progress_meter(void) | ||
194 | static void | ||
195 | sig_winch(int sig) | ||
196 | { | ||
197 | + signal(SIGWINCH, sig_winch); | ||
198 | win_resized = 1; | ||
199 | } | ||
200 | |||
201 | diff --git a/progressmeter.h b/progressmeter.h | ||
202 | index bf179dca6..8f6678060 100644 | ||
203 | --- a/progressmeter.h | ||
204 | +++ b/progressmeter.h | ||
205 | @@ -1,4 +1,4 @@ | ||
206 | -/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */ | ||
207 | +/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */ | ||
208 | /* | ||
209 | * Copyright (c) 2002 Nils Nordman. All rights reserved. | ||
210 | * | ||
211 | @@ -24,4 +24,5 @@ | ||
212 | */ | ||
213 | |||
214 | void start_progress_meter(const char *, off_t, off_t *); | ||
215 | +void refresh_progress_meter(void); | ||
216 | void stop_progress_meter(void); | ||
217 | diff --git a/scp.c b/scp.c | ||
218 | index 7163d33dc..80308573c 100644 | ||
219 | --- a/scp.c | ||
220 | +++ b/scp.c | ||
221 | @@ -593,6 +593,7 @@ scpio(void *_cnt, size_t s) | ||
222 | off_t *cnt = (off_t *)_cnt; | ||
223 | |||
224 | *cnt += s; | ||
225 | + refresh_progress_meter(); | ||
226 | if (limit_kbps > 0) | ||
227 | bandwidth_limit(&bwlimit, s); | ||
228 | return 0; | ||
229 | diff --git a/sftp-client.c b/sftp-client.c | ||
230 | index 4986d6d8d..2bc698f86 100644 | ||
231 | --- a/sftp-client.c | ||
232 | +++ b/sftp-client.c | ||
233 | @@ -101,7 +101,9 @@ sftpio(void *_bwlimit, size_t amount) | ||
234 | { | ||
235 | struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; | ||
236 | |||
237 | - bandwidth_limit(bwlimit, amount); | ||
238 | + refresh_progress_meter(); | ||
239 | + if (bwlimit != NULL) | ||
240 | + bandwidth_limit(bwlimit, amount); | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | @@ -121,8 +123,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m) | ||
245 | iov[1].iov_base = (u_char *)sshbuf_ptr(m); | ||
246 | iov[1].iov_len = sshbuf_len(m); | ||
247 | |||
248 | - if (atomiciov6(writev, conn->fd_out, iov, 2, | ||
249 | - conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != | ||
250 | + if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, | ||
251 | + conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != | ||
252 | sshbuf_len(m) + sizeof(mlen)) | ||
253 | fatal("Couldn't send packet: %s", strerror(errno)); | ||
254 | |||
255 | @@ -138,8 +140,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) | ||
256 | |||
257 | if ((r = sshbuf_reserve(m, 4, &p)) != 0) | ||
258 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
259 | - if (atomicio6(read, conn->fd_in, p, 4, | ||
260 | - conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { | ||
261 | + if (atomicio6(read, conn->fd_in, p, 4, sftpio, | ||
262 | + conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { | ||
263 | if (errno == EPIPE || errno == ECONNRESET) | ||
264 | fatal("Connection closed"); | ||
265 | else | ||
266 | @@ -157,8 +159,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) | ||
267 | |||
268 | if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) | ||
269 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
270 | - if (atomicio6(read, conn->fd_in, p, msg_len, | ||
271 | - conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) | ||
272 | + if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, | ||
273 | + conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) | ||
274 | != msg_len) { | ||
275 | if (errno == EPIPE) | ||
276 | fatal("Connection closed"); | ||
diff --git a/debian/patches/series b/debian/patches/series index a6fc19449..710e56b7b 100644 --- a/debian/patches/series +++ b/debian/patches/series | |||
@@ -25,3 +25,5 @@ seccomp-s390-flock-ipc.patch | |||
25 | seccomp-s390-ioctl-ep11-crypto.patch | 25 | seccomp-s390-ioctl-ep11-crypto.patch |
26 | conch-old-privkey-format.patch | 26 | conch-old-privkey-format.patch |
27 | scp-disallow-dot-or-empty-filename.patch | 27 | scp-disallow-dot-or-empty-filename.patch |
28 | sanitize-scp-filenames-via-snmprintf.patch | ||
29 | have-progressmeter-force-update-at-beginning-and-end-transfer.patch | ||