Merge ~rafaeldtinoco/ubuntu/+source/haproxy:lp1894879-focal into ubuntu/+source/haproxy:ubuntu/focal-devel

Proposed by Rafael David Tinoco
Status: Merged
Approved by: Rafael David Tinoco
Approved revision: a257f0359b18685aaa3026245b24df3b7c9d6f1b
Merged at revision: a257f0359b18685aaa3026245b24df3b7c9d6f1b
Proposed branch: ~rafaeldtinoco/ubuntu/+source/haproxy:lp1894879-focal
Merge into: ubuntu/+source/haproxy:ubuntu/focal-devel
Diff against target: 351 lines (+305/-1)
6 files modified
debian/changelog (+10/-0)
debian/control (+2/-1)
debian/patches/lp1894879-BUG-CRITICAL-dns-Make-the-do-resolve-action-thread-safe.patch (+132/-0)
debian/patches/lp1894879-BUG-MEDIUM-dns-Dont-yield-in-do-resolve-action-on-a-final.patch (+106/-0)
debian/patches/lp1894879-BUG-MEDIUM-dns-Release-answer-items-when-a-DNS-resolution-is-freed.patch (+51/-0)
debian/patches/series (+4/-0)
Reviewer Review Type Date Requested Status
Rafael David Tinoco Pending
Review via email: mp+390625@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

$ git push pkg upload/2.0.13-2ubuntu0.1
Counting objects: 17, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (17/17), done.
Writing objects: 100% (17/17), 6.47 KiB | 602.00 KiB/s, done.
Total 17 (delta 9), reused 0 (delta 0)
To ssh://git.launchpad.net/ubuntu/+source/haproxy
 * [new tag] upload/2.0.13-2ubuntu0.1 -> upload/2.0.13-2ubuntu0.1

$ debdiff *.dsc 2>&1 | diffstat -l | grep -v gpg
changelog
control
patches/lp1894879-BUG-CRITICAL-dns-Make-the-do-resolve-action-thread-safe.patch
patches/lp1894879-BUG-MEDIUM-dns-Dont-yield-in-do-resolve-action-on-a-final.patch
patches/lp1894879-BUG-MEDIUM-dns-Release-answer-items-when-a-DNS-resolution-is-freed.patch
patches/series

$ dput ubuntu haproxy_2.0.13-2ubuntu0.1_source.changes
Checking signature on .changes
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading haproxy_2.0.13-2ubuntu0.1.dsc: done.
  Uploading haproxy_2.0.13-2ubuntu0.1.debian.tar.xz: done.
  Uploading haproxy_2.0.13-2ubuntu0.1_source.buildinfo: done.
  Uploading haproxy_2.0.13-2ubuntu0.1_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/changelog b/debian/changelog
index 5c9fe8b..35cd7fb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
1haproxy (2.0.13-2ubuntu0.1) focal; urgency=medium
2
3 * Backport dns related fixes from git to resolve crashes when
4 using do-resolve action (LP: #1894879)
5 - BUG/CRITICAL: dns: Make the do-resolve action thread safe
6 - BUG/MEDIUM: dns: Release answer items when a DNS resolution is freed
7 - BUG/MEDIUM: dns: Don't yield in do resolve action on a final
8
9 -- Simon Deziel <simon@sdeziel.info> Tue, 08 Sep 2020 17:16:14 +0000
10
1haproxy (2.0.13-2) unstable; urgency=medium11haproxy (2.0.13-2) unstable; urgency=medium
212
3 * d/dconv: replace cgi.escape by html.escape. Closes: #951416.13 * d/dconv: replace cgi.escape by html.escape. Closes: #951416.
diff --git a/debian/control b/debian/control
index cc08457..05a48d5 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,8 @@
1Source: haproxy1Source: haproxy
2Section: net2Section: net
3Priority: optional3Priority: optional
4Maintainer: Debian HAProxy Maintainers <haproxy@tracker.debian.org>4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5XSBC-Original-Maintainer: Debian HAProxy Maintainers <haproxy@tracker.debian.org>
5Uploaders: Apollon Oikonomopoulos <apoikos@debian.org>,6Uploaders: Apollon Oikonomopoulos <apoikos@debian.org>,
6 Prach Pongpanich <prach@debian.org>,7 Prach Pongpanich <prach@debian.org>,
7 Vincent Bernat <bernat@debian.org>8 Vincent Bernat <bernat@debian.org>
diff --git a/debian/patches/lp1894879-BUG-CRITICAL-dns-Make-the-do-resolve-action-thread-safe.patch b/debian/patches/lp1894879-BUG-CRITICAL-dns-Make-the-do-resolve-action-thread-safe.patch
8new file mode 1006449new file mode 100644
index 0000000..e9e6edc
--- /dev/null
+++ b/debian/patches/lp1894879-BUG-CRITICAL-dns-Make-the-do-resolve-action-thread-safe.patch
@@ -0,0 +1,132 @@
1From ef131aee357478c45d547abcb0ab21c2a191f578 Mon Sep 17 00:00:00 2001
2From: Christopher Faulet <cfaulet@haproxy.com>
3Date: Wed, 22 Jul 2020 11:46:32 +0200
4Subject: [PATCH] BUG/MAJOR: dns: Make the do-resolve action thread-safe
5
6The do-resolve HTTP action, performing a DNS resolution of a sample expression
7output, is not thread-safe at all. The resolver object used to do the resolution
8must be locked when the action is executed or when the stream is released
9because its curr or wait resolution lists and the requester list inside a
10resolution are updated. It is also important to not wake up a released stream
11(with a destroyed task).
12
13Of course, because of this bug, various kind of crashes may be observed.
14
15This patch should fix the issue #236. It must be backported as far as 2.0.
16
17(cherry picked from commit 5098a08c2fafb0d9513996729d2a30c9785378f3)
18Signed-off-by: Willy Tarreau <w@1wt.eu>
19(cherry picked from commit 99f4623952cbbad2bcae451abdd0f3133bcbe75c)
20Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
21(cherry picked from commit 6e5861d72fe1e3c9d34b591d6f77ffd28ddde197)
22Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
23---
24 src/dns.c | 36 +++++++++++++++++++++++++++---------
25 src/stream.c | 4 ++++
26 2 files changed, 31 insertions(+), 9 deletions(-)
27
28diff --git a/src/dns.c b/src/dns.c
29index 282fa92..40e29ad 100644
30--- a/src/dns.c
31+++ b/src/dns.c
32@@ -2162,14 +2162,23 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px,
33 struct dns_requester *req;
34 struct dns_resolvers *resolvers;
35 struct dns_resolution *res;
36- int exp;
37+ int exp, locked = 0;
38+ enum act_return ret = ACT_RET_CONT;
39+
40+ resolvers = rule->arg.dns.resolvers;
41
42 /* we have a response to our DNS resolution */
43 use_cache:
44 if (s->dns_ctx.dns_requester && s->dns_ctx.dns_requester->resolution != NULL) {
45 resolution = s->dns_ctx.dns_requester->resolution;
46+ if (!locked) {
47+ HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
48+ locked = 1;
49+ }
50+
51 if (resolution->step == RSLV_STEP_RUNNING) {
52- return ACT_RET_YIELD;
53+ ret = ACT_RET_YIELD;
54+ goto end;
55 }
56 if (resolution->step == RSLV_STEP_NONE) {
57 /* We update the variable only if we have a valid response. */
58@@ -2211,29 +2220,33 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px,
59 pool_free(dns_requester_pool, s->dns_ctx.dns_requester);
60 s->dns_ctx.dns_requester = NULL;
61
62- return ACT_RET_CONT;
63+ goto end;
64 }
65
66 /* need to configure and start a new DNS resolution */
67 smp = sample_fetch_as_type(px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.dns.expr, SMP_T_STR);
68 if (smp == NULL)
69- return ACT_RET_CONT;
70+ goto end;
71
72 fqdn = smp->data.u.str.area;
73 if (action_prepare_for_resolution(s, fqdn) == -1)
74- return ACT_RET_ERR;
75+ goto end; /* on error, ignore the action */
76
77 s->dns_ctx.parent = rule;
78+
79+ HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
80+ locked = 1;
81+
82 dns_link_resolution(s, OBJ_TYPE_STREAM, 0);
83
84 /* Check if there is a fresh enough response in the cache of our associated resolution */
85 req = s->dns_ctx.dns_requester;
86 if (!req || !req->resolution) {
87 dns_trigger_resolution(s->dns_ctx.dns_requester);
88- return ACT_RET_YIELD;
89+ ret = ACT_RET_YIELD;
90+ goto end;
91 }
92- res = req->resolution;
93- resolvers = res->resolvers;
94+ res = req->resolution;
95
96 exp = tick_add(res->last_resolution, resolvers->hold.valid);
97 if (resolvers->t && res->status == RSLV_STATUS_VALID && tick_isset(res->last_resolution)
98@@ -2242,7 +2255,12 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px,
99 }
100
101 dns_trigger_resolution(s->dns_ctx.dns_requester);
102- return ACT_RET_YIELD;
103+ ret = ACT_RET_YIELD;
104+
105+ end:
106+ if (locked)
107+ HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
108+ return ret;
109 }
110
111
112diff --git a/src/stream.c b/src/stream.c
113index 080189e..2eb7cfa 100644
114--- a/src/stream.c
115+++ b/src/stream.c
116@@ -435,9 +435,13 @@ static void stream_free(struct stream *s)
117 }
118
119 if (s->dns_ctx.dns_requester) {
120+ __decl_hathreads(struct dns_resolvers *resolvers = s->dns_ctx.parent->arg.dns.resolvers);
121+
122+ HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
123 free(s->dns_ctx.hostname_dn); s->dns_ctx.hostname_dn = NULL;
124 s->dns_ctx.hostname_dn_len = 0;
125 dns_unlink_resolution(s->dns_ctx.dns_requester);
126+ HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
127
128 pool_free(dns_requester_pool, s->dns_ctx.dns_requester);
129 s->dns_ctx.dns_requester = NULL;
130--
1311.7.10.4
132
diff --git a/debian/patches/lp1894879-BUG-MEDIUM-dns-Dont-yield-in-do-resolve-action-on-a-final.patch b/debian/patches/lp1894879-BUG-MEDIUM-dns-Dont-yield-in-do-resolve-action-on-a-final.patch
0new file mode 100644133new file mode 100644
index 0000000..34a6a37
--- /dev/null
+++ b/debian/patches/lp1894879-BUG-MEDIUM-dns-Dont-yield-in-do-resolve-action-on-a-final.patch
@@ -0,0 +1,106 @@
1From 74d704f2f36945d60f1ff7ea75dbfe3f40508861 Mon Sep 17 00:00:00 2001
2From: Christopher Faulet <cfaulet@haproxy.com>
3Date: Tue, 28 Jul 2020 10:21:54 +0200
4Subject: [PATCH] BUG/MEDIUM: dns: Don't yield in do-resolve action on a final
5 evaluation
6
7When an action is evaluated, flags are passed to know if it is the first call
8(ACT_OPT_FIRST) and if it must be the last one (ACT_OPT_FINAL). For the
9do-resolve DNS action, the ACT_OPT_FINAL flag must be handled because the
10action may yield. It must never yield when this flag is set. Otherwise, it may
11lead to a wakeup loop of the stream because the inspected-delay of a tcp-request
12content ruleset was reached without stopping the rules evaluation.
13
14This patch is related to the issue #222. It must be backported as far as 2.0.
15
16(cherry picked from commit 385101e53816dc1b7bc1fc957adc512ce8a07cb4)
17Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
18(cherry picked from commit 5c038f759959adf95b4b347aba9d97e60ab87e93)
19Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
20(cherry picked from commit af018c4865400dda4553a732df4c43751a4ff88c)
21Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
22---
23 src/dns.c | 39 +++++++++++++++++++++------------------
24 1 file changed, 21 insertions(+), 18 deletions(-)
25
26diff --git a/src/dns.c b/src/dns.c
27index 18e64d9..095040e 100644
28--- a/src/dns.c
29+++ b/src/dns.c
30@@ -2182,10 +2182,8 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px,
31 locked = 1;
32 }
33
34- if (resolution->step == RSLV_STEP_RUNNING) {
35- ret = ACT_RET_YIELD;
36- goto end;
37- }
38+ if (resolution->step == RSLV_STEP_RUNNING)
39+ goto yield;
40 if (resolution->step == RSLV_STEP_NONE) {
41 /* We update the variable only if we have a valid response. */
42 if (resolution->status == RSLV_STATUS_VALID) {
43@@ -2219,14 +2217,7 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px,
44 }
45 }
46
47- free(s->dns_ctx.hostname_dn); s->dns_ctx.hostname_dn = NULL;
48- s->dns_ctx.hostname_dn_len = 0;
49- dns_unlink_resolution(s->dns_ctx.dns_requester);
50-
51- pool_free(dns_requester_pool, s->dns_ctx.dns_requester);
52- s->dns_ctx.dns_requester = NULL;
53-
54- goto end;
55+ goto release_requester;
56 }
57
58 /* need to configure and start a new DNS resolution */
59@@ -2247,26 +2238,38 @@ enum act_return dns_action_do_resolve(struct act_rule *rule, struct proxy *px,
60
61 /* Check if there is a fresh enough response in the cache of our associated resolution */
62 req = s->dns_ctx.dns_requester;
63- if (!req || !req->resolution) {
64- dns_trigger_resolution(s->dns_ctx.dns_requester);
65- ret = ACT_RET_YIELD;
66- goto end;
67- }
68+ if (!req || !req->resolution)
69+ goto release_requester; /* on error, ignore the action */
70 res = req->resolution;
71
72 exp = tick_add(res->last_resolution, resolvers->hold.valid);
73 if (resolvers->t && res->status == RSLV_STATUS_VALID && tick_isset(res->last_resolution)
74- && !tick_is_expired(exp, now_ms)) {
75+ && !tick_is_expired(exp, now_ms)) {
76 goto use_cache;
77 }
78
79 dns_trigger_resolution(s->dns_ctx.dns_requester);
80+
81+ yield:
82+ if (flags & ACT_FLAG_FINAL)
83+ goto release_requester;
84 ret = ACT_RET_YIELD;
85
86 end:
87 if (locked)
88 HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
89 return ret;
90+
91+ release_requester:
92+ free(s->dns_ctx.hostname_dn);
93+ s->dns_ctx.hostname_dn = NULL;
94+ s->dns_ctx.hostname_dn_len = 0;
95+ if (s->dns_ctx.dns_requester) {
96+ dns_unlink_resolution(s->dns_ctx.dns_requester);
97+ pool_free(dns_requester_pool, s->dns_ctx.dns_requester);
98+ s->dns_ctx.dns_requester = NULL;
99+ }
100+ goto end;
101 }
102
103
104--
1051.7.10.4
106
diff --git a/debian/patches/lp1894879-BUG-MEDIUM-dns-Release-answer-items-when-a-DNS-resolution-is-freed.patch b/debian/patches/lp1894879-BUG-MEDIUM-dns-Release-answer-items-when-a-DNS-resolution-is-freed.patch
0new file mode 100644107new file mode 100644
index 0000000..f83de45
--- /dev/null
+++ b/debian/patches/lp1894879-BUG-MEDIUM-dns-Release-answer-items-when-a-DNS-resolution-is-freed.patch
@@ -0,0 +1,51 @@
1From 39eb766825d8aad09946dfc284d4a73f610ebd64 Mon Sep 17 00:00:00 2001
2From: Christopher Faulet <cfaulet@haproxy.com>
3Date: Wed, 22 Jul 2020 15:55:49 +0200
4Subject: [PATCH] BUG/MEDIUM: dns: Release answer items when a DNS resolution
5 is freed
6
7When a DNS resolution is freed, the remaining items in .ar_list and .answer_list
8are also released. It must be done to avoid a memory leak. And it is the last
9chance to release these objects. I've honestly no idea if there is a better
10place to release them earlier. But at least, there is no more leak.
11
12This patch should solve the issue #222. It must be backported, at least, as far
13as 2.0, and probably, with caution, as far as 1.8 or 1.7.
14
15(cherry picked from commit 010ab35a9118daf17a670fb2b42e40447f967f7c)
16Signed-off-by: Willy Tarreau <w@1wt.eu>
17(cherry picked from commit c58ac80d00284886b108b209a5bf993de5ab38ed)
18Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
19(cherry picked from commit 81120e6ea286ae3f2566959167fb56a7d1f0de19)
20Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
21---
22 src/dns.c | 6 ++++++
23 1 file changed, 6 insertions(+)
24
25diff --git a/src/dns.c b/src/dns.c
26index 40e29ad..18e64d9 100644
27--- a/src/dns.c
28+++ b/src/dns.c
29@@ -1336,6 +1336,7 @@ static struct dns_resolution *dns_pick_resolution(struct dns_resolvers *resolver
30 static void dns_free_resolution(struct dns_resolution *resolution)
31 {
32 struct dns_requester *req, *reqback;
33+ struct dns_answer_item *item, *itemback;
34
35 /* clean up configuration */
36 dns_reset_resolution(resolution);
37@@ -1347,6 +1348,11 @@ static void dns_free_resolution(struct dns_resolution *resolution)
38 req->resolution = NULL;
39 }
40
41+ list_for_each_entry_safe(item, itemback, &resolution->response.answer_list, list) {
42+ LIST_DEL(&item->list);
43+ pool_free(dns_answer_item_pool, item);
44+ }
45+
46 LIST_DEL(&resolution->list);
47 pool_free(dns_resolution_pool, resolution);
48 }
49--
501.7.10.4
51
diff --git a/debian/patches/series b/debian/patches/series
index b57f722..c8fe75d 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -7,3 +7,7 @@ haproxy.service-add-documentation.patch
77
8# applied during the build process:8# applied during the build process:
9# debianize-dconv.patch9# debianize-dconv.patch
10
11lp1894879-BUG-CRITICAL-dns-Make-the-do-resolve-action-thread-safe.patch
12lp1894879-BUG-MEDIUM-dns-Release-answer-items-when-a-DNS-resolution-is-freed.patch
13lp1894879-BUG-MEDIUM-dns-Dont-yield-in-do-resolve-action-on-a-final.patch

Subscribers

People subscribed via source and target branches