From: Aurelien DARRAGON Date: Wed, 13 Nov 2024 18:54:32 +0000 (+0100) Subject: MEDIUM: uri_auth: implement clean uri_auth cleaning X-Git-Tag: v3.1-dev13~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42710b73200c4828ade2b1ffab582506f05a9731;p=thirdparty%2Fhaproxy.git MEDIUM: uri_auth: implement clean uri_auth cleaning proxy auth_uri struct was manually cleaned up during deinit, but the logic behind was kind of akward because it was required to find out which ones were shared or not. Instead, let's switch to a proper refcount mechanism and free the auth_uri struct directly in proxy_free_common(). --- diff --git a/include/haproxy/uri_auth-t.h b/include/haproxy/uri_auth-t.h index 009adfdfe6..b2d829ab00 100644 --- a/include/haproxy/uri_auth-t.h +++ b/include/haproxy/uri_auth-t.h @@ -29,6 +29,7 @@ struct stat_scope { /* later we may link them to support multiple URI matching */ struct uri_auth { int uri_len; /* the prefix length */ + uint refcount; /* to free when unused */ char *uri_prefix; /* the prefix we want to match */ char *auth_realm; /* the realm reported to the client */ char *node, *desc; /* node name & description reported in this stats */ diff --git a/include/haproxy/uri_auth.h b/include/haproxy/uri_auth.h index ae5dbb04a0..3b61e8fff2 100644 --- a/include/haproxy/uri_auth.h +++ b/include/haproxy/uri_auth.h @@ -34,6 +34,8 @@ struct uri_auth *stats_add_scope(struct uri_auth **root, char *scope); struct uri_auth *stats_set_node(struct uri_auth **root, char *name); struct uri_auth *stats_set_desc(struct uri_auth **root, char *desc); void stats_uri_auth_free(struct uri_auth *uri_auth); +void stats_uri_auth_take(struct uri_auth *uri_auth); +void stats_uri_auth_drop(struct uri_auth *uri_auth); #endif /* _HAPROXY_URI_AUTH_H */ diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index bb722b3eef..760ca71671 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -1761,8 +1761,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) LIST_APPEND(&curproxy->sticking_rules, &rule->list); } else if (strcmp(args[0], "stats") == 0) { - if (!(curproxy->cap & PR_CAP_DEF) && curproxy->uri_auth == curr_defproxy->uri_auth) - curproxy->uri_auth = NULL; /* we must detach from the default config */ + if (!(curproxy->cap & PR_CAP_DEF) && curproxy->uri_auth == curr_defproxy->uri_auth) { + /* we must detach from the default config */ + stats_uri_auth_drop(curproxy->uri_auth); + curproxy->uri_auth = NULL; + } if (!*args[1]) { goto stats_error_parsing; diff --git a/src/cfgparse.c b/src/cfgparse.c index c29b6f6dba..de5405a9a4 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -90,7 +90,7 @@ #include #include #include -#include +#include /* Used to chain configuration sections definitions. This list @@ -3936,6 +3936,7 @@ out_uri_auth_compat: ha_warning("'stats' statement ignored for %s '%s' as it requires HTTP mode.\n", proxy_type_str(curproxy), curproxy->id); err_code |= ERR_WARN; + stats_uri_auth_drop(curproxy->uri_auth); curproxy->uri_auth = NULL; } diff --git a/src/haproxy.c b/src/haproxy.c index 56bd38b465..43b282bd54 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -3200,7 +3200,6 @@ void deinit(void) { struct proxy *p = proxies_list, *p0; struct cfgfile *cfg, *cfg_tmp; - struct uri_auth *uap, *ua = NULL; struct logger *log, *logb; struct build_opts_str *bol, *bolb; struct post_deinit_fct *pdf, *pdfb; @@ -3254,22 +3253,6 @@ void deinit(void) deinit_signals(); while (p) { - /* build a list of unique uri_auths */ - if (!ua) - ua = p->uri_auth; - else { - /* check if p->uri_auth is unique */ - for (uap = ua; uap; uap=uap->next) - if (uap == p->uri_auth) - break; - - if (!uap && p->uri_auth) { - /* add it, if it is */ - p->uri_auth->next = ua; - ua = p->uri_auth; - } - } - p0 = p; p = p->next; free_proxy(p0); @@ -3282,12 +3265,6 @@ void deinit(void) /* destroy all referenced defaults proxies */ proxy_destroy_all_unref_defaults(); - while (ua) { - uap = ua; - ua = ua->next; - stats_uri_auth_free(uap); - } - userlist_free(userlist); cfg_unregister_sections(); diff --git a/src/proxy.c b/src/proxy.c index 9850d45a5b..6f951cd506 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -54,6 +54,7 @@ #include #include #include +#include int listeners; /* # of proxy listeners, set by cfgparse */ @@ -271,6 +272,8 @@ static inline void proxy_free_common(struct proxy *px) } free_email_alert(px); + stats_uri_auth_drop(px->uri_auth); + px->uri_auth = NULL; } void free_proxy(struct proxy *p) @@ -1513,10 +1516,6 @@ void proxy_free_defaults(struct proxy *defproxy) proxy_release_conf_errors(defproxy); deinit_proxy_tcpcheck(defproxy); - - /* FIXME: we cannot free uri_auth because it might already be used by - * another proxy (legacy code for stats URI ...). Refcount anyone ? - */ } /* delete a defproxy from the tree if still in it, frees its content and its @@ -1803,7 +1802,11 @@ static int proxy_defproxy_cpy(struct proxy *curproxy, const struct proxy *defpro } curproxy->mode = defproxy->mode; - curproxy->uri_auth = defproxy->uri_auth; /* for stats */ + + /* for stats */ + stats_uri_auth_drop(curproxy->uri_auth); + stats_uri_auth_take(defproxy->uri_auth); + curproxy->uri_auth = defproxy->uri_auth; /* copy default loggers to curproxy */ list_for_each_entry(tmplogger, &defproxy->loggers, list) { diff --git a/src/uri_auth.c b/src/uri_auth.c index a487ed3755..eddb1a0a50 100644 --- a/src/uri_auth.c +++ b/src/uri_auth.c @@ -38,6 +38,7 @@ struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root) LIST_INIT(&u->http_req_rules); LIST_INIT(&u->admin_rules); + stats_uri_auth_take(u); } else u = *root; @@ -342,6 +343,21 @@ void stats_uri_auth_free(struct uri_auth *uri_auth) free(uri_auth); } +void stats_uri_auth_drop(struct uri_auth *uri_auth) +{ + if (!uri_auth) + return; + if (HA_ATOMIC_SUB_FETCH(&uri_auth->refcount, 1) == 0) + stats_uri_auth_free(uri_auth); +} + +void stats_uri_auth_take(struct uri_auth *uri_auth) +{ + if (!uri_auth) + return; + HA_ATOMIC_INC(&uri_auth->refcount); +} + /* * Local variables: * c-indent-level: 8