1 From: Justus Winter <justus@g10code.com>
2 Date: Wed, 8 Feb 2017 13:49:41 +0100
3 Subject: gpg,common: Make sure that all fd given are valid.
5 * common/sysutils.c (gnupg_fd_valid): New function.
6 * common/sysutils.h (gnupg_fd_valid): New declaration.
7 * common/logging.c (log_set_file): Use the new function.
8 * g10/cpr.c (set_status_fd): Likewise.
9 * g10/gpg.c (main): Likewise.
10 * g10/keylist.c (read_sessionkey_from_fd): Likewise.
11 * g10/passphrase.c (set_attrib_fd): Likewise.
12 * tests/openpgp/Makefile.am (XTESTS): Add the new test.
13 * tests/openpgp/issue2941.scm: New file.
16 Consider a situation where the user passes "--status-fd 3" but file
17 descriptor 3 is not open.
19 During the course of executing the rest of the commands, it's possible
20 that gpg itself will open some files, and file descriptor 3 will get
23 In this situation, the status information will be appended directly to
24 whatever file happens to have landed on fd 3 (the trustdb? the
27 This is a potential data destruction issue for all writable file
34 It's also a potential issue for readable file descriptor options, but
35 the risk is merely weird behavior, and not data corruption:
37 --override-session-key-fd
41 Fixes this by checking whether the fd is valid early on before using
45 Signed-off-by: Justus Winter <justus@g10code.com>
46 (cherry picked from commit 6823ed46584e753de3aba48a00ab738ab009a860)
48 common/logging.c | 3 +++
49 common/sysutils.c | 11 +++++++++++
50 common/sysutils.h | 1 +
54 g10/passphrase.c | 3 +++
55 tests/openpgp/Makefile.am | 4 ++--
56 tests/openpgp/issue2941.scm | 34 ++++++++++++++++++++++++++++++++++
57 9 files changed, 65 insertions(+), 2 deletions(-)
58 create mode 100755 tests/openpgp/issue2941.scm
60 diff --git a/common/logging.c b/common/logging.c
61 index 8c70742..ac13053 100644
62 --- a/common/logging.c
63 +++ b/common/logging.c
64 @@ -570,6 +570,9 @@ log_set_file (const char *name)
68 + if (! gnupg_fd_valid (fd))
69 + log_fatal ("logger-fd is invalid: %s\n", strerror (errno));
71 set_file_fd (NULL, fd);
74 diff --git a/common/sysutils.c b/common/sysutils.c
75 index e67420f..a796677 100644
76 --- a/common/sysutils.c
77 +++ b/common/sysutils.c
78 @@ -1281,3 +1281,14 @@ gnupg_get_socket_name (int fd)
81 #endif /*!HAVE_W32_SYSTEM*/
83 +/* Check whether FD is valid. */
85 +gnupg_fd_valid (int fd)
93 diff --git a/common/sysutils.h b/common/sysutils.h
94 index a9316d7..ecd9f84 100644
95 --- a/common/sysutils.h
96 +++ b/common/sysutils.h
97 @@ -72,6 +72,7 @@ int gnupg_setenv (const char *name, const char *value, int overwrite);
98 int gnupg_unsetenv (const char *name);
99 char *gnupg_getcwd (void);
100 char *gnupg_get_socket_name (int fd);
101 +int gnupg_fd_valid (int fd);
103 gpg_error_t gnupg_inotify_watch_socket (int *r_fd, const char *socket_name);
104 int gnupg_inotify_has_name (int fd, const char *name);
105 diff --git a/g10/cpr.c b/g10/cpr.c
106 index 0133cad..4984e89 100644
109 @@ -107,6 +107,9 @@ set_status_fd (int fd)
113 + if (! gnupg_fd_valid (fd))
114 + log_fatal ("status-fd is invalid: %s\n", strerror (errno));
117 statusfp = es_stdout;
119 diff --git a/g10/gpg.c b/g10/gpg.c
120 index e280c22..66a2055 100644
123 @@ -3079,6 +3079,8 @@ main (int argc, char **argv)
126 opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
127 + if (! gnupg_fd_valid (opt.command_fd))
128 + log_fatal ("command-fd is invalid: %s\n", strerror (errno));
131 opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1);
132 @@ -5293,6 +5295,9 @@ read_sessionkey_from_fd (int fd)
136 + if (! gnupg_fd_valid (fd))
137 + log_fatal ("override-session-key-fd is invalid: %s\n", strerror (errno));
139 for (line = NULL, i = len = 100; ; i++ )
142 diff --git a/g10/keylist.c b/g10/keylist.c
143 index 4fe1e40..abdcb9f 100644
146 @@ -1900,6 +1900,9 @@ set_attrib_fd (int fd)
150 + if (! gnupg_fd_valid (fd))
151 + log_fatal ("attribute-fd is invalid: %s\n", strerror (errno));
153 #ifdef HAVE_DOSISH_SYSTEM
154 setmode (fd, O_BINARY);
156 diff --git a/g10/passphrase.c b/g10/passphrase.c
157 index fb4ec4c..37abc0f 100644
158 --- a/g10/passphrase.c
159 +++ b/g10/passphrase.c
160 @@ -166,6 +166,9 @@ read_passphrase_from_fd( int fd )
164 + if (! gnupg_fd_valid (fd))
165 + log_fatal ("passphrase-fd is invalid: %s\n", strerror (errno));
167 if ( !opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
168 { /* Not used but we have to do a dummy read, so that it won't end
169 up at the begin of the message if the quite usual trick to
170 diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am
171 index 05341fb..377a2ed 100644
172 --- a/tests/openpgp/Makefile.am
173 +++ b/tests/openpgp/Makefile.am
174 @@ -95,12 +95,12 @@ XTESTS = \
182 # Fixme: gpgconf.scm does not yet work with make distcheck.
186 # XXX: Currently, one cannot override automake's 'check' target. As a
187 # workaround, we avoid defining 'TESTS', thus automake will not emit
188 # the 'check' target. For extra robustness, we merely define a
189 diff --git a/tests/openpgp/issue2941.scm b/tests/openpgp/issue2941.scm
191 index 0000000..d7220e0
193 +++ b/tests/openpgp/issue2941.scm
195 +#!/usr/bin/env gpgscm
197 +;; Copyright (C) 2017 g10 Code GmbH
199 +;; This file is part of GnuPG.
201 +;; GnuPG is free software; you can redistribute it and/or modify
202 +;; it under the terms of the GNU General Public License as published by
203 +;; the Free Software Foundation; either version 3 of the License, or
204 +;; (at your option) any later version.
206 +;; GnuPG is distributed in the hope that it will be useful,
207 +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
208 +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
209 +;; GNU General Public License for more details.
211 +;; You should have received a copy of the GNU General Public License
212 +;; along with this program; if not, see <http://www.gnu.org/licenses/>.
214 +(load (with-path "defs.scm"))
215 +(setup-legacy-environment)
217 +(define (check-failure options)
218 + (let ((command `(,@gpg ,@options)))
220 + (call-check command)
221 + (error "Expected an error, but got none when executing" command))))
224 + "Checking invocation with invalid file descriptors (issue2941)."
226 + (check-failure `(,(string-append "--" option "=23") --sign gpg.conf)))
227 + '("status-fd" "attribute-fd" "logger-fd"
228 + "override-session-key-fd" "passphrase-fd" "command-fd"))