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.

111 lines
5.7 KiB

  1. From f94735eb76e634d7531f9c903113f64820c4cec0 Mon Sep 17 00:00:00 2001
  2. From: Willy Tarreau <w@1wt.eu>
  3. Date: Wed, 30 Jul 2014 08:56:35 +0200
  4. Subject: [PATCH 3/3] BUG/MAJOR: tcp: fix a possible busy spinning loop in
  5. content track-sc*
  6. As a consequence of various recent changes on the sample conversion,
  7. a corner case has emerged where it is possible to wait forever for a
  8. sample in track-sc*.
  9. The issue is caused by the fact that functions relying on sample_process()
  10. don't all exactly work the same regarding the SMP_F_MAY_CHANGE flag and
  11. the output result. Here it was possible to wait forever for an output
  12. sample from stktable_fetch_key() without checking the SMP_OPT_FINAL flag.
  13. As a result, if the client connects and closes without sending the data
  14. and haproxy expects a sample which is capable of coming, it will ignore
  15. this impossible case and will continue to wait.
  16. This change adds control for SMP_OPT_FINAL before waiting for extra data.
  17. The various relevant functions have been better documented regarding their
  18. output values.
  19. This fix must be backported to 1.5 since it appeared there.
  20. (cherry picked from commit 6bcb0a84e7256f00793fa8ec8a0d6c19c3b22935)
  21. ---
  22. src/proto_tcp.c | 4 ++--
  23. src/sample.c | 23 ++++++++++++++++++++++-
  24. src/stick_table.c | 11 ++++++++++-
  25. 3 files changed, 34 insertions(+), 4 deletions(-)
  26. diff --git a/src/proto_tcp.c b/src/proto_tcp.c
  27. index 9778856..72dc92b 100644
  28. --- a/src/proto_tcp.c
  29. +++ b/src/proto_tcp.c
  30. @@ -1048,8 +1048,8 @@ int tcp_inspect_request(struct session *s, struct channel *req, int an_bit)
  31. t = rule->act_prm.trk_ctr.table.t;
  32. key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ | partial, rule->act_prm.trk_ctr.expr, &smp);
  33. - if (smp.flags & SMP_F_MAY_CHANGE)
  34. - goto missing_data;
  35. + if ((smp.flags & SMP_F_MAY_CHANGE) && !(partial & SMP_OPT_FINAL))
  36. + goto missing_data; /* key might appear later */
  37. if (key && (ts = stktable_get_entry(t, key))) {
  38. session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts);
  39. diff --git a/src/sample.c b/src/sample.c
  40. index 3a0f3fb..8e62640 100644
  41. --- a/src/sample.c
  42. +++ b/src/sample.c
  43. @@ -896,6 +896,18 @@ out_error:
  44. * Note: the fetch functions are required to properly set the return type. The
  45. * conversion functions must do so too. However the cast functions do not need
  46. * to since they're made to cast mutiple types according to what is required.
  47. + *
  48. + * The caller may indicate in <opt> if it considers the result final or not.
  49. + * The caller needs to check the SMP_F_MAY_CHANGE flag in p->flags to verify
  50. + * if the result is stable or not, according to the following table :
  51. + *
  52. + * return MAY_CHANGE FINAL Meaning for the sample
  53. + * NULL 0 * Not present and will never be (eg: header)
  54. + * NULL 1 0 Not present yet, could change (eg: POST param)
  55. + * NULL 1 1 Not present yet, will not change anymore
  56. + * smp 0 * Present and will not change (eg: header)
  57. + * smp 1 0 Present, may change (eg: request length)
  58. + * smp 1 1 Present, last known value (eg: request length)
  59. */
  60. struct sample *sample_process(struct proxy *px, struct session *l4, void *l7,
  61. unsigned int opt,
  62. @@ -1153,7 +1165,16 @@ int smp_resolve_args(struct proxy *p)
  63. * and <opt> does not contain SMP_OPT_FINAL, then the sample is returned as-is
  64. * with its SMP_F_MAY_CHANGE flag so that the caller can check it and decide to
  65. * take actions (eg: wait longer). If a sample could not be found or could not
  66. - * be converted, NULL is returned.
  67. + * be converted, NULL is returned. The caller MUST NOT use the sample if the
  68. + * SMP_F_MAY_CHANGE flag is present, as it is used only as a hint that there is
  69. + * still hope to get it after waiting longer, and is not converted to string.
  70. + * The possible output combinations are the following :
  71. + *
  72. + * return MAY_CHANGE FINAL Meaning for the sample
  73. + * NULL * * Not present and will never be (eg: header)
  74. + * smp 0 * Final value converted (eg: header)
  75. + * smp 1 0 Not present yet, may appear later (eg: header)
  76. + * smp 1 1 never happens (either flag is cleared on output)
  77. */
  78. struct sample *sample_fetch_string(struct proxy *px, struct session *l4, void *l7,
  79. unsigned int opt, struct sample_expr *expr)
  80. diff --git a/src/stick_table.c b/src/stick_table.c
  81. index a708d3c..d39b4ff 100644
  82. --- a/src/stick_table.c
  83. +++ b/src/stick_table.c
  84. @@ -603,7 +603,16 @@ static sample_to_key_fct sample_to_key[SMP_TYPES][STKTABLE_TYPES] = {
  85. * no key could be extracted, or a pointer to the converted result stored in
  86. * static_table_key in format <table_type>. If <smp> is not NULL, it will be reset
  87. * and its flags will be initialized so that the caller gets a copy of the input
  88. - * sample, and knows why it was not accepted (eg: SMP_F_MAY_CHANGE is present).
  89. + * sample, and knows why it was not accepted (eg: SMP_F_MAY_CHANGE is present
  90. + * without SMP_OPT_FINAL). The output will be usable like this :
  91. + *
  92. + * return MAY_CHANGE FINAL Meaning for the sample
  93. + * NULL 0 * Not present and will never be (eg: header)
  94. + * NULL 1 0 Not present or unstable, could change (eg: req_len)
  95. + * NULL 1 1 Not present, will not change anymore
  96. + * smp 0 * Present and will not change (eg: header)
  97. + * smp 1 0 not possible
  98. + * smp 1 1 Present, last known value (eg: request length)
  99. */
  100. struct stktable_key *stktable_fetch_key(struct stktable *t, struct proxy *px, struct session *l4, void *l7,
  101. unsigned int opt, struct sample_expr *expr, struct sample *smp)
  102. --
  103. 1.8.5.5