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().
This commit is contained in:
Aurelien DARRAGON 2024-11-13 19:54:32 +01:00
parent e1ec37ea51
commit 42710b7320
7 changed files with 34 additions and 31 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -90,7 +90,7 @@
#include <haproxy/tcpcheck.h>
#include <haproxy/thread.h>
#include <haproxy/tools.h>
#include <haproxy/uri_auth-t.h>
#include <haproxy/uri_auth.h>
/* 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;
}

View File

@ -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();

View File

@ -54,6 +54,7 @@
#include <haproxy/tcpcheck.h>
#include <haproxy/time.h>
#include <haproxy/tools.h>
#include <haproxy/uri_auth.h>
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) {

View File

@ -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