]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: prevent gcc from moving empty keywords lists into BSS
authorWilly Tarreau <w@1wt.eu>
Fri, 21 Jun 2013 21:16:39 +0000 (23:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 21 Jun 2013 21:29:02 +0000 (23:29 +0200)
Benoit Dolez reported a failure to start haproxy 1.5-dev19. The
process would immediately report an internal error with missing
fetches from some crap instead of ACL names.

The cause is that some versions of gcc seem to trim static structs
containing a variable array when moving them to BSS, and only keep
the fixed size, which is just a list head for all ACL and sample
fetch keywords. This was confirmed at least with gcc 3.4.6. And we
can't move these structs to const because they contain a list element
which is needed to link all of them together during the parsing.

The bug indeed appeared with 1.5-dev19 because it's the first one
to have some empty ACL keyword lists.

One solution is to impose -fno-zero-initialized-in-bss to everyone
but this is not really nice. Another solution consists in ensuring
the struct is never empty so that it does not move there. The easy
solution consists in having a non-null list head since it's not yet
initialized.

A new "ILH" list head type was thus created for this purpose : create
an Initialized List Head so that gcc cannot move the struct to BSS.
This fixes the issue for this version of gcc and does not create any
burden for the declarations.

14 files changed:
include/common/mini-clist.h
src/acl.c
src/backend.c
src/compression.c
src/dumpstats.c
src/frontend.c
src/listener.c
src/payload.c
src/proto_http.c
src/proto_tcp.c
src/proxy.c
src/sample.c
src/session.c
src/ssl_sock.c

index e89ffe0aecda6a51f03775a9312fa10655da8741..3c3f0018f31fdaa225cb685159c1cb732ca62e11 100644 (file)
@@ -53,6 +53,12 @@ struct cond_wordlist {
 #undef LIST_INIT
 #undef LIST_NEXT
 
+/* ILH = Initialized List Head : used to prevent gcc from moving an empty
+ * list to BSS. Some older version tend to trim all the array and cause
+ * corruption.
+ */
+#define ILH            { .n = (struct list *)1, .p = (struct list *)2 }
+
 #define LIST_HEAD(a)   ((void *)(&(a)))
 
 #define LIST_INIT(l) ((l)->n = (l)->p = (l))
index 664ef5c6590613f6e42277f100fe9274752fb799..845e1de1e981a408bcfaff9dc541439829c08f45 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -2010,7 +2010,7 @@ smp_fetch_env(struct proxy *px, struct session *s, void *l7, unsigned int opt,
  * common denominator, the type that can be casted into all other ones. For
  * instance IPv4/IPv6 must be declared IPv4.
  */
-static struct sample_fetch_kw_list smp_kws = {{ },{
+static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "always_false", smp_fetch_false, 0,            NULL, SMP_T_BOOL, SMP_USE_INTRN },
        { "always_true",  smp_fetch_true,  0,            NULL, SMP_T_BOOL, SMP_USE_INTRN },
        { "env",          smp_fetch_env,   ARG1(1,STR),  NULL, SMP_T_CSTR, SMP_USE_INTRN },
@@ -2021,7 +2021,7 @@ static struct sample_fetch_kw_list smp_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
index 0392355fc803d6b6409bca80e7fc05f08dba715f..d677ab2a51393504dd4d3912747e7a4225cb041c 100644 (file)
@@ -1579,7 +1579,7 @@ smp_fetch_srv_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct sample_fetch_kw_list smp_kws = {{ },{
+static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "avg_queue",     smp_fetch_avg_queue_size, ARG1(1,BE),  NULL, SMP_T_UINT, SMP_USE_INTRN, },
        { "be_conn",       smp_fetch_be_conn,        ARG1(1,BE),  NULL, SMP_T_UINT, SMP_USE_INTRN, },
        { "be_id",         smp_fetch_be_id,          0,           NULL, SMP_T_UINT, SMP_USE_BKEND, },
@@ -1598,7 +1598,7 @@ static struct sample_fetch_kw_list smp_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
index 75b232baa4079cda0021fdca93078cd549344b31..24900610940129d634eb5942c4be718bdefb7c29 100644 (file)
@@ -635,12 +635,12 @@ smp_fetch_res_comp_algo(struct proxy *px, struct session *l4, void *l7, unsigned
 }
 
 /* Note: must not be declared <const> as its list will be overwritten */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
 /* Note: must not be declared <const> as its list will be overwritten */
-static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
+static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "res.comp",             smp_fetch_res_comp,      0,                NULL,    SMP_T_BOOL, SMP_USE_HRSHP },
        { "res.comp_algo",        smp_fetch_res_comp_algo, 0,                NULL,    SMP_T_STR, SMP_USE_HRSHP },
        { /* END */ },
index 25f54416c29d2ec00012284cd2bdf209e2085061..e4c3f4342a80d56ff64ab01c66977a0eb2e02a17 100644 (file)
@@ -4439,7 +4439,7 @@ static struct si_applet cli_applet = {
        .release = cli_release_handler,
 };
 
-static struct cfg_kw_list cfg_kws = {{ },{
+static struct cfg_kw_list cfg_kws = {ILH, {
        { CFG_GLOBAL, "stats", stats_parse_global },
        { 0, NULL, NULL },
 }};
index e0fd30ff708c35f187710be1afb34e0b1ab3ba7c..58236ba433da0d01523a9613ce6dc6e5284ae656 100644 (file)
@@ -256,7 +256,7 @@ smp_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, unsigned int o
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct sample_fetch_kw_list smp_kws = {{ },{
+static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "fe_conn",      smp_fetch_fe_conn,      ARG1(1,FE), NULL, SMP_T_UINT, SMP_USE_INTRN, },
        { "fe_id",        smp_fetch_fe_id,        0,          NULL, SMP_T_UINT, SMP_USE_FTEND, },
        { "fe_sess_rate", smp_fetch_fe_sess_rate, ARG1(1,FE), NULL, SMP_T_UINT, SMP_USE_INTRN, },
@@ -267,7 +267,7 @@ static struct sample_fetch_kw_list smp_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
index 1ee95251c6475ee7afdb866dc42ca3c158c87252..ce8b4f2bed011147a6d55c6cdb31f05c82cae5ec 100644 (file)
@@ -643,7 +643,7 @@ static int bind_parse_nice(char **args, int cur_arg, struct proxy *px, struct bi
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct sample_fetch_kw_list smp_kws = {{ },{
+static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "dst_conn", smp_fetch_dconn, 0, NULL, SMP_T_UINT, SMP_USE_FTEND, },
        { "so_id",    smp_fetch_so_id, 0, NULL, SMP_T_UINT, SMP_USE_FTEND, },
        { /* END */ },
@@ -652,7 +652,7 @@ static struct sample_fetch_kw_list smp_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
index ee3e6ebbf262706268a26a0a092567ba831bccf2..bc54e114a7a4fef3ba54247aa68ea7105c2f8c10 100644 (file)
@@ -650,7 +650,7 @@ static int val_payload_lv(struct arg *arg, char **err_msg)
  * common denominator, the type that can be casted into all other ones. For
  * instance IPv4/IPv6 must be declared IPv4.
  */
-static struct sample_fetch_kw_list smp_kws = {{ },{
+static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "payload",             smp_fetch_payload,        ARG2(2,UINT,UINT),      val_payload,    SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES },
        { "payload_lv",          smp_fetch_payload_lv,     ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES },
        { "rdp_cookie",          smp_fetch_rdp_cookie,     ARG1(0,STR),            NULL,           SMP_T_CSTR, SMP_USE_L6REQ },
@@ -680,7 +680,7 @@ static struct sample_fetch_kw_list smp_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { "payload",            "req.payload",        acl_parse_str,        acl_match_str     },
        { "payload_lv",         "req.payload_lv",     acl_parse_str,        acl_match_str     },
        { "req_rdp_cookie",     "req.rdp_cookie",     acl_parse_str,        acl_match_str     },
index 9068050a5e995abef2d24dd5194097c53a132fa2..8d9844011edfdd897433d72ebe275b6c1fec080e 100644 (file)
@@ -10106,7 +10106,7 @@ static int val_hdr(struct arg *arg, char **err_msg)
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { "base",            "base",          acl_parse_str,     acl_match_str     },
        { "base_beg",        "base",          acl_parse_str,     acl_match_beg     },
        { "base_dir",        "base",          acl_parse_str,     acl_match_dir     },
@@ -10193,7 +10193,7 @@ static struct acl_kw_list acl_kws = {{ },{
 /*         All supported pattern keywords must be declared here.        */
 /************************************************************************/
 /* Note: must not be declared <const> as its list will be overwritten */
-static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
+static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "base",            smp_fetch_base,           0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
        { "base32",          smp_fetch_base32,         0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
        { "base32+src",      smp_fetch_base32_src,     0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
index bfce6a265fb24e1c422897ada1789344ec90c498..4357b0407f1c3da833984aa08601a5dcd85c7c6a 100644 (file)
@@ -1731,7 +1731,7 @@ static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, stru
 }
 #endif
 
-static struct cfg_kw_list cfg_kws = {{ },{
+static struct cfg_kw_list cfg_kws = {ILH, {
        { CFG_LISTEN, "tcp-request",  tcp_parse_tcp_req },
        { CFG_LISTEN, "tcp-response", tcp_parse_tcp_rep },
        { 0, NULL, NULL },
@@ -1741,7 +1741,7 @@ static struct cfg_kw_list cfg_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
@@ -1751,7 +1751,7 @@ static struct acl_kw_list acl_kws = {{ },{
  * common denominator, the type that can be casted into all other ones. For
  * instance v4/v6 must be declared v4.
  */
-static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
+static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "dst",      smp_fetch_dst,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
        { "dst_port", smp_fetch_dport, 0, NULL, SMP_T_UINT, SMP_USE_L4CLI },
        { "src",      smp_fetch_src,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
index e6720c9f19813412c4b096b1bfe94bd7df100c83..b67f024268a9f986c515efcbf7186317a864f735 100644 (file)
@@ -859,7 +859,7 @@ int session_set_backend(struct session *s, struct proxy *be)
        return 1;
 }
 
-static struct cfg_kw_list cfg_kws = {{ },{
+static struct cfg_kw_list cfg_kws = {ILH, {
        { CFG_LISTEN, "timeout", proxy_parse_timeout },
        { CFG_LISTEN, "clitimeout", proxy_parse_timeout },
        { CFG_LISTEN, "contimeout", proxy_parse_timeout },
index 753b45737d1a27ade3a6da31a2de5a54fd49bf4a..fd18934e9050b7b5cbe928398bc14a485dbe2adf 100644 (file)
@@ -1073,7 +1073,7 @@ static int sample_conv_ipmask(const struct arg *arg_p, struct sample *smp)
 }
 
 /* Note: must not be declared <const> as its list will be overwritten */
-static struct sample_conv_kw_list sample_conv_kws = {{ },{
+static struct sample_conv_kw_list sample_conv_kws = {ILH, {
        { "upper",  sample_conv_str2upper, 0,            NULL, SMP_T_STR,  SMP_T_STR  },
        { "lower",  sample_conv_str2lower, 0,            NULL, SMP_T_STR,  SMP_T_STR  },
        { "ipmask", sample_conv_ipmask,    ARG1(1,MSK4), NULL, SMP_T_IPV4, SMP_T_IPV4 },
index 004f293c0013eba8282f7813aaee1ca1ea6ab20c..ec26522f69e547ad036f533e6a8a18f77054ec89 100644 (file)
@@ -3938,14 +3938,14 @@ smp_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, unsigned int
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { /* END */ },
 }};
 
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct sample_fetch_kw_list smp_fetch_keywords = {{ },{
+static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
        { "sc0_bytes_in_rate",  smp_fetch_sc0_bytes_in_rate,  0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
        { "sc0_bytes_out_rate", smp_fetch_sc0_bytes_out_rate, 0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
        { "sc0_clr_gpc0",       smp_fetch_sc0_clr_gpc0,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
index 160502c95026c090f1f5b6ef24ab58559104a4cd..5d245cf999559e7a93daf2d4626813886abcee82 100644 (file)
@@ -3080,7 +3080,7 @@ static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
+static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "ssl_c_ca_err",           smp_fetch_ssl_c_ca_err,       0,                   NULL,    SMP_T_UINT, SMP_USE_L5CLI },
        { "ssl_c_ca_err_depth",     smp_fetch_ssl_c_ca_err_depth, 0,                   NULL,    SMP_T_UINT, SMP_USE_L5CLI },
        { "ssl_c_err",              smp_fetch_ssl_c_err,          0,                   NULL,    SMP_T_UINT, SMP_USE_L5CLI },
@@ -3124,7 +3124,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
-static struct acl_kw_list acl_kws = {{ },{
+static struct acl_kw_list acl_kws = {ILH, {
        { "ssl_c_i_dn",             NULL,         acl_parse_str,     acl_match_str     },
        { "ssl_c_key_alg",          NULL,         acl_parse_str,     acl_match_str     },
        { "ssl_c_notafter",         NULL,         acl_parse_str,     acl_match_str     },