summaryrefslogtreecommitdiff
path: root/progressmeter.c
diff options
context:
space:
mode:
authordtucker@openbsd.org <dtucker@openbsd.org>2019-01-23 08:01:46 +0000
committerColin Watson <cjwatson@debian.org>2019-02-08 15:38:28 +0000
commit11b88754cadcad0ba79b4ffcc127223248dccb54 (patch)
tree2c9793f792675bc79de7f7a3bcae66cdfaa719ca /progressmeter.c
parentdee21e97428e69d30e2d15c71f3e7cc08bf8e4f8 (diff)
upstream: Sanitize scp filenames via snmprintf. To do this we move
the progressmeter formatting outside of signal handler context and have the atomicio callback called for EINTR too. bz#2434 with contributions from djm and jjelen at redhat.com, ok djm@ OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8 CVE-2019-6109 Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=8976f1c4b2721c26e878151f52bdf346dfe2d54c Bug-Debian: https://bugs.debian.org/793412 Last-Update: 2019-02-08 Patch-Name: sanitize-scp-filenames-via-snmprintf.patch
Diffstat (limited to 'progressmeter.c')
-rw-r--r--progressmeter.c53
1 files changed, 24 insertions, 29 deletions
diff --git a/progressmeter.c b/progressmeter.c
index fe9bf52e4..add462dde 100644
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: progressmeter.c,v 1.45 2016/06/30 05:17:05 dtucker Exp $ */ 1/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2003 Nils Nordman. All rights reserved. 3 * Copyright (c) 2003 Nils Nordman. All rights reserved.
4 * 4 *
@@ -31,6 +31,7 @@
31 31
32#include <errno.h> 32#include <errno.h>
33#include <signal.h> 33#include <signal.h>
34#include <stdarg.h>
34#include <stdio.h> 35#include <stdio.h>
35#include <string.h> 36#include <string.h>
36#include <time.h> 37#include <time.h>
@@ -39,6 +40,7 @@
39#include "progressmeter.h" 40#include "progressmeter.h"
40#include "atomicio.h" 41#include "atomicio.h"
41#include "misc.h" 42#include "misc.h"
43#include "utf8.h"
42 44
43#define DEFAULT_WINSIZE 80 45#define DEFAULT_WINSIZE 80
44#define MAX_WINSIZE 512 46#define MAX_WINSIZE 512
@@ -61,7 +63,7 @@ static void setscreensize(void);
61void refresh_progress_meter(void); 63void refresh_progress_meter(void);
62 64
63/* signal handler for updating the progress meter */ 65/* signal handler for updating the progress meter */
64static void update_progress_meter(int); 66static void sig_alarm(int);
65 67
66static double start; /* start progress */ 68static double start; /* start progress */
67static double last_update; /* last progress update */ 69static double last_update; /* last progress update */
@@ -74,6 +76,7 @@ static long stalled; /* how long we have been stalled */
74static int bytes_per_second; /* current speed in bytes per second */ 76static int bytes_per_second; /* current speed in bytes per second */
75static int win_size; /* terminal window size */ 77static int win_size; /* terminal window size */
76static volatile sig_atomic_t win_resized; /* for window resizing */ 78static volatile sig_atomic_t win_resized; /* for window resizing */
79static volatile sig_atomic_t alarm_fired;
77 80
78/* units for format_size */ 81/* units for format_size */
79static const char unit[] = " KMGT"; 82static const char unit[] = " KMGT";
@@ -126,9 +129,17 @@ refresh_progress_meter(void)
126 off_t bytes_left; 129 off_t bytes_left;
127 int cur_speed; 130 int cur_speed;
128 int hours, minutes, seconds; 131 int hours, minutes, seconds;
129 int i, len;
130 int file_len; 132 int file_len;
131 133
134 if ((!alarm_fired && !win_resized) || !can_output())
135 return;
136 alarm_fired = 0;
137
138 if (win_resized) {
139 setscreensize();
140 win_resized = 0;
141 }
142
132 transferred = *counter - (cur_pos ? cur_pos : start_pos); 143 transferred = *counter - (cur_pos ? cur_pos : start_pos);
133 cur_pos = *counter; 144 cur_pos = *counter;
134 now = monotime_double(); 145 now = monotime_double();
@@ -158,16 +169,11 @@ refresh_progress_meter(void)
158 169
159 /* filename */ 170 /* filename */
160 buf[0] = '\0'; 171 buf[0] = '\0';
161 file_len = win_size - 35; 172 file_len = win_size - 36;
162 if (file_len > 0) { 173 if (file_len > 0) {
163 len = snprintf(buf, file_len + 1, "\r%s", file); 174 buf[0] = '\r';
164 if (len < 0) 175 snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s",
165 len = 0; 176 file_len * -1, file);
166 if (len >= file_len + 1)
167 len = file_len;
168 for (i = len; i < file_len; i++)
169 buf[i] = ' ';
170 buf[file_len] = '\0';
171 } 177 }
172 178
173 /* percent of transfer done */ 179 /* percent of transfer done */
@@ -228,22 +234,11 @@ refresh_progress_meter(void)
228 234
229/*ARGSUSED*/ 235/*ARGSUSED*/
230static void 236static void
231update_progress_meter(int ignore) 237sig_alarm(int ignore)
232{ 238{
233 int save_errno; 239 signal(SIGALRM, sig_alarm);
234 240 alarm_fired = 1;
235 save_errno = errno;
236
237 if (win_resized) {
238 setscreensize();
239 win_resized = 0;
240 }
241 if (can_output())
242 refresh_progress_meter();
243
244 signal(SIGALRM, update_progress_meter);
245 alarm(UPDATE_INTERVAL); 241 alarm(UPDATE_INTERVAL);
246 errno = save_errno;
247} 242}
248 243
249void 244void
@@ -259,10 +254,9 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr)
259 bytes_per_second = 0; 254 bytes_per_second = 0;
260 255
261 setscreensize(); 256 setscreensize();
262 if (can_output()) 257 refresh_progress_meter();
263 refresh_progress_meter();
264 258
265 signal(SIGALRM, update_progress_meter); 259 signal(SIGALRM, sig_alarm);
266 signal(SIGWINCH, sig_winch); 260 signal(SIGWINCH, sig_winch);
267 alarm(UPDATE_INTERVAL); 261 alarm(UPDATE_INTERVAL);
268} 262}
@@ -286,6 +280,7 @@ stop_progress_meter(void)
286static void 280static void
287sig_winch(int sig) 281sig_winch(int sig)
288{ 282{
283 signal(SIGWINCH, sig_winch);
289 win_resized = 1; 284 win_resized = 1;
290} 285}
291 286