summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordtucker@openbsd.org <dtucker@openbsd.org>2019-01-23 08:01:46 +0000
committerDarren Tucker <dtucker@dtucker.net>2019-01-24 12:30:30 +1100
commit8976f1c4b2721c26e878151f52bdf346dfe2d54c (patch)
tree528e309cbe5944c0127a1c3fa0752fe2f9701232
parent6249451f381755f792c6b9e2c2f80cdc699c14e2 (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
-rw-r--r--atomicio.c20
-rw-r--r--progressmeter.c53
-rw-r--r--progressmeter.h3
-rw-r--r--scp.c3
-rw-r--r--sftp-client.c18
5 files changed, 53 insertions, 44 deletions
diff --git a/atomicio.c b/atomicio.c
index cffa9fa7d..845b328ee 100644
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: atomicio.c,v 1.28 2016/07/27 23:18:12 djm Exp $ */ 1/* $OpenBSD: atomicio.c,v 1.29 2019/01/23 08:01:46 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2006 Damien Miller. All rights reserved. 3 * Copyright (c) 2006 Damien Miller. All rights reserved.
4 * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. 4 * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
@@ -67,9 +67,14 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
67 res = (f) (fd, s + pos, n - pos); 67 res = (f) (fd, s + pos, n - pos);
68 switch (res) { 68 switch (res) {
69 case -1: 69 case -1:
70 if (errno == EINTR) 70 if (errno == EINTR) {
71 /* possible SIGALARM, update callback */
72 if (cb != NULL && cb(cb_arg, 0) == -1) {
73 errno = EINTR;
74 return pos;
75 }
71 continue; 76 continue;
72 if (errno == EAGAIN || errno == EWOULDBLOCK) { 77 } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
73 (void)poll(&pfd, 1, -1); 78 (void)poll(&pfd, 1, -1);
74 continue; 79 continue;
75 } 80 }
@@ -124,9 +129,14 @@ atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
124 res = (f) (fd, iov, iovcnt); 129 res = (f) (fd, iov, iovcnt);
125 switch (res) { 130 switch (res) {
126 case -1: 131 case -1:
127 if (errno == EINTR) 132 if (errno == EINTR) {
133 /* possible SIGALARM, update callback */
134 if (cb != NULL && cb(cb_arg, 0) == -1) {
135 errno = EINTR;
136 return pos;
137 }
128 continue; 138 continue;
129 if (errno == EAGAIN || errno == EWOULDBLOCK) { 139 } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
130 (void)poll(&pfd, 1, -1); 140 (void)poll(&pfd, 1, -1);
131 continue; 141 continue;
132 } 142 }
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
diff --git a/progressmeter.h b/progressmeter.h
index bf179dca6..8f6678060 100644
--- a/progressmeter.h
+++ b/progressmeter.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */ 1/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2002 Nils Nordman. All rights reserved. 3 * Copyright (c) 2002 Nils Nordman. All rights reserved.
4 * 4 *
@@ -24,4 +24,5 @@
24 */ 24 */
25 25
26void start_progress_meter(const char *, off_t, off_t *); 26void start_progress_meter(const char *, off_t, off_t *);
27void refresh_progress_meter(void);
27void stop_progress_meter(void); 28void stop_progress_meter(void);
diff --git a/scp.c b/scp.c
index ae51137ee..25595a299 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: scp.c,v 1.199 2019/01/21 22:50:42 tb Exp $ */ 1/* $OpenBSD: scp.c,v 1.200 2019/01/23 08:01:46 dtucker Exp $ */
2/* 2/*
3 * scp - secure remote copy. This is basically patched BSD rcp which 3 * scp - secure remote copy. This is basically patched BSD rcp which
4 * uses ssh to do the data transfer (instead of using rcmd). 4 * uses ssh to do the data transfer (instead of using rcmd).
@@ -588,6 +588,7 @@ scpio(void *_cnt, size_t s)
588 off_t *cnt = (off_t *)_cnt; 588 off_t *cnt = (off_t *)_cnt;
589 589
590 *cnt += s; 590 *cnt += s;
591 refresh_progress_meter();
591 if (limit_kbps > 0) 592 if (limit_kbps > 0)
592 bandwidth_limit(&bwlimit, s); 593 bandwidth_limit(&bwlimit, s);
593 return 0; 594 return 0;
diff --git a/sftp-client.c b/sftp-client.c
index d3f80e5a0..36c4b8a4a 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.131 2019/01/16 23:23:45 djm Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.132 2019/01/23 08:01:46 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -102,7 +102,9 @@ sftpio(void *_bwlimit, size_t amount)
102{ 102{
103 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 103 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
104 104
105 bandwidth_limit(bwlimit, amount); 105 refresh_progress_meter();
106 if (bwlimit != NULL)
107 bandwidth_limit(bwlimit, amount);
106 return 0; 108 return 0;
107} 109}
108 110
@@ -122,8 +124,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m)
122 iov[1].iov_base = (u_char *)sshbuf_ptr(m); 124 iov[1].iov_base = (u_char *)sshbuf_ptr(m);
123 iov[1].iov_len = sshbuf_len(m); 125 iov[1].iov_len = sshbuf_len(m);
124 126
125 if (atomiciov6(writev, conn->fd_out, iov, 2, 127 if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
126 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != 128 conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
127 sshbuf_len(m) + sizeof(mlen)) 129 sshbuf_len(m) + sizeof(mlen))
128 fatal("Couldn't send packet: %s", strerror(errno)); 130 fatal("Couldn't send packet: %s", strerror(errno));
129 131
@@ -139,8 +141,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
139 141
140 if ((r = sshbuf_reserve(m, 4, &p)) != 0) 142 if ((r = sshbuf_reserve(m, 4, &p)) != 0)
141 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 143 fatal("%s: buffer error: %s", __func__, ssh_err(r));
142 if (atomicio6(read, conn->fd_in, p, 4, 144 if (atomicio6(read, conn->fd_in, p, 4, sftpio,
143 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { 145 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
144 if (errno == EPIPE || errno == ECONNRESET) 146 if (errno == EPIPE || errno == ECONNRESET)
145 fatal("Connection closed"); 147 fatal("Connection closed");
146 else 148 else
@@ -158,8 +160,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
158 160
159 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 161 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
160 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 162 fatal("%s: buffer error: %s", __func__, ssh_err(r));
161 if (atomicio6(read, conn->fd_in, p, msg_len, 163 if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
162 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) 164 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
163 != msg_len) { 165 != msg_len) {
164 if (errno == EPIPE) 166 if (errno == EPIPE)
165 fatal("Connection closed"); 167 fatal("Connection closed");