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

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