Version in base suite: 1.3.6-4+deb10u3 Base version: proftpd-dfsg_1.3.6-4+deb10u3 Target version: proftpd-dfsg_1.3.6-4+deb10u4 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/proftpd-dfsg/proftpd-dfsg_1.3.6-4+deb10u3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/proftpd-dfsg/proftpd-dfsg_1.3.6-4+deb10u4.dsc changelog | 10 patches/Issue-903-Ensure-that-we-do-not-reuse-already-destro.patch | 193 ++++++++++ patches/Issue-903-We-want-to-remove-the-data-transfer-comman.patch | 29 + patches/series | 2 4 files changed, 234 insertions(+) diff -Nru proftpd-dfsg-1.3.6/debian/changelog proftpd-dfsg-1.3.6/debian/changelog --- proftpd-dfsg-1.3.6/debian/changelog 2019-12-31 11:06:17.000000000 +0000 +++ proftpd-dfsg-1.3.6/debian/changelog 2020-02-25 21:23:14.000000000 +0000 @@ -1,3 +1,13 @@ +proftpd-dfsg (1.3.6-4+deb10u4) buster-security; urgency=high + + * Non-maintainer upload by the Security Team. + * Ensure that we do not reuse already-destroyed memory pools during data + transfers (CVE-2020-9273) (Closes: #951800) + * Clear the data-transfer instigating command pool but keep a memory pool. + Fixes regression in the %{transfer-status} LogFormat functionality. + + -- Salvatore Bonaccorso Tue, 25 Feb 2020 22:23:14 +0100 + proftpd-dfsg (1.3.6-4+deb10u3) buster; urgency=medium * Cherry pick patch from upstream: diff -Nru proftpd-dfsg-1.3.6/debian/patches/Issue-903-Ensure-that-we-do-not-reuse-already-destro.patch proftpd-dfsg-1.3.6/debian/patches/Issue-903-Ensure-that-we-do-not-reuse-already-destro.patch --- proftpd-dfsg-1.3.6/debian/patches/Issue-903-Ensure-that-we-do-not-reuse-already-destro.patch 1970-01-01 00:00:00.000000000 +0000 +++ proftpd-dfsg-1.3.6/debian/patches/Issue-903-Ensure-that-we-do-not-reuse-already-destro.patch 2020-02-25 21:23:14.000000000 +0000 @@ -0,0 +1,193 @@ +From: TJ Saunders +Date: Tue, 18 Feb 2020 09:48:18 -0800 +Subject: Issue #903: Ensure that we do not reuse already-destroyed memory + pools during data transfers. +Origin: https://github.com/proftpd/proftpd/commit/e845abc1bd86eebec7a0342fded908a1b0f1996b +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-9273 +Bug-Debian: https://bugs.debian.org/951800 +Bug: https://github.com/proftpd/proftpd/issues/903 + +[Salvatore Bonaccorso: Drop copyright header year update changes hunks] +--- + src/data.c | 27 ++++++++++++++++++++------- + src/main.c | 6 ++++-- + src/response.c | 12 ++++++++++++ + tests/api/data.c | 2 +- + tests/api/response.c | 10 ++++++++++ + 5 files changed, 47 insertions(+), 10 deletions(-) + +diff --git a/src/data.c b/src/data.c +index d5c85114b76a..6ef6d420ef4d 100644 +--- a/src/data.c ++++ b/src/data.c +@@ -684,7 +684,7 @@ void pr_data_close(int quiet) { + */ + void pr_data_cleanup(void) { + /* sanity check */ +- if (session.d) { ++ if (session.d != NULL) { + pr_inet_lingering_close(session.pool, session.d, timeout_linger); + session.d = NULL; + } +@@ -711,7 +711,7 @@ void pr_data_abort(int err, int quiet) { + strerror(err), err, quiet ? "true" : "false", + true_abort ? "true" : "false"); + +- if (session.d) { ++ if (session.d != NULL) { + if (true_abort == FALSE) { + pr_inet_lingering_close(session.pool, session.d, timeout_linger); + +@@ -893,6 +893,11 @@ void pr_data_abort(int err, int quiet) { + if (true_abort == FALSE) { + pr_response_add_err(respcode, _("Transfer aborted. %s"), msg ? msg : ""); + } ++ ++ /* Forcibly clear the data-transfer instigating command pool from the ++ * Response API. ++ */ ++ pr_response_set_pool(NULL); + } + + if (true_abort) { +@@ -925,6 +930,7 @@ static void poll_ctrl(void) { + res = pr_cmd_read(&cmd); + if (res < 0) { + int xerrno; ++ + #if defined(ECONNABORTED) + xerrno = ECONNABORTED; + #elif defined(ENOTCONN) +@@ -993,8 +999,8 @@ static void poll_ctrl(void) { + + pr_response_flush(&resp_err_list); + +- destroy_pool(cmd->pool); + pr_response_set_pool(resp_pool); ++ destroy_pool(cmd->pool); + + /* We don't want to actually dispatch the NOOP command, since that + * would overwrite the scoreboard with the NOOP state; admins probably +@@ -1019,13 +1025,14 @@ static void poll_ctrl(void) { + + pr_response_flush(&resp_list); + +- destroy_pool(cmd->pool); + pr_response_set_pool(resp_pool); ++ destroy_pool(cmd->pool); + + } else { + char *title_buf = NULL; +- int title_len = -1; +- const char *sce_cmd = NULL, *sce_cmd_arg = NULL; ++ int curr_cmd_id = 0, title_len = -1; ++ const char *curr_cmd = NULL, *sce_cmd = NULL, *sce_cmd_arg = NULL; ++ cmd_rec *curr_cmd_rec = NULL; + + pr_trace_msg(trace_channel, 5, + "client sent '%s' command during data transfer, dispatching", +@@ -1037,6 +1044,9 @@ static void poll_ctrl(void) { + pr_proctitle_get(title_buf, title_len + 1); + } + ++ curr_cmd = session.curr_cmd; ++ curr_cmd_id = session.curr_cmd_id; ++ curr_cmd_rec = session.curr_cmd_rec; + sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD); + sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG); + +@@ -1052,6 +1062,9 @@ static void poll_ctrl(void) { + } + + destroy_pool(cmd->pool); ++ session.curr_cmd = curr_cmd; ++ session.curr_cmd_id = curr_cmd_id; ++ session.curr_cmd_rec = curr_cmd_rec; + } + + } else { +diff --git a/src/main.c b/src/main.c +index 0e926c96967c..aa18ead86d38 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -900,8 +900,7 @@ static void cmd_loop(server_rec *server, conn_t *c) { + pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE); + } + +- if (cmd) { +- ++ if (cmd != NULL) { + /* Detect known commands for other protocols; if found, drop the + * connection, lest we be used as part of an attack on a different + * protocol server (Bug#4143). +@@ -917,6 +916,9 @@ static void cmd_loop(server_rec *server, conn_t *c) { + + pr_cmd_dispatch(cmd); + destroy_pool(cmd->pool); ++ session.curr_cmd = NULL; ++ session.curr_cmd_id = 0; ++ session.curr_cmd_rec = NULL; + + } else { + pr_event_generate("core.invalid-command", NULL); +diff --git a/src/response.c b/src/response.c +index 9b4395ff9ea9..93d31e2d67a4 100644 +--- a/src/response.c ++++ b/src/response.c +@@ -219,6 +219,12 @@ void pr_response_add_err(const char *numeric, const char *fmt, ...) { + return; + } + ++ if (resp_pool == NULL) { ++ pr_trace_msg(trace_channel, 1, ++ "no response pool set, ignoring added %s error response", numeric); ++ return; ++ } ++ + va_start(msg, fmt); + res = vsnprintf(resp_buf, sizeof(resp_buf), fmt, msg); + va_end(msg); +@@ -272,6 +278,12 @@ void pr_response_add(const char *numeric, const char *fmt, ...) { + return; + } + ++ if (resp_pool == NULL) { ++ pr_trace_msg(trace_channel, 1, ++ "no response pool set, ignoring added %s response", numeric); ++ return; ++ } ++ + va_start(msg, fmt); + res = vsnprintf(resp_buf, sizeof(resp_buf), fmt, msg); + va_end(msg); +diff --git a/tests/api/response.c b/tests/api/response.c +index 0d9506977703..9a047741cc4f 100644 +--- a/tests/api/response.c ++++ b/tests/api/response.c +@@ -87,6 +87,11 @@ START_TEST (response_add_test) { + const char *last_resp_code = NULL, *last_resp_msg = NULL; + char *resp_code = R_200, *resp_msg = "OK"; + ++ pr_response_set_pool(NULL); ++ ++ mark_point(); ++ pr_response_add(resp_code, "%s", resp_msg); ++ + pr_response_set_pool(p); + + mark_point(); +@@ -118,6 +123,11 @@ START_TEST (response_add_err_test) { + const char *last_resp_code = NULL, *last_resp_msg = NULL; + char *resp_code = R_450, *resp_msg = "Busy"; + ++ pr_response_set_pool(NULL); ++ ++ mark_point(); ++ pr_response_add(resp_code, "%s", resp_msg); ++ + pr_response_set_pool(p); + + mark_point(); +-- +2.20.1 + diff -Nru proftpd-dfsg-1.3.6/debian/patches/Issue-903-We-want-to-remove-the-data-transfer-comman.patch proftpd-dfsg-1.3.6/debian/patches/Issue-903-We-want-to-remove-the-data-transfer-comman.patch --- proftpd-dfsg-1.3.6/debian/patches/Issue-903-We-want-to-remove-the-data-transfer-comman.patch 1970-01-01 00:00:00.000000000 +0000 +++ proftpd-dfsg-1.3.6/debian/patches/Issue-903-We-want-to-remove-the-data-transfer-comman.patch 2020-02-25 21:23:14.000000000 +0000 @@ -0,0 +1,29 @@ +From: TJ Saunders +Date: Sat, 22 Feb 2020 09:40:32 -0800 +Subject: Issue #903: We want to remove the data transfer command pool, but we + _do_ want some memory pool, lest we regress the %{transfer-status} LogFormat + functionality. +Origin: https://github.com/proftpd/proftpd/commit/cd9036f4ef7a05c107f0ffcb19a018b20267c531 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-9273 +Bug: https://github.com/proftpd/proftpd/issues/903 + +--- + src/data.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/data.c b/src/data.c +index 6ef6d420ef4d..e7b03e231b80 100644 +--- a/src/data.c ++++ b/src/data.c +@@ -897,7 +897,7 @@ void pr_data_abort(int err, int quiet) { + /* Forcibly clear the data-transfer instigating command pool from the + * Response API. + */ +- pr_response_set_pool(NULL); ++ pr_response_set_pool(session.pool); + } + + if (true_abort) { +-- +2.20.1 + diff -Nru proftpd-dfsg-1.3.6/debian/patches/series proftpd-dfsg-1.3.6/debian/patches/series --- proftpd-dfsg-1.3.6/debian/patches/series 2019-12-10 22:08:11.000000000 +0000 +++ proftpd-dfsg-1.3.6/debian/patches/series 2020-02-25 21:23:14.000000000 +0000 @@ -20,3 +20,5 @@ CVE-2019-12815.patch bug_846_CVE-2019-18217.patch upstream_pull_859_861_CVE-2019-19270_CVE-2019-19269 +Issue-903-Ensure-that-we-do-not-reuse-already-destro.patch +Issue-903-We-want-to-remove-the-data-transfer-comman.patch