Blame SOURCES/0018-curl-7.65.3-CVE-2019-5482.patch

b4d5e8
From 63f9837b4ccf600da79314e8667f91bda69988fc Mon Sep 17 00:00:00 2001
b4d5e8
From: Thomas Vegas <>
b4d5e8
Date: Sat, 31 Aug 2019 16:59:56 +0200
b4d5e8
Subject: [PATCH 1/2] tftp: return error when packet is too small for options
b4d5e8
b4d5e8
Upstream-commit: 82f3ba3806a34fe94dcf9e5c9b88deda6679ca1b
b4d5e8
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
b4d5e8
---
b4d5e8
 lib/tftp.c | 53 +++++++++++++++++++++++++++++++++--------------------
b4d5e8
 1 file changed, 33 insertions(+), 20 deletions(-)
b4d5e8
b4d5e8
diff --git a/lib/tftp.c b/lib/tftp.c
b4d5e8
index 289cda2..4532170 100644
b4d5e8
--- a/lib/tftp.c
b4d5e8
+++ b/lib/tftp.c
b4d5e8
@@ -404,13 +404,14 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
b4d5e8
   return CURLE_OK;
b4d5e8
 }
b4d5e8
 
b4d5e8
-static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
b4d5e8
-                              char *buf, const char *option)
b4d5e8
+static CURLcode tftp_option_add(tftp_state_data_t *state, size_t *csize,
b4d5e8
+                                char *buf, const char *option)
b4d5e8
 {
b4d5e8
-  if(( strlen(option) + csize + 1) > (size_t)state->blksize)
b4d5e8
-    return 0;
b4d5e8
+  if(( strlen(option) + *csize + 1) > (size_t)state->blksize)
b4d5e8
+    return CURLE_TFTP_ILLEGAL;
b4d5e8
   strcpy(buf, option);
b4d5e8
-  return strlen(option) + 1;
b4d5e8
+  *csize += strlen(option) + 1;
b4d5e8
+  return CURLE_OK;
b4d5e8
 }
b4d5e8
 
b4d5e8
 static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
b4d5e8
@@ -511,26 +512,38 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
b4d5e8
       else
b4d5e8
         strcpy(buf, "0"); /* the destination is large enough */
b4d5e8
 
b4d5e8
-      sbytes += tftp_option_add(state, sbytes,
b4d5e8
-                                (char *)state->spacket.data + sbytes,
b4d5e8
-                                TFTP_OPTION_TSIZE);
b4d5e8
-      sbytes += tftp_option_add(state, sbytes,
b4d5e8
-                                (char *)state->spacket.data + sbytes, buf);
b4d5e8
+      result = tftp_option_add(state, &sbytes,
b4d5e8
+                               (char *)state->spacket.data + sbytes,
b4d5e8
+                               TFTP_OPTION_TSIZE);
b4d5e8
+      if(result == CURLE_OK)
b4d5e8
+        result = tftp_option_add(state, &sbytes,
b4d5e8
+                                 (char *)state->spacket.data + sbytes, buf);
b4d5e8
+
b4d5e8
       /* add blksize option */
b4d5e8
       snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
b4d5e8
-      sbytes += tftp_option_add(state, sbytes,
b4d5e8
-                                (char *)state->spacket.data + sbytes,
b4d5e8
-                                TFTP_OPTION_BLKSIZE);
b4d5e8
-      sbytes += tftp_option_add(state, sbytes,
b4d5e8
-                                (char *)state->spacket.data + sbytes, buf);
b4d5e8
+      if(result == CURLE_OK)
b4d5e8
+        result = tftp_option_add(state, &sbytes,
b4d5e8
+                                 (char *)state->spacket.data + sbytes,
b4d5e8
+                                 TFTP_OPTION_BLKSIZE);
b4d5e8
+      if(result == CURLE_OK)
b4d5e8
+        result = tftp_option_add(state, &sbytes,
b4d5e8
+                                 (char *)state->spacket.data + sbytes, buf);
b4d5e8
 
b4d5e8
       /* add timeout option */
b4d5e8
       snprintf(buf, sizeof(buf), "%d", state->retry_time);
b4d5e8
-      sbytes += tftp_option_add(state, sbytes,
b4d5e8
-                                (char *)state->spacket.data + sbytes,
b4d5e8
-                                TFTP_OPTION_INTERVAL);
b4d5e8
-      sbytes += tftp_option_add(state, sbytes,
b4d5e8
-                                (char *)state->spacket.data + sbytes, buf);
b4d5e8
+      if(result == CURLE_OK)
b4d5e8
+        result = tftp_option_add(state, &sbytes,
b4d5e8
+                                 (char *)state->spacket.data + sbytes,
b4d5e8
+                                 TFTP_OPTION_INTERVAL);
b4d5e8
+      if(result == CURLE_OK)
b4d5e8
+        result = tftp_option_add(state, &sbytes,
b4d5e8
+                                 (char *)state->spacket.data + sbytes, buf);
b4d5e8
+
b4d5e8
+      if(result != CURLE_OK) {
b4d5e8
+        failf(data, "TFTP buffer too small for options");
b4d5e8
+        free(filename);
b4d5e8
+        return CURLE_TFTP_ILLEGAL;
b4d5e8
+      }
b4d5e8
     }
b4d5e8
 
b4d5e8
     /* the typecase for the 3rd argument is mostly for systems that do
b4d5e8
-- 
b4d5e8
2.20.1
b4d5e8
b4d5e8
b4d5e8
From b6b12a4cfe00c4850a1d6cee4cf267f00dee5987 Mon Sep 17 00:00:00 2001
b4d5e8
From: Thomas Vegas <>
b4d5e8
Date: Sat, 31 Aug 2019 17:30:51 +0200
b4d5e8
Subject: [PATCH 2/2] tftp: Alloc maximum blksize, and use default unless OACK
b4d5e8
 is received
b4d5e8
b4d5e8
Fixes potential buffer overflow from 'recvfrom()', should the server
b4d5e8
return an OACK without blksize.
b4d5e8
b4d5e8
Bug: https://curl.haxx.se/docs/CVE-2019-5482.html
b4d5e8
CVE-2019-5482
b4d5e8
b4d5e8
Upstream-commit: facb0e4662415b5f28163e853dc6742ac5fafb3d
b4d5e8
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
b4d5e8
---
b4d5e8
 lib/tftp.c | 12 +++++++++---
b4d5e8
 1 file changed, 9 insertions(+), 3 deletions(-)
b4d5e8
b4d5e8
diff --git a/lib/tftp.c b/lib/tftp.c
b4d5e8
index 4532170..5651b62 100644
b4d5e8
--- a/lib/tftp.c
b4d5e8
+++ b/lib/tftp.c
b4d5e8
@@ -982,6 +982,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
b4d5e8
 {
b4d5e8
   tftp_state_data_t *state;
b4d5e8
   int blksize;
b4d5e8
+  int need_blksize;
b4d5e8
 
b4d5e8
   blksize = TFTP_BLKSIZE_DEFAULT;
b4d5e8
 
b4d5e8
@@ -996,15 +997,20 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
b4d5e8
       return CURLE_TFTP_ILLEGAL;
b4d5e8
   }
b4d5e8
 
b4d5e8
+  need_blksize = blksize;
b4d5e8
+  /* default size is the fallback when no OACK is received */
b4d5e8
+  if(need_blksize < TFTP_BLKSIZE_DEFAULT)
b4d5e8
+    need_blksize = TFTP_BLKSIZE_DEFAULT;
b4d5e8
+
b4d5e8
   if(!state->rpacket.data) {
b4d5e8
-    state->rpacket.data = calloc(1, blksize + 2 + 2);
b4d5e8
+    state->rpacket.data = calloc(1, need_blksize + 2 + 2);
b4d5e8
 
b4d5e8
     if(!state->rpacket.data)
b4d5e8
       return CURLE_OUT_OF_MEMORY;
b4d5e8
   }
b4d5e8
 
b4d5e8
   if(!state->spacket.data) {
b4d5e8
-    state->spacket.data = calloc(1, blksize + 2 + 2);
b4d5e8
+    state->spacket.data = calloc(1, need_blksize + 2 + 2);
b4d5e8
 
b4d5e8
     if(!state->spacket.data)
b4d5e8
       return CURLE_OUT_OF_MEMORY;
b4d5e8
@@ -1018,7 +1024,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
b4d5e8
   state->sockfd = state->conn->sock[FIRSTSOCKET];
b4d5e8
   state->state = TFTP_STATE_START;
b4d5e8
   state->error = TFTP_ERR_NONE;
b4d5e8
-  state->blksize = blksize;
b4d5e8
+  state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */
b4d5e8
   state->requested_blksize = blksize;
b4d5e8
 
b4d5e8
   ((struct sockaddr *)&state->local_addr)->sa_family =
b4d5e8
-- 
b4d5e8
2.20.1
b4d5e8