]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stick-table: allocate the table key of size buffer size
authorWilly Tarreau <w@1wt.eu>
Mon, 29 Oct 2012 20:56:59 +0000 (21:56 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 29 Oct 2012 20:56:59 +0000 (21:56 +0100)
Keys are copied from samples to stick_table_key. If a key is larger
than the stick_table_key, we have an overflow. In pratice it does not
happen because it requires :
   1) a configuration with tune.bufsize larger than BUFSIZE (common)
   2) a stick-table configured with keys strictly larger than buffers
   3) extraction of data larger than BUFSIZE (eg: using payload())

Points 2 and 3 don't make any sense for a real world configuration. That
said the issue needs be fixed. The solution consists in allocating it the
same size as the global buffer size, just like the samples. This fixes the
issue.

include/proto/proto_tcp.h
include/proto/stick_table.h
include/types/stick_table.h
src/dumpstats.c
src/haproxy.c
src/stick_table.c

index 1a1dcfab51fc1023c9d0df19313490293caef872..a41e025a879a75484100b8313e0d1c0383661472 100644 (file)
@@ -48,15 +48,15 @@ static inline struct stktable_key *addr_to_stktable_key(struct sockaddr_storage
 {
        switch (addr->ss_family) {
        case AF_INET:
-               static_table_key.key = (void *)&((struct sockaddr_in *)addr)->sin_addr;
+               static_table_key->key = (void *)&((struct sockaddr_in *)addr)->sin_addr;
                break;
        case AF_INET6:
-               static_table_key.key = (void *)&((struct sockaddr_in6 *)addr)->sin6_addr;
+               static_table_key->key = (void *)&((struct sockaddr_in6 *)addr)->sin6_addr;
                break;
        default:
                return NULL;
        }
-       return &static_table_key;
+       return static_table_key;
 }
 
 
index f7d650a1579323ee0a6c97c7f2bac702b8386e27..d9a25d0c7d6a0e61800be71da0da1613cf3886af 100644 (file)
@@ -31,7 +31,7 @@
 #define stktable_data_size(type) (sizeof(((union stktable_data*)0)->type))
 #define stktable_data_cast(ptr, type) ((union stktable_data*)(ptr))->type
 
-extern struct stktable_key static_table_key;
+extern struct stktable_key *static_table_key;
 
 struct stksess *stksess_new(struct stktable *t, struct stktable_key *key);
 void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key);
index cccf9fbecd9b91a341c01fd04ba8ef7973bf26fe..520f57aed0823a8192257bb20233b6fe00173d17 100644 (file)
@@ -176,15 +176,14 @@ union stktable_key_data {
        struct in_addr ip;        /* used to store an ipv4 key */
        struct in6_addr ipv6;     /* used to store an ipv6 key */
        uint32_t integer;         /* used to store an integer key */
-       char buf[BUFSIZE];        /* used to store a null terminated string key or a buffer of data */
+       char buf[0];              /* dynamically allocated, used to store a null terminated string key or a buffer of data */
 };
 
 /* stick table key */
 struct stktable_key {
        void *key;                      /* pointer on key buffer */
        size_t key_len;                 /* data len to read in buff in case of null terminated string */
-       union stktable_key_data data;   /* data */
+       union stktable_key_data data;   /* data, must always be last */
 };
 
 #endif /* _TYPES_STICK_TABLE_H */
-
index eefce5812c5996af4b2d8ff4f4b8012129d33a73..da84f2a3de8edbd6abd58e17234e3352c984c9a4 100644 (file)
@@ -541,11 +541,11 @@ static void stats_sock_table_key_request(struct stream_interface *si, char **arg
        switch (px->table.type) {
        case STKTABLE_TYPE_IP:
                uint32_key = htonl(inetaddr_host(args[4]));
-               static_table_key.key = &uint32_key;
+               static_table_key->key = &uint32_key;
                break;
        case STKTABLE_TYPE_IPV6:
                inet_pton(AF_INET6, args[4], ip6_key);
-               static_table_key.key = &ip6_key;
+               static_table_key->key = &ip6_key;
                break;
        case STKTABLE_TYPE_INTEGER:
                {
@@ -561,13 +561,13 @@ static void stats_sock_table_key_request(struct stream_interface *si, char **arg
                                return;
                        }
                        uint32_key = (uint32_t) val;
-                       static_table_key.key = &uint32_key;
+                       static_table_key->key = &uint32_key;
                        break;
                }
                break;
        case STKTABLE_TYPE_STRING:
-               static_table_key.key = args[4];
-               static_table_key.key_len = strlen(args[4]);
+               static_table_key->key = args[4];
+               static_table_key->key_len = strlen(args[4]);
                break;
        default:
                switch (action) {
@@ -592,7 +592,7 @@ static void stats_sock_table_key_request(struct stream_interface *si, char **arg
                return;
        }
 
-       ts = stktable_lookup_key(&px->table, &static_table_key);
+       ts = stktable_lookup_key(&px->table, static_table_key);
 
        switch (action) {
        case STAT_CLI_O_TAB:
@@ -645,7 +645,7 @@ static void stats_sock_table_key_request(struct stream_interface *si, char **arg
                if (ts)
                        stktable_touch(&px->table, ts, 1);
                else {
-                       ts = stksess_new(&px->table, &static_table_key);
+                       ts = stksess_new(&px->table, static_table_key);
                        if (!ts) {
                                /* don't delete an entry which is currently referenced */
                                si->applet.ctx.cli.msg = "Unable to allocate a new entry\n";
index 068a3ddf1d3c3921846952ef2190b9fb311ad535..c6933c33d4a59076e7ad852916a3645c45317b56 100644 (file)
@@ -745,6 +745,7 @@ void init(int argc, char **argv)
        sample_trash_buf1 = (char *)calloc(1, global.tune.bufsize);
        sample_trash_buf2 = (char *)calloc(1, global.tune.bufsize);
        get_http_auth_buff = (char *)calloc(1, global.tune.bufsize);
+       static_table_key = calloc(1, sizeof(*static_table_key) + global.tune.bufsize);
 
 
        fdinfo = (struct fdinfo *)calloc(1,
index 75267e1d38db2bf0eb0ca52429b4200cbbce0ae4..b681a8b86b5fa2039eab2503514ed8adb3daa0bd 100644 (file)
@@ -31,7 +31,7 @@
 #include <types/global.h>
 
 /* structure used to return a table key built from a sample */
-struct stktable_key static_table_key;
+struct stktable_key *static_table_key;
 
 /*
  * Free an allocated sticky session <ts>, and decrease sticky sessions counter
@@ -618,42 +618,42 @@ struct stktable_key *stktable_fetch_key(struct stktable *t, struct proxy *px, st
        if (!sample_to_key[smp->type][t->type])
                return NULL;
 
-       static_table_key.key_len = t->key_size;
-       static_table_key.key = sample_to_key[smp->type][t->type](smp, &static_table_key.data, &static_table_key.key_len);
+       static_table_key->key_len = t->key_size;
+       static_table_key->key = sample_to_key[smp->type][t->type](smp, &static_table_key->data, &static_table_key->key_len);
 
-       if (!static_table_key.key)
+       if (!static_table_key->key)
                return NULL;
 
-       if (static_table_key.key_len == 0)
+       if (static_table_key->key_len == 0)
                return NULL;
 
-       if ((static_table_key.key_len < t->key_size) && (t->type != STKTABLE_TYPE_STRING)) {
+       if ((static_table_key->key_len < t->key_size) && (t->type != STKTABLE_TYPE_STRING)) {
                /* need padding with null */
 
                /* assume static_table_key.key_len is less than sizeof(static_table_key.data.buf)
                cause t->key_size is necessary less than sizeof(static_table_key.data) */
 
-               if ((char *)static_table_key.key > (char *)&static_table_key.data &&
-                   (char *)static_table_key.key <  (char *)&static_table_key.data + sizeof(static_table_key.data)) {
+               if ((char *)static_table_key->key > (char *)&static_table_key->data &&
+                   (char *)static_table_key->key <  (char *)&static_table_key->data + global.tune.bufsize) {
                        /* key buffer is part of the static_table_key private data buffer, but is not aligned */
 
-                       if (sizeof(static_table_key.data) - ((char *)static_table_key.key - (char *)&static_table_key.data) < t->key_size) {
-                               /* if not remain enougth place for padding , process a realign */
-                               memmove(static_table_key.data.buf, static_table_key.key, static_table_key.key_len);
-                               static_table_key.key = static_table_key.data.buf;
+                       if (global.tune.bufsize - ((char *)static_table_key->key - (char *)&static_table_key->data) < t->key_size) {
+                               /* if not remain enough place for padding , process a realign */
+                               memmove(static_table_key->data.buf, static_table_key->key, static_table_key->key_len);
+                               static_table_key->key = static_table_key->data.buf;
                        }
                }
-               else if (static_table_key.key != static_table_key.data.buf) {
+               else if (static_table_key->key != static_table_key->data.buf) {
                        /* key definitly not part of the static_table_key private data buffer */
 
-                       memcpy(static_table_key.data.buf, static_table_key.key, static_table_key.key_len);
-                       static_table_key.key = static_table_key.data.buf;
+                       memcpy(static_table_key->data.buf, static_table_key->key, static_table_key->key_len);
+                       static_table_key->key = static_table_key->data.buf;
                }
 
-               memset(static_table_key.key + static_table_key.key_len, 0, t->key_size - static_table_key.key_len);
+               memset(static_table_key->key + static_table_key->key_len, 0, t->key_size - static_table_key->key_len);
        }
 
-       return &static_table_key;
+       return static_table_key;
 }
 
 /*