You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.5 KiB

  1. From 97fccc87f1297d189ee80735e5b8746c34956eda Mon Sep 17 00:00:00 2001
  2. From: Willy Tarreau <w@1wt.eu>
  3. Date: Wed, 13 May 2015 12:08:21 +0200
  4. Subject: [PATCH 7/8] BUG/MAJOR: checks: always check for end of list before
  5. proceeding
  6. This is the most important fix of this series. There's a risk of endless
  7. loop and crashes caused by the fact that we go past the head of the list
  8. when skipping to next rule, without checking if it's still a valid element.
  9. Most of the time, the ->action field is checked, which points to the proxy's
  10. check_req pointer (generally NULL), meaning the element is confused with a
  11. TCPCHK_ACT_SEND action.
  12. The situation was accidently made worse with the addition of tcp-check
  13. comment since it also skips list elements. However, since the action that
  14. makes it go forward is TCPCHK_ACT_COMMENT (3), there's little chance to
  15. see this as a valid pointer, except on 64-bit machines where it can match
  16. the end of a check_req string pointer.
  17. This fix heavily depends on previous cleanup and both must be backported
  18. to 1.5 where the bug is present.
  19. (cherry picked from commit f2c87353a7f8160930b5f342bb6d6ad0991ee3d1)
  20. [wt: this patch differs significantly from 1.6 since we don't have comments]
  21. ---
  22. src/cfgparse.c | 4 +++-
  23. src/checks.c | 12 ++++++++++++
  24. 2 files changed, 15 insertions(+), 1 deletion(-)
  25. diff --git a/src/cfgparse.c b/src/cfgparse.c
  26. index 746c7eb..dba59d1 100644
  27. --- a/src/cfgparse.c
  28. +++ b/src/cfgparse.c
  29. @@ -4368,7 +4368,9 @@ stats_error_parsing:
  30. l = (struct list *)&curproxy->tcpcheck_rules;
  31. if (l->p != l->n) {
  32. tcpcheck = (struct tcpcheck_rule *)l->n;
  33. - if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
  34. +
  35. + if (&tcpcheck->list != &curproxy->tcpcheck_rules
  36. + && tcpcheck->action != TCPCHK_ACT_CONNECT) {
  37. Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
  38. file, linenum);
  39. err_code |= ERR_ALERT | ERR_FATAL;
  40. diff --git a/src/checks.c b/src/checks.c
  41. index a0c42f2..e13d561 100644
  42. --- a/src/checks.c
  43. +++ b/src/checks.c
  44. @@ -2057,6 +2057,9 @@ static void tcpcheck_main(struct connection *conn)
  45. /* allow next rule */
  46. check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
  47. + if (&check->current_step->list == head)
  48. + break;
  49. +
  50. /* don't do anything until the connection is established */
  51. if (!(conn->flags & CO_FL_CONNECTED)) {
  52. /* update expire time, should be done by process_chk */
  53. @@ -2110,6 +2113,9 @@ static void tcpcheck_main(struct connection *conn)
  54. /* go to next rule and try to send */
  55. check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
  56. +
  57. + if (&check->current_step->list == head)
  58. + break;
  59. } /* end 'send' */
  60. else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
  61. if (unlikely(check->result == CHK_RES_FAILED))
  62. @@ -2196,6 +2202,9 @@ static void tcpcheck_main(struct connection *conn)
  63. /* allow next rule */
  64. check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
  65. + if (&check->current_step->list == head)
  66. + break;
  67. +
  68. if (check->current_step->action == TCPCHK_ACT_EXPECT)
  69. goto tcpcheck_expect;
  70. __conn_data_stop_recv(conn);
  71. @@ -2208,6 +2217,9 @@ static void tcpcheck_main(struct connection *conn)
  72. /* allow next rule */
  73. check->current_step = (struct tcpcheck_rule *)check->current_step->list.n;
  74. + if (&check->current_step->list == head)
  75. + break;
  76. +
  77. if (check->current_step->action == TCPCHK_ACT_EXPECT)
  78. goto tcpcheck_expect;
  79. __conn_data_stop_recv(conn);
  80. --
  81. 2.0.5