Thanks for your feedback. I have some followup questions.

> I think you should initialized this ebtree with EB_ROOT_UNIQUE as
value.

I'm not sure I understand what the distinction between EB_ROOT and
EB_ROOT_UNIQUE is. I'm happy to add this, but I'd like to understand
why it should be EB_ROOT_UNIQUE here (since it looks like it is
initialized as EB_ROOT for used_server_id and used_listener_id, and I
can't find where it is initialized for used_server_name, which I
believe would be equivalent since EB_ROOT is basically just zero
initialized).

> I think this is dangerous to initialize two objects with the same value
as a string. I would strdup() <key> to initialize s->addr_node.key.

ok. I was following the pattern used with conf.name in struct server.
Would it be better to use strdup, or to not have a separate field for
addr_desc, and just use addr_node.key (which is a void*)? If the
latter maybe rename addr_node as addr_desc?

Additionally:

In srv_set_addr_desc, would it be better to hold the lock over the
entire operation, or just while we are actually manipulating the tree?
Meaning should I release the lock between deleting the old node and
inserting the new node? And should this use the existing proxy lock,
or should there be a separate dedicated lock for used_server_addr?

I'm also a little bit concerned about leaking memory in the
server_key_dict. I couldn't find anything that cleans up these keys,
although there is a refcount on them. In an environment that uses
service discovery and the servers change frequently, this could lead
to a memory leak as this dict only grows in size.

Thank you,

Thayne

Thayne McCombs
Senior Software Engineer
[email protected]


Lucid.co



On Tue, Dec 1, 2020 at 10:24 AM Frederic Lecaille <[email protected]> wrote:
>
> On 12/1/20 11:50 AM, Emeric Brun wrote:
> > Hi,
>
> Hi Thayne,
>
> See my answers below.
>
> > On 11/30/20 10:23 AM, PR Bot wrote:
> >> Dear list!
> >>
> >> Author: Thayne McCombs <[email protected]>
> >> Number of patches: 2
> >>
> >> This is an automated relay of the Github pull request:
> >>     Add srvkey option to stick-table
> >>
> >> Patch title(s):
> >>     Add srvkey option to stick-table
> >>     Harden sa2str agains 107-byte-long abstract unix domain path
> >>
> >> Link:
> >>     https://github.com/haproxy/haproxy/pull/979
> >>
> >> Edit locally:
> >>     wget https://github.com/haproxy/haproxy/pull/979.patch && vi 979.patch
> >>
> >> Apply locally:
> >>     curl https://github.com/haproxy/haproxy/pull/979.patch | git am -
> >>
> >> Description:
> >>     This allows using the address of the server rather than the name of
> >>     the
> >>     server for keeping track of servers in a backend for
> >>     stickiness.
> >>
> >>     Fixes #814
> >>
> >>     I haven't tested this at all
> >>     yet, and it still needs some polish, but here is a draft of how to fix
> >>     #814.
> >>
> >>     This is my first significant contribution to haproxy,
> >>     so I would not be surprised if I'm doing something terribly wrong, and
> >>     I'm sure there are at least some small mistakes in it. Initial
> >>     feedback would be very welcome.
>
> Thank you for this first contribution which looks almost good!!! We all
> do wrong things ;) Even if it not easy to comment your code because it
> is not included in this mail, let's giving a try.
>
>
> I have noticed two places where initializations are missing:
>
>
> diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h
> index 998e210f6..e62b79765 100644
> --- a/include/haproxy/proxy-t.h
> +++ b/include/haproxy/proxy-t.h
> @@ -424,6 +424,7 @@ struct proxy {
>                 char *lfsd_file;                /* file name where the 
> structured-data logformat
> string for RFC5424 appears (strdup) */
>                 int  lfsd_line;                 /* file name where the 
> structured-data logformat
> string for RFC5424 appears */
>         } conf;                                 /* config information */
> +       struct eb_root used_server_addr;        /* list of server addresses in
> use */
>
>
> < used_server_addr> ebtree is not initialized. This would make haproxy
> crash. I think you should initialized this ebtree with EB_ROOT_UNIQUE as
> value.
>
>
> You should comment all the new functions (see srv_set_addr_desc() and
> perhaps others).
>
> The following function should be commente as this done for
> srv_set_dyncookie() espcially for the locks we need even if this
> function is only used at parsing time, as far as I see. What if we want
> to use it at runing time? This function should be called with a lock on
> <s> server (not necessary at parsing time).
>
>
> +static void srv_set_addr_desc(struct server *s)
> +{
> +       struct proxy *p = s->proxy;
> +       char *key;
> +
> +       key = sa2str(&s->addr, s->svc_port, s->flags & SRV_F_MAPPORTS);
> +
> +       if (strcmp(key, s->addr_desc) == 0) {
>
> ->addr_desc is initialized only by srv_set_addr_desc(). So the first
> time we enter this function ->addr_desc has NULL as value.
>
>
> +               free(key);
> +               return;
> +       }
> +
> +       HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock);
> +       ebpt_delete(&s->addr_node);
> +       HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock);
> +
> +       free(s->addr_desc);
> +       s->addr_desc = key;
> +       s->addr_node.key = key;
>
> I think this is dangerous to initialize two objects with the same value
> as a string. I would strdup() <key> to initialize s->addr_node.key.
>
> +       // TODO: should this use a dedicated lock?
> +       HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock);
> +       ebis_insert(&p->used_server_addr, &s->addr_node);
> +       HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock);
> +}
> +
>
>
>
> There are two typos in the documentation:
>
> +      a template). If "addr" is given, then the server is idntified
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
> +      by it's current network address
> ~~~~~~~~~~~~^
>
>
> You should split your patch to provide such cleanup code in seperated patch:
>
> @@ -1453,7 +1497,7 @@ int url2sa(const char *url, int ulen, struct
> sockaddr_storage *addr, struct spli
>         /* Secondly, if :// pattern is found, verify parsed stuff
>          * before pattern is matching our http pattern.
>          * If so parse ip address and port in uri.
> -        *
> +        *
>
>
>
> I am not sure at all about this modification, but it semms
> implementation dependent to me:
>
> diff --git a/src/tools.c b/src/tools.c
> index c51f542c6..21e3f06ef 100644
> --- a/src/tools.c
> +++ b/src/tools.c
> @@ -1228,7 +1228,7 @@ char * sa2str(const struct sockaddr_storage *addr,
> int port, int map_ports)
>         case AF_UNIX:
>                 path = ((struct sockaddr_un *)addr)->sun_path;
>                 if (path[0] == '\0') {
> -                       return memprintf(&out, "abns@%s", path+1);
> +                       return memprintf(&out, "abns@%107s", path+1);
>                 } else {
>                         return strdup(path);
>                 }
>
>
> I would not implement this function:
>
> +static void srv_addr_updated(struct server *srv)
> +{
> +       srv_set_dyncookie(srv);
> +       srv_set_addr_desc(srv);
> +}
>
>
> Note something important: there are regression tests which can be run.
> See reg-tests directory.

Reply via email to