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.

131 lines
4.9 KiB

  1. From a72d39058a7a5d004e0c6b69a91663591bb3bf89 Mon Sep 17 00:00:00 2001
  2. From: Vincent Bernat <vincent@bernat.im>
  3. Date: Thu, 19 May 2016 11:15:51 +0200
  4. Subject: [PATCH 1/4] BUG/MAJOR: fix listening IP address storage for frontends
  5. When compiled with GCC 6, the IP address specified for a frontend was
  6. ignored and HAProxy was listening on all addresses instead. This is
  7. caused by an incomplete copy of a "struct sockaddr_storage".
  8. With the GNU Libc, "struct sockaddr_storage" is defined as this:
  9. struct sockaddr_storage
  10. {
  11. sa_family_t ss_family;
  12. unsigned long int __ss_align;
  13. char __ss_padding[(128 - (2 * sizeof (unsigned long int)))];
  14. };
  15. Doing an aggregate copy (ss1 = ss2) is different than using memcpy():
  16. only members of the aggregate have to be copied. Notably, padding can be
  17. or not be copied. In GCC 6, some optimizations use this fact and if a
  18. "struct sockaddr_storage" contains a "struct sockaddr_in", the port and
  19. the address are part of the padding (between sa_family and __ss_align)
  20. and can be not copied over.
  21. Therefore, we replace any aggregate copy by a memcpy(). There is another
  22. place using the same pattern. We also fix a function receiving a "struct
  23. sockaddr_storage" by copy instead of by reference. Since it only needs a
  24. read-only copy, the function is converted to request a reference.
  25. This is a backport for 1.5 of 6e6158 and 6e46ff1.
  26. ---
  27. src/cfgparse.c | 4 ++--
  28. src/connection.c | 2 +-
  29. src/proto_http.c | 12 ++++++------
  30. src/proto_tcp.c | 2 +-
  31. 4 files changed, 10 insertions(+), 10 deletions(-)
  32. diff --git a/src/cfgparse.c b/src/cfgparse.c
  33. index 39abf6b..9331415 100644
  34. --- a/src/cfgparse.c
  35. +++ b/src/cfgparse.c
  36. @@ -280,7 +280,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
  37. }
  38. /* OK the address looks correct */
  39. - ss = *ss2;
  40. + memcpy(&ss, ss2, sizeof(ss));
  41. for (; port <= end; port++) {
  42. l = (struct listener *)calloc(1, sizeof(struct listener));
  43. @@ -291,7 +291,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
  44. l->bind_conf = bind_conf;
  45. l->fd = fd;
  46. - l->addr = ss;
  47. + memcpy(&l->addr, &ss, sizeof(ss));
  48. l->xprt = &raw_sock;
  49. l->state = LI_INIT;
  50. diff --git a/src/connection.c b/src/connection.c
  51. index dab1c90..09fd04e 100644
  52. --- a/src/connection.c
  53. +++ b/src/connection.c
  54. @@ -620,7 +620,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
  55. const char pp2_signature[] = PP2_SIGNATURE;
  56. int ret = 0;
  57. struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf;
  58. - struct sockaddr_storage null_addr = {0};
  59. + struct sockaddr_storage null_addr = { .ss_family = 0 };
  60. struct sockaddr_storage *src = &null_addr;
  61. struct sockaddr_storage *dst = &null_addr;
  62. #ifdef USE_OPENSSL
  63. diff --git a/src/proto_http.c b/src/proto_http.c
  64. index b3aa4d8..0b13c5e 100644
  65. --- a/src/proto_http.c
  66. +++ b/src/proto_http.c
  67. @@ -3220,15 +3220,15 @@ int http_handle_stats(struct session *s, struct channel *req)
  68. /* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets
  69. * (as per RFC3260 #4 and BCP37 #4.2 and #5.2).
  70. */
  71. -static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos)
  72. +static inline void inet_set_tos(int fd, struct sockaddr_storage *from, int tos)
  73. {
  74. #ifdef IP_TOS
  75. - if (from.ss_family == AF_INET)
  76. + if (from->ss_family == AF_INET)
  77. setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
  78. #endif
  79. #ifdef IPV6_TCLASS
  80. - if (from.ss_family == AF_INET6) {
  81. - if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr))
  82. + if (from->ss_family == AF_INET6) {
  83. + if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)from)->sin6_addr))
  84. /* v4-mapped addresses need IP_TOS */
  85. setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
  86. else
  87. @@ -3366,7 +3366,7 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
  88. case HTTP_REQ_ACT_SET_TOS:
  89. if ((cli_conn = objt_conn(s->req->prod->end)) && conn_ctrl_ready(cli_conn))
  90. - inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
  91. + inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos);
  92. break;
  93. case HTTP_REQ_ACT_SET_MARK:
  94. @@ -3563,7 +3563,7 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session
  95. case HTTP_RES_ACT_SET_TOS:
  96. if ((cli_conn = objt_conn(s->req->prod->end)) && conn_ctrl_ready(cli_conn))
  97. - inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
  98. + inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, rule->arg.tos);
  99. break;
  100. case HTTP_RES_ACT_SET_MARK:
  101. diff --git a/src/proto_tcp.c b/src/proto_tcp.c
  102. index cfa62f7..8c06441 100644
  103. --- a/src/proto_tcp.c
  104. +++ b/src/proto_tcp.c
  105. @@ -394,7 +394,7 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
  106. struct sockaddr_storage sa;
  107. ret = 1;
  108. - sa = src->source_addr;
  109. + memcpy(&sa, &src->source_addr, sizeof(sa));
  110. do {
  111. /* note: in case of retry, we may have to release a previously
  112. --
  113. 2.7.3