diff --git a/common/Makefile.in b/common/Makefile.in index f9e33b41c..cdbc5b990 100644 --- a/common/Makefile.in +++ b/common/Makefile.in @@ -189,7 +189,8 @@ event_select.lo: $(srcdir)/event_select.c $(top_builddir)/config.h \ $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/event_select.c fatal.lo: $(srcdir)/fatal.c $(top_builddir)/config.h \ $(top_srcdir)/compat/stdbool.h $(incdir)/missing.h $(incdir)/alloc.h \ - $(incdir)/fatal.h $(incdir)/sudo_plugin.h $(incdir)/gettext.h + $(incdir)/fatal.h $(incdir)/queue.h $(incdir)/sudo_plugin.h \ + $(incdir)/gettext.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/fatal.c fileops.lo: $(srcdir)/fileops.c $(top_builddir)/config.h \ $(top_srcdir)/compat/stdbool.h $(top_srcdir)/compat/timespec.h \ diff --git a/common/fatal.c b/common/fatal.c index 1133f94ae..1b50a4654 100644 --- a/common/fatal.c +++ b/common/fatal.c @@ -31,17 +31,21 @@ #include "missing.h" #include "alloc.h" #include "fatal.h" +#include "queue.h" #include "sudo_plugin.h" #define DEFAULT_TEXT_DOMAIN "sudo" #include "gettext.h" +struct sudo_fatal_callback { + SLIST_ENTRY(sudo_fatal_callback) entries; + void (*func)(void); +}; +SLIST_HEAD(sudo_fatal_callback_list, sudo_fatal_callback); + sigjmp_buf fatal_jmp; static bool setjmp_enabled = false; -static struct sudo_fatal_callback { - void (*func)(void); - struct sudo_fatal_callback *next; -} *callbacks; +static struct sudo_fatal_callback_list callbacks; static void _warning(int, const char *, va_list); @@ -51,8 +55,8 @@ do_cleanup(void) struct sudo_fatal_callback *cb; /* Run callbacks, removing them from the list as we go. */ - while ((cb = callbacks) != NULL) { - callbacks = cb->next; + while ((cb = SLIST_FIRST(&callbacks)) != NULL) { + SLIST_REMOVE_HEAD(&callbacks, entries); cb->func(); free(cb); } @@ -173,8 +177,7 @@ fatal_callback_register(void (*func)(void)) if (cb == NULL) return -1; cb->func = func; - cb->next = callbacks; - callbacks = cb; + SLIST_INSERT_HEAD(&callbacks, cb, entries); return 0; } diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 8a9e868bc..08d4ef352 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -841,8 +841,8 @@ sudoreplay.o: $(srcdir)/sudoreplay.c $(top_builddir)/config.h \ $(top_srcdir)/compat/getopt.h $(top_builddir)/pathnames.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/gettext.h $(srcdir)/logging.h $(srcdir)/iolog.h \ - $(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h $(incdir)/queue.h \ - $(incdir)/sudo_debug.h + $(incdir)/queue.h $(incdir)/sudo_plugin.h $(incdir)/sudo_conf.h \ + $(incdir)/queue.h $(incdir)/sudo_debug.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudoreplay.c testsudoers.o: $(srcdir)/testsudoers.c $(top_builddir)/config.h \ $(top_srcdir)/compat/fnmatch.h $(srcdir)/tsgetgrpw.h \ @@ -903,6 +903,6 @@ visudo.o: $(srcdir)/visudo.c $(top_builddir)/config.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h \ - $(incdir)/queue.h $(incdir)/gettext.h $(srcdir)/sudoers_version.h \ + $(incdir)/gettext.h $(srcdir)/sudoers_version.h \ $(incdir)/sudo_conf.h $(incdir)/queue.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/visudo.c diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index f263033b6..249e0e999 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -162,9 +162,9 @@ dump_defaults(void) sudo_printf(SUDO_CONV_INFO_MSG, "\n"); break; case T_LIST: - if (cur->sd_un.list) { + if (!SLIST_EMPTY(&cur->sd_un.list)) { sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc); - for (item = cur->sd_un.list; item; item = item->next) { + SLIST_FOREACH(item, &cur->sd_un.list, entries) { sudo_printf(SUDO_CONV_INFO_MSG, "\t%s\n", item->value); } @@ -826,43 +826,41 @@ store_mode(char *val, struct sudo_defs_types *def, int op) static void list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op) { - struct list_member *cur, *prev, *tmp; + struct list_member *tmp, *cur, *prev = NULL; debug_decl(list_op, SUDO_DEBUG_DEFAULTS) if (op == freeall) { - for (cur = def->sd_un.list; cur; ) { - tmp = cur; - cur = tmp->next; + SLIST_FOREACH_SAFE(cur, &def->sd_un.list, entries, tmp) { efree(tmp->value); efree(tmp); } - def->sd_un.list = NULL; + SLIST_INIT(&def->sd_un.list); debug_return; } - for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) { + SLIST_FOREACH(cur, &def->sd_un.list, entries) { if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) { if (op == add) debug_return; /* already exists */ /* Delete node */ - if (prev != NULL) - prev->next = cur->next; + if (prev == NULL) + SLIST_REMOVE_HEAD(&def->sd_un.list, entries); else - def->sd_un.list = cur->next; + SLIST_REMOVE_AFTER(prev, entries); efree(cur->value); efree(cur); break; } + prev = cur; } /* Add new node to the head of the list. */ if (op == add) { cur = ecalloc(1, sizeof(struct list_member)); cur->value = estrndup(val, len); - cur->next = def->sd_un.list; - def->sd_un.list = cur; + SLIST_INSERT_HEAD(&def->sd_un.list, cur, entries); } debug_return; } diff --git a/plugins/sudoers/defaults.h b/plugins/sudoers/defaults.h index 082a00100..ef9ae65b0 100644 --- a/plugins/sudoers/defaults.h +++ b/plugins/sudoers/defaults.h @@ -25,10 +25,12 @@ #include struct list_member { + SLIST_ENTRY(list_member) entries; char *value; - struct list_member *next; }; +SLIST_HEAD(list_members, list_member); + struct def_values { char *sval; /* string value */ int ival; /* actually an enum */ @@ -56,7 +58,7 @@ struct sudo_defs_types { enum def_tuple tuple; char *str; mode_t mode; - struct list_member *list; + struct list_members list; } sd_un; }; diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c index 72218725a..6076181cf 100644 --- a/plugins/sudoers/env.c +++ b/plugins/sudoers/env.c @@ -558,7 +558,7 @@ matches_env_delete(const char *var) debug_decl(matches_env_delete, SUDO_DEBUG_ENV) /* Skip anything listed in env_delete. */ - for (cur = def_env_delete; cur; cur = cur->next) { + SLIST_FOREACH(cur, &def_env_delete, entries) { len = strlen(cur->value); /* Deal with '*' wildcard */ if (cur->value[len - 1] == '*') { @@ -589,7 +589,7 @@ matches_env_check(const char *var) int keepit = -1; debug_decl(matches_env_check, SUDO_DEBUG_ENV) - for (cur = def_env_check; cur; cur = cur->next) { + SLIST_FOREACH(cur, &def_env_check, entries) { len = strlen(cur->value); /* Deal with '*' wildcard */ if (cur->value[len - 1] == '*') { @@ -624,7 +624,7 @@ matches_env_keep(const char *var) goto done; } - for (cur = def_env_keep; cur; cur = cur->next) { + SLIST_FOREACH(cur, &def_env_keep, entries) { len = strlen(cur->value); /* Deal with '*' wildcard */ if (cur->value[len - 1] == '*') { @@ -1085,24 +1085,21 @@ init_envtables(void) for (p = initial_badenv_table; *p; p++) { cur = ecalloc(1, sizeof(struct list_member)); cur->value = estrdup(*p); - cur->next = def_env_delete; - def_env_delete = cur; + SLIST_INSERT_HEAD(&def_env_delete, cur, entries); } /* Fill in the "env_check" list. */ for (p = initial_checkenv_table; *p; p++) { cur = ecalloc(1, sizeof(struct list_member)); cur->value = estrdup(*p); - cur->next = def_env_check; - def_env_check = cur; + SLIST_INSERT_HEAD(&def_env_check, cur, entries); } /* Fill in the "env_keep" list. */ for (p = initial_keepenv_table; *p; p++) { cur = ecalloc(1, sizeof(struct list_member)); cur->value = estrdup(*p); - cur->next = def_env_keep; - def_env_keep = cur; + SLIST_INSERT_HEAD(&def_env_keep, cur, entries); } } diff --git a/plugins/sudoers/interfaces.c b/plugins/sudoers/interfaces.c index 4dc6012a3..baf31d3c8 100644 --- a/plugins/sudoers/interfaces.c +++ b/plugins/sudoers/interfaces.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 Todd C. Miller + * Copyright (c) 2010-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -51,7 +51,7 @@ # define INADDR_NONE ((unsigned int)-1) #endif -static struct interface *interfaces; +static struct interface_list interfaces; /* * Parse a space-delimited list of IP address/netmask pairs and @@ -95,17 +95,16 @@ set_interfaces(const char *ai) continue; } } - ifp->next = interfaces; - interfaces = ifp; + SLIST_INSERT_HEAD(&interfaces, ifp, entries); } efree(addrinfo); debug_return; } -struct interface * +struct interface_list * get_interfaces(void) { - return interfaces; + return &interfaces; } void diff --git a/plugins/sudoers/interfaces.h b/plugins/sudoers/interfaces.h index 3ccd8169c..26e669824 100644 --- a/plugins/sudoers/interfaces.h +++ b/plugins/sudoers/interfaces.h @@ -36,18 +36,20 @@ union sudo_in_addr_un { * IP address and netmask pairs for checking against local interfaces. */ struct interface { + SLIST_ENTRY(interface) entries; int family; /* AF_INET or AF_INET6 */ union sudo_in_addr_un addr; union sudo_in_addr_un netmask; - struct interface *next; }; +SLIST_HEAD(interface_list, interface); + /* * Prototypes for external functions. */ int get_net_ifs(char **addrinfo); void dump_interfaces(const char *); void set_interfaces(const char *); -struct interface *get_interfaces(void); +struct interface_list *get_interfaces(void); #endif /* _SUDOERS_INTERFACES_H */ diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index cb7be8cb6..8bd1708d6 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -159,13 +159,13 @@ extern int ldapssl_set_strength(LDAP *ldap, int strength); * The ldap_search structure implements a linked list of ldap and * search result pointers, which allows us to remove them after * all search results have been combined in memory. - * XXX - should probably be a tailq since we do appends */ -struct ldap_search_list { +struct ldap_search_result { + STAILQ_ENTRY(ldap_search_result) entries; LDAP *ldap; LDAPMessage *searchresult; - struct ldap_search_list *next; }; +STAILQ_HEAD(ldap_search_list, ldap_search_result); /* * The ldap_entry_wrapper structure is used to implement sorted result entries. @@ -184,7 +184,7 @@ struct ldap_entry_wrapper { * well as an array of all result entries sorted by the sudoOrder attribute. */ struct ldap_result { - struct ldap_search_list *searches; + struct ldap_search_list searches; struct ldap_entry_wrapper *entries; int allocated_entries; int nentries; @@ -200,11 +200,13 @@ struct ldap_config_table { void *valp; /* pointer into ldap_conf */ }; -struct ldap_config_list_str { - struct ldap_config_list_str *next; +struct ldap_config_str { + STAILQ_ENTRY(ldap_config_str) entries; char val[1]; }; +STAILQ_HEAD(ldap_config_str_list, ldap_config_str); + /* LDAP configuration structure */ static struct ldap_config { int port; @@ -221,11 +223,11 @@ static struct ldap_config { int timed; int deref; char *host; - struct ldap_config_list_str *uri; + struct ldap_config_str_list uri; char *binddn; char *bindpw; char *rootbinddn; - struct ldap_config_list_str *base; + struct ldap_config_str_list base; char *search_filter; char *ssl; char *tls_cacertfile; @@ -433,16 +435,17 @@ toobig: * where the trailing slash is optional. */ static int -sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list) +sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list) { + const struct ldap_config_str *entry; char *buf, *uri, *host, *cp, *port; char hostbuf[LINE_MAX]; int nldap = 0, nldaps = 0; int rc = -1; debug_decl(sudo_ldap_parse_uri, SUDO_DEBUG_LDAP) - do { - buf = estrdup(uri_list->val); + STAILQ_FOREACH(entry, uri_list, entries) { + buf = estrdup(entry->val); hostbuf[0] = '\0'; for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) { if (strncasecmp(uri, "ldap://", 7) == 0) { @@ -481,7 +484,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list) } } if (hostbuf[0] == '\0') { - warningx(_("invalid uri: %s"), uri_list->val); + warningx(_("invalid uri: %s"), entry->val); goto done; } @@ -500,7 +503,7 @@ sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list) efree(ldap_conf.host); ldap_conf.host = estrdup(hostbuf); efree(buf); - } while ((uri_list = uri_list->next)); + } buf = NULL; rc = 0; @@ -514,23 +517,24 @@ toobig: } #else static char * -sudo_ldap_join_uri(struct ldap_config_list_str *uri_list) +sudo_ldap_join_uri(struct ldap_config_str_list *uri_list) { - struct ldap_config_list_str *uri; + struct ldap_config_str *uri; size_t len = 0; char *buf, *cp; debug_decl(sudo_ldap_join_uri, SUDO_DEBUG_LDAP) /* Usually just a single entry. */ - if (uri_list->next == NULL) - debug_return_str(estrdup(uri_list->val)); + if (STAILQ_NEXT(STAILQ_FIRST(uri_list), entries) == NULL) + debug_return_str(estrdup(STAILQ_FIRST(uri_list)->val)); - for (uri = uri_list; uri != NULL; uri = uri->next) { + /* Multiple entries. */ + STAILQ_FOREACH(uri, uri_list, entries) { len += strlen(uri->val) + 1; } buf = cp = emalloc(len); buf[0] = '\0'; - for (uri = uri_list; uri != NULL; uri = uri->next) { + STAILQ_FOREACH(uri, uri_list, entries) { cp += strlcpy(cp, uri->val, len - (cp - buf)); *cp++ = ' '; } @@ -1420,16 +1424,15 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value, break; case CONF_LIST_STR: { - struct ldap_config_list_str **p; + struct ldap_config_str_list *head; + struct ldap_config_str *str; size_t len = strlen(value); if (len > 0) { - p = (struct ldap_config_list_str **)cur->valp; - while (*p != NULL) - p = &(*p)->next; - *p = emalloc(sizeof(struct ldap_config_list_str) + len); - memcpy((*p)->val, value, len + 1); - (*p)->next = NULL; + head = (struct ldap_config_str_list *)cur->valp; + str = emalloc(sizeof(*str) + len); + memcpy(str->val, value, len + 1); + STAILQ_INSERT_TAIL(head, str, entries); } } break; @@ -1513,6 +1516,8 @@ sudo_ldap_read_config(void) ldap_conf.use_sasl = -1; ldap_conf.rootuse_sasl = -1; ldap_conf.deref = -1; + STAILQ_INIT(&ldap_conf.uri); + STAILQ_INIT(&ldap_conf.base); if ((fp = fopen(path_ldap_conf, "r")) == NULL) debug_return_bool(false); @@ -1545,12 +1550,12 @@ sudo_ldap_read_config(void) DPRINTF1("LDAP Config Summary"); DPRINTF1("==================="); - if (ldap_conf.uri) { - struct ldap_config_list_str *uri = ldap_conf.uri; + if (!STAILQ_EMPTY(&ldap_conf.uri)) { + struct ldap_config_str *uri; - do { + STAILQ_FOREACH(uri, &ldap_conf.uri, entries) { DPRINTF1("uri %s", uri->val); - } while ((uri = uri->next) != NULL); + } } else { DPRINTF1("host %s", ldap_conf.host ? ldap_conf.host : "(NONE)"); @@ -1558,11 +1563,11 @@ sudo_ldap_read_config(void) } DPRINTF1("ldap_version %d", ldap_conf.version); - if (ldap_conf.base) { - struct ldap_config_list_str *base = ldap_conf.base; - do { + if (!STAILQ_EMPTY(&ldap_conf.base)) { + struct ldap_config_str *base; + STAILQ_FOREACH(base, &ldap_conf.base, entries) { DPRINTF1("sudoers_base %s", base->val); - } while ((base = base->next) != NULL); + } } else { DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)"); } @@ -1622,7 +1627,7 @@ sudo_ldap_read_config(void) #endif DPRINTF1("==================="); - if (!ldap_conf.base) + if (STAILQ_EMPTY(&ldap_conf.base)) debug_return_bool(false); /* if no base is defined, ignore LDAP */ if (ldap_conf.bind_timelimit > 0) @@ -1647,19 +1652,20 @@ sudo_ldap_read_config(void) #ifndef HAVE_LDAP_INITIALIZE /* Convert uri list to host list if no ldap_initialize(). */ - if (ldap_conf.uri) { - struct ldap_config_list_str *uri = ldap_conf.uri; - if (sudo_ldap_parse_uri(uri) != 0) + if (!STAILQ_EMPTY(&ldap_conf.uri)) { + struct ldap_config_str *uri; + + if (sudo_ldap_parse_uri(&ldap_conf.uri) != 0) debug_return_bool(false); - do { - ldap_conf.uri = uri->next; + while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) { + STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries); efree(uri); - } while ((uri = ldap_conf.uri)); + } ldap_conf.port = LDAP_PORT; } #endif - if (!ldap_conf.uri) { + if (STAILQ_EMPTY(&ldap_conf.uri)) { /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */ if (ldap_conf.port < 0) ldap_conf.port = @@ -1744,7 +1750,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw, { struct berval **bv, **p; struct timeval tv, *tvp = NULL; - struct ldap_config_list_str *base; + struct ldap_config_str *base; struct sudo_ldap_handle *handle = nss->handle; LDAP *ld; LDAPMessage *entry, *result; @@ -1757,7 +1763,7 @@ sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw, ld = handle->ld; filt = sudo_ldap_build_default_filter(); - for (base = ldap_conf.base; base != NULL; base = base->next) { + STAILQ_FOREACH(base, &ldap_conf.base, entries) { if (ldap_conf.timeout > 0) { tv.tv_sec = ldap_conf.timeout; tv.tv_usec = 0; @@ -2299,7 +2305,10 @@ sudo_ldap_result_alloc(void) struct ldap_result *result; debug_decl(sudo_ldap_result_alloc, SUDO_DEBUG_LDAP) - debug_return_ptr(ecalloc(1, sizeof(*result))); + result = ecalloc(1, sizeof(*result)); + STAILQ_INIT(&result->searches); + + debug_return_ptr(result); } /* @@ -2308,7 +2317,7 @@ sudo_ldap_result_alloc(void) static void sudo_ldap_result_free(struct ldap_result *lres) { - struct ldap_search_list *s; + struct ldap_search_result *s; debug_decl(sudo_ldap_result_free, SUDO_DEBUG_LDAP) if (lres != NULL) { @@ -2316,12 +2325,10 @@ sudo_ldap_result_free(struct ldap_result *lres) efree(lres->entries); lres->entries = NULL; } - if (lres->searches) { - while ((s = lres->searches) != NULL) { - ldap_msgfree(s->searchresult); - lres->searches = s->next; - efree(s); - } + while ((s = STAILQ_FIRST(&lres->searches)) != NULL) { + STAILQ_REMOVE_HEAD(&lres->searches, entries); + ldap_msgfree(s->searchresult); + efree(s); } efree(lres); } @@ -2331,26 +2338,19 @@ sudo_ldap_result_free(struct ldap_result *lres) /* * Add a search result to the ldap_result structure. */ -static struct ldap_search_list * +static struct ldap_search_result * sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap, LDAPMessage *searchresult) { - struct ldap_search_list *s, *news; + struct ldap_search_result *news; debug_decl(sudo_ldap_result_add_search, SUDO_DEBUG_LDAP) - news = ecalloc(1, sizeof(struct ldap_search_list)); + /* Create new entry and add it to the end of the chain. */ + news = ecalloc(1, sizeof(*news)); news->ldap = ldap; news->searchresult = searchresult; - /* news->next = NULL; */ + STAILQ_INSERT_TAIL(&lres->searches, news, entries); - /* Add entry to the end of the chain (XXX - tailq instead?). */ - if (lres->searches) { - for (s = lres->searches; s->next != NULL; s = s->next) - continue; - s->next = news; - } else { - lres->searches = news; - } debug_return_ptr(news); } @@ -2471,8 +2471,8 @@ sudo_ldap_open(struct sudo_nss *nss) /* Connect to LDAP server */ #ifdef HAVE_LDAP_INITIALIZE - if (ldap_conf.uri != NULL) { - char *buf = sudo_ldap_join_uri(ldap_conf.uri); + if (!STAILQ_EMPTY(&ldap_conf.uri)) { + char *buf = sudo_ldap_join_uri(&ldap_conf.uri); DPRINTF2("ldap_initialize(ld, %s)", buf); rc = ldap_initialize(&ld, buf); efree(buf); @@ -2537,7 +2537,7 @@ sudo_ldap_open(struct sudo_nss *nss) static int sudo_ldap_setdefs(struct sudo_nss *nss) { - struct ldap_config_list_str *base; + struct ldap_config_str *base; struct sudo_ldap_handle *handle = nss->handle; struct timeval tv, *tvp = NULL; LDAP *ld; @@ -2553,7 +2553,7 @@ sudo_ldap_setdefs(struct sudo_nss *nss) filt = sudo_ldap_build_default_filter(); DPRINTF1("Looking for cn=defaults: %s", filt); - for (base = ldap_conf.base; base != NULL; base = base->next) { + STAILQ_FOREACH(base, &ldap_conf.base, entries) { if (ldap_conf.timeout > 0) { tv.tv_sec = ldap_conf.timeout; tv.tv_usec = 0; @@ -2713,21 +2713,15 @@ ldap_entry_compare(const void *a, const void *b) } /* - * Find the last entry in the list of searches, usually the + * Return the last entry in the list of searches, usually the * one currently being used to add entries. - * XXX - use a tailq instead? */ -static struct ldap_search_list * +static struct ldap_search_result * sudo_ldap_result_last_search(struct ldap_result *lres) { - struct ldap_search_list *result = lres->searches; debug_decl(sudo_ldap_result_last_search, SUDO_DEBUG_LDAP) - if (result) { - while (result->next) - result = result->next; - } - debug_return_ptr(result); + debug_return_ptr(STAILQ_LAST(&lres->searches, ldap_search_result, entries)); } /* @@ -2736,7 +2730,7 @@ sudo_ldap_result_last_search(struct ldap_result *lres) static struct ldap_entry_wrapper * sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry) { - struct ldap_search_list *last; + struct ldap_search_result *last; struct berval **bv; double order = 0.0; char *ep; @@ -2806,7 +2800,7 @@ static struct ldap_result * sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw) { struct sudo_ldap_handle *handle = nss->handle; - struct ldap_config_list_str *base; + struct ldap_config_str *base; struct ldap_result *lres; struct timeval tv, *tvp = NULL; LDAPMessage *entry, *result; @@ -2854,7 +2848,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw) for (pass = 0; pass < 2; pass++) { filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(pw); DPRINTF1("ldap search '%s'", filt); - for (base = ldap_conf.base; base != NULL; base = base->next) { + STAILQ_FOREACH(base, &ldap_conf.base, entries) { DPRINTF1("searching from base '%s'", base->val); if (ldap_conf.timeout > 0) { @@ -2957,7 +2951,7 @@ sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *searchresult) * Build a new list node for the search result, this creates the * list node. */ - struct ldap_search_list *last = sudo_ldap_result_add_search(result, + struct ldap_search_result *last = sudo_ldap_result_add_search(result, ldap, searchresult); /* diff --git a/plugins/sudoers/match_addr.c b/plugins/sudoers/match_addr.c index 75f82c9fb..29bfd52dc 100644 --- a/plugins/sudoers/match_addr.c +++ b/plugins/sudoers/match_addr.c @@ -70,7 +70,7 @@ addr_matches_if(char *n) addr.ip4.s_addr = inet_addr(n); } - for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) { + SLIST_FOREACH(ifp, get_interfaces(), entries) { if (ifp->family != family) continue; switch (family) { @@ -153,7 +153,7 @@ addr_matches_if_netmask(char *n, char *m) } #endif /* HAVE_STRUCT_IN6_ADDR */ - for (ifp = get_interfaces(); ifp != NULL; ifp = ifp->next) { + SLIST_FOREACH(ifp, get_interfaces(), entries) { if (ifp->family != family) continue; switch (family) { diff --git a/plugins/sudoers/sudoreplay.c b/plugins/sudoers/sudoreplay.c index 31f089746..fcf2eafbc 100644 --- a/plugins/sudoers/sudoreplay.c +++ b/plugins/sudoers/sudoreplay.c @@ -101,6 +101,7 @@ #include "gettext.h" #include "logging.h" #include "iolog.h" +#include "queue.h" #include "sudo_plugin.h" #include "sudo_conf.h" #include "sudo_debug.h" @@ -128,8 +129,9 @@ struct log_info { * Handle expressions like: * ( user millert or user root ) and tty console and command /bin/sh */ -static struct search_node { - struct search_node *next; +STAILQ_HEAD(search_node_list, search_node); +struct search_node { + STAILQ_ENTRY(search_node) entries; #define ST_EXPR 1 #define ST_TTY 2 #define ST_USER 3 @@ -140,9 +142,8 @@ static struct search_node { #define ST_TODATE 8 #define ST_CWD 9 char type; - char negated; - char or; - char pad; + bool negated; + bool or; union { #ifdef HAVE_REGCOMP regex_t cmdre; @@ -154,14 +155,12 @@ static struct search_node { char *pattern; char *runas_group; char *runas_user; - struct search_node *expr; + struct search_node_list expr; void *ptr; } u; -} *search_expr; +}; -#define STACK_NODE_SIZE 32 -static struct search_node *node_stack[32]; -static int stack_top; +static struct search_node_list search_expr = STAILQ_HEAD_INITIALIZER(search_expr); static int timing_idx_adj = 0; @@ -186,7 +185,7 @@ extern int term_restore(int, int); extern void get_ttysize(int *rowp, int *colp); static int list_sessions(int, char **, const char *, const char *, const char *); -static int parse_expr(struct search_node **, char **); +static int parse_expr(struct search_node_list *, char **, bool); static void check_input(int, double *); static void delay(double); static void help(void) __attribute__((__noreturn__)); @@ -606,14 +605,14 @@ atomic_writev(int fd, struct iovec *iov, int iovcnt) * Build expression list from search args */ static int -parse_expr(struct search_node **headp, char *argv[]) +parse_expr(struct search_node_list *head, char *argv[], bool sub_expr) { - struct search_node *sn, *newsn; - char or = 0, not = 0, type, **av; + bool or = false, not = false; + struct search_node *sn; + char type, **av; debug_decl(parse_expr, SUDO_DEBUG_UTIL) - sn = *headp; - for (av = argv; *av; av++) { + for (av = argv; *av != NULL; av++) { switch (av[0][0]) { case 'a': /* and (ignore) */ if (strncmp(*av, "and", strlen(*av)) != 0) @@ -622,12 +621,12 @@ parse_expr(struct search_node **headp, char *argv[]) case 'o': /* or */ if (strncmp(*av, "or", strlen(*av)) != 0) goto bad; - or = 1; + or = true; continue; case '!': /* negate */ if (av[0][1] != '\0') goto bad; - not = 1; + not = true; continue; case 'c': /* command */ if (av[0][1] == '\0') @@ -672,21 +671,13 @@ parse_expr(struct search_node **headp, char *argv[]) case '(': /* start sub-expression */ if (av[0][1] != '\0') goto bad; - if (stack_top + 1 == STACK_NODE_SIZE) { - fatalx(_("too many parenthesized expressions, max %d"), - STACK_NODE_SIZE); - } - node_stack[stack_top++] = sn; type = ST_EXPR; break; case ')': /* end sub-expression */ if (av[0][1] != '\0') goto bad; - /* pop */ - if (--stack_top < 0) + if (!sub_expr) fatalx(_("unmatched ')' in expression")); - if (node_stack[stack_top]) - sn->next = node_stack[stack_top]->next; debug_return_int(av - argv + 1); bad: default: @@ -695,38 +686,34 @@ parse_expr(struct search_node **headp, char *argv[]) } /* Allocate new search node */ - newsn = ecalloc(1, sizeof(*newsn)); - newsn->type = type; - newsn->or = or; - newsn->negated = not; - /* newsn->next = NULL; */ + sn = ecalloc(1, sizeof(*sn)); + sn->type = type; + sn->or = or; + sn->negated = not; if (type == ST_EXPR) { - av += parse_expr(&newsn->u.expr, av + 1); + STAILQ_INIT(&sn->u.expr); + av += parse_expr(&sn->u.expr, av + 1, true); } else { if (*(++av) == NULL) fatalx(_("%s requires an argument"), av[-1]); #ifdef HAVE_REGCOMP if (type == ST_PATTERN) { - if (regcomp(&newsn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0) + if (regcomp(&sn->u.cmdre, *av, REG_EXTENDED|REG_NOSUB) != 0) fatalx(_("invalid regular expression: %s"), *av); } else #endif if (type == ST_TODATE || type == ST_FROMDATE) { - newsn->u.tstamp = get_date(*av); - if (newsn->u.tstamp == -1) + sn->u.tstamp = get_date(*av); + if (sn->u.tstamp == -1) fatalx(_("could not parse date \"%s\""), *av); } else { - newsn->u.ptr = *av; + sn->u.ptr = *av; } } - not = or = 0; /* reset state */ - if (sn) - sn->next = newsn; - else - *headp = newsn; - sn = newsn; + not = or = false; /* reset state */ + STAILQ_INSERT_TAIL(head, sn, entries); } - if (stack_top) + if (sub_expr) fatalx(_("unmatched '(' in expression")); if (or) fatalx(_("illegal trailing \"or\"")); @@ -737,17 +724,17 @@ parse_expr(struct search_node **headp, char *argv[]) } static bool -match_expr(struct search_node *head, struct log_info *log, bool last_match) +match_expr(struct search_node_list *head, struct log_info *log, bool last_match) { struct search_node *sn; bool res, matched = last_match; int rc; debug_decl(match_expr, SUDO_DEBUG_UTIL) - for (sn = head; sn; sn = sn->next) { + STAILQ_FOREACH(sn, head, entries) { switch (sn->type) { case ST_EXPR: - res = match_expr(sn->u.expr, log, matched); + res = match_expr(&sn->u.expr, log, matched); break; case ST_CWD: res = strcmp(sn->u.cwd, log->cwd) == 0; @@ -909,7 +896,7 @@ list_session(char *logfile, REGEX_T *re, const char *user, const char *tty) goto done; /* Match on search expression if there is one. */ - if (search_expr && !match_expr(search_expr, li, true)) + if (!STAILQ_EMPTY(&search_expr) && !match_expr(&search_expr, li, true)) goto done; /* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */ @@ -1042,7 +1029,7 @@ list_sessions(int argc, char **argv, const char *pattern, const char *user, debug_decl(list_sessions, SUDO_DEBUG_UTIL) /* Parse search expression if present */ - parse_expr(&search_expr, argv); + parse_expr(&search_expr, argv, false); #ifdef HAVE_REGCOMP /* optional regex */ diff --git a/plugins/sudoers/toke.c b/plugins/sudoers/toke.c index 03a979575..936c93b88 100644 --- a/plugins/sudoers/toke.c +++ b/plugins/sudoers/toke.c @@ -3983,37 +3983,42 @@ int main() #line 725 "toke.l" struct path_list { + SLIST_ENTRY(path_list) entries; char *path; - struct path_list *next; }; +SLIST_HEAD(path_list_head, path_list); + struct include_stack { YY_BUFFER_STATE bs; char *path; - struct path_list *more; /* more files in case of includedir */ + struct path_list_head more; /* more files in case of includedir */ int lineno; bool keepopen; }; +/* + * Compare two struct path_list structs in reverse order. + */ static int pl_compare(const void *v1, const void *v2) { const struct path_list * const *p1 = v1; const struct path_list * const *p2 = v2; - return strcmp((*p1)->path, (*p2)->path); + return strcmp((*p2)->path, (*p1)->path); } static char * switch_dir(struct include_stack *stack, char *dirpath) { DIR *dir; - int i, count = 0; + unsigned int i, count = 0; + unsigned int max_paths = 32; char *path = NULL; struct dirent *dent; struct stat sb; - struct path_list *pl, *first = NULL; - struct path_list **sorted = NULL; + struct path_list *pl, **paths = NULL; debug_decl(switch_dir, SUDO_DEBUG_PARSER) if (!(dir = opendir(dirpath))) { @@ -4023,6 +4028,11 @@ switch_dir(struct include_stack *stack, char *dirpath) } goto done; } + paths = malloc(sizeof(*paths) * max_paths); + if (paths == NULL) { + closedir(dir); + goto bad; + } while ((dent = readdir(dir))) { /* Ignore files that end in '~' or have a '.' in them. */ if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' @@ -4042,54 +4052,47 @@ switch_dir(struct include_stack *stack, char *dirpath) if (pl == NULL) goto bad; pl->path = path; - pl->next = first; - first = pl; + if (count >= max_paths) { + struct path_list **tmp; + max_paths <<= 1; + tmp = realloc(paths, sizeof(*paths) * max_paths); + if (tmp == NULL) { + closedir(dir); + goto bad; + } + paths = tmp; + } + paths[count++] = pl; path = NULL; - count++; } closedir(dir); if (count == 0) goto done; - /* Sort the list as an array. */ - sorted = malloc(sizeof(*sorted) * count); - if (sorted == NULL) - goto bad; - pl = first; - for (i = 0; i < count; i++) { - sorted[i] = pl; - pl = pl->next; - } - qsort(sorted, count, sizeof(*sorted), pl_compare); + /* Sort the list as an array in reverse order. */ + qsort(paths, count, sizeof(*paths), pl_compare); - /* Apply sorting to the list. */ - first = sorted[0]; - sorted[count - 1]->next = NULL; - for (i = 1; i < count; i++) - sorted[i - 1]->next = sorted[i]; - efree(sorted); + /* Build up the list in sorted order. */ + for (i = 0; i < count; i++) { + SLIST_INSERT_HEAD(&stack->more, paths[i], entries); + } /* Pull out the first element for parsing, leave the rest for later. */ - if (count) { - path = first->path; - pl = first->next; - efree(first); - stack->more = pl; - } else { - path = NULL; - } + pl = SLIST_FIRST(&stack->more); + SLIST_REMOVE_HEAD(&stack->more, entries); + path = pl->path; + efree(pl); done: + efree(paths); efree(dirpath); debug_return_str(path); bad: - while (first != NULL) { - pl = first; - first = pl->next; - efree(pl->path); - efree(pl); + for (i = 0; i < count; i++) { + efree(paths[i]->path); + efree(paths[i]); } - efree(sorted); + efree(paths); efree(dirpath); efree(path); debug_return_str(NULL); @@ -4110,8 +4113,8 @@ init_lexer(void) while (idepth) { idepth--; - while ((pl = istack[idepth].more) != NULL) { - istack[idepth].more = pl->next; + while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) { + SLIST_REMOVE_HEAD(&istack[idepth].more, entries); efree(pl->path); efree(pl); } @@ -4154,6 +4157,7 @@ _push_include(char *path, bool isdir) debug_return_bool(false); } } + SLIST_INIT(&istack[idepth].more); if (isdir) { struct stat sb; switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) { @@ -4197,10 +4201,10 @@ _push_include(char *path, bool isdir) while ((fp = open_sudoers(path, false, &keepopen)) == NULL) { /* Unable to open path in includedir, go to next one, if any. */ efree(path); - if ((pl = istack[idepth].more) == NULL) + if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL) debug_return_bool(false); + SLIST_REMOVE_HEAD(&istack[idepth].more, entries); path = pl->path; - istack[idepth].more = pl->next; efree(pl); } } else { @@ -4209,7 +4213,6 @@ _push_include(char *path, bool isdir) sudoerserror(NULL); debug_return_bool(false); } - istack[idepth].more = NULL; } /* Push the old (current) file and open the new one. */ istack[idepth].path = sudoers; /* push old path */ @@ -4238,10 +4241,10 @@ pop_include(void) fclose(YY_CURRENT_BUFFER->yy_input_file); sudoers_delete_buffer(YY_CURRENT_BUFFER); /* If we are in an include dir, move to the next file. */ - while ((pl = istack[idepth - 1].more) != NULL) { + while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) { + SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries); fp = open_sudoers(pl->path, false, &keepopen); if (fp != NULL) { - istack[idepth - 1].more = pl->next; efree(sudoers); sudoers = pl->path; sudolineno = 1; @@ -4250,7 +4253,6 @@ pop_include(void) break; } /* Unable to open path in include dir, go to next one. */ - istack[idepth - 1].more = pl->next; efree(pl->path); efree(pl); } diff --git a/plugins/sudoers/toke.l b/plugins/sudoers/toke.l index d693a693b..e90405d4a 100644 --- a/plugins/sudoers/toke.l +++ b/plugins/sudoers/toke.l @@ -724,37 +724,42 @@ sudoedit { %% struct path_list { + SLIST_ENTRY(path_list) entries; char *path; - struct path_list *next; }; +SLIST_HEAD(path_list_head, path_list); + struct include_stack { YY_BUFFER_STATE bs; char *path; - struct path_list *more; /* more files in case of includedir */ + struct path_list_head more; /* more files in case of includedir */ int lineno; bool keepopen; }; +/* + * Compare two struct path_list structs in reverse order. + */ static int pl_compare(const void *v1, const void *v2) { const struct path_list * const *p1 = v1; const struct path_list * const *p2 = v2; - return strcmp((*p1)->path, (*p2)->path); + return strcmp((*p2)->path, (*p1)->path); } static char * switch_dir(struct include_stack *stack, char *dirpath) { DIR *dir; - int i, count = 0; + unsigned int i, count = 0; + unsigned int max_paths = 32; char *path = NULL; struct dirent *dent; struct stat sb; - struct path_list *pl, *first = NULL; - struct path_list **sorted = NULL; + struct path_list *pl, **paths = NULL; debug_decl(switch_dir, SUDO_DEBUG_PARSER) if (!(dir = opendir(dirpath))) { @@ -764,6 +769,11 @@ switch_dir(struct include_stack *stack, char *dirpath) } goto done; } + paths = malloc(sizeof(*paths) * max_paths); + if (paths == NULL) { + closedir(dir); + goto bad; + } while ((dent = readdir(dir))) { /* Ignore files that end in '~' or have a '.' in them. */ if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' @@ -783,54 +793,47 @@ switch_dir(struct include_stack *stack, char *dirpath) if (pl == NULL) goto bad; pl->path = path; - pl->next = first; - first = pl; + if (count >= max_paths) { + struct path_list **tmp; + max_paths <<= 1; + tmp = realloc(paths, sizeof(*paths) * max_paths); + if (tmp == NULL) { + closedir(dir); + goto bad; + } + paths = tmp; + } + paths[count++] = pl; path = NULL; - count++; } closedir(dir); if (count == 0) goto done; - /* Sort the list as an array. */ - sorted = malloc(sizeof(*sorted) * count); - if (sorted == NULL) - goto bad; - pl = first; - for (i = 0; i < count; i++) { - sorted[i] = pl; - pl = pl->next; - } - qsort(sorted, count, sizeof(*sorted), pl_compare); + /* Sort the list as an array in reverse order. */ + qsort(paths, count, sizeof(*paths), pl_compare); - /* Apply sorting to the list. */ - first = sorted[0]; - sorted[count - 1]->next = NULL; - for (i = 1; i < count; i++) - sorted[i - 1]->next = sorted[i]; - efree(sorted); + /* Build up the list in sorted order. */ + for (i = 0; i < count; i++) { + SLIST_INSERT_HEAD(&stack->more, paths[i], entries); + } /* Pull out the first element for parsing, leave the rest for later. */ - if (count) { - path = first->path; - pl = first->next; - efree(first); - stack->more = pl; - } else { - path = NULL; - } + pl = SLIST_FIRST(&stack->more); + SLIST_REMOVE_HEAD(&stack->more, entries); + path = pl->path; + efree(pl); done: + efree(paths); efree(dirpath); debug_return_str(path); bad: - while (first != NULL) { - pl = first; - first = pl->next; - efree(pl->path); - efree(pl); + for (i = 0; i < count; i++) { + efree(paths[i]->path); + efree(paths[i]); } - efree(sorted); + efree(paths); efree(dirpath); efree(path); debug_return_str(NULL); @@ -851,8 +854,8 @@ init_lexer(void) while (idepth) { idepth--; - while ((pl = istack[idepth].more) != NULL) { - istack[idepth].more = pl->next; + while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) { + SLIST_REMOVE_HEAD(&istack[idepth].more, entries); efree(pl->path); efree(pl); } @@ -895,6 +898,7 @@ _push_include(char *path, bool isdir) debug_return_bool(false); } } + SLIST_INIT(&istack[idepth].more); if (isdir) { struct stat sb; switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) { @@ -938,10 +942,10 @@ _push_include(char *path, bool isdir) while ((fp = open_sudoers(path, false, &keepopen)) == NULL) { /* Unable to open path in includedir, go to next one, if any. */ efree(path); - if ((pl = istack[idepth].more) == NULL) + if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL) debug_return_bool(false); + SLIST_REMOVE_HEAD(&istack[idepth].more, entries); path = pl->path; - istack[idepth].more = pl->next; efree(pl); } } else { @@ -950,7 +954,6 @@ _push_include(char *path, bool isdir) sudoerserror(NULL); debug_return_bool(false); } - istack[idepth].more = NULL; } /* Push the old (current) file and open the new one. */ istack[idepth].path = sudoers; /* push old path */ @@ -979,10 +982,10 @@ pop_include(void) fclose(YY_CURRENT_BUFFER->yy_input_file); sudoers_delete_buffer(YY_CURRENT_BUFFER); /* If we are in an include dir, move to the next file. */ - while ((pl = istack[idepth - 1].more) != NULL) { + while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) { + SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries); fp = open_sudoers(pl->path, false, &keepopen); if (fp != NULL) { - istack[idepth - 1].more = pl->next; efree(sudoers); sudoers = pl->path; sudolineno = 1; @@ -991,7 +994,6 @@ pop_include(void) break; } /* Unable to open path in include dir, go to next one. */ - istack[idepth - 1].more = pl->next; efree(pl->path); efree(pl); } diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index 79418de27..5228083c2 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -79,7 +79,6 @@ #include "sudoers.h" #include "parse.h" #include "redblack.h" -#include "queue.h" #include "gettext.h" #include "sudoers_version.h" #include "sudo_conf.h" diff --git a/src/Makefile.in b/src/Makefile.in index 9a3f93e2a..55f9c4f7e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -231,7 +231,7 @@ hooks.o: $(srcdir)/hooks.c $(top_builddir)/config.h $(srcdir)/sudo.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/fatal.h \ $(incdir)/fileops.h $(incdir)/sudo_conf.h $(incdir)/queue.h \ $(incdir)/sudo_debug.h $(incdir)/gettext.h $(incdir)/sudo_plugin.h \ - $(srcdir)/sudo_plugin_int.h $(incdir)/sudo_debug.h + $(srcdir)/sudo_plugin_int.h $(incdir)/sudo_debug.h $(incdir)/queue.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/hooks.c load_plugins.o: $(srcdir)/load_plugins.c $(top_builddir)/config.h \ $(top_srcdir)/compat/dlfcn.h $(srcdir)/sudo.h \ diff --git a/src/exec_pty.c b/src/exec_pty.c index a4a635e3f..7aaa8b0f2 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -77,7 +77,7 @@ #endif struct io_buffer { - struct io_buffer *next; + SLIST_ENTRY(io_buffer) entries; struct sudo_event *revent; struct sudo_event *wevent; bool (*action)(const char *buf, unsigned int len); @@ -86,10 +86,7 @@ struct io_buffer { char buf[32 * 1024]; }; -struct io_buffer_list { - struct io_buffer *first; - /* XXX - stash cstat too? */ -}; +SLIST_HEAD(io_buffer_list, io_buffer); static char slavename[PATH_MAX]; static bool foreground, pipeline, tty_initialized; @@ -609,9 +606,8 @@ io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int), if (n != -1 && !ISSET(n, O_NONBLOCK)) (void) fcntl(wfd, F_SETFL, n | O_NONBLOCK); - /* Add to head of list. */ + /* Allocate and add to head of list. */ iob = emalloc(sizeof(*iob)); - iob->next = head->first; iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ, io_callback, iob); iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE, io_callback, iob); iob->len = 0; @@ -620,7 +616,7 @@ io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int), iob->buf[0] = '\0'; if (iob->revent == NULL || iob->wevent == NULL) fatal(NULL); - head->first = iob; + SLIST_INSERT_HEAD(head, iob, entries); debug_return; } @@ -822,8 +818,8 @@ pty_close(struct command_status *cstat) del_io_events(); /* Free I/O buffers. */ - while ((iob = iobufs.first) != NULL) { - iobufs.first = iob->next; + while ((iob = SLIST_FIRST(&iobufs)) != NULL) { + SLIST_REMOVE_HEAD(&iobufs, entries); efree(iob); } @@ -871,7 +867,7 @@ add_io_events(struct sudo_event_base *evbase) * Schedule writers that contain buffered data. * Normally, write buffers are added on demand when data is read. */ - for (iob = iobufs.first; iob != NULL; iob = iob->next) { + SLIST_FOREACH(iob, &iobufs, entries) { /* Don't read/write from /dev/tty if we are not in the foreground. */ if (iob->revent != NULL && (ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) { @@ -909,7 +905,7 @@ del_io_events(void) debug_decl(del_io_events, SUDO_DEBUG_EXEC); /* Remove iobufs from existing event base. */ - for (iob = iobufs.first; iob != NULL; iob = iob->next) { + SLIST_FOREACH(iob, &iobufs, entries) { if (iob->revent != NULL) { sudo_debug_printf(SUDO_DEBUG_INFO, "deleted I/O revent %p, fd %d, events %d", @@ -930,7 +926,7 @@ del_io_events(void) fatal(NULL); /* Avoid reading from /dev/tty, just flush existing data. */ - for (iob = iobufs.first; iob != NULL; iob = iob->next) { + SLIST_FOREACH(iob, &iobufs, entries) { /* Don't read from /dev/tty while flushing. */ if (iob->revent != NULL && !USERTTY_EVENT(iob->revent)) { if (iob->len != sizeof(iob->buf)) { @@ -951,7 +947,7 @@ del_io_events(void) (void) sudo_ev_loop(evbase, SUDO_EVLOOP_NONBLOCK); /* Free temporary event base. */ - for (iob = iobufs.first; iob != NULL; iob = iob->next) { + SLIST_FOREACH(iob, &iobufs, entries) { if (iob->revent != NULL) sudo_ev_del(evbase, iob->revent); if (iob->wevent != NULL) @@ -1484,7 +1480,7 @@ safe_close(int fd) debug_return_int(-1); } /* Deschedule any other users of the fd. */ - for (iob = iobufs.first; iob != NULL; iob = iob->next) { + SLIST_FOREACH(iob, &iobufs, entries) { if (iob->revent != NULL) { if (sudo_ev_get_fd(iob->revent) == fd) { sudo_debug_printf(SUDO_DEBUG_INFO, diff --git a/src/hooks.c b/src/hooks.c index 1c5f4f4b5..25edff66a 100644 --- a/src/hooks.c +++ b/src/hooks.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Todd C. Miller + * Copyright (c) 2012-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -40,10 +40,11 @@ #include "sudo_plugin.h" #include "sudo_plugin_int.h" #include "sudo_debug.h" +#include "queue.h" /* Singly linked hook list. */ -struct sudo_hook_list { - struct sudo_hook_list *next; +struct sudo_hook_entry { + SLIST_ENTRY(sudo_hook_entry) entries; union { sudo_hook_fn_t generic_fn; sudo_hook_fn_setenv_t setenv_fn; @@ -53,22 +54,27 @@ struct sudo_hook_list { } u; void *closure; }; +SLIST_HEAD(sudo_hook_list, sudo_hook_entry); /* Each hook type gets own hook list. */ -static struct sudo_hook_list *sudo_hook_setenv_list; -static struct sudo_hook_list *sudo_hook_unsetenv_list; -static struct sudo_hook_list *sudo_hook_getenv_list; -static struct sudo_hook_list *sudo_hook_putenv_list; +static struct sudo_hook_list sudo_hook_setenv_list = + SLIST_HEAD_INITIALIZER(sudo_hook_setenv_list); +static struct sudo_hook_list sudo_hook_unsetenv_list = + SLIST_HEAD_INITIALIZER(sudo_hook_unsetenv_list); +static struct sudo_hook_list sudo_hook_getenv_list = + SLIST_HEAD_INITIALIZER(sudo_hook_getenv_list); +static struct sudo_hook_list sudo_hook_putenv_list = + SLIST_HEAD_INITIALIZER(sudo_hook_putenv_list); /* NOTE: must not anything that might call setenv() */ int process_hooks_setenv(const char *name, const char *value, int overwrite) { - struct sudo_hook_list *hook; + struct sudo_hook_entry *hook; int rc = SUDO_HOOK_RET_NEXT; /* First process the hooks. */ - for (hook = sudo_hook_setenv_list; hook != NULL; hook = hook->next) { + SLIST_FOREACH(hook, &sudo_hook_setenv_list, entries) { rc = hook->u.setenv_fn(name, value, overwrite, hook->closure); switch (rc) { case SUDO_HOOK_RET_NEXT: @@ -89,11 +95,11 @@ done: int process_hooks_putenv(char *string) { - struct sudo_hook_list *hook; + struct sudo_hook_entry *hook; int rc = SUDO_HOOK_RET_NEXT; /* First process the hooks. */ - for (hook = sudo_hook_putenv_list; hook != NULL; hook = hook->next) { + SLIST_FOREACH(hook, &sudo_hook_putenv_list, entries) { rc = hook->u.putenv_fn(string, hook->closure); switch (rc) { case SUDO_HOOK_RET_NEXT: @@ -114,12 +120,12 @@ done: int process_hooks_getenv(const char *name, char **value) { - struct sudo_hook_list *hook; + struct sudo_hook_entry *hook; char *val = NULL; int rc = SUDO_HOOK_RET_NEXT; /* First process the hooks. */ - for (hook = sudo_hook_getenv_list; hook != NULL; hook = hook->next) { + SLIST_FOREACH(hook, &sudo_hook_getenv_list, entries) { rc = hook->u.getenv_fn(name, &val, hook->closure); switch (rc) { case SUDO_HOOK_RET_NEXT: @@ -142,11 +148,11 @@ done: int process_hooks_unsetenv(const char *name) { - struct sudo_hook_list *hook; + struct sudo_hook_entry *hook; int rc = SUDO_HOOK_RET_NEXT; /* First process the hooks. */ - for (hook = sudo_hook_unsetenv_list; hook != NULL; hook = hook->next) { + SLIST_FOREACH(hook, &sudo_hook_unsetenv_list, entries) { rc = hook->u.unsetenv_fn(name, hook->closure); switch (rc) { case SUDO_HOOK_RET_NEXT: @@ -165,17 +171,16 @@ done: /* Hook registration internals. */ static void -register_hook_internal(struct sudo_hook_list **head, +register_hook_internal(struct sudo_hook_list *head, int (*hook_fn)(), void *closure) { - struct sudo_hook_list *hook; + struct sudo_hook_entry *hook; debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS) hook = ecalloc(1, sizeof(*hook)); hook->u.generic_fn = hook_fn; hook->closure = closure; - hook->next = *head; - *head = hook; + SLIST_INSERT_HEAD(head, hook, entries); debug_return; } @@ -220,22 +225,23 @@ register_hook(struct sudo_hook *hook) /* Hook deregistration internals. */ static void -deregister_hook_internal(struct sudo_hook_list **head, +deregister_hook_internal(struct sudo_hook_list *head, int (*hook_fn)(), void *closure) { - struct sudo_hook_list *hook, *prev = NULL; + struct sudo_hook_entry *hook, *prev = NULL; debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS) - for (hook = *head, prev = NULL; hook != NULL; prev = hook, hook = hook->next) { + SLIST_FOREACH(hook, head, entries) { if (hook->u.generic_fn == hook_fn && hook->closure == closure) { /* Remove from list and free. */ if (prev == NULL) - *head = hook->next; + SLIST_REMOVE_HEAD(head, entries); else - prev->next = hook->next; + SLIST_REMOVE_AFTER(prev, entries); efree(hook); break; } + prev = hook; } debug_return;