chiark / gitweb /
gnupg2 (2.1.18-8~deb9u1) stretch; urgency=medium
[gnupg2.git] / debian / patches / 0032-gpg-common-Make-sure-that-all-fd-given-are-valid.patch
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.
4
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.
14 --
15
16 Consider a situation where the user passes "--status-fd 3" but file
17 descriptor 3 is not open.
18
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
21 allocated.
22
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
25 keyring?).
26
27 This is a potential data destruction issue for all writable file
28 descriptor options:
29
30    --status-fd
31    --attribute-fd
32    --logger-fd
33
34 It's also a potential issue for readable file descriptor options, but
35 the risk is merely weird behavior, and not data corruption:
36
37    --override-session-key-fd
38    --passphrase-fd
39    --command-fd
40
41 Fixes this by checking whether the fd is valid early on before using
42 it.
43
44 GnuPG-bug-id: 2941
45 Signed-off-by: Justus Winter <justus@g10code.com>
46 (cherry picked from commit 6823ed46584e753de3aba48a00ab738ab009a860)
47 ---
48  common/logging.c            |  3 +++
49  common/sysutils.c           | 11 +++++++++++
50  common/sysutils.h           |  1 +
51  g10/cpr.c                   |  3 +++
52  g10/gpg.c                   |  5 +++++
53  g10/keylist.c               |  3 +++
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
59
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)
65  void
66  log_set_fd (int fd)
67  {
68 +  if (! gnupg_fd_valid (fd))
69 +    log_fatal ("logger-fd is invalid: %s\n", strerror (errno));
70 +
71    set_file_fd (NULL, fd);
72  }
73  
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)
79    return name;
80  }
81  #endif /*!HAVE_W32_SYSTEM*/
82 +
83 +/* Check whether FD is valid.  */
84 +int
85 +gnupg_fd_valid (int fd)
86 +{
87 +  int d = dup (fd);
88 +  if (d < 0)
89 +    return 0;
90 +  close (d);
91 +  return 1;
92 +}
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);
102  
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
107 --- a/g10/cpr.c
108 +++ b/g10/cpr.c
109 @@ -107,6 +107,9 @@ set_status_fd (int fd)
110    if (fd == -1)
111      return;
112  
113 +  if (! gnupg_fd_valid (fd))
114 +    log_fatal ("status-fd is invalid: %s\n", strerror (errno));
115 +
116    if (fd == 1)
117      statusfp = es_stdout;
118    else if (fd == 2)
119 diff --git a/g10/gpg.c b/g10/gpg.c
120 index e280c22..66a2055 100644
121 --- a/g10/gpg.c
122 +++ b/g10/gpg.c
123 @@ -3079,6 +3079,8 @@ main (int argc, char **argv)
124  
125           case oCommandFD:
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));
129              break;
130           case oCommandFile:
131              opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1);
132 @@ -5293,6 +5295,9 @@ read_sessionkey_from_fd (int fd)
133    int i, len;
134    char *line;
135  
136 +  if (! gnupg_fd_valid (fd))
137 +    log_fatal ("override-session-key-fd is invalid: %s\n", strerror (errno));
138 +
139    for (line = NULL, i = len = 100; ; i++ )
140      {
141        if (i >= len-1 )
142 diff --git a/g10/keylist.c b/g10/keylist.c
143 index 4fe1e40..abdcb9f 100644
144 --- a/g10/keylist.c
145 +++ b/g10/keylist.c
146 @@ -1900,6 +1900,9 @@ set_attrib_fd (int fd)
147    if (fd == -1)
148      return;
149  
150 +  if (! gnupg_fd_valid (fd))
151 +    log_fatal ("attribute-fd is invalid: %s\n", strerror (errno));
152 +
153  #ifdef HAVE_DOSISH_SYSTEM
154    setmode (fd, O_BINARY);
155  #endif
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 )
161    int i, len;
162    char *pw;
163  
164 +  if (! gnupg_fd_valid (fd))
165 +    log_fatal ("passphrase-fd is invalid: %s\n", strerror (errno));
166 +
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 = \
175         issue2015.scm \
176         issue2346.scm \
177         issue2417.scm \
178 -       issue2419.scm
179 +       issue2419.scm \
180 +       issue2941.scm
181  
182  # Fixme: gpgconf.scm does not yet work with make distcheck.
183  #      gpgconf.scm
184  
185 -
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
190 new file mode 100755
191 index 0000000..d7220e0
192 --- /dev/null
193 +++ b/tests/openpgp/issue2941.scm
194 @@ -0,0 +1,34 @@
195 +#!/usr/bin/env gpgscm
196 +
197 +;; Copyright (C) 2017 g10 Code GmbH
198 +;;
199 +;; This file is part of GnuPG.
200 +;;
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.
205 +;;
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.
210 +;;
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/>.
213 +
214 +(load (with-path "defs.scm"))
215 +(setup-legacy-environment)
216 +
217 +(define (check-failure options)
218 +  (let ((command `(,@gpg ,@options)))
219 +    (catch '()
220 +          (call-check command)
221 +          (error "Expected an error, but got none when executing" command))))
222 +
223 +(for-each-p
224 + "Checking invocation with invalid file descriptors (issue2941)."
225 + (lambda (option)
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"))