xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-support/curl/curl/CVE-2022-32207.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From 759088694e2ba68ddc5ffe042b071dadad6ff675 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Wed, 25 May 2022 10:09:53 +0200
4Subject: [PATCH] fopen: add Curl_fopen() for better overwriting of files
5
6Bug: https://curl.se/docs/CVE-2022-32207.html
7CVE-2022-32207
8Reported-by: Harry Sintonen
9Closes #9050
10
11Upstream-Status: Backport [https://github.com/curl/curl/commit/20f9dd6bae50b]
12Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org>
13---
14 CMakeLists.txt          |   1 +
15 configure.ac            |   1 +
16 lib/Makefile.inc        |   2 +
17 lib/cookie.c            |  19 ++-----
18 lib/curl_config.h.cmake |   3 ++
19 lib/fopen.c             | 113 ++++++++++++++++++++++++++++++++++++++++
20 lib/fopen.h             |  30 +++++++++++
21 7 files changed, 154 insertions(+), 15 deletions(-)
22 create mode 100644 lib/fopen.c
23 create mode 100644 lib/fopen.h
24
25diff --git a/CMakeLists.txt b/CMakeLists.txt
26index b77de6d..a0bfaad 100644
27--- a/CMakeLists.txt
28+++ b/CMakeLists.txt
29@@ -1027,6 +1027,7 @@ elseif(HAVE_LIBSOCKET)
30   set(CMAKE_REQUIRED_LIBRARIES socket)
31 endif()
32
33+check_symbol_exists(fchmod        "${CURL_INCLUDES}" HAVE_FCHMOD)
34 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
35 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
36 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
37diff --git a/configure.ac b/configure.ac
38index d431870..7433bb9 100644
39--- a/configure.ac
40+++ b/configure.ac
41@@ -3351,6 +3351,7 @@ AC_CHECK_DECLS([getpwuid_r], [], [AC_DEFINE(HAVE_DECL_GETPWUID_R_MISSING, 1, "Se
42
43
44 AC_CHECK_FUNCS([fnmatch \
45+  fchmod \
46   geteuid \
47   getpass_r \
48   getppid \
49diff --git a/lib/Makefile.inc b/lib/Makefile.inc
50index e8f110f..5139b03 100644
51--- a/lib/Makefile.inc
52+++ b/lib/Makefile.inc
53@@ -133,6 +133,7 @@ LIB_CFILES =         \
54   escape.c           \
55   file.c             \
56   fileinfo.c         \
57+  fopen.c            \
58   formdata.c         \
59   ftp.c              \
60   ftplistparser.c    \
61@@ -263,6 +264,7 @@ LIB_HFILES =         \
62   escape.h           \
63   file.h             \
64   fileinfo.h         \
65+  fopen.h            \
66   formdata.h         \
67   ftp.h              \
68   ftplistparser.h    \
69diff --git a/lib/cookie.c b/lib/cookie.c
70index 8a6aa1a..cb0c03b 100644
71--- a/lib/cookie.c
72+++ b/lib/cookie.c
73@@ -96,8 +96,8 @@ Example set of cookies:
74 #include "curl_get_line.h"
75 #include "curl_memrchr.h"
76 #include "parsedate.h"
77-#include "rand.h"
78 #include "rename.h"
79+#include "fopen.h"
80
81 /* The last 3 #include files should be in this order */
82 #include "curl_printf.h"
83@@ -1620,20 +1620,9 @@ static CURLcode cookie_output(struct Curl_easy *data,
84     use_stdout = TRUE;
85   }
86   else {
87-    unsigned char randsuffix[9];
88-
89-    if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
90-      return 2;
91-
92-    tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
93-    if(!tempstore)
94-      return CURLE_OUT_OF_MEMORY;
95-
96-    out = fopen(tempstore, FOPEN_WRITETEXT);
97-    if(!out) {
98-      error = CURLE_WRITE_ERROR;
99+    error = Curl_fopen(data, filename, &out, &tempstore);
100+    if(error)
101       goto error;
102-    }
103   }
104
105   fputs("# Netscape HTTP Cookie File\n"
106@@ -1680,7 +1669,7 @@ static CURLcode cookie_output(struct Curl_easy *data,
107   if(!use_stdout) {
108     fclose(out);
109     out = NULL;
110-    if(Curl_rename(tempstore, filename)) {
111+    if(tempstore && Curl_rename(tempstore, filename)) {
112       unlink(tempstore);
113       error = CURLE_WRITE_ERROR;
114       goto error;
115diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
116index d2a0f43..c254359 100644
117--- a/lib/curl_config.h.cmake
118+++ b/lib/curl_config.h.cmake
119@@ -157,6 +157,9 @@
120 /* Define to 1 if you have the <assert.h> header file. */
121 #cmakedefine HAVE_ASSERT_H 1
122
123+/* Define to 1 if you have the `fchmod' function. */
124+#cmakedefine HAVE_FCHMOD 1
125+
126 /* Define to 1 if you have the `basename' function. */
127 #cmakedefine HAVE_BASENAME 1
128
129diff --git a/lib/fopen.c b/lib/fopen.c
130new file mode 100644
131index 0000000..ad3691b
132--- /dev/null
133+++ b/lib/fopen.c
134@@ -0,0 +1,113 @@
135+/***************************************************************************
136+ *                                  _   _ ____  _
137+ *  Project                     ___| | | |  _ \| |
138+ *                             / __| | | | |_) | |
139+ *                            | (__| |_| |  _ <| |___
140+ *                             \___|\___/|_| \_\_____|
141+ *
142+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
143+ *
144+ * This software is licensed as described in the file COPYING, which
145+ * you should have received as part of this distribution. The terms
146+ * are also available at https://curl.se/docs/copyright.html.
147+ *
148+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
149+ * copies of the Software, and permit persons to whom the Software is
150+ * furnished to do so, under the terms of the COPYING file.
151+ *
152+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
153+ * KIND, either express or implied.
154+ *
155+ * SPDX-License-Identifier: curl
156+ *
157+ ***************************************************************************/
158+
159+#include "curl_setup.h"
160+
161+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) ||  \
162+  !defined(CURL_DISABLE_HSTS)
163+
164+#ifdef HAVE_FCNTL_H
165+#include <fcntl.h>
166+#endif
167+
168+#include "urldata.h"
169+#include "rand.h"
170+#include "fopen.h"
171+/* The last 3 #include files should be in this order */
172+#include "curl_printf.h"
173+#include "curl_memory.h"
174+#include "memdebug.h"
175+
176+/*
177+ * Curl_fopen() opens a file for writing with a temp name, to be renamed
178+ * to the final name when completed. If there is an existing file using this
179+ * name at the time of the open, this function will clone the mode from that
180+ * file.  if 'tempname' is non-NULL, it needs a rename after the file is
181+ * written.
182+ */
183+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
184+                    FILE **fh, char **tempname)
185+{
186+  CURLcode result = CURLE_WRITE_ERROR;
187+  unsigned char randsuffix[9];
188+  char *tempstore = NULL;
189+  struct_stat sb;
190+  int fd = -1;
191+  *tempname = NULL;
192+
193+  if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) {
194+    /* a non-regular file, fallback to direct fopen() */
195+    *fh = fopen(filename, FOPEN_WRITETEXT);
196+    if(*fh)
197+      return CURLE_OK;
198+    goto fail;
199+  }
200+
201+  result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
202+  if(result)
203+    goto fail;
204+
205+  tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
206+  if(!tempstore) {
207+    result = CURLE_OUT_OF_MEMORY;
208+    goto fail;
209+  }
210+
211+  result = CURLE_WRITE_ERROR;
212+  fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
213+  if(fd == -1)
214+    goto fail;
215+
216+#ifdef HAVE_FCHMOD
217+  {
218+    struct_stat nsb;
219+    if((fstat(fd, &nsb) != -1) &&
220+       (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
221+      /* if the user and group are the same, clone the original mode */
222+      if(fchmod(fd, sb.st_mode) == -1)
223+        goto fail;
224+    }
225+  }
226+#endif
227+
228+  *fh = fdopen(fd, FOPEN_WRITETEXT);
229+  if(!*fh)
230+    goto fail;
231+
232+  *tempname = tempstore;
233+  return CURLE_OK;
234+
235+fail:
236+  if(fd != -1) {
237+    close(fd);
238+    unlink(tempstore);
239+  }
240+
241+  free(tempstore);
242+
243+  *tempname = NULL;
244+  return result;
245+}
246+
247+#endif /* ! disabled */
248diff --git a/lib/fopen.h b/lib/fopen.h
249new file mode 100644
250index 0000000..289e55f
251--- /dev/null
252+++ b/lib/fopen.h
253@@ -0,0 +1,30 @@
254+#ifndef HEADER_CURL_FOPEN_H
255+#define HEADER_CURL_FOPEN_H
256+/***************************************************************************
257+ *                                  _   _ ____  _
258+ *  Project                     ___| | | |  _ \| |
259+ *                             / __| | | | |_) | |
260+ *                            | (__| |_| |  _ <| |___
261+ *                             \___|\___/|_| \_\_____|
262+ *
263+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
264+ *
265+ * This software is licensed as described in the file COPYING, which
266+ * you should have received as part of this distribution. The terms
267+ * are also available at https://curl.se/docs/copyright.html.
268+ *
269+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
270+ * copies of the Software, and permit persons to whom the Software is
271+ * furnished to do so, under the terms of the COPYING file.
272+ *
273+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
274+ * KIND, either express or implied.
275+ *
276+ * SPDX-License-Identifier: curl
277+ *
278+ ***************************************************************************/
279+
280+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
281+                    FILE **fh, char **tempname);
282+
283+#endif
284